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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22 
23 #include "precomp.h"
24 
25 #ifndef SPI_GETDESKWALLPAPER
26 #define SPI_GETDESKWALLPAPER 0x0073
27 #endif
28 
29 #ifndef WM_SYSTIMER
30 #define WM_SYSTIMER 0x0118
31 #endif
32 
33 #define LONG_PTR INT_PTR
34 #define ULONG_PTR UINT_PTR
35 
36 void dump_region(HRGN hrgn);
37 
38 static HWND (WINAPI *pGetAncestor)(HWND,UINT);
39 static BOOL (WINAPI *pGetWindowInfo)(HWND,WINDOWINFO*);
40 static UINT (WINAPI *pGetWindowModuleFileNameA)(HWND,LPSTR,UINT);
41 static BOOL (WINAPI *pGetLayeredWindowAttributes)(HWND,COLORREF*,BYTE*,DWORD*);
42 static BOOL (WINAPI *pSetLayeredWindowAttributes)(HWND,COLORREF,BYTE,DWORD);
43 static BOOL (WINAPI *pUpdateLayeredWindow)(HWND,HDC,POINT*,SIZE*,HDC,POINT*,COLORREF,BLENDFUNCTION*,DWORD);
44 static BOOL (WINAPI *pUpdateLayeredWindowIndirect)(HWND,const UPDATELAYEREDWINDOWINFO*);
45 static BOOL (WINAPI *pGetMonitorInfoA)(HMONITOR,LPMONITORINFO);
46 static HMONITOR (WINAPI *pMonitorFromPoint)(POINT,DWORD);
47 static int  (WINAPI *pGetWindowRgnBox)(HWND,LPRECT);
48 static BOOL (WINAPI *pGetGUIThreadInfo)(DWORD, GUITHREADINFO*);
49 static BOOL (WINAPI *pGetProcessDefaultLayout)( DWORD *layout );
50 static BOOL (WINAPI *pSetProcessDefaultLayout)( DWORD layout );
51 static BOOL (WINAPI *pFlashWindow)( HWND hwnd, BOOL bInvert );
52 static BOOL (WINAPI *pFlashWindowEx)( PFLASHWINFO pfwi );
53 static DWORD (WINAPI *pSetLayout)(HDC hdc, DWORD layout);
54 static DWORD (WINAPI *pGetLayout)(HDC hdc);
55 static BOOL (WINAPI *pMirrorRgn)(HWND hwnd, HRGN hrgn);
56 
57 static BOOL test_lbuttondown_flag;
58 static DWORD num_gettext_msgs;
59 static DWORD num_settext_msgs;
60 static HWND hwndMessage;
61 static HWND hwndMain, hwndMain2;
62 static HHOOK hhook;
63 static BOOL app_activated, app_deactivated;
64 
65 static const char* szAWRClass = "Winsize";
66 static HMENU hmenu;
67 static DWORD our_pid;
68 
69 static BOOL is_win9x = FALSE;
70 
71 #define COUNTOF(arr) (sizeof(arr)/sizeof(arr[0]))
72 
73 static void dump_minmax_info( const MINMAXINFO *minmax )
74 {
75     trace("Reserved=%d,%d MaxSize=%d,%d MaxPos=%d,%d MinTrack=%d,%d MaxTrack=%d,%d\n",
76           minmax->ptReserved.x, minmax->ptReserved.y,
77           minmax->ptMaxSize.x, minmax->ptMaxSize.y,
78           minmax->ptMaxPosition.x, minmax->ptMaxPosition.y,
79           minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y,
80           minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y);
81 }
82 
83 /* try to make sure pending X events have been processed before continuing */
84 static void flush_events( BOOL remove_messages )
85 {
86     MSG msg;
87     int diff = 200;
88     int min_timeout = 100;
89     DWORD time = GetTickCount() + diff;
90 
91     while (diff > 0)
92     {
93         if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min_timeout, QS_ALLINPUT ) == WAIT_TIMEOUT) break;
94         if (remove_messages)
95             while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
96         diff = time - GetTickCount();
97         min_timeout = 50;
98     }
99 }
100 
101 static BOOL wait_for_event(HANDLE event, int timeout)
102 {
103     DWORD end_time = GetTickCount() + timeout;
104     MSG msg;
105 
106     do {
107         if(MsgWaitForMultipleObjects(1, &event, FALSE, timeout, QS_ALLINPUT) == WAIT_OBJECT_0)
108             return TRUE;
109         while(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
110             DispatchMessageA(&msg);
111         timeout = end_time - GetTickCount();
112     }while(timeout > 0);
113 
114     return FALSE;
115 }
116 
117 /* check the values returned by the various parent/owner functions on a given window */
118 static void check_parents( HWND hwnd, HWND ga_parent, HWND gwl_parent, HWND get_parent,
119                            HWND gw_owner, HWND ga_root, HWND ga_root_owner )
120 {
121     HWND res;
122 
123     if (pGetAncestor)
124     {
125         res = pGetAncestor( hwnd, GA_PARENT );
126         ok( res == ga_parent, "Wrong result for GA_PARENT %p expected %p\n", res, ga_parent );
127     }
128     res = (HWND)GetWindowLongPtrA( hwnd, GWLP_HWNDPARENT );
129     ok( res == gwl_parent, "Wrong result for GWL_HWNDPARENT %p expected %p\n", res, gwl_parent );
130     res = GetParent( hwnd );
131     ok( res == get_parent, "Wrong result for GetParent %p expected %p\n", res, get_parent );
132     res = GetWindow( hwnd, GW_OWNER );
133     ok( res == gw_owner, "Wrong result for GW_OWNER %p expected %p\n", res, gw_owner );
134     if (pGetAncestor)
135     {
136         res = pGetAncestor( hwnd, GA_ROOT );
137         ok( res == ga_root, "Wrong result for GA_ROOT %p expected %p\n", res, ga_root );
138         res = pGetAncestor( hwnd, GA_ROOTOWNER );
139         ok( res == ga_root_owner, "Wrong result for GA_ROOTOWNER %p expected %p\n", res, ga_root_owner );
140     }
141 }
142 
143 #define check_wnd_state(a,b,c,d) check_wnd_state_(__FILE__,__LINE__,a,b,c,d)
144 static void check_wnd_state_(const char *file, int line,
145                              HWND active, HWND foreground, HWND focus, HWND capture)
146 {
147     ok_(file, line)(active == GetActiveWindow(), "GetActiveWindow() = %p\n", GetActiveWindow());
148     /* only check foreground if it belongs to the current thread */
149     /* foreground can be moved to a different app pretty much at any time */
150     if (foreground && GetForegroundWindow() &&
151         GetWindowThreadProcessId(GetForegroundWindow(), NULL) == GetCurrentThreadId())
152         ok_(file, line)(foreground == GetForegroundWindow(), "GetForegroundWindow() = %p\n", GetForegroundWindow());
153     ok_(file, line)(focus == GetFocus(), "GetFocus() = %p\n", GetFocus());
154     ok_(file, line)(capture == GetCapture(), "GetCapture() = %p\n", GetCapture());
155 }
156 
157 /* same as above but without capture test */
158 #define check_active_state(a,b,c) check_active_state_(__FILE__,__LINE__,a,b,c)
159 static void check_active_state_(const char *file, int line,
160                                 HWND active, HWND foreground, HWND focus)
161 {
162     ok_(file, line)(active == GetActiveWindow(), "GetActiveWindow() = %p\n", GetActiveWindow());
163     /* only check foreground if it belongs to the current thread */
164     /* foreground can be moved to a different app pretty much at any time */
165     if (foreground && GetForegroundWindow() &&
166         GetWindowThreadProcessId(GetForegroundWindow(), NULL) == GetCurrentThreadId())
167         ok_(file, line)(foreground == GetForegroundWindow(), "GetForegroundWindow() = %p\n", GetForegroundWindow());
168     ok_(file, line)(focus == GetFocus(), "GetFocus() = %p\n", GetFocus());
169 }
170 
171 static BOOL ignore_message( UINT message )
172 {
173     /* these are always ignored */
174     return (message >= 0xc000 ||
175             message == WM_GETICON ||
176             message == WM_GETOBJECT ||
177             message == WM_TIMER ||
178             message == WM_SYSTIMER ||
179             message == WM_TIMECHANGE ||
180             message == WM_DEVICECHANGE);
181 }
182 
183 static BOOL CALLBACK EnumChildProc( HWND hwndChild, LPARAM lParam)
184 {
185     (*(LPINT)lParam)++;
186     trace("EnumChildProc on %p\n", hwndChild);
187     if (*(LPINT)lParam > 1) return FALSE;
188     return TRUE;
189 }
190 
191 /* will search for the given window */
192 static BOOL CALLBACK EnumChildProc1( HWND hwndChild, LPARAM lParam)
193 {
194     trace("EnumChildProc1 on %p\n", hwndChild);
195     if ((HWND)lParam == hwndChild) return FALSE;
196     return TRUE;
197 }
198 
199 static HWND create_tool_window( LONG style, HWND parent )
200 {
201     HWND ret = CreateWindowExA(0, "ToolWindowClass", "Tool window 1", style,
202                                0, 0, 100, 100, parent, 0, 0, NULL );
203     ok( ret != 0, "Creation failed\n" );
204     return ret;
205 }
206 
207 /* test parent and owner values for various combinations */
208 static void test_parent_owner(void)
209 {
210     LONG style;
211     HWND test, owner, ret;
212     HWND desktop = GetDesktopWindow();
213     HWND child = create_tool_window( WS_CHILD, hwndMain );
214     INT  numChildren;
215 
216     trace( "main window %p main2 %p desktop %p child %p\n", hwndMain, hwndMain2, desktop, child );
217 
218     /* child without parent, should fail */
219     SetLastError(0xdeadbeef);
220     test = CreateWindowExA(0, "ToolWindowClass", "Tool window 1",
221                            WS_CHILD, 0, 0, 100, 100, 0, 0, 0, NULL );
222     ok( !test, "WS_CHILD without parent created\n" );
223     ok( GetLastError() == ERROR_TLW_WITH_WSCHILD ||
224         broken(GetLastError() == 0xdeadbeef), /* win9x */
225         "CreateWindowExA error %u\n", GetLastError() );
226 
227     /* desktop window */
228     check_parents( desktop, 0, 0, 0, 0, 0, 0 );
229     style = GetWindowLongA( desktop, GWL_STYLE );
230     ok( !SetWindowLongA( desktop, GWL_STYLE, WS_POPUP ), "Set GWL_STYLE on desktop succeeded\n" );
231     ok( !SetWindowLongA( desktop, GWL_STYLE, 0 ), "Set GWL_STYLE on desktop succeeded\n" );
232     ok( GetWindowLongA( desktop, GWL_STYLE ) == style, "Desktop style changed\n" );
233 
234     /* normal child window */
235     test = create_tool_window( WS_CHILD, hwndMain );
236     trace( "created child %p\n", test );
237     check_parents( test, hwndMain, hwndMain, hwndMain, 0, hwndMain, hwndMain );
238     SetWindowLongA( test, GWL_STYLE, 0 );
239     check_parents( test, hwndMain, hwndMain, 0, 0, hwndMain, test );
240     SetWindowLongA( test, GWL_STYLE, WS_POPUP );
241     check_parents( test, hwndMain, hwndMain, 0, 0, hwndMain, test );
242     SetWindowLongA( test, GWL_STYLE, WS_POPUP|WS_CHILD );
243     check_parents( test, hwndMain, hwndMain, 0, 0, hwndMain, test );
244     SetWindowLongA( test, GWL_STYLE, WS_CHILD );
245     DestroyWindow( test );
246 
247     /* normal child window with WS_MAXIMIZE */
248     test = create_tool_window( WS_CHILD | WS_MAXIMIZE, hwndMain );
249     DestroyWindow( test );
250 
251     /* normal child window with WS_THICKFRAME */
252     test = create_tool_window( WS_CHILD | WS_THICKFRAME, hwndMain );
253     DestroyWindow( test );
254 
255     /* popup window with WS_THICKFRAME */
256     test = create_tool_window( WS_POPUP | WS_THICKFRAME, hwndMain );
257     DestroyWindow( test );
258 
259     /* child of desktop */
260     test = create_tool_window( WS_CHILD, desktop );
261     trace( "created child of desktop %p\n", test );
262     check_parents( test, desktop, 0, desktop, 0, test, desktop );
263     SetWindowLongA( test, GWL_STYLE, WS_POPUP );
264     check_parents( test, desktop, 0, 0, 0, test, test );
265     SetWindowLongA( test, GWL_STYLE, 0 );
266     check_parents( test, desktop, 0, 0, 0, test, test );
267     DestroyWindow( test );
268 
269     /* child of desktop with WS_MAXIMIZE */
270     test = create_tool_window( WS_CHILD | WS_MAXIMIZE, desktop );
271     DestroyWindow( test );
272 
273     /* child of desktop with WS_MINIMIZE */
274     test = create_tool_window( WS_CHILD | WS_MINIMIZE, desktop );
275     DestroyWindow( test );
276 
277     /* child of child */
278     test = create_tool_window( WS_CHILD, child );
279     trace( "created child of child %p\n", test );
280     check_parents( test, child, child, child, 0, hwndMain, hwndMain );
281     SetWindowLongA( test, GWL_STYLE, 0 );
282     check_parents( test, child, child, 0, 0, hwndMain, test );
283     SetWindowLongA( test, GWL_STYLE, WS_POPUP );
284     check_parents( test, child, child, 0, 0, hwndMain, test );
285     DestroyWindow( test );
286 
287     /* child of child with WS_MAXIMIZE */
288     test = create_tool_window( WS_CHILD | WS_MAXIMIZE, child );
289     DestroyWindow( test );
290 
291     /* child of child with WS_MINIMIZE */
292     test = create_tool_window( WS_CHILD | WS_MINIMIZE, child );
293     DestroyWindow( test );
294 
295     /* not owned top-level window */
296     test = create_tool_window( 0, 0 );
297     trace( "created top-level %p\n", test );
298     check_parents( test, desktop, 0, 0, 0, test, test );
299     SetWindowLongA( test, GWL_STYLE, WS_POPUP );
300     check_parents( test, desktop, 0, 0, 0, test, test );
301     SetWindowLongA( test, GWL_STYLE, WS_CHILD );
302     check_parents( test, desktop, 0, desktop, 0, test, desktop );
303     DestroyWindow( test );
304 
305     /* not owned top-level window with WS_MAXIMIZE */
306     test = create_tool_window( WS_MAXIMIZE, 0 );
307     DestroyWindow( test );
308 
309     /* owned top-level window */
310     test = create_tool_window( 0, hwndMain );
311     trace( "created owned top-level %p\n", test );
312     check_parents( test, desktop, hwndMain, 0, hwndMain, test, test );
313     SetWindowLongA( test, GWL_STYLE, WS_POPUP );
314     check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
315     SetWindowLongA( test, GWL_STYLE, WS_CHILD );
316     check_parents( test, desktop, hwndMain, desktop, hwndMain, test, desktop );
317     DestroyWindow( test );
318 
319     /* owned top-level window with WS_MAXIMIZE */
320     test = create_tool_window( WS_MAXIMIZE, hwndMain );
321     DestroyWindow( test );
322 
323     /* not owned popup */
324     test = create_tool_window( WS_POPUP, 0 );
325     trace( "created popup %p\n", test );
326     check_parents( test, desktop, 0, 0, 0, test, test );
327     SetWindowLongA( test, GWL_STYLE, WS_CHILD );
328     check_parents( test, desktop, 0, desktop, 0, test, desktop );
329     SetWindowLongA( test, GWL_STYLE, 0 );
330     check_parents( test, desktop, 0, 0, 0, test, test );
331     DestroyWindow( test );
332 
333     /* not owned popup with WS_MAXIMIZE */
334     test = create_tool_window( WS_POPUP | WS_MAXIMIZE, 0 );
335     DestroyWindow( test );
336 
337     /* owned popup */
338     test = create_tool_window( WS_POPUP, hwndMain );
339     trace( "created owned popup %p\n", test );
340     check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
341     SetWindowLongA( test, GWL_STYLE, WS_CHILD );
342     check_parents( test, desktop, hwndMain, desktop, hwndMain, test, desktop );
343     SetWindowLongA( test, GWL_STYLE, 0 );
344     check_parents( test, desktop, hwndMain, 0, hwndMain, test, test );
345     DestroyWindow( test );
346 
347     /* owned popup with WS_MAXIMIZE */
348     test = create_tool_window( WS_POPUP | WS_MAXIMIZE, hwndMain );
349     DestroyWindow( test );
350 
351     /* top-level window owned by child (same as owned by top-level) */
352     test = create_tool_window( 0, child );
353     trace( "created top-level owned by child %p\n", test );
354     check_parents( test, desktop, hwndMain, 0, hwndMain, test, test );
355     DestroyWindow( test );
356 
357     /* top-level window owned by child (same as owned by top-level) with WS_MAXIMIZE */
358     test = create_tool_window( WS_MAXIMIZE, child );
359     DestroyWindow( test );
360 
361     /* popup owned by desktop (same as not owned) */
362     test = create_tool_window( WS_POPUP, desktop );
363     trace( "created popup owned by desktop %p\n", test );
364     check_parents( test, desktop, 0, 0, 0, test, test );
365     DestroyWindow( test );
366 
367     /* popup owned by desktop (same as not owned) with WS_MAXIMIZE */
368     test = create_tool_window( WS_POPUP | WS_MAXIMIZE, desktop );
369     DestroyWindow( test );
370 
371     /* popup owned by child (same as owned by top-level) */
372     test = create_tool_window( WS_POPUP, child );
373     trace( "created popup owned by child %p\n", test );
374     check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
375     DestroyWindow( test );
376 
377     /* popup owned by child (same as owned by top-level) with WS_MAXIMIZE */
378     test = create_tool_window( WS_POPUP | WS_MAXIMIZE, child );
379     DestroyWindow( test );
380 
381     /* not owned popup with WS_CHILD (same as WS_POPUP only) */
382     test = create_tool_window( WS_POPUP | WS_CHILD, 0 );
383     trace( "created WS_CHILD popup %p\n", test );
384     check_parents( test, desktop, 0, 0, 0, test, test );
385     DestroyWindow( test );
386 
387     /* not owned popup with WS_CHILD | WS_MAXIMIZE (same as WS_POPUP only) */
388     test = create_tool_window( WS_POPUP | WS_CHILD | WS_MAXIMIZE, 0 );
389     DestroyWindow( test );
390 
391     /* owned popup with WS_CHILD (same as WS_POPUP only) */
392     test = create_tool_window( WS_POPUP | WS_CHILD, hwndMain );
393     trace( "created owned WS_CHILD popup %p\n", test );
394     check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
395     DestroyWindow( test );
396 
397     /* owned popup with WS_CHILD (same as WS_POPUP only) with WS_MAXIMIZE */
398     test = create_tool_window( WS_POPUP | WS_CHILD | WS_MAXIMIZE, hwndMain );
399     DestroyWindow( test );
400 
401     /******************** parent changes *************************/
402     trace( "testing parent changes\n" );
403 
404     /* desktop window */
405     check_parents( desktop, 0, 0, 0, 0, 0, 0 );
406     if (0)
407     {
408     /* this test succeeds on NT but crashes on win9x systems */
409     ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)hwndMain2 );
410     ok( !ret, "Set GWL_HWNDPARENT succeeded on desktop\n" );
411     check_parents( desktop, 0, 0, 0, 0, 0, 0 );
412     ok( !SetParent( desktop, hwndMain ), "SetParent succeeded on desktop\n" );
413     check_parents( desktop, 0, 0, 0, 0, 0, 0 );
414     }
415     /* normal child window */
416     test = create_tool_window( WS_CHILD, hwndMain );
417     trace( "created child %p\n", test );
418 
419     ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)hwndMain2 );
420     ok( ret == hwndMain, "GWL_HWNDPARENT return value %p expected %p\n", ret, hwndMain );
421     check_parents( test, hwndMain2, hwndMain2, hwndMain2, 0, hwndMain2, hwndMain2 );
422 
423     ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)child );
424     ok( ret == hwndMain2, "GWL_HWNDPARENT return value %p expected %p\n", ret, hwndMain2 );
425     check_parents( test, child, child, child, 0, hwndMain, hwndMain );
426 
427     ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)desktop );
428     ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
429     check_parents( test, desktop, 0, desktop, 0, test, desktop );
430 
431     /* window is now child of desktop so GWLP_HWNDPARENT changes owner from now on */
432     if (!is_win9x)
433     {
434         ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)test );
435         ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
436         check_parents( test, desktop, 0, desktop, 0, test, desktop );
437     }
438     else
439         win_skip("Test creates circular window tree under Win9x/WinMe\n" );
440 
441     ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)child );
442     ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
443     check_parents( test, desktop, child, desktop, child, test, desktop );
444 
445     ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, 0 );
446     ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
447     check_parents( test, desktop, 0, desktop, 0, test, desktop );
448     DestroyWindow( test );
449 
450     /* not owned top-level window */
451     test = create_tool_window( 0, 0 );
452     trace( "created top-level %p\n", test );
453 
454     ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)hwndMain2 );
455     ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
456     check_parents( test, desktop, hwndMain2, 0, hwndMain2, test, test );
457 
458     ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)child );
459     ok( ret == hwndMain2, "GWL_HWNDPARENT return value %p expected %p\n", ret, hwndMain2 );
460     check_parents( test, desktop, child, 0, child, test, test );
461 
462     ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, 0 );
463     ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
464     check_parents( test, desktop, 0, 0, 0, test, test );
465     DestroyWindow( test );
466 
467     /* not owned popup */
468     test = create_tool_window( WS_POPUP, 0 );
469     trace( "created popup %p\n", test );
470 
471     ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)hwndMain2 );
472     ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
473     check_parents( test, desktop, hwndMain2, hwndMain2, hwndMain2, test, hwndMain2 );
474 
475     ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)child );
476     ok( ret == hwndMain2, "GWL_HWNDPARENT return value %p expected %p\n", ret, hwndMain2 );
477     check_parents( test, desktop, child, child, child, test, hwndMain );
478 
479     ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, 0 );
480     ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
481     check_parents( test, desktop, 0, 0, 0, test, test );
482     DestroyWindow( test );
483 
484     /* normal child window */
485     test = create_tool_window( WS_CHILD, hwndMain );
486     trace( "created child %p\n", test );
487 
488     ret = SetParent( test, desktop );
489     ok( ret == hwndMain, "SetParent return value %p expected %p\n", ret, hwndMain );
490     check_parents( test, desktop, 0, desktop, 0, test, desktop );
491 
492     ret = SetParent( test, child );
493     ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
494     check_parents( test, child, child, child, 0, hwndMain, hwndMain );
495 
496     ret = SetParent( test, hwndMain2 );
497     ok( ret == child, "SetParent return value %p expected %p\n", ret, child );
498     check_parents( test, hwndMain2, hwndMain2, hwndMain2, 0, hwndMain2, hwndMain2 );
499     DestroyWindow( test );
500 
501     /* not owned top-level window */
502     test = create_tool_window( 0, 0 );
503     trace( "created top-level %p\n", test );
504 
505     ret = SetParent( test, child );
506     ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
507     check_parents( test, child, child, 0, 0, hwndMain, test );
508 
509     if (!is_win9x)
510     {
511         ShowWindow( test, SW_SHOW );
512         ret = SetParent( test, test );
513         ok( ret == NULL, "SetParent return value %p expected %p\n", ret, NULL );
514         ok( GetWindowLongA( test, GWL_STYLE ) & WS_VISIBLE, "window is not visible after SetParent\n" );
515         check_parents( test, child, child, 0, 0, hwndMain, test );
516     }
517     else
518         win_skip( "Test crashes on Win9x/WinMe\n" );
519     DestroyWindow( test );
520 
521     /* owned popup */
522     test = create_tool_window( WS_POPUP, hwndMain2 );
523     trace( "created owned popup %p\n", test );
524 
525     ret = SetParent( test, child );
526     ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
527     check_parents( test, child, child, hwndMain2, hwndMain2, hwndMain, hwndMain2 );
528 
529     ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (ULONG_PTR)hwndMain );
530     ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
531     check_parents( test, hwndMain, hwndMain, hwndMain2, hwndMain2, hwndMain, hwndMain2 );
532     DestroyWindow( test );
533 
534     /**************** test owner destruction *******************/
535 
536     /* owned child popup */
537     owner = create_tool_window( 0, 0 );
538     test = create_tool_window( WS_POPUP, owner );
539     trace( "created owner %p and popup %p\n", owner, test );
540     ret = SetParent( test, child );
541     ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
542     check_parents( test, child, child, owner, owner, hwndMain, owner );
543     /* window is now child of 'child' but owned by 'owner' */
544     DestroyWindow( owner );
545     ok( IsWindow(test), "Window %p destroyed by owner destruction\n", test );
546     /* Win98 doesn't pass this test. It doesn't allow a destroyed owner,
547      * while Win95, Win2k, WinXP do.
548      */
549     /*check_parents( test, child, child, owner, owner, hwndMain, owner );*/
550     ok( !IsWindow(owner), "Owner %p not destroyed\n", owner );
551     DestroyWindow(test);
552 
553     /* owned top-level popup */
554     owner = create_tool_window( 0, 0 );
555     test = create_tool_window( WS_POPUP, owner );
556     trace( "created owner %p and popup %p\n", owner, test );
557     check_parents( test, desktop, owner, owner, owner, test, owner );
558     DestroyWindow( owner );
559     ok( !IsWindow(test), "Window %p not destroyed by owner destruction\n", test );
560 
561     /* top-level popup owned by child */
562     owner = create_tool_window( WS_CHILD, hwndMain2 );
563     test = create_tool_window( WS_POPUP, 0 );
564     trace( "created owner %p and popup %p\n", owner, test );
565     ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (ULONG_PTR)owner );
566     ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
567     check_parents( test, desktop, owner, owner, owner, test, hwndMain2 );
568     DestroyWindow( owner );
569     ok( IsWindow(test), "Window %p destroyed by owner destruction\n", test );
570     ok( !IsWindow(owner), "Owner %p not destroyed\n", owner );
571     /* Win98 doesn't pass this test. It doesn't allow a destroyed owner,
572      * while Win95, Win2k, WinXP do.
573      */
574     /*check_parents( test, desktop, owner, owner, owner, test, owner );*/
575     DestroyWindow(test);
576 
577     /* final cleanup */
578     DestroyWindow(child);
579 
580 
581     owner = create_tool_window( WS_OVERLAPPED, 0 );
582     test = create_tool_window( WS_POPUP, desktop );
583 
584     ok( !GetWindow( test, GW_OWNER ), "Wrong owner window\n" );
585     numChildren = 0;
586     ok( !EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
587         "EnumChildWindows should have returned FALSE\n" );
588     ok( numChildren == 0, "numChildren should be 0 got %d\n", numChildren );
589 
590     SetWindowLongA( test, GWL_STYLE, (GetWindowLongA( test, GWL_STYLE ) & ~WS_POPUP) | WS_CHILD );
591     ret = SetParent( test, owner );
592     ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
593 
594     numChildren = 0;
595     ok( EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
596         "EnumChildWindows should have returned TRUE\n" );
597     ok( numChildren == 1, "numChildren should be 1 got %d\n", numChildren );
598 
599     child = create_tool_window( WS_CHILD, owner );
600     numChildren = 0;
601     ok( !EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
602         "EnumChildWindows should have returned FALSE\n" );
603     ok( numChildren == 2, "numChildren should be 2 got %d\n", numChildren );
604     DestroyWindow( child );
605 
606     child = create_tool_window( WS_VISIBLE | WS_OVERLAPPEDWINDOW, owner );
607     ok( GetWindow( child, GW_OWNER ) == owner, "Wrong owner window\n" );
608     numChildren = 0;
609     ok( EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
610         "EnumChildWindows should have returned TRUE\n" );
611     ok( numChildren == 1, "numChildren should be 1 got %d\n", numChildren );
612 
613     ret = SetParent( child, owner );
614     ok( GetWindow( child, GW_OWNER ) == owner, "Wrong owner window\n" );
615     ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
616     numChildren = 0;
617     ok( !EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
618         "EnumChildWindows should have returned FALSE\n" );
619     ok( numChildren == 2, "numChildren should be 2 got %d\n", numChildren );
620 
621     ret = SetParent( child, NULL );
622     ok( GetWindow( child, GW_OWNER ) == owner, "Wrong owner window\n" );
623     ok( ret == owner, "SetParent return value %p expected %p\n", ret, owner );
624     numChildren = 0;
625     ok( EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
626         "EnumChildWindows should have returned TRUE\n" );
627     ok( numChildren == 1, "numChildren should be 1 got %d\n", numChildren );
628 
629     /* even GW_OWNER == owner it's still a desktop's child */
630     ok( !EnumChildWindows( desktop, EnumChildProc1, (LPARAM)child ),
631         "EnumChildWindows should have found %p and returned FALSE\n", child );
632 
633     DestroyWindow( child );
634     child = create_tool_window( WS_VISIBLE | WS_OVERLAPPEDWINDOW, NULL );
635 
636     ok( !EnumChildWindows( desktop, EnumChildProc1, (LPARAM)child ),
637         "EnumChildWindows should have found %p and returned FALSE\n", child );
638 
639     DestroyWindow( child );
640     DestroyWindow( test );
641     DestroyWindow( owner );
642 
643     /* Test that owner window takes into account WS_CHILD flag even if parent is set by SetParent. */
644     owner = create_tool_window( WS_VISIBLE | WS_OVERLAPPEDWINDOW, desktop );
645     SetParent(owner, hwndMain);
646     check_parents( owner, hwndMain, hwndMain, NULL, NULL, hwndMain, owner );
647     test = create_tool_window( WS_VISIBLE | WS_OVERLAPPEDWINDOW, owner );
648     check_parents( test, desktop, owner, NULL, owner, test, test );
649     DestroyWindow( owner );
650     DestroyWindow( test );
651 
652     owner = create_tool_window( WS_VISIBLE | WS_CHILD, desktop );
653     SetParent(owner, hwndMain);
654     check_parents( owner, hwndMain, hwndMain, hwndMain, NULL, hwndMain, hwndMain );
655     test = create_tool_window( WS_VISIBLE | WS_OVERLAPPEDWINDOW, owner );
656     check_parents( test, desktop, hwndMain, NULL, hwndMain, test, test );
657     DestroyWindow( owner );
658     DestroyWindow( test );
659 
660     owner = create_tool_window( WS_VISIBLE | WS_POPUP | WS_CHILD, desktop );
661     SetParent(owner, hwndMain);
662     check_parents( owner, hwndMain, hwndMain, NULL, NULL, hwndMain, owner );
663     test = create_tool_window( WS_VISIBLE | WS_OVERLAPPEDWINDOW, owner );
664     check_parents( test, desktop, owner, NULL, owner, test, test );
665     DestroyWindow( owner );
666     DestroyWindow( test );
667 }
668 
669 static BOOL CALLBACK enum_proc( HWND hwnd, LPARAM lParam)
670 {
671     (*(LPINT)lParam)++;
672     if (*(LPINT)lParam > 2) return FALSE;
673     return TRUE;
674 }
675 static DWORD CALLBACK enum_thread( void *arg )
676 {
677     INT count;
678     HWND hwnd[3];
679     BOOL ret;
680     MSG msg;
681 
682     if (pGetGUIThreadInfo)
683     {
684         GUITHREADINFO info;
685         info.cbSize = sizeof(info);
686         ret = pGetGUIThreadInfo( GetCurrentThreadId(), &info );
687         ok( ret || broken(!ret), /* win9x */
688             "GetGUIThreadInfo failed without message queue\n" );
689         SetLastError( 0xdeadbeef );
690         info.cbSize = sizeof(info) + 1;
691         ret = pGetGUIThreadInfo( GetCurrentThreadId(), &info );
692         ok( !ret, "GetGUIThreadInfo succeeded with wrong size\n" );
693         ok( GetLastError() == ERROR_INVALID_PARAMETER ||
694             broken(GetLastError() == 0xdeadbeef), /* win9x */
695             "wrong error %u\n", GetLastError() );
696     }
697 
698     PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE );  /* make sure we have a message queue */
699 
700     count = 0;
701     ret = EnumThreadWindows( GetCurrentThreadId(), enum_proc, (LPARAM)&count );
702     ok( ret, "EnumThreadWindows should have returned TRUE\n" );
703     ok( count == 0, "count should be 0 got %d\n", count );
704 
705     hwnd[0] = CreateWindowExA(0, "ToolWindowClass", "Tool window 1", WS_POPUP,
706                               0, 0, 100, 100, 0, 0, 0, NULL );
707     count = 0;
708     ret = EnumThreadWindows( GetCurrentThreadId(), enum_proc, (LPARAM)&count );
709     ok( ret, "EnumThreadWindows should have returned TRUE\n" );
710     if (count != 2)  /* Vista gives us two windows for the price of one */
711     {
712         ok( count == 1, "count should be 1 got %d\n", count );
713         hwnd[2] = CreateWindowExA(0, "ToolWindowClass", "Tool window 2", WS_POPUP,
714                                   0, 0, 100, 100, 0, 0, 0, NULL );
715     }
716     else hwnd[2] = 0;
717 
718     hwnd[1] = CreateWindowExA(0, "ToolWindowClass", "Tool window 3", WS_POPUP,
719                               0, 0, 100, 100, 0, 0, 0, NULL );
720     count = 0;
721     ret = EnumThreadWindows( GetCurrentThreadId(), enum_proc, (LPARAM)&count );
722     ok( !ret, "EnumThreadWindows should have returned FALSE\n" );
723     ok( count == 3, "count should be 3 got %d\n", count );
724 
725     if (hwnd[2]) DestroyWindow(hwnd[2]);
726     DestroyWindow(hwnd[1]);
727     DestroyWindow(hwnd[0]);
728     return 0;
729 }
730 
731 /* test EnumThreadWindows in a separate thread */
732 static void test_enum_thread_windows(void)
733 {
734     DWORD id;
735     HANDLE handle = CreateThread( NULL, 0, enum_thread, 0, 0, &id );
736     ok( !WaitForSingleObject( handle, 10000 ), "wait failed\n" );
737     CloseHandle( handle );
738 }
739 
740 static struct wm_gettext_override_data
741 {
742     BOOL   enabled; /* when 1 bypasses default procedure */
743     char  *buff;    /* expected text buffer pointer */
744     WCHAR *buffW;   /* same, for W test */
745 } g_wm_gettext_override;
746 
747 static LRESULT WINAPI main_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
748 {
749     switch (msg)
750     {
751 	case WM_GETMINMAXINFO:
752 	{
753 	    SetWindowLongPtrA(hwnd, GWLP_USERDATA, 0x20031021);
754 	    break;
755 	}
756 	case WM_WINDOWPOSCHANGING:
757 	{
758 	    WINDOWPOS *winpos = (WINDOWPOS *)lparam;
759 	    if (!(winpos->flags & SWP_NOMOVE))
760 	    {
761 		ok(winpos->x >= -32768 && winpos->x <= 32767, "bad winpos->x %d\n", winpos->x);
762 		ok(winpos->y >= -32768 && winpos->y <= 32767, "bad winpos->y %d\n", winpos->y);
763 	    }
764 	    /* Win9x does not fixup cx/xy for WM_WINDOWPOSCHANGING */
765 	    if (!(winpos->flags & SWP_NOSIZE) && !is_win9x)
766 	    {
767 		ok((winpos->cx >= 0 && winpos->cx <= 32767) ||
768                    winpos->cx == 32768, /* win7 doesn't truncate */
769                    "bad winpos->cx %d\n", winpos->cx);
770 		ok((winpos->cy >= 0 && winpos->cy <= 32767) ||
771                    winpos->cy == 40000, /* win7 doesn't truncate */
772                    "bad winpos->cy %d\n", winpos->cy);
773 	    }
774 	    break;
775 	}
776 	case WM_WINDOWPOSCHANGED:
777 	{
778             RECT rc1, rc2;
779 	    WINDOWPOS *winpos = (WINDOWPOS *)lparam;
780 	    ok(winpos->x >= -32768 && winpos->x <= 32767, "bad winpos->x %d\n", winpos->x);
781 	    ok(winpos->y >= -32768 && winpos->y <= 32767, "bad winpos->y %d\n", winpos->y);
782 
783             ok((winpos->cx >= 0 && winpos->cx <= 32767) ||
784                winpos->cx == 32768, /* win7 doesn't truncate */
785                "bad winpos->cx %d\n", winpos->cx);
786             ok((winpos->cy >= 0 && winpos->cy <= 32767) ||
787                winpos->cy == 40000, /* win7 doesn't truncate */
788                "bad winpos->cy %d\n", winpos->cy);
789 
790             GetWindowRect(hwnd, &rc1);
791             SetRect(&rc2, winpos->x, winpos->y, winpos->x + winpos->cx, winpos->y + winpos->cy);
792             /* note: winpos coordinates are relative to parent */
793             MapWindowPoints(GetParent(hwnd), 0, (LPPOINT)&rc2, 2);
794             if (0)
795             {
796             /* Uncomment this once the test succeeds in all cases */
797             ok(EqualRect(&rc1, &rc2), "rects do not match %s / %s\n", wine_dbgstr_rect(&rc1),
798                wine_dbgstr_rect(&rc2));
799 
800             GetClientRect(hwnd, &rc2);
801             DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, (LPARAM)&rc1);
802             MapWindowPoints(0, hwnd, (LPPOINT)&rc1, 2);
803             ok(EqualRect(&rc1, &rc2), "rects do not match %s / %s\n", wine_dbgstr_rect(&rc1),
804                wine_dbgstr_rect(&rc2));
805             }
806 	    break;
807 	}
808 	case WM_NCCREATE:
809 	{
810 	    BOOL got_getminmaxinfo = GetWindowLongPtrA(hwnd, GWLP_USERDATA) == 0x20031021;
811 	    CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam;
812 
813 	    if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
814 		ok(got_getminmaxinfo, "main: WM_GETMINMAXINFO should have been received before WM_NCCREATE\n");
815 	    else
816 		ok(!got_getminmaxinfo, "main: WM_GETMINMAXINFO should NOT have been received before WM_NCCREATE\n");
817 	    break;
818 	}
819         case WM_COMMAND:
820             if (test_lbuttondown_flag)
821             {
822                 ShowWindow((HWND)wparam, SW_SHOW);
823                 flush_events( FALSE );
824             }
825             break;
826         case WM_GETTEXT:
827             num_gettext_msgs++;
828             if (g_wm_gettext_override.enabled)
829             {
830                 char *text = (char*)lparam;
831                 ok(g_wm_gettext_override.buff == text, "expected buffer %p, got %p\n", g_wm_gettext_override.buff, text);
832                 ok(*text == 0, "expected empty string buffer %x\n", *text);
833                 return 0;
834             }
835             break;
836         case WM_SETTEXT:
837             num_settext_msgs++;
838             break;
839         case WM_ACTIVATEAPP:
840             if (wparam) app_activated = TRUE;
841             else app_deactivated = TRUE;
842             break;
843     }
844 
845     return DefWindowProcA(hwnd, msg, wparam, lparam);
846 }
847 
848 static LRESULT WINAPI main_window_procW(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
849 {
850     switch (msg)
851     {
852         case WM_GETTEXT:
853             num_gettext_msgs++;
854             if (g_wm_gettext_override.enabled)
855             {
856                 WCHAR *text = (WCHAR*)lparam;
857                 ok(g_wm_gettext_override.buffW == text, "expected buffer %p, got %p\n", g_wm_gettext_override.buffW, text);
858                 ok(*text == 0, "expected empty string buffer %x\n", *text);
859                 return 0;
860             }
861             break;
862     }
863 
864     return DefWindowProcA(hwnd, msg, wparam, lparam);
865 }
866 
867 static LRESULT WINAPI tool_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
868 {
869     switch (msg)
870     {
871 	case WM_GETMINMAXINFO:
872 	{
873 	    SetWindowLongPtrA(hwnd, GWLP_USERDATA, 0x20031021);
874 	    break;
875 	}
876 	case WM_NCCREATE:
877 	{
878 	    BOOL got_getminmaxinfo = GetWindowLongPtrA(hwnd, GWLP_USERDATA) == 0x20031021;
879 	    CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam;
880 
881 	    if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
882 		ok(got_getminmaxinfo, "tool: WM_GETMINMAXINFO should have been received before WM_NCCREATE\n");
883 	    else
884 		ok(!got_getminmaxinfo, "tool: WM_GETMINMAXINFO should NOT have been received before WM_NCCREATE\n");
885 	    break;
886 	}
887     }
888 
889     return DefWindowProcA(hwnd, msg, wparam, lparam);
890 }
891 
892 static const WCHAR mainclassW[] = {'M','a','i','n','W','i','n','d','o','w','C','l','a','s','s','W',0};
893 
894 static BOOL RegisterWindowClasses(void)
895 {
896     WNDCLASSW clsW;
897     WNDCLASSA cls;
898 
899     cls.style = CS_DBLCLKS;
900     cls.lpfnWndProc = main_window_procA;
901     cls.cbClsExtra = 0;
902     cls.cbWndExtra = 0;
903     cls.hInstance = GetModuleHandleA(0);
904     cls.hIcon = 0;
905     cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
906     cls.hbrBackground = GetStockObject(WHITE_BRUSH);
907     cls.lpszMenuName = NULL;
908     cls.lpszClassName = "MainWindowClass";
909 
910     if(!RegisterClassA(&cls)) return FALSE;
911 
912     clsW.style = CS_DBLCLKS;
913     clsW.lpfnWndProc = main_window_procW;
914     clsW.cbClsExtra = 0;
915     clsW.cbWndExtra = 0;
916     clsW.hInstance = GetModuleHandleA(0);
917     clsW.hIcon = 0;
918     clsW.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
919     clsW.hbrBackground = GetStockObject(WHITE_BRUSH);
920     clsW.lpszMenuName = NULL;
921     clsW.lpszClassName = mainclassW;
922 
923     if(!RegisterClassW(&clsW)) return FALSE;
924 
925     cls.style = 0;
926     cls.lpfnWndProc = tool_window_procA;
927     cls.cbClsExtra = 0;
928     cls.cbWndExtra = 0;
929     cls.hInstance = GetModuleHandleA(0);
930     cls.hIcon = 0;
931     cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
932     cls.hbrBackground = GetStockObject(WHITE_BRUSH);
933     cls.lpszMenuName = NULL;
934     cls.lpszClassName = "ToolWindowClass";
935 
936     if(!RegisterClassA(&cls)) return FALSE;
937 
938     return TRUE;
939 }
940 
941 static void verify_window_info(const char *hook, HWND hwnd, const WINDOWINFO *info)
942 {
943     RECT rcWindow, rcClient;
944     DWORD status;
945 
946     ok(IsWindow(hwnd), "bad window handle %p in hook %s\n", hwnd, hook);
947 
948     GetWindowRect(hwnd, &rcWindow);
949     ok(EqualRect(&rcWindow, &info->rcWindow), "wrong rcWindow for %p in hook %s\n", hwnd, hook);
950 
951     GetClientRect(hwnd, &rcClient);
952     /* translate to screen coordinates */
953     MapWindowPoints(hwnd, 0, (LPPOINT)&rcClient, 2);
954     ok(EqualRect(&rcClient, &info->rcClient), "wrong rcClient for %p in hook %s\n", hwnd, hook);
955 
956     ok(info->dwStyle == (DWORD)GetWindowLongA(hwnd, GWL_STYLE),
957        "wrong dwStyle: %08x != %08x for %p in hook %s\n",
958        info->dwStyle, GetWindowLongA(hwnd, GWL_STYLE), hwnd, hook);
959     /* Windows reports some undocumented exstyles in WINDOWINFO, but
960      * doesn't return them in GetWindowLong(hwnd, GWL_EXSTYLE).
961      */
962     ok((info->dwExStyle & ~0xe0000800) == (DWORD)GetWindowLongA(hwnd, GWL_EXSTYLE),
963        "wrong dwExStyle: %08x != %08x for %p in hook %s\n",
964        info->dwExStyle, GetWindowLongA(hwnd, GWL_EXSTYLE), hwnd, hook);
965     status = (GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0;
966     if (GetForegroundWindow())
967         ok(info->dwWindowStatus == status, "wrong dwWindowStatus: %04x != %04x active %p fg %p in hook %s\n",
968            info->dwWindowStatus, status, GetActiveWindow(), GetForegroundWindow(), hook);
969 
970     /* win2k and XP return broken border info in GetWindowInfo most of
971      * the time, so there is no point in testing it.
972      */
973 if (0)
974 {
975     UINT border;
976     ok(info->cxWindowBorders == (unsigned)(rcClient.left - rcWindow.left),
977        "wrong cxWindowBorders %d != %d\n", info->cxWindowBorders, rcClient.left - rcWindow.left);
978     border = min(rcWindow.bottom - rcClient.bottom, rcClient.top - rcWindow.top);
979     ok(info->cyWindowBorders == border,
980        "wrong cyWindowBorders %d != %d\n", info->cyWindowBorders, border);
981 }
982     ok(info->atomWindowType == GetClassLongA(hwnd, GCW_ATOM), "wrong atomWindowType for %p in hook %s\n",
983        hwnd, hook);
984     ok(info->wCreatorVersion == 0x0400 /* NT4, Win2000, XP, Win2003 */ ||
985        info->wCreatorVersion == 0x0500 /* Vista */,
986        "wrong wCreatorVersion %04x for %p in hook %s\n", info->wCreatorVersion, hwnd, hook);
987 }
988 
989 static void FixedAdjustWindowRectEx(RECT* rc, LONG style, BOOL menu, LONG exstyle)
990 {
991     AdjustWindowRectEx(rc, style, menu, exstyle);
992     /* AdjustWindowRectEx does not include scroll bars */
993     if (style & WS_VSCROLL)
994     {
995         if(exstyle & WS_EX_LEFTSCROLLBAR)
996             rc->left  -= GetSystemMetrics(SM_CXVSCROLL);
997         else
998             rc->right += GetSystemMetrics(SM_CXVSCROLL);
999     }
1000     if (style & WS_HSCROLL)
1001 	rc->bottom += GetSystemMetrics(SM_CYHSCROLL);
1002 }
1003 
1004 /* reimplement it to check that the Wine algorithm gives the correct result */
1005 static void wine_AdjustWindowRectEx( RECT *rect, LONG style, BOOL menu, LONG exStyle )
1006 {
1007     int adjust;
1008 
1009     if ((exStyle & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) ==
1010         WS_EX_STATICEDGE)
1011     {
1012         adjust = 1; /* for the outer frame always present */
1013     }
1014     else
1015     {
1016         adjust = 0;
1017         if ((exStyle & WS_EX_DLGMODALFRAME) ||
1018             (style & (WS_THICKFRAME|WS_DLGFRAME))) adjust = 2; /* outer */
1019     }
1020     if (style & WS_THICKFRAME)
1021         adjust += GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME); /* The resize border */
1022     if ((style & (WS_BORDER|WS_DLGFRAME)) ||
1023         (exStyle & WS_EX_DLGMODALFRAME))
1024         adjust++; /* The other border */
1025 
1026     InflateRect (rect, adjust, adjust);
1027 
1028     if ((style & WS_CAPTION) == WS_CAPTION)
1029     {
1030         if (exStyle & WS_EX_TOOLWINDOW)
1031             rect->top -= GetSystemMetrics(SM_CYSMCAPTION);
1032         else
1033             rect->top -= GetSystemMetrics(SM_CYCAPTION);
1034     }
1035     if (menu) rect->top -= GetSystemMetrics(SM_CYMENU);
1036 
1037     if (exStyle & WS_EX_CLIENTEDGE)
1038         InflateRect(rect, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
1039 
1040     if (style & WS_VSCROLL)
1041     {
1042         if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
1043             rect->left  -= GetSystemMetrics(SM_CXVSCROLL);
1044         else
1045             rect->right += GetSystemMetrics(SM_CXVSCROLL);
1046     }
1047     if (style & WS_HSCROLL) rect->bottom += GetSystemMetrics(SM_CYHSCROLL);
1048 }
1049 
1050 static void test_nonclient_area(HWND hwnd)
1051 {
1052     DWORD style, exstyle;
1053     RECT rc_window, rc_client, rc;
1054     BOOL menu;
1055     LRESULT ret;
1056 
1057     style = GetWindowLongA(hwnd, GWL_STYLE);
1058     exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
1059     menu = !(style & WS_CHILD) && GetMenu(hwnd) != 0;
1060 
1061     GetWindowRect(hwnd, &rc_window);
1062     GetClientRect(hwnd, &rc_client);
1063 
1064     /* avoid some cases when things go wrong */
1065     if (IsRectEmpty(&rc_window) || IsRectEmpty(&rc_client) ||
1066 	rc_window.right > 32768 || rc_window.bottom > 32768) return;
1067 
1068     rc = rc_client;
1069     MapWindowPoints(hwnd, 0, (LPPOINT)&rc, 2);
1070     FixedAdjustWindowRectEx(&rc, style, menu, exstyle);
1071 
1072     ok(EqualRect(&rc, &rc_window),
1073        "window rect does not match: style:exstyle=0x%08x:0x%08x, menu=%d, win=%s, calc=%s\n",
1074        style, exstyle, menu, wine_dbgstr_rect(&rc_window), wine_dbgstr_rect(&rc));
1075 
1076     rc = rc_client;
1077     MapWindowPoints(hwnd, 0, (LPPOINT)&rc, 2);
1078     wine_AdjustWindowRectEx(&rc, style, menu, exstyle);
1079     ok(EqualRect(&rc, &rc_window),
1080        "window rect does not match: style:exstyle=0x%08x:0x%08x, menu=%d, win=%s, calc=%s\n",
1081        style, exstyle, menu, wine_dbgstr_rect(&rc_window), wine_dbgstr_rect(&rc));
1082 
1083 
1084     rc = rc_window;
1085     DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, (LPARAM)&rc);
1086     MapWindowPoints(0, hwnd, (LPPOINT)&rc, 2);
1087     ok(EqualRect(&rc, &rc_client),
1088        "client rect does not match: style:exstyle=0x%08x:0x%08x, menu=%d client=%s, calc=%s\n",
1089        style, exstyle, menu, wine_dbgstr_rect(&rc_client), wine_dbgstr_rect(&rc));
1090 
1091     /* NULL rectangle shouldn't crash */
1092     ret = DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, 0);
1093     ok(ret == 0, "NULL rectangle returned %ld instead of 0\n", ret);
1094 
1095     /* Win9x doesn't like WM_NCCALCSIZE with synthetic data and crashes */;
1096     if (is_win9x)
1097 	return;
1098 
1099     /* and now test AdjustWindowRectEx and WM_NCCALCSIZE on synthetic data */
1100     SetRect(&rc_client, 0, 0, 250, 150);
1101     rc_window = rc_client;
1102     MapWindowPoints(hwnd, 0, (LPPOINT)&rc_window, 2);
1103     FixedAdjustWindowRectEx(&rc_window, style, menu, exstyle);
1104 
1105     rc = rc_window;
1106     DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, (LPARAM)&rc);
1107     MapWindowPoints(0, hwnd, (LPPOINT)&rc, 2);
1108     ok(EqualRect(&rc, &rc_client),
1109        "synthetic rect does not match: style:exstyle=0x%08x:0x%08x, menu=%d, client=%s, calc=%s\n",
1110        style, exstyle, menu, wine_dbgstr_rect(&rc_client), wine_dbgstr_rect(&rc));
1111 }
1112 
1113 static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam)
1114 {
1115     static const char *CBT_code_name[10] = {
1116 	"HCBT_MOVESIZE",
1117 	"HCBT_MINMAX",
1118 	"HCBT_QS",
1119 	"HCBT_CREATEWND",
1120 	"HCBT_DESTROYWND",
1121 	"HCBT_ACTIVATE",
1122 	"HCBT_CLICKSKIPPED",
1123 	"HCBT_KEYSKIPPED",
1124 	"HCBT_SYSCOMMAND",
1125 	"HCBT_SETFOCUS" };
1126     const char *code_name = (nCode >= 0 && nCode <= HCBT_SETFOCUS) ? CBT_code_name[nCode] : "Unknown";
1127     HWND hwnd = (HWND)wParam;
1128 
1129     switch (nCode)
1130     {
1131     case HCBT_CREATEWND:
1132 	{
1133 	    static const RECT rc_null;
1134 	    RECT rc;
1135 	    LONG style;
1136 	    CBT_CREATEWNDA *createwnd = (CBT_CREATEWNDA *)lParam;
1137 	    ok(createwnd->hwndInsertAfter == HWND_TOP, "hwndInsertAfter should be always HWND_TOP\n");
1138 
1139             if (pGetWindowInfo)
1140             {
1141                 WINDOWINFO info;
1142                 info.cbSize = sizeof(WINDOWINFO);
1143                 ok(pGetWindowInfo(hwnd, &info), "GetWindowInfo should not fail\n");
1144                 verify_window_info(code_name, hwnd, &info);
1145             }
1146 
1147 	    /* WS_VISIBLE should be turned off yet */
1148 	    style = createwnd->lpcs->style & ~WS_VISIBLE;
1149 	    ok(style == GetWindowLongA(hwnd, GWL_STYLE),
1150 		"style of hwnd and style in the CREATESTRUCT do not match: %08x != %08x\n",
1151 		GetWindowLongA(hwnd, GWL_STYLE), style);
1152 
1153             if (0)
1154             {
1155             /* Uncomment this once the test succeeds in all cases */
1156 	    if ((style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1157 	    {
1158 		ok(GetParent(hwnd) == hwndMessage,
1159 		   "wrong result from GetParent %p: message window %p\n",
1160 		   GetParent(hwnd), hwndMessage);
1161 	    }
1162 	    else
1163 		ok(!GetParent(hwnd), "GetParent should return 0 at this point\n");
1164 
1165 	    ok(!GetWindow(hwnd, GW_OWNER), "GW_OWNER should be set to 0 at this point\n");
1166             }
1167             if (0)
1168             {
1169 	    /* while NT assigns GW_HWNDFIRST/LAST some values at this point,
1170 	     * Win9x still has them set to 0.
1171 	     */
1172 	    ok(GetWindow(hwnd, GW_HWNDFIRST) != 0, "GW_HWNDFIRST should not be set to 0 at this point\n");
1173 	    ok(GetWindow(hwnd, GW_HWNDLAST) != 0, "GW_HWNDLAST should not be set to 0 at this point\n");
1174             }
1175 	    ok(!GetWindow(hwnd, GW_HWNDPREV), "GW_HWNDPREV should be set to 0 at this point\n");
1176 	    ok(!GetWindow(hwnd, GW_HWNDNEXT), "GW_HWNDNEXT should be set to 0 at this point\n");
1177 
1178             if (0)
1179             {
1180             /* Uncomment this once the test succeeds in all cases */
1181 	    if (pGetAncestor)
1182 	    {
1183 		ok(pGetAncestor(hwnd, GA_PARENT) == hwndMessage, "GA_PARENT should be set to hwndMessage at this point\n");
1184 		ok(pGetAncestor(hwnd, GA_ROOT) == hwnd,
1185 		   "GA_ROOT is set to %p, expected %p\n", pGetAncestor(hwnd, GA_ROOT), hwnd);
1186 
1187 		if ((style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1188 		    ok(pGetAncestor(hwnd, GA_ROOTOWNER) == hwndMessage,
1189 		       "GA_ROOTOWNER should be set to hwndMessage at this point\n");
1190 		else
1191 		    ok(pGetAncestor(hwnd, GA_ROOTOWNER) == hwnd,
1192 		       "GA_ROOTOWNER is set to %p, expected %p\n", pGetAncestor(hwnd, GA_ROOTOWNER), hwnd);
1193             }
1194 
1195 	    ok(GetWindowRect(hwnd, &rc), "GetWindowRect failed\n");
1196 	    ok(EqualRect(&rc, &rc_null), "window rect should be set to 0 HCBT_CREATEWND\n");
1197 	    ok(GetClientRect(hwnd, &rc), "GetClientRect failed\n");
1198 	    ok(EqualRect(&rc, &rc_null), "client rect should be set to 0 on HCBT_CREATEWND\n");
1199             }
1200 	    break;
1201 	}
1202     case HCBT_MOVESIZE:
1203     case HCBT_MINMAX:
1204     case HCBT_ACTIVATE:
1205 	if (pGetWindowInfo && IsWindow(hwnd))
1206 	{
1207 	    WINDOWINFO info;
1208 
1209 	    /* Win98 actually does check the info.cbSize and doesn't allow
1210 	     * it to be anything except sizeof(WINDOWINFO), while Win95, Win2k,
1211 	     * WinXP do not check it at all.
1212 	     */
1213 	    info.cbSize = sizeof(WINDOWINFO);
1214 	    ok(pGetWindowInfo(hwnd, &info), "GetWindowInfo should not fail\n");
1215 	    verify_window_info(code_name, hwnd, &info);
1216 	}
1217         break;
1218     /* window state is undefined */
1219     case HCBT_SETFOCUS:
1220     case HCBT_DESTROYWND:
1221         break;
1222     default:
1223         break;
1224     }
1225 
1226     return CallNextHookEx(hhook, nCode, wParam, lParam);
1227 }
1228 
1229 static void test_shell_window(void)
1230 {
1231     BOOL ret;
1232     DWORD error;
1233     HMODULE hinst, hUser32;
1234     BOOL (WINAPI*SetShellWindow)(HWND);
1235     HWND hwnd1, hwnd2, hwnd3, hwnd4, hwnd5;
1236     HWND shellWindow, nextWnd;
1237 
1238     if (is_win9x)
1239     {
1240         win_skip("Skipping shell window test on Win9x\n");
1241         return;
1242     }
1243 
1244     shellWindow = GetShellWindow();
1245     hinst = GetModuleHandleA(NULL);
1246     hUser32 = GetModuleHandleA("user32");
1247 
1248     SetShellWindow = (void *)GetProcAddress(hUser32, "SetShellWindow");
1249 
1250     trace("previous shell window: %p\n", shellWindow);
1251 
1252     if (shellWindow) {
1253         DWORD pid;
1254         HANDLE hProcess;
1255 
1256         GetWindowThreadProcessId(shellWindow, &pid);
1257         hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
1258         if (!hProcess)
1259         {
1260             skip( "cannot get access to shell process\n" );
1261             return;
1262         }
1263 
1264         SetLastError(0xdeadbeef);
1265         ret = DestroyWindow(shellWindow);
1266         error = GetLastError();
1267 
1268         ok(!ret, "DestroyWindow(shellWindow)\n");
1269         /* passes on Win XP, but not on Win98 */
1270         ok(error==ERROR_ACCESS_DENIED || error == 0xdeadbeef,
1271            "got %u after DestroyWindow(shellWindow)\n", error);
1272 
1273         /* close old shell instance */
1274         ret = TerminateProcess(hProcess, 0);
1275         ok(ret, "termination of previous shell process failed: GetLastError()=%d\n", GetLastError());
1276         WaitForSingleObject(hProcess, INFINITE);    /* wait for termination */
1277         CloseHandle(hProcess);
1278     }
1279 
1280     hwnd1 = CreateWindowExA(0, "#32770", "TEST1", WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 100, 100, 300, 200, 0, 0, hinst, 0);
1281     trace("created window 1: %p\n", hwnd1);
1282 
1283     ret = SetShellWindow(hwnd1);
1284     ok(ret, "first call to SetShellWindow(hwnd1)\n");
1285     shellWindow = GetShellWindow();
1286     ok(shellWindow==hwnd1, "wrong shell window: %p\n", shellWindow);
1287 
1288     ret = SetShellWindow(hwnd1);
1289     ok(!ret, "second call to SetShellWindow(hwnd1)\n");
1290 
1291     ret = SetShellWindow(0);
1292     error = GetLastError();
1293     /* passes on Win XP, but not on Win98
1294     ok(!ret, "reset shell window by SetShellWindow(0)\n");
1295     ok(error==ERROR_INVALID_WINDOW_HANDLE, "ERROR_INVALID_WINDOW_HANDLE after SetShellWindow(0)\n"); */
1296 
1297     ret = SetShellWindow(hwnd1);
1298     /* passes on Win XP, but not on Win98
1299     ok(!ret, "third call to SetShellWindow(hwnd1)\n"); */
1300 
1301     SetWindowLongA(hwnd1, GWL_EXSTYLE, GetWindowLongA(hwnd1,GWL_EXSTYLE)|WS_EX_TOPMOST);
1302     ret = (GetWindowLongA(hwnd1,GWL_EXSTYLE) & WS_EX_TOPMOST) != 0;
1303     ok(!ret, "SetWindowExStyle(hwnd1, WS_EX_TOPMOST)\n");
1304 
1305     ret = DestroyWindow(hwnd1);
1306     ok(ret, "DestroyWindow(hwnd1)\n");
1307 
1308     hwnd2 = CreateWindowExA(WS_EX_TOPMOST, "#32770", "TEST2", WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 150, 250, 300, 200, 0, 0, hinst, 0);
1309     trace("created window 2: %p\n", hwnd2);
1310     ret = SetShellWindow(hwnd2);
1311     ok(!ret, "SetShellWindow(hwnd2) with WS_EX_TOPMOST\n");
1312 
1313     hwnd3 = CreateWindowExA(0, "#32770", "TEST3", WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 200, 400, 300, 200, 0, 0, hinst, 0);
1314     trace("created window 3: %p\n", hwnd3);
1315 
1316     hwnd4 = CreateWindowExA(0, "#32770", "TEST4", WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 250, 500, 300, 200, 0, 0, hinst, 0);
1317     trace("created window 4: %p\n", hwnd4);
1318 
1319     nextWnd = GetWindow(hwnd4, GW_HWNDNEXT);
1320     ok(nextWnd==hwnd3, "wrong next window for hwnd4: %p - expected hwnd3\n", nextWnd);
1321 
1322     ret = SetShellWindow(hwnd4);
1323     ok(ret, "SetShellWindow(hwnd4)\n");
1324     shellWindow = GetShellWindow();
1325     ok(shellWindow==hwnd4, "wrong shell window: %p - expected hwnd4\n", shellWindow);
1326 
1327     nextWnd = GetWindow(hwnd4, GW_HWNDNEXT);
1328     ok(nextWnd==0, "wrong next window for hwnd4: %p - expected 0\n", nextWnd);
1329 
1330     ret = SetWindowPos(hwnd4, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
1331     ok(ret, "SetWindowPos(hwnd4, HWND_TOPMOST)\n");
1332 
1333     ret = SetWindowPos(hwnd4, hwnd3, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
1334     ok(ret, "SetWindowPos(hwnd4, hwnd3\n");
1335 
1336     ret = SetShellWindow(hwnd3);
1337     ok(!ret, "SetShellWindow(hwnd3)\n");
1338     shellWindow = GetShellWindow();
1339     ok(shellWindow==hwnd4, "wrong shell window: %p - expected hwnd4\n", shellWindow);
1340 
1341     hwnd5 = CreateWindowExA(0, "#32770", "TEST5", WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 300, 600, 300, 200, 0, 0, hinst, 0);
1342     trace("created window 5: %p\n", hwnd5);
1343     ret = SetWindowPos(hwnd4, hwnd5, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
1344     ok(ret, "SetWindowPos(hwnd4, hwnd5)\n");
1345 
1346     todo_wine
1347     {
1348         nextWnd = GetWindow(hwnd4, GW_HWNDNEXT);
1349         ok(nextWnd==0, "wrong next window for hwnd4 after SetWindowPos(): %p - expected 0\n", nextWnd);
1350     }
1351 
1352     /* destroy test windows */
1353     DestroyWindow(hwnd2);
1354     DestroyWindow(hwnd3);
1355     DestroyWindow(hwnd4);
1356     DestroyWindow(hwnd5);
1357 }
1358 
1359 /************** MDI test ****************/
1360 
1361 static char mdi_lParam_test_message[] = "just a test string";
1362 
1363 static void test_MDI_create(HWND parent, HWND mdi_client, INT_PTR first_id)
1364 {
1365     MDICREATESTRUCTA mdi_cs;
1366     HWND mdi_child, hwnd, exp_hwnd;
1367     INT_PTR id;
1368     static const WCHAR classW[] = {'M','D','I','_','c','h','i','l','d','_','C','l','a','s','s','_','1',0};
1369     static const WCHAR titleW[] = {'M','D','I',' ','c','h','i','l','d',0};
1370     BOOL isWin9x = FALSE;
1371     HMENU frame_menu = GetMenu(parent);
1372 
1373     ok(frame_menu != NULL, "Frame window didn't have a menu\n");
1374 
1375     mdi_cs.szClass = "MDI_child_Class_1";
1376     mdi_cs.szTitle = "MDI child";
1377     mdi_cs.hOwner = GetModuleHandleA(NULL);
1378     mdi_cs.x = CW_USEDEFAULT;
1379     mdi_cs.y = CW_USEDEFAULT;
1380     mdi_cs.cx = CW_USEDEFAULT;
1381     mdi_cs.cy = CW_USEDEFAULT;
1382     mdi_cs.style = 0;
1383     mdi_cs.lParam = (LPARAM)mdi_lParam_test_message;
1384     mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
1385     ok(mdi_child != 0, "MDI child creation failed\n");
1386     id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1387     ok(id == first_id, "wrong child id %ld\n", id);
1388     hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1389     exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0;
1390     ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd);
1391     SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1392     ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1393 
1394     mdi_cs.style = 0x7fffffff; /* without WS_POPUP */
1395     mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
1396     ok(mdi_child != 0, "MDI child creation failed\n");
1397     id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1398     ok(id == first_id, "wrong child id %ld\n", id);
1399     hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1400     ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1401     SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1402     ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1403 
1404     mdi_cs.style = 0xffffffff; /* with WS_POPUP */
1405     mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
1406     if (GetWindowLongA(mdi_client, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
1407     {
1408         ok(!mdi_child, "MDI child with WS_POPUP and with MDIS_ALLCHILDSTYLES should fail\n");
1409     }
1410     else
1411     {
1412         ok(mdi_child != 0, "MDI child creation failed\n");
1413         id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1414         ok(id == first_id, "wrong child id %ld\n", id);
1415         hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1416         ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1417         ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1418         SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1419         ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1420     }
1421 
1422     /* test MDICREATESTRUCT A<->W mapping */
1423     /* MDICREATESTRUCTA and MDICREATESTRUCTW have the same layout */
1424     mdi_cs.style = 0;
1425     mdi_cs.szClass = (LPCSTR)classW;
1426     mdi_cs.szTitle = (LPCSTR)titleW;
1427     SetLastError(0xdeadbeef);
1428     mdi_child = (HWND)SendMessageW(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
1429     if (!mdi_child)
1430     {
1431         if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1432             isWin9x = TRUE;
1433         else
1434             ok(mdi_child != 0, "MDI child creation failed\n");
1435     }
1436     else
1437     {
1438         id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1439         ok(id == first_id, "wrong child id %ld\n", id);
1440         hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1441         exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0;
1442         ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd);
1443         ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1444         SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1445         ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1446     }
1447 
1448     mdi_child = CreateMDIWindowA("MDI_child_Class_1", "MDI child",
1449                                  0,
1450                                  CW_USEDEFAULT, CW_USEDEFAULT,
1451                                  CW_USEDEFAULT, CW_USEDEFAULT,
1452                                  mdi_client, GetModuleHandleA(NULL),
1453                                  (LPARAM)mdi_lParam_test_message);
1454     ok(mdi_child != 0, "MDI child creation failed\n");
1455     id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1456     ok(id == first_id, "wrong child id %ld\n", id);
1457     hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1458     exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0;
1459     ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd);
1460     ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1461     SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1462     ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1463 
1464     mdi_child = CreateMDIWindowA("MDI_child_Class_1", "MDI child",
1465                                  0x7fffffff, /* without WS_POPUP */
1466                                  CW_USEDEFAULT, CW_USEDEFAULT,
1467                                  CW_USEDEFAULT, CW_USEDEFAULT,
1468                                  mdi_client, GetModuleHandleA(NULL),
1469                                  (LPARAM)mdi_lParam_test_message);
1470     ok(mdi_child != 0, "MDI child creation failed\n");
1471     id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1472     ok(id == first_id, "wrong child id %ld\n", id);
1473     hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1474     ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1475     ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1476     SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1477     ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1478 
1479     mdi_child = CreateMDIWindowA("MDI_child_Class_1", "MDI child",
1480                                  0xffffffff, /* with WS_POPUP */
1481                                  CW_USEDEFAULT, CW_USEDEFAULT,
1482                                  CW_USEDEFAULT, CW_USEDEFAULT,
1483                                  mdi_client, GetModuleHandleA(NULL),
1484                                  (LPARAM)mdi_lParam_test_message);
1485     if (GetWindowLongA(mdi_client, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
1486     {
1487         ok(!mdi_child, "MDI child with WS_POPUP and with MDIS_ALLCHILDSTYLES should fail\n");
1488     }
1489     else
1490     {
1491         ok(mdi_child != 0, "MDI child creation failed\n");
1492         id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1493         ok(id == first_id, "wrong child id %ld\n", id);
1494         hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1495         ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1496         ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1497         SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1498         ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1499     }
1500 
1501     /* test MDICREATESTRUCT A<->W mapping */
1502     SetLastError(0xdeadbeef);
1503     mdi_child = CreateMDIWindowW(classW, titleW,
1504                                  0,
1505                                  CW_USEDEFAULT, CW_USEDEFAULT,
1506                                  CW_USEDEFAULT, CW_USEDEFAULT,
1507                                  mdi_client, GetModuleHandleA(NULL),
1508                                  (LPARAM)mdi_lParam_test_message);
1509     if (!mdi_child)
1510     {
1511         if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1512             isWin9x = TRUE;
1513         else
1514             ok(mdi_child != 0, "MDI child creation failed\n");
1515     }
1516     else
1517     {
1518         id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1519         ok(id == first_id, "wrong child id %ld\n", id);
1520         hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1521         exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0;
1522         ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd);
1523         ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1524         SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1525         ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1526     }
1527 
1528     mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
1529                                 0,
1530                                 CW_USEDEFAULT, CW_USEDEFAULT,
1531                                 CW_USEDEFAULT, CW_USEDEFAULT,
1532                                 mdi_client, 0, GetModuleHandleA(NULL),
1533                                 mdi_lParam_test_message);
1534     ok(mdi_child != 0, "MDI child creation failed\n");
1535     id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1536     ok(id == first_id, "wrong child id %ld\n", id);
1537     hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1538     exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0;
1539     ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd);
1540     ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1541     SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1542     ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1543 
1544     mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
1545                                 WS_MAXIMIZE,
1546                                 CW_USEDEFAULT, CW_USEDEFAULT,
1547                                 CW_USEDEFAULT, CW_USEDEFAULT,
1548                                 mdi_client, 0, GetModuleHandleA(NULL),
1549                                 mdi_lParam_test_message);
1550     ok(mdi_child != 0, "MDI child creation failed\n");
1551     id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1552     ok(id == first_id, "wrong child id %ld\n", id);
1553     hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1554     exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0;
1555     ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd);
1556     if (GetWindowLongA(mdi_client, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
1557         ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1558     else
1559         ok(GetMenuItemCount(frame_menu) == 4, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1560     SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1561     ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1562 
1563     mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
1564                                 0x7fffffff, /* without WS_POPUP */
1565                                 CW_USEDEFAULT, CW_USEDEFAULT,
1566                                 CW_USEDEFAULT, CW_USEDEFAULT,
1567                                 mdi_client, 0, GetModuleHandleA(NULL),
1568                                 mdi_lParam_test_message);
1569     ok(mdi_child != 0, "MDI child creation failed\n");
1570     id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1571     ok(id == first_id, "wrong child id %ld\n", id);
1572     hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1573     ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1574     ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1575     SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1576     ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1577 
1578     mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
1579                                 0xffffffff, /* with WS_POPUP */
1580                                 CW_USEDEFAULT, CW_USEDEFAULT,
1581                                 CW_USEDEFAULT, CW_USEDEFAULT,
1582                                 mdi_client, 0, GetModuleHandleA(NULL),
1583                                 mdi_lParam_test_message);
1584     if (GetWindowLongA(mdi_client, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
1585     {
1586         ok(!mdi_child, "MDI child with WS_POPUP and with MDIS_ALLCHILDSTYLES should fail\n");
1587     }
1588     else
1589     {
1590         ok(mdi_child != 0, "MDI child creation failed\n");
1591         id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1592         ok(id == first_id, "wrong child id %ld\n", id);
1593         hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1594         ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1595         ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1596         SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1597         ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1598     }
1599 
1600     /* test MDICREATESTRUCT A<->W mapping */
1601     SetLastError(0xdeadbeef);
1602     mdi_child = CreateWindowExW(WS_EX_MDICHILD, classW, titleW,
1603                                 0,
1604                                 CW_USEDEFAULT, CW_USEDEFAULT,
1605                                 CW_USEDEFAULT, CW_USEDEFAULT,
1606                                 mdi_client, 0, GetModuleHandleA(NULL),
1607                                 mdi_lParam_test_message);
1608     if (!mdi_child)
1609     {
1610         if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1611             isWin9x = TRUE;
1612         else
1613             ok(mdi_child != 0, "MDI child creation failed\n");
1614     }
1615     else
1616     {
1617         id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1618         ok(id == first_id, "wrong child id %ld\n", id);
1619         hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1620         exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0;
1621         ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd);
1622         ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1623         SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1624         ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1625     }
1626 
1627     /* This test fails on Win9x */
1628     if (!isWin9x)
1629     {
1630         mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_2", "MDI child",
1631                                 WS_CHILD,
1632                                 CW_USEDEFAULT, CW_USEDEFAULT,
1633                                 CW_USEDEFAULT, CW_USEDEFAULT,
1634                                 parent, 0, GetModuleHandleA(NULL),
1635                                 mdi_lParam_test_message);
1636         ok(!mdi_child, "WS_EX_MDICHILD with a not MDIClient parent should fail\n");
1637     }
1638 
1639     mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
1640                                 WS_CHILD, /* without WS_POPUP */
1641                                 CW_USEDEFAULT, CW_USEDEFAULT,
1642                                 CW_USEDEFAULT, CW_USEDEFAULT,
1643                                 mdi_client, 0, GetModuleHandleA(NULL),
1644                                 mdi_lParam_test_message);
1645     ok(mdi_child != 0, "MDI child creation failed\n");
1646     id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1647     ok(id == 0, "wrong child id %ld\n", id);
1648     ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1649     hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1650     ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1651     DestroyWindow(mdi_child);
1652 
1653     mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
1654                                 WS_CHILD | WS_POPUP, /* with WS_POPUP */
1655                                 CW_USEDEFAULT, CW_USEDEFAULT,
1656                                 CW_USEDEFAULT, CW_USEDEFAULT,
1657                                 mdi_client, 0, GetModuleHandleA(NULL),
1658                                 mdi_lParam_test_message);
1659     ok(mdi_child != 0, "MDI child creation failed\n");
1660     id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1661     ok(id == 0, "wrong child id %ld\n", id);
1662     hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1663     ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1664     ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1665     DestroyWindow(mdi_child);
1666 
1667     /* maximized child */
1668     mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
1669                                 WS_CHILD | WS_MAXIMIZE,
1670                                 CW_USEDEFAULT, CW_USEDEFAULT,
1671                                 CW_USEDEFAULT, CW_USEDEFAULT,
1672                                 mdi_client, 0, GetModuleHandleA(NULL),
1673                                 mdi_lParam_test_message);
1674     ok(mdi_child != 0, "MDI child creation failed\n");
1675     id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1676     ok(id == 0, "wrong child id %ld\n", id);
1677     hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1678     ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1679     ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1680     DestroyWindow(mdi_child);
1681 
1682     trace("Creating maximized child with a caption\n");
1683     mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
1684                                 WS_CHILD | WS_MAXIMIZE | WS_CAPTION,
1685                                 CW_USEDEFAULT, CW_USEDEFAULT,
1686                                 CW_USEDEFAULT, CW_USEDEFAULT,
1687                                 mdi_client, 0, GetModuleHandleA(NULL),
1688                                 mdi_lParam_test_message);
1689     ok(mdi_child != 0, "MDI child creation failed\n");
1690     id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1691     ok(id == 0, "wrong child id %ld\n", id);
1692     hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1693     ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1694     ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1695     DestroyWindow(mdi_child);
1696 
1697     trace("Creating maximized child with a caption and a thick frame\n");
1698     mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
1699                                 WS_CHILD | WS_MAXIMIZE | WS_CAPTION | WS_THICKFRAME,
1700                                 CW_USEDEFAULT, CW_USEDEFAULT,
1701                                 CW_USEDEFAULT, CW_USEDEFAULT,
1702                                 mdi_client, 0, GetModuleHandleA(NULL),
1703                                 mdi_lParam_test_message);
1704     ok(mdi_child != 0, "MDI child creation failed\n");
1705     id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1706     ok(id == 0, "wrong child id %ld\n", id);
1707     hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1708     ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1709     ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1710     DestroyWindow(mdi_child);
1711 }
1712 
1713 static void test_MDI_child_stack(HWND mdi_client)
1714 {
1715     HWND child_1, child_2, child_3, child_4;
1716     HWND stack[4];
1717     MDICREATESTRUCTA cs;
1718 
1719     cs.szClass = "MDI_child_Class_1";
1720     cs.szTitle = "MDI child";
1721     cs.hOwner  = GetModuleHandleA(0);
1722     cs.x       = CW_USEDEFAULT;
1723     cs.y       = CW_USEDEFAULT;
1724     cs.cx      = CW_USEDEFAULT;
1725     cs.cy      = CW_USEDEFAULT;
1726     cs.style   = 0;
1727     cs.lParam  = (LPARAM)mdi_lParam_test_message;
1728 
1729     child_1 = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&cs);
1730     ok(child_1 != 0, "expected child_1 to be non NULL\n");
1731     child_2 = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&cs);
1732     ok(child_2 != 0, "expected child_2 to be non NULL\n");
1733     child_3 = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&cs);
1734     ok(child_3 != 0, "expected child_3 to be non NULL\n");
1735     child_4 = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&cs);
1736     ok(child_4 != 0, "expected child_4 to be non NULL\n");
1737 
1738     stack[0] = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1739     stack[1] = GetWindow(stack[0], GW_HWNDNEXT);
1740     stack[2] = GetWindow(stack[1], GW_HWNDNEXT);
1741     stack[3] = GetWindow(stack[2], GW_HWNDNEXT);
1742     trace("Initial MDI child stack: %p->%p->%p->%p\n", stack[0], stack[1], stack[2], stack[3]);
1743     ok(stack[0] == child_4 && stack[1] == child_3 &&
1744         stack[2] == child_2 && stack[3] == child_1,
1745         "Unexpected initial order, should be: %p->%p->%p->%p\n",
1746             child_4, child_3, child_2, child_1);
1747 
1748     trace("Activate child next to %p\n", child_3);
1749     SendMessageA(mdi_client, WM_MDINEXT, (WPARAM)child_3, 0);
1750 
1751     stack[0] = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1752     stack[1] = GetWindow(stack[0], GW_HWNDNEXT);
1753     stack[2] = GetWindow(stack[1], GW_HWNDNEXT);
1754     stack[3] = GetWindow(stack[2], GW_HWNDNEXT);
1755     ok(stack[0] == child_2 && stack[1] == child_4 &&
1756         stack[2] == child_1 && stack[3] == child_3,
1757         "Broken MDI child stack:\nexpected: %p->%p->%p->%p, but got: %p->%p->%p->%p\n",
1758             child_2, child_4, child_1, child_3, stack[0], stack[1], stack[2], stack[3]);
1759 
1760     trace("Activate child previous to %p\n", child_1);
1761     SendMessageA(mdi_client, WM_MDINEXT, (WPARAM)child_1, 1);
1762 
1763     stack[0] = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1764     stack[1] = GetWindow(stack[0], GW_HWNDNEXT);
1765     stack[2] = GetWindow(stack[1], GW_HWNDNEXT);
1766     stack[3] = GetWindow(stack[2], GW_HWNDNEXT);
1767     ok(stack[0] == child_4 && stack[1] == child_2 &&
1768         stack[2] == child_1 && stack[3] == child_3,
1769         "Broken MDI child stack:\nexpected: %p->%p->%p->%p, but got: %p->%p->%p->%p\n",
1770             child_4, child_2, child_1, child_3, stack[0], stack[1], stack[2], stack[3]);
1771 
1772     DestroyWindow(child_1);
1773     DestroyWindow(child_2);
1774     DestroyWindow(child_3);
1775     DestroyWindow(child_4);
1776 }
1777 
1778 /**********************************************************************
1779  * MDI_ChildGetMinMaxInfo (copied from windows/mdi.c)
1780  *
1781  * Note: The rule here is that client rect of the maximized MDI child
1782  *	 is equal to the client rect of the MDI client window.
1783  */
1784 static void MDI_ChildGetMinMaxInfo( HWND client, HWND hwnd, MINMAXINFO* lpMinMax )
1785 {
1786     RECT rect;
1787 
1788     GetClientRect( client, &rect );
1789     AdjustWindowRectEx( &rect, GetWindowLongA( hwnd, GWL_STYLE ),
1790                         0, GetWindowLongA( hwnd, GWL_EXSTYLE ));
1791 
1792     rect.right -= rect.left;
1793     rect.bottom -= rect.top;
1794     lpMinMax->ptMaxSize.x = rect.right;
1795     lpMinMax->ptMaxSize.y = rect.bottom;
1796 
1797     lpMinMax->ptMaxPosition.x = rect.left;
1798     lpMinMax->ptMaxPosition.y = rect.top;
1799 
1800     trace("max rect %s\n", wine_dbgstr_rect(&rect));
1801 }
1802 
1803 static LRESULT WINAPI mdi_child_wnd_proc_1(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
1804 {
1805     switch (msg)
1806     {
1807         case WM_NCCREATE:
1808         case WM_CREATE:
1809         {
1810             CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam;
1811             MDICREATESTRUCTA *mdi_cs = cs->lpCreateParams;
1812 
1813             ok(cs->dwExStyle & WS_EX_MDICHILD, "WS_EX_MDICHILD should be set\n");
1814             ok(mdi_cs->lParam == (LPARAM)mdi_lParam_test_message, "wrong mdi_cs->lParam\n");
1815 
1816             ok(!lstrcmpA(cs->lpszClass, "MDI_child_Class_1"), "wrong class name\n");
1817             ok(!lstrcmpA(cs->lpszClass, mdi_cs->szClass), "class name does not match\n");
1818             ok(!lstrcmpA(cs->lpszName, "MDI child"), "wrong title\n");
1819             ok(!lstrcmpA(cs->lpszName, mdi_cs->szTitle), "title does not match\n");
1820             ok(cs->hInstance == mdi_cs->hOwner, "%p != %p\n", cs->hInstance, mdi_cs->hOwner);
1821 
1822             /* MDICREATESTRUCT should have original values */
1823             ok(mdi_cs->style == 0 || mdi_cs->style == 0x7fffffff || mdi_cs->style == 0xffffffff || mdi_cs->style == WS_MAXIMIZE,
1824                 "mdi_cs->style does not match (%08x)\n", mdi_cs->style);
1825             ok(mdi_cs->x == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->x);
1826             ok(mdi_cs->y == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->y);
1827             ok(mdi_cs->cx == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->cx);
1828             ok(mdi_cs->cy == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->cy);
1829 
1830             /* CREATESTRUCT should have fixed values */
1831             ok(cs->x != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->x);
1832             ok(cs->y != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->y);
1833 
1834             /* cx/cy == CW_USEDEFAULT are translated to NOT zero values */
1835             ok(cs->cx != CW_USEDEFAULT && cs->cx != 0, "%d == CW_USEDEFAULT\n", cs->cx);
1836             ok(cs->cy != CW_USEDEFAULT && cs->cy != 0, "%d == CW_USEDEFAULT\n", cs->cy);
1837 
1838             ok(!(cs->style & WS_POPUP), "WS_POPUP is not allowed\n");
1839 
1840             if (GetWindowLongA(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
1841             {
1842                 LONG style = mdi_cs->style | WS_CHILD | WS_CLIPSIBLINGS;
1843                 ok(cs->style == style,
1844                    "cs->style does not match (%08x)\n", cs->style);
1845             }
1846             else
1847             {
1848                 LONG style = mdi_cs->style;
1849                 style &= ~WS_POPUP;
1850                 style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
1851                     WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
1852                 ok(cs->style == style,
1853                    "cs->style does not match (%08x)\n", cs->style);
1854             }
1855             break;
1856         }
1857 
1858         case WM_GETMINMAXINFO:
1859         {
1860             HWND client = GetParent(hwnd);
1861             RECT rc;
1862             MINMAXINFO *minmax = (MINMAXINFO *)lparam;
1863             MINMAXINFO my_minmax;
1864             LONG style, exstyle;
1865 
1866             style = GetWindowLongA(hwnd, GWL_STYLE);
1867             exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
1868 
1869             GetClientRect(client, &rc);
1870 
1871             GetClientRect(client, &rc);
1872             if ((style & WS_CAPTION) == WS_CAPTION)
1873                 style &= ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
1874             AdjustWindowRectEx(&rc, style, 0, exstyle);
1875             trace("MDI child: calculated max window size = (%d x %d)\n", rc.right-rc.left, rc.bottom-rc.top);
1876             dump_minmax_info( minmax );
1877 
1878             ok(minmax->ptMaxSize.x == rc.right - rc.left, "default width of maximized child %d != %d\n",
1879                minmax->ptMaxSize.x, rc.right - rc.left);
1880             ok(minmax->ptMaxSize.y == rc.bottom - rc.top, "default height of maximized child %d != %d\n",
1881                minmax->ptMaxSize.y, rc.bottom - rc.top);
1882 
1883             DefMDIChildProcA(hwnd, msg, wparam, lparam);
1884 
1885             trace("DefMDIChildProc returned:\n");
1886             dump_minmax_info( minmax );
1887 
1888             MDI_ChildGetMinMaxInfo(client, hwnd, &my_minmax);
1889             ok(minmax->ptMaxSize.x == my_minmax.ptMaxSize.x, "default width of maximized child %d != %d\n",
1890                minmax->ptMaxSize.x, my_minmax.ptMaxSize.x);
1891             ok(minmax->ptMaxSize.y == my_minmax.ptMaxSize.y, "default height of maximized child %d != %d\n",
1892                minmax->ptMaxSize.y, my_minmax.ptMaxSize.y);
1893 
1894             return 1;
1895         }
1896 
1897         case WM_MDIACTIVATE:
1898         {
1899             HWND active, client = GetParent(hwnd);
1900             /*trace("%p WM_MDIACTIVATE %08x %08lx\n", hwnd, wparam, lparam);*/
1901             active = (HWND)SendMessageA(client, WM_MDIGETACTIVE, 0, 0);
1902             if (hwnd == (HWND)lparam) /* if we are being activated */
1903                 ok (active == (HWND)lparam, "new active %p != active %p\n", (HWND)lparam, active);
1904             else
1905                 ok (active == (HWND)wparam, "old active %p != active %p\n", (HWND)wparam, active);
1906             break;
1907         }
1908     }
1909     return DefMDIChildProcA(hwnd, msg, wparam, lparam);
1910 }
1911 
1912 static LRESULT WINAPI mdi_child_wnd_proc_2(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
1913 {
1914     switch (msg)
1915     {
1916         case WM_NCCREATE:
1917         case WM_CREATE:
1918         {
1919             CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam;
1920 
1921             trace("%s: x %d, y %d, cx %d, cy %d\n", (msg == WM_NCCREATE) ? "WM_NCCREATE" : "WM_CREATE",
1922                 cs->x, cs->y, cs->cx, cs->cy);
1923 
1924             ok(!(cs->dwExStyle & WS_EX_MDICHILD), "WS_EX_MDICHILD should not be set\n");
1925             ok(cs->lpCreateParams == mdi_lParam_test_message, "wrong cs->lpCreateParams\n");
1926 
1927             ok(!lstrcmpA(cs->lpszClass, "MDI_child_Class_2"), "wrong class name\n");
1928             ok(!lstrcmpA(cs->lpszName, "MDI child"), "wrong title\n");
1929 
1930             /* CREATESTRUCT should have fixed values */
1931             /* For some reason Win9x doesn't translate cs->x from CW_USEDEFAULT,
1932                while NT does. */
1933             /*ok(cs->x != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->x);*/
1934             ok(cs->y != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->y);
1935 
1936             /* cx/cy == CW_USEDEFAULT are translated to 0 */
1937             /* For some reason Win98 doesn't translate cs->cx from CW_USEDEFAULT,
1938                while Win95, Win2k, WinXP do. */
1939             /*ok(cs->cx == 0, "%d != 0\n", cs->cx);*/
1940             ok(cs->cy == 0, "%d != 0\n", cs->cy);
1941             break;
1942         }
1943 
1944         case WM_GETMINMAXINFO:
1945         {
1946             HWND parent = GetParent(hwnd);
1947             RECT rc;
1948             MINMAXINFO *minmax = (MINMAXINFO *)lparam;
1949             LONG style, exstyle;
1950 
1951             style = GetWindowLongA(hwnd, GWL_STYLE);
1952             exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
1953 
1954             GetClientRect(parent, &rc);
1955             trace("WM_GETMINMAXINFO: parent %p client size = (%d x %d)\n", parent, rc.right, rc.bottom);
1956 
1957             GetClientRect(parent, &rc);
1958             if ((style & WS_CAPTION) == WS_CAPTION)
1959                 style &= ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
1960             AdjustWindowRectEx(&rc, style, 0, exstyle);
1961             dump_minmax_info( minmax );
1962 
1963             ok(minmax->ptMaxSize.x == rc.right - rc.left, "default width of maximized child %d != %d\n",
1964                minmax->ptMaxSize.x, rc.right - rc.left);
1965             ok(minmax->ptMaxSize.y == rc.bottom - rc.top, "default height of maximized child %d != %d\n",
1966                minmax->ptMaxSize.y, rc.bottom - rc.top);
1967             break;
1968         }
1969 
1970         case WM_WINDOWPOSCHANGED:
1971         {
1972             WINDOWPOS *winpos = (WINDOWPOS *)lparam;
1973             RECT rc1, rc2;
1974 
1975             GetWindowRect(hwnd, &rc1);
1976             SetRect(&rc2, winpos->x, winpos->y, winpos->x + winpos->cx, winpos->y + winpos->cy);
1977             /* note: winpos coordinates are relative to parent */
1978             MapWindowPoints(GetParent(hwnd), 0, (LPPOINT)&rc2, 2);
1979             ok(EqualRect(&rc1, &rc2), "rects do not match, window=%s pos=%s\n",
1980                wine_dbgstr_rect(&rc1), wine_dbgstr_rect(&rc2));
1981             GetWindowRect(hwnd, &rc1);
1982             GetClientRect(hwnd, &rc2);
1983             DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, (LPARAM)&rc1);
1984             MapWindowPoints(0, hwnd, (LPPOINT)&rc1, 2);
1985             ok(EqualRect(&rc1, &rc2), "rects do not match, window=%s client=%s\n",
1986                wine_dbgstr_rect(&rc1), wine_dbgstr_rect(&rc2));
1987         }
1988         /* fall through */
1989         case WM_WINDOWPOSCHANGING:
1990         {
1991             WINDOWPOS *winpos = (WINDOWPOS *)lparam;
1992             WINDOWPOS my_winpos = *winpos;
1993 
1994             trace("%s: %p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
1995                   (msg == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED",
1996                   winpos->hwnd, winpos->hwndInsertAfter,
1997                   winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
1998 
1999             DefWindowProcA(hwnd, msg, wparam, lparam);
2000 
2001             ok(!memcmp(&my_winpos, winpos, sizeof(WINDOWPOS)),
2002                "DefWindowProc should not change WINDOWPOS: %p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
2003                   winpos->hwnd, winpos->hwndInsertAfter,
2004                   winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
2005 
2006             return 1;
2007         }
2008     }
2009     return DefWindowProcA(hwnd, msg, wparam, lparam);
2010 }
2011 
2012 static LRESULT WINAPI mdi_main_wnd_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
2013 {
2014     static HWND mdi_client;
2015 
2016     switch (msg)
2017     {
2018         case WM_CREATE:
2019             return 1;
2020 
2021         case WM_WINDOWPOSCHANGED:
2022         {
2023             WINDOWPOS *winpos = (WINDOWPOS *)lparam;
2024             RECT rc1, rc2;
2025 
2026             GetWindowRect(hwnd, &rc1);
2027             trace("window: %s\n", wine_dbgstr_rect(&rc1));
2028             SetRect(&rc2, winpos->x, winpos->y, winpos->x + winpos->cx, winpos->y + winpos->cy);
2029             /* note: winpos coordinates are relative to parent */
2030             MapWindowPoints(GetParent(hwnd), 0, (LPPOINT)&rc2, 2);
2031             trace("pos: %s\n", wine_dbgstr_rect(&rc2));
2032             ok(EqualRect(&rc1, &rc2), "rects do not match\n");
2033 
2034             GetWindowRect(hwnd, &rc1);
2035             GetClientRect(hwnd, &rc2);
2036             DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, (LPARAM)&rc1);
2037             MapWindowPoints(0, hwnd, (LPPOINT)&rc1, 2);
2038             ok(EqualRect(&rc1, &rc2), "rects do not match\n");
2039         }
2040         /* fall through */
2041         case WM_WINDOWPOSCHANGING:
2042         {
2043             WINDOWPOS *winpos = (WINDOWPOS *)lparam;
2044             WINDOWPOS my_winpos = *winpos;
2045 
2046             trace("%s\n", (msg == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
2047             trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
2048                   winpos->hwnd, winpos->hwndInsertAfter,
2049                   winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
2050 
2051             DefWindowProcA(hwnd, msg, wparam, lparam);
2052 
2053             trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
2054                   winpos->hwnd, winpos->hwndInsertAfter,
2055                   winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
2056 
2057             ok(!memcmp(&my_winpos, winpos, sizeof(WINDOWPOS)),
2058                "DefWindowProc should not change WINDOWPOS values\n");
2059 
2060             return 1;
2061         }
2062 
2063         case WM_CLOSE:
2064             PostQuitMessage(0);
2065             break;
2066     }
2067     return DefFrameProcA(hwnd, mdi_client, msg, wparam, lparam);
2068 }
2069 
2070 static BOOL mdi_RegisterWindowClasses(void)
2071 {
2072     WNDCLASSA cls;
2073 
2074     cls.style = 0;
2075     cls.lpfnWndProc = mdi_main_wnd_procA;
2076     cls.cbClsExtra = 0;
2077     cls.cbWndExtra = 0;
2078     cls.hInstance = GetModuleHandleA(0);
2079     cls.hIcon = 0;
2080     cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
2081     cls.hbrBackground = GetStockObject(WHITE_BRUSH);
2082     cls.lpszMenuName = NULL;
2083     cls.lpszClassName = "MDI_parent_Class";
2084     if(!RegisterClassA(&cls)) return FALSE;
2085 
2086     cls.lpfnWndProc = mdi_child_wnd_proc_1;
2087     cls.lpszClassName = "MDI_child_Class_1";
2088     if(!RegisterClassA(&cls)) return FALSE;
2089 
2090     cls.lpfnWndProc = mdi_child_wnd_proc_2;
2091     cls.lpszClassName = "MDI_child_Class_2";
2092     if(!RegisterClassA(&cls)) return FALSE;
2093 
2094     return TRUE;
2095 }
2096 
2097 static void test_mdi(void)
2098 {
2099     static const DWORD style[] = { 0, WS_HSCROLL, WS_VSCROLL, WS_HSCROLL | WS_VSCROLL };
2100     HWND mdi_hwndMain, mdi_client, mdi_child;
2101     CLIENTCREATESTRUCT client_cs;
2102     RECT rc;
2103     DWORD i;
2104     MSG msg;
2105     HMENU frame_menu, child_menu;
2106 
2107     if (!mdi_RegisterWindowClasses()) assert(0);
2108 
2109     mdi_hwndMain = CreateWindowExA(0, "MDI_parent_Class", "MDI parent window",
2110                                    WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
2111                                    WS_MAXIMIZEBOX /*| WS_VISIBLE*/,
2112                                    100, 100, CW_USEDEFAULT, CW_USEDEFAULT,
2113                                    GetDesktopWindow(), 0,
2114                                    GetModuleHandleA(NULL), NULL);
2115     assert(mdi_hwndMain);
2116 
2117     frame_menu = CreateMenu();
2118 
2119     GetClientRect(mdi_hwndMain, &rc);
2120 
2121     client_cs.hWindowMenu = 0;
2122     client_cs.idFirstChild = 1;
2123 
2124     for (i = 0; i < sizeof(style)/sizeof(style[0]); i++)
2125     {
2126         SCROLLINFO si;
2127         BOOL ret, gotit;
2128 
2129         mdi_client = CreateWindowExA(0, "mdiclient", NULL,
2130                                  WS_CHILD | style[i],
2131                                  0, 0, rc.right, rc.bottom,
2132                                  mdi_hwndMain, 0, 0, &client_cs);
2133         ok(mdi_client != 0, "MDI client creation failed\n");
2134 
2135         mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
2136                                 0,
2137                                 CW_USEDEFAULT, CW_USEDEFAULT,
2138                                 CW_USEDEFAULT, CW_USEDEFAULT,
2139                                 mdi_client, 0, 0,
2140                                 mdi_lParam_test_message);
2141         ok(mdi_child != 0, "MDI child creation failed\n");
2142 
2143         SendMessageW(mdi_child, WM_SIZE, SIZE_MAXIMIZED, 0);
2144         SetMenu(mdi_hwndMain, frame_menu);
2145 
2146         ok(GetMenuItemCount(frame_menu) == 0, "Frame menu should be empty after child maximize, but has %u\n",
2147                 GetMenuItemCount(frame_menu));
2148 
2149         child_menu = CreateMenu();
2150         SendMessageW(mdi_client, WM_MDISETMENU, 0, (LPARAM)child_menu);
2151 
2152         ok(GetMenuItemCount(frame_menu) == 0, "Frame menu should be empty after WM_MDISETMENU, but has %u\n",
2153                 GetMenuItemCount(frame_menu));
2154 
2155         SendMessageW(mdi_child, WM_SIZE, SIZE_RESTORED, 0);
2156 
2157         ok(GetMenuItemCount(frame_menu) == 0, "Frame menu should be empty after child restored, but has %u items\n",
2158                 GetMenuItemCount(frame_menu));
2159 
2160         SetMenu(mdi_hwndMain, NULL);
2161 
2162         si.cbSize = sizeof(si);
2163         si.fMask = SIF_ALL;
2164         ret = GetScrollInfo(mdi_client, SB_HORZ, &si);
2165         if (style[i] & (WS_HSCROLL | WS_VSCROLL))
2166         {
2167             ok(ret, "style %#x: GetScrollInfo(SB_HORZ) failed\n", style[i]);
2168             ok(si.nPage == 0, "expected 0\n");
2169             ok(si.nPos == 0, "expected 0\n");
2170             ok(si.nTrackPos == 0, "expected 0\n");
2171             ok(si.nMin == 0, "expected 0\n");
2172             ok(si.nMax == 100, "expected 100\n");
2173         }
2174         else
2175             ok(!ret, "style %#x: GetScrollInfo(SB_HORZ) should fail\n", style[i]);
2176 
2177         ret = GetScrollInfo(mdi_client, SB_VERT, &si);
2178         if (style[i] & (WS_HSCROLL | WS_VSCROLL))
2179         {
2180             ok(ret, "style %#x: GetScrollInfo(SB_VERT) failed\n", style[i]);
2181             ok(si.nPage == 0, "expected 0\n");
2182             ok(si.nPos == 0, "expected 0\n");
2183             ok(si.nTrackPos == 0, "expected 0\n");
2184             ok(si.nMin == 0, "expected 0\n");
2185             ok(si.nMax == 100, "expected 100\n");
2186         }
2187         else
2188             ok(!ret, "style %#x: GetScrollInfo(SB_VERT) should fail\n", style[i]);
2189 
2190         SetWindowPos(mdi_child, 0, -100, -100, 0, 0, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE);
2191 
2192         si.cbSize = sizeof(si);
2193         si.fMask = SIF_ALL;
2194         ret = GetScrollInfo(mdi_client, SB_HORZ, &si);
2195         if (style[i] & (WS_HSCROLL | WS_VSCROLL))
2196         {
2197             ok(ret, "style %#x: GetScrollInfo(SB_HORZ) failed\n", style[i]);
2198             ok(si.nPage == 0, "expected 0\n");
2199             ok(si.nPos == 0, "expected 0\n");
2200             ok(si.nTrackPos == 0, "expected 0\n");
2201             ok(si.nMin == 0, "expected 0\n");
2202             ok(si.nMax == 100, "expected 100\n");
2203         }
2204         else
2205             ok(!ret, "style %#x: GetScrollInfo(SB_HORZ) should fail\n", style[i]);
2206 
2207         ret = GetScrollInfo(mdi_client, SB_VERT, &si);
2208         if (style[i] & (WS_HSCROLL | WS_VSCROLL))
2209         {
2210             ok(ret, "style %#x: GetScrollInfo(SB_VERT) failed\n", style[i]);
2211             ok(si.nPage == 0, "expected 0\n");
2212             ok(si.nPos == 0, "expected 0\n");
2213             ok(si.nTrackPos == 0, "expected 0\n");
2214             ok(si.nMin == 0, "expected 0\n");
2215             ok(si.nMax == 100, "expected 100\n");
2216         }
2217         else
2218             ok(!ret, "style %#x: GetScrollInfo(SB_VERT) should fail\n", style[i]);
2219 
2220         gotit = FALSE;
2221         while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
2222         {
2223             if (msg.message == WM_MOUSEMOVE || msg.message == WM_PAINT)
2224             {
2225                 DispatchMessageA(&msg);
2226                 continue;
2227             }
2228 
2229             if (msg.message == 0x003f) /* WM_MDICALCCHILDSCROLL ??? */
2230             {
2231                 ok(msg.hwnd == mdi_client, "message 0x003f should be posted to mdiclient\n");
2232                 gotit = TRUE;
2233             }
2234             else
2235                 ok(msg.hwnd != mdi_client, "message %04x should not be posted to mdiclient\n", msg.message);
2236             DispatchMessageA(&msg);
2237         }
2238         ok(gotit, "message 0x003f should appear after SetWindowPos\n");
2239 
2240         si.cbSize = sizeof(si);
2241         si.fMask = SIF_ALL;
2242         ret = GetScrollInfo(mdi_client, SB_HORZ, &si);
2243         if (style[i] & (WS_HSCROLL | WS_VSCROLL))
2244         {
2245             ok(ret, "style %#x: GetScrollInfo(SB_HORZ) failed\n", style[i]);
2246 todo_wine
2247             ok(si.nPage != 0, "expected !0\n");
2248             ok(si.nPos == 0, "expected 0\n");
2249             ok(si.nTrackPos == 0, "expected 0\n");
2250             ok(si.nMin != 0, "expected !0\n");
2251             ok(si.nMax != 100, "expected !100\n");
2252         }
2253         else
2254             ok(!ret, "style %#x: GetScrollInfo(SB_HORZ) should fail\n", style[i]);
2255 
2256         ret = GetScrollInfo(mdi_client, SB_VERT, &si);
2257         if (style[i] & (WS_HSCROLL | WS_VSCROLL))
2258         {
2259             ok(ret, "style %#x: GetScrollInfo(SB_VERT) failed\n", style[i]);
2260 todo_wine
2261             ok(si.nPage != 0, "expected !0\n");
2262             ok(si.nPos == 0, "expected 0\n");
2263             ok(si.nTrackPos == 0, "expected 0\n");
2264             ok(si.nMin != 0, "expected !0\n");
2265             ok(si.nMax != 100, "expected !100\n");
2266         }
2267         else
2268             ok(!ret, "style %#x: GetScrollInfo(SB_VERT) should fail\n", style[i]);
2269 
2270         DestroyMenu(child_menu);
2271         DestroyWindow(mdi_child);
2272         DestroyWindow(mdi_client);
2273     }
2274 
2275     SetMenu(mdi_hwndMain, frame_menu);
2276 
2277     mdi_client = CreateWindowExA(0, "mdiclient", NULL,
2278                              WS_CHILD,
2279                              0, 0, rc.right, rc.bottom,
2280                              mdi_hwndMain, 0, 0, &client_cs);
2281     ok(mdi_client != 0, "MDI client creation failed\n");
2282 
2283     mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
2284                             0,
2285                             CW_USEDEFAULT, CW_USEDEFAULT,
2286                             CW_USEDEFAULT, CW_USEDEFAULT,
2287                             mdi_client, 0, 0,
2288                             mdi_lParam_test_message);
2289     ok(mdi_child != 0, "MDI child creation failed\n");
2290 
2291     SendMessageW(mdi_child, WM_SIZE, SIZE_MAXIMIZED, 0);
2292     ok(GetMenuItemCount(frame_menu) == 4, "Frame menu should have 4 items after child maximize, but has %u\n",
2293             GetMenuItemCount(frame_menu));
2294 
2295     child_menu = CreateMenu();
2296     SendMessageW(mdi_client, WM_MDISETMENU, 0, (LPARAM)child_menu);
2297 
2298     ok(GetMenuItemCount(frame_menu) == 4, "Frame menu should have 4 items after WM_MDISETMENU, but has %u\n",
2299             GetMenuItemCount(frame_menu));
2300 
2301     SendMessageW(mdi_child, WM_SIZE, SIZE_RESTORED, 0);
2302 
2303     ok(GetMenuItemCount(frame_menu) == 0, "Frame menu should be empty after child restored, but has %u items\n",
2304             GetMenuItemCount(frame_menu));
2305 
2306     DestroyMenu(child_menu);
2307     DestroyWindow(mdi_child);
2308     DestroyWindow(mdi_client);
2309 
2310     /* MDIClient without MDIS_ALLCHILDSTYLES */
2311     mdi_client = CreateWindowExA(0, "mdiclient",
2312                                  NULL,
2313                                  WS_CHILD /*| WS_VISIBLE*/,
2314                                   /* tests depend on a not zero MDIClient size */
2315                                  0, 0, rc.right, rc.bottom,
2316                                  mdi_hwndMain, 0, GetModuleHandleA(NULL),
2317                                  &client_cs);
2318     assert(mdi_client);
2319     test_MDI_create(mdi_hwndMain, mdi_client, client_cs.idFirstChild);
2320     DestroyWindow(mdi_client);
2321 
2322     /* MDIClient with MDIS_ALLCHILDSTYLES */
2323     mdi_client = CreateWindowExA(0, "mdiclient",
2324                                  NULL,
2325                                  WS_CHILD | MDIS_ALLCHILDSTYLES /*| WS_VISIBLE*/,
2326                                   /* tests depend on a not zero MDIClient size */
2327                                  0, 0, rc.right, rc.bottom,
2328                                  mdi_hwndMain, 0, GetModuleHandleA(NULL),
2329                                  &client_cs);
2330     assert(mdi_client);
2331     test_MDI_create(mdi_hwndMain, mdi_client, client_cs.idFirstChild);
2332     DestroyWindow(mdi_client);
2333 
2334     /* Test child window stack management */
2335     mdi_client = CreateWindowExA(0, "mdiclient",
2336                                  NULL,
2337                                  WS_CHILD,
2338                                  0, 0, rc.right, rc.bottom,
2339                                  mdi_hwndMain, 0, GetModuleHandleA(NULL),
2340                                  &client_cs);
2341     assert(mdi_client);
2342     test_MDI_child_stack(mdi_client);
2343     DestroyWindow(mdi_client);
2344 /*
2345     while(GetMessage(&msg, 0, 0, 0))
2346     {
2347         TranslateMessage(&msg);
2348         DispatchMessage(&msg);
2349     }
2350 */
2351     DestroyWindow(mdi_hwndMain);
2352 }
2353 
2354 static void test_icons(void)
2355 {
2356     WNDCLASSEXA cls;
2357     HWND hwnd;
2358     HICON icon = LoadIconA(0, (LPCSTR)IDI_APPLICATION);
2359     HICON icon2 = LoadIconA(0, (LPCSTR)IDI_QUESTION);
2360     HICON small_icon = LoadImageA(0, (LPCSTR)IDI_APPLICATION, IMAGE_ICON,
2361                                   GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED );
2362     HICON res;
2363 
2364     cls.cbSize = sizeof(cls);
2365     cls.style = 0;
2366     cls.lpfnWndProc = DefWindowProcA;
2367     cls.cbClsExtra = 0;
2368     cls.cbWndExtra = 0;
2369     cls.hInstance = 0;
2370     cls.hIcon = LoadIconA(0, (LPCSTR)IDI_HAND);
2371     cls.hIconSm = small_icon;
2372     cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
2373     cls.hbrBackground = GetStockObject(WHITE_BRUSH);
2374     cls.lpszMenuName = NULL;
2375     cls.lpszClassName = "IconWindowClass";
2376 
2377     RegisterClassExA(&cls);
2378 
2379     hwnd = CreateWindowExA(0, "IconWindowClass", "icon test", 0,
2380                            100, 100, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, NULL, NULL);
2381     assert( hwnd );
2382 
2383     res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
2384     ok( res == 0, "wrong big icon %p/0\n", res );
2385     res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_BIG, (LPARAM)icon );
2386     ok( res == 0, "wrong previous big icon %p/0\n", res );
2387     res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
2388     ok( res == icon, "wrong big icon after set %p/%p\n", res, icon );
2389     res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_BIG, (LPARAM)icon2 );
2390     ok( res == icon, "wrong previous big icon %p/%p\n", res, icon );
2391     res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
2392     ok( res == icon2, "wrong big icon after set %p/%p\n", res, icon2 );
2393 
2394     res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 );
2395     ok( res == 0, "wrong small icon %p/0\n", res );
2396     res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
2397     ok( (res && res != small_icon && res != icon2) || broken(!res), "wrong small2 icon %p\n", res );
2398     res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_SMALL, (LPARAM)icon );
2399     ok( res == 0, "wrong previous small icon %p/0\n", res );
2400     res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 );
2401     ok( res == icon, "wrong small icon after set %p/%p\n", res, icon );
2402     res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
2403     ok( res == icon || broken(!res), "wrong small2 icon after set %p/%p\n", res, icon );
2404     res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_SMALL, (LPARAM)small_icon );
2405     ok( res == icon, "wrong previous small icon %p/%p\n", res, icon );
2406     res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 );
2407     ok( res == small_icon, "wrong small icon after set %p/%p\n", res, small_icon );
2408     res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
2409     ok( res == small_icon || broken(!res), "wrong small2 icon after set %p/%p\n", res, small_icon );
2410 
2411     /* make sure the big icon hasn't changed */
2412     res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
2413     ok( res == icon2, "wrong big icon after set %p/%p\n", res, icon2 );
2414 
2415     DestroyWindow( hwnd );
2416 }
2417 
2418 static LRESULT WINAPI nccalcsize_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
2419 {
2420     if (msg == WM_NCCALCSIZE)
2421     {
2422         RECT *rect = (RECT *)lparam;
2423         /* first time around increase the rectangle, next time decrease it */
2424         if (rect->left == 100) InflateRect( rect, 10, 10 );
2425         else InflateRect( rect, -10, -10 );
2426         return 0;
2427     }
2428     return DefWindowProcA( hwnd, msg, wparam, lparam );
2429 }
2430 
2431 static void test_SetWindowPos(HWND hwnd, HWND hwnd2)
2432 {
2433     RECT orig_win_rc, rect;
2434     LONG_PTR old_proc;
2435     HWND hwnd_grandchild, hwnd_child, hwnd_child2;
2436     HWND hwnd_desktop;
2437     RECT rc1, rc2;
2438     BOOL ret;
2439 
2440     SetRect(&rect, 111, 222, 333, 444);
2441     ok(!GetWindowRect(0, &rect), "GetWindowRect succeeded\n");
2442     ok(rect.left == 111 && rect.top == 222 && rect.right == 333 && rect.bottom == 444,
2443        "wrong window rect %s\n", wine_dbgstr_rect(&rect));
2444 
2445     SetRect(&rect, 111, 222, 333, 444);
2446     ok(!GetClientRect(0, &rect), "GetClientRect succeeded\n");
2447     ok(rect.left == 111 && rect.top == 222 && rect.right == 333 && rect.bottom == 444,
2448        "wrong window rect %s\n", wine_dbgstr_rect(&rect));
2449 
2450     GetWindowRect(hwnd, &orig_win_rc);
2451 
2452     old_proc = SetWindowLongPtrA( hwnd, GWLP_WNDPROC, (ULONG_PTR)nccalcsize_proc );
2453     ret = SetWindowPos(hwnd, 0, 100, 100, 0, 0, SWP_NOZORDER|SWP_FRAMECHANGED);
2454     ok(ret, "Got %d\n", ret);
2455     GetWindowRect( hwnd, &rect );
2456     ok( rect.left == 100 && rect.top == 100 && rect.right == 100 && rect.bottom == 100,
2457         "invalid window rect %s\n", wine_dbgstr_rect(&rect));
2458     GetClientRect( hwnd, &rect );
2459     MapWindowPoints( hwnd, 0, (POINT *)&rect, 2 );
2460     ok( rect.left == 90 && rect.top == 90 && rect.right == 110 && rect.bottom == 110,
2461         "invalid client rect %s\n", wine_dbgstr_rect(&rect));
2462 
2463     ret = SetWindowPos(hwnd, 0, 200, 200, 0, 0, SWP_NOZORDER|SWP_FRAMECHANGED);
2464     ok(ret, "Got %d\n", ret);
2465     GetWindowRect( hwnd, &rect );
2466     ok( rect.left == 200 && rect.top == 200 && rect.right == 200 && rect.bottom == 200,
2467         "invalid window rect %s\n", wine_dbgstr_rect(&rect));
2468     GetClientRect( hwnd, &rect );
2469     MapWindowPoints( hwnd, 0, (POINT *)&rect, 2 );
2470     ok( rect.left == 210 && rect.top == 210 && rect.right == 190 && rect.bottom == 190,
2471         "invalid client rect %s\n", wine_dbgstr_rect(&rect));
2472 
2473     ret = SetWindowPos(hwnd, 0, orig_win_rc.left, orig_win_rc.top,
2474                       orig_win_rc.right, orig_win_rc.bottom, 0);
2475     ok(ret, "Got %d\n", ret);
2476     SetWindowLongPtrA( hwnd, GWLP_WNDPROC, old_proc );
2477 
2478     /* Win9x truncates coordinates to 16-bit irrespectively */
2479     if (!is_win9x)
2480     {
2481         ret = SetWindowPos(hwnd, 0, -32769, -40000, -32769, -90000, SWP_NOMOVE);
2482         ok(ret, "Got %d\n", ret);
2483         ret = SetWindowPos(hwnd, 0, 32768, 40000, 32768, 40000, SWP_NOMOVE);
2484         ok(ret, "Got %d\n", ret);
2485 
2486         ret = SetWindowPos(hwnd, 0, -32769, -40000, -32769, -90000, SWP_NOSIZE);
2487         ok(ret, "Got %d\n", ret);
2488         ret = SetWindowPos(hwnd, 0, 32768, 40000, 32768, 40000, SWP_NOSIZE);
2489         ok(ret, "Got %d\n", ret);
2490     }
2491 
2492     ret = SetWindowPos(hwnd, 0, orig_win_rc.left, orig_win_rc.top,
2493                        orig_win_rc.right, orig_win_rc.bottom, 0);
2494     ok(ret, "Got %d\n", ret);
2495 
2496     ok(!(GetWindowLongA(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST), "WS_EX_TOPMOST should not be set\n");
2497     ret = SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
2498     ok(ret, "Got %d\n", ret);
2499     ok(GetWindowLongA(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST, "WS_EX_TOPMOST should be set\n");
2500     ret = SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
2501     ok(ret, "Got %d\n", ret);
2502     ok(GetWindowLongA(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST, "WS_EX_TOPMOST should be set\n");
2503     ret = SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
2504     ok(ret, "Got %d\n", ret);
2505     ok(!(GetWindowLongA(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST), "WS_EX_TOPMOST should not be set\n");
2506 
2507     hwnd_desktop = GetDesktopWindow();
2508     ok(!!hwnd_desktop, "Failed to get hwnd_desktop window (%d).\n", GetLastError());
2509     hwnd_child = create_tool_window(WS_VISIBLE|WS_CHILD, hwnd);
2510     ok(!!hwnd_child, "Failed to create child window (%d)\n", GetLastError());
2511     hwnd_grandchild = create_tool_window(WS_VISIBLE|WS_CHILD, hwnd_child);
2512     ok(!!hwnd_child, "Failed to create child window (%d)\n", GetLastError());
2513     hwnd_child2 = create_tool_window(WS_VISIBLE|WS_CHILD, hwnd);
2514     ok(!!hwnd_child2, "Failed to create second child window (%d)\n", GetLastError());
2515 
2516     ret = SetWindowPos(hwnd, hwnd2, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2517     ok(ret, "Got %d\n", ret);
2518     check_active_state(hwnd, hwnd, hwnd);
2519 
2520     ret = SetWindowPos(hwnd2, hwnd, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2521     ok(ret, "Got %d\n", ret);
2522     check_active_state(hwnd2, hwnd2, hwnd2);
2523 
2524     /* Returns TRUE also for windows that are not siblings */
2525     ret = SetWindowPos(hwnd_child, hwnd2, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2526     ok(ret, "Got %d\n", ret);
2527     check_active_state(hwnd2, hwnd2, hwnd2);
2528 
2529     ret = SetWindowPos(hwnd2, hwnd_child, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2530     ok(ret, "Got %d\n", ret);
2531     check_active_state(hwnd2, hwnd2, hwnd2);
2532 
2533     /* Does not seem to do anything even without passing flags, still returns TRUE */
2534     GetWindowRect(hwnd_child, &rc1);
2535     ret = SetWindowPos(hwnd_child, hwnd2 , 1, 2, 3, 4, 0);
2536     ok(ret, "Got %d\n", ret);
2537     GetWindowRect(hwnd_child, &rc2);
2538     ok(EqualRect(&rc1, &rc2), "%s != %s\n", wine_dbgstr_rect(&rc1), wine_dbgstr_rect(&rc2));
2539     check_active_state(hwnd2, hwnd2, hwnd2);
2540 
2541     /* Same thing the other way around. */
2542     GetWindowRect(hwnd2, &rc1);
2543     ret = SetWindowPos(hwnd2, hwnd_child, 1, 2, 3, 4, 0);
2544     ok(ret, "Got %d\n", ret);
2545     GetWindowRect(hwnd2, &rc2);
2546     ok(EqualRect(&rc1, &rc2), "%s != %s\n", wine_dbgstr_rect(&rc1), wine_dbgstr_rect(&rc2));
2547     check_active_state(hwnd2, hwnd2, hwnd2);
2548 
2549     /* .. and with these windows. */
2550     GetWindowRect(hwnd_grandchild, &rc1);
2551     ret = SetWindowPos(hwnd_grandchild, hwnd_child2, 1, 2, 3, 4, 0);
2552     ok(ret, "Got %d\n", ret);
2553     GetWindowRect(hwnd_grandchild, &rc2);
2554     ok(EqualRect(&rc1, &rc2), "%s != %s\n", wine_dbgstr_rect(&rc1), wine_dbgstr_rect(&rc2));
2555     check_active_state(hwnd2, hwnd2, hwnd2);
2556 
2557     /* Add SWP_NOZORDER and it will be properly resized. */
2558     GetWindowRect(hwnd_grandchild, &rc1);
2559     ret = SetWindowPos(hwnd_grandchild, hwnd_child2, 1, 2, 3, 4, SWP_NOZORDER);
2560     ok(ret, "Got %d\n", ret);
2561     GetWindowRect(hwnd_grandchild, &rc2);
2562     ok((rc1.left+1) == rc2.left && (rc1.top+2) == rc2.top &&
2563        (rc1.left+4) == rc2.right && (rc1.top+6) == rc2.bottom,
2564        "(%d,%d)-(%d,%d) != %s\n", rc1.left+1, rc1.top+2, rc1.left+4, rc1.top+6,
2565        wine_dbgstr_rect(&rc2));
2566     check_active_state(hwnd2, hwnd2, hwnd2);
2567 
2568     /* Given a sibling window, the window is properly resized. */
2569     GetWindowRect(hwnd_child, &rc1);
2570     ret = SetWindowPos(hwnd_child, hwnd_child2, 1, 2, 3, 4, 0);
2571     ok(ret, "Got %d\n", ret);
2572     GetWindowRect(hwnd_child, &rc2);
2573     ok((rc1.left+1) == rc2.left && (rc1.top+2) == rc2.top &&
2574        (rc1.left+4) == rc2.right && (rc1.top+6) == rc2.bottom,
2575        "(%d,%d)-(%d,%d) != %s\n", rc1.left+1, rc1.top+2, rc1.left+4, rc1.top+6,
2576        wine_dbgstr_rect(&rc2));
2577     check_active_state(hwnd2, hwnd2, hwnd2);
2578 
2579     /* Involving the desktop window changes things. */
2580     ret = SetWindowPos(hwnd_child, hwnd_desktop, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2581     ok(!ret, "Got %d\n", ret);
2582     check_active_state(hwnd2, hwnd2, hwnd2);
2583 
2584     GetWindowRect(hwnd_child, &rc1);
2585     ret = SetWindowPos(hwnd_child, hwnd_desktop, 0, 0, 0, 0, 0);
2586     ok(!ret, "Got %d\n", ret);
2587     GetWindowRect(hwnd_child, &rc2);
2588     ok(EqualRect(&rc1, &rc2), "%s != %s\n", wine_dbgstr_rect(&rc1), wine_dbgstr_rect(&rc2));
2589     check_active_state(hwnd2, hwnd2, hwnd2);
2590 
2591     ret = SetWindowPos(hwnd_desktop, hwnd_child, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2592     ok(!ret, "Got %d\n", ret);
2593     check_active_state(hwnd2, hwnd2, hwnd2);
2594 
2595     ret = SetWindowPos(hwnd_desktop, hwnd, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2596     ok(!ret, "Got %d\n", ret);
2597     check_active_state(hwnd2, hwnd2, hwnd2);
2598 
2599     ret = SetWindowPos(hwnd, hwnd_desktop, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2600     ok(!ret, "Got %d\n", ret);
2601     check_active_state(hwnd2, hwnd2, hwnd2);
2602 
2603     DestroyWindow(hwnd_grandchild);
2604     DestroyWindow(hwnd_child);
2605     DestroyWindow(hwnd_child2);
2606 
2607     hwnd_child = create_tool_window(WS_CHILD|WS_POPUP|WS_SYSMENU, hwnd2);
2608     ok(!!hwnd_child, "Failed to create child window (%d)\n", GetLastError());
2609     ret = SetWindowPos(hwnd_child, NULL, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_SHOWWINDOW);
2610     ok(ret, "Got %d\n", ret);
2611     flush_events( TRUE );
2612     todo_wine check_active_state(hwnd2, hwnd2, hwnd2);
2613     DestroyWindow(hwnd_child);
2614 }
2615 
2616 static void test_SetMenu(HWND parent)
2617 {
2618     HWND child;
2619     HMENU hMenu, ret;
2620     BOOL retok;
2621     DWORD style;
2622 
2623     hMenu = CreateMenu();
2624     assert(hMenu);
2625 
2626     ok(SetMenu(parent, hMenu), "SetMenu on a top level window should not fail\n");
2627     if (0)
2628     {
2629     /* fails on (at least) Wine, NT4, XP SP2 */
2630     test_nonclient_area(parent);
2631     }
2632     ret = GetMenu(parent);
2633     ok(ret == hMenu, "unexpected menu id %p\n", ret);
2634     /* test whether we can destroy a menu assigned to a window */
2635     retok = DestroyMenu(hMenu);
2636     ok( retok, "DestroyMenu error %d\n", GetLastError());
2637     retok = IsMenu(hMenu);
2638     ok(!retok || broken(retok) /* nt4 */, "menu handle should be not valid after DestroyMenu\n");
2639     ret = GetMenu(parent);
2640     /* This test fails on Win9x */
2641     if (!is_win9x)
2642         ok(ret == hMenu, "unexpected menu id %p\n", ret);
2643     ok(SetMenu(parent, 0), "SetMenu(0) on a top level window should not fail\n");
2644     test_nonclient_area(parent);
2645 
2646     hMenu = CreateMenu();
2647     assert(hMenu);
2648 
2649     /* parent */
2650     ret = GetMenu(parent);
2651     ok(ret == 0, "unexpected menu id %p\n", ret);
2652 
2653     ok(!SetMenu(parent, (HMENU)20), "SetMenu with invalid menu handle should fail\n");
2654     test_nonclient_area(parent);
2655     ret = GetMenu(parent);
2656     ok(ret == 0, "unexpected menu id %p\n", ret);
2657 
2658     ok(SetMenu(parent, hMenu), "SetMenu on a top level window should not fail\n");
2659     if (0)
2660     {
2661     /* fails on (at least) Wine, NT4, XP SP2 */
2662     test_nonclient_area(parent);
2663     }
2664     ret = GetMenu(parent);
2665     ok(ret == hMenu, "unexpected menu id %p\n", ret);
2666 
2667     ok(SetMenu(parent, 0), "SetMenu(0) on a top level window should not fail\n");
2668     test_nonclient_area(parent);
2669     ret = GetMenu(parent);
2670     ok(ret == 0, "unexpected menu id %p\n", ret);
2671 
2672     /* child */
2673     child = CreateWindowExA(0, "static", NULL, WS_CHILD, 0, 0, 0, 0, parent, (HMENU)10, 0, NULL);
2674     assert(child);
2675 
2676     ret = GetMenu(child);
2677     ok(ret == (HMENU)10, "unexpected menu id %p\n", ret);
2678 
2679     ok(!SetMenu(child, (HMENU)20), "SetMenu with invalid menu handle should fail\n");
2680     test_nonclient_area(child);
2681     ret = GetMenu(child);
2682     ok(ret == (HMENU)10, "unexpected menu id %p\n", ret);
2683 
2684     ok(!SetMenu(child, hMenu), "SetMenu on a child window should fail\n");
2685     test_nonclient_area(child);
2686     ret = GetMenu(child);
2687     ok(ret == (HMENU)10, "unexpected menu id %p\n", ret);
2688 
2689     ok(!SetMenu(child, 0), "SetMenu(0) on a child window should fail\n");
2690     test_nonclient_area(child);
2691     ret = GetMenu(child);
2692     ok(ret == (HMENU)10, "unexpected menu id %p\n", ret);
2693 
2694     style = GetWindowLongA(child, GWL_STYLE);
2695     SetWindowLongA(child, GWL_STYLE, style | WS_POPUP);
2696     ok(SetMenu(child, hMenu), "SetMenu on a popup child window should not fail\n");
2697     ok(SetMenu(child, 0), "SetMenu on a popup child window should not fail\n");
2698     SetWindowLongA(child, GWL_STYLE, style);
2699 
2700     SetWindowLongA(child, GWL_STYLE, style | WS_OVERLAPPED);
2701     ok(!SetMenu(child, hMenu), "SetMenu on an overlapped child window should fail\n");
2702     SetWindowLongA(child, GWL_STYLE, style);
2703 
2704     DestroyWindow(child);
2705     DestroyMenu(hMenu);
2706 }
2707 
2708 static void test_window_tree(HWND parent, const DWORD *style, const int *order, int total)
2709 {
2710     HWND child[5], hwnd;
2711     INT_PTR i;
2712 
2713     assert(total <= 5);
2714 
2715     hwnd = GetWindow(parent, GW_CHILD);
2716     ok(!hwnd, "have to start without children to perform the test\n");
2717 
2718     for (i = 0; i < total; i++)
2719     {
2720         if (style[i] & DS_CONTROL)
2721         {
2722             child[i] = CreateWindowExA(0, (LPCSTR)MAKEINTATOM(32770), "", style[i] & ~WS_VISIBLE,
2723                                        0,0,0,0, parent, (HMENU)i, 0, NULL);
2724             if (style[i] & WS_VISIBLE)
2725                 ShowWindow(child[i], SW_SHOW);
2726 
2727             SetWindowPos(child[i], HWND_BOTTOM, 0,0,10,10, SWP_NOACTIVATE);
2728         }
2729         else
2730             child[i] = CreateWindowExA(0, "static", "", style[i], 0,0,10,10,
2731                                        parent, (HMENU)i, 0, NULL);
2732         trace("child[%ld] = %p\n", i, child[i]);
2733         ok(child[i] != 0, "CreateWindowEx failed to create child window\n");
2734     }
2735 
2736     hwnd = GetWindow(parent, GW_CHILD);
2737     ok(hwnd != 0, "GetWindow(GW_CHILD) failed\n");
2738     ok(hwnd == GetWindow(child[total - 1], GW_HWNDFIRST), "GW_HWNDFIRST is wrong\n");
2739     ok(child[order[total - 1]] == GetWindow(child[0], GW_HWNDLAST), "GW_HWNDLAST is wrong\n");
2740 
2741     for (i = 0; i < total; i++)
2742     {
2743         trace("hwnd[%ld] = %p\n", i, hwnd);
2744         ok(child[order[i]] == hwnd, "Z order of child #%ld is wrong\n", i);
2745 
2746         hwnd = GetWindow(hwnd, GW_HWNDNEXT);
2747     }
2748 
2749     for (i = 0; i < total; i++)
2750         ok(DestroyWindow(child[i]), "DestroyWindow failed\n");
2751 }
2752 
2753 static void test_children_zorder(HWND parent)
2754 {
2755     const DWORD simple_style[5] = { WS_CHILD, WS_CHILD, WS_CHILD, WS_CHILD,
2756                                     WS_CHILD };
2757     const int simple_order[5] = { 0, 1, 2, 3, 4 };
2758 
2759     const DWORD complex_style[5] = { WS_CHILD, WS_CHILD | WS_MAXIMIZE,
2760                              WS_CHILD | WS_VISIBLE, WS_CHILD,
2761                              WS_CHILD | WS_MAXIMIZE | WS_VISIBLE };
2762     const int complex_order_1[1] = { 0 };
2763     const int complex_order_2[2] = { 1, 0 };
2764     const int complex_order_3[3] = { 1, 0, 2 };
2765     const int complex_order_4[4] = { 1, 0, 2, 3 };
2766     const int complex_order_5[5] = { 4, 1, 0, 2, 3 };
2767     const DWORD complex_style_6[3] = { WS_CHILD | WS_VISIBLE,
2768                                        WS_CHILD | WS_CLIPSIBLINGS | DS_CONTROL | WS_VISIBLE,
2769                                        WS_CHILD | WS_VISIBLE };
2770     const int complex_order_6[3] = { 0, 1, 2 };
2771 
2772     /* simple WS_CHILD */
2773     test_window_tree(parent, simple_style, simple_order, 5);
2774 
2775     /* complex children styles */
2776     test_window_tree(parent, complex_style, complex_order_1, 1);
2777     test_window_tree(parent, complex_style, complex_order_2, 2);
2778     test_window_tree(parent, complex_style, complex_order_3, 3);
2779     test_window_tree(parent, complex_style, complex_order_4, 4);
2780     test_window_tree(parent, complex_style, complex_order_5, 5);
2781 
2782     /* another set of complex children styles */
2783     test_window_tree(parent, complex_style_6, complex_order_6, 3);
2784 }
2785 
2786 #define check_z_order(hwnd, next, prev, owner, topmost) \
2787         check_z_order_debug((hwnd), (next), (prev), (owner), (topmost), \
2788                             __FILE__, __LINE__)
2789 
2790 static void check_z_order_debug(HWND hwnd, HWND next, HWND prev, HWND owner,
2791                                 BOOL topmost, const char *file, int line)
2792 {
2793     HWND test;
2794     DWORD ex_style;
2795 
2796     test = GetWindow(hwnd, GW_HWNDNEXT);
2797     /* skip foreign windows */
2798     while (test && test != next &&
2799            (GetWindowThreadProcessId(test, NULL) != our_pid ||
2800             UlongToHandle(GetWindowLongPtrA(test, GWLP_HINSTANCE)) != GetModuleHandleA(NULL) ||
2801             GetWindow(test, GW_OWNER) == next))
2802     {
2803         /*trace("skipping next %p (%p)\n", test, UlongToHandle(GetWindowLongPtr(test, GWLP_HINSTANCE)));*/
2804         test = GetWindow(test, GW_HWNDNEXT);
2805     }
2806     ok_(file, line)(next == test, "%p: expected next %p, got %p\n", hwnd, next, test);
2807 
2808     test = GetWindow(hwnd, GW_HWNDPREV);
2809     /* skip foreign windows */
2810     while (test && test != prev &&
2811            (GetWindowThreadProcessId(test, NULL) != our_pid ||
2812             UlongToHandle(GetWindowLongPtrA(test, GWLP_HINSTANCE)) != GetModuleHandleA(NULL) ||
2813             GetWindow(test, GW_OWNER) == hwnd))
2814     {
2815         /*trace("skipping prev %p (%p)\n", test, UlongToHandle(GetWindowLongPtr(test, GWLP_HINSTANCE)));*/
2816         test = GetWindow(test, GW_HWNDPREV);
2817     }
2818     ok_(file, line)(prev == test, "%p: expected prev %p, got %p\n", hwnd, prev, test);
2819 
2820     test = GetWindow(hwnd, GW_OWNER);
2821     ok_(file, line)(owner == test, "%p: expected owner %p, got %p\n", hwnd, owner, test);
2822 
2823     ex_style = GetWindowLongA(hwnd, GWL_EXSTYLE);
2824     ok_(file, line)(!(ex_style & WS_EX_TOPMOST) == !topmost, "%p: expected %stopmost\n",
2825                     hwnd, topmost ? "" : "NOT ");
2826 }
2827 
2828 static void test_popup_zorder(HWND hwnd_D, HWND hwnd_E, DWORD style)
2829 {
2830     HWND hwnd_A, hwnd_B, hwnd_C, hwnd_F;
2831 
2832     trace("hwnd_D %p, hwnd_E %p\n", hwnd_D, hwnd_E);
2833 
2834     SetWindowPos(hwnd_E, hwnd_D, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
2835 
2836     check_z_order(hwnd_D, hwnd_E, 0, 0, FALSE);
2837     check_z_order(hwnd_E, 0, hwnd_D, 0, FALSE);
2838 
2839     hwnd_F = CreateWindowExA(0, "MainWindowClass", "Owner window",
2840                             WS_OVERLAPPED | WS_CAPTION,
2841                             100, 100, 100, 100,
2842                             0, 0, GetModuleHandleA(NULL), NULL);
2843     trace("hwnd_F %p\n", hwnd_F);
2844     check_z_order(hwnd_F, hwnd_D, 0, 0, FALSE);
2845 
2846     SetWindowPos(hwnd_F, hwnd_E, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
2847     check_z_order(hwnd_F, 0, hwnd_E, 0, FALSE);
2848     check_z_order(hwnd_E, hwnd_F, hwnd_D, 0, FALSE);
2849     check_z_order(hwnd_D, hwnd_E, 0, 0, FALSE);
2850 
2851     hwnd_C = CreateWindowExA(0, "MainWindowClass", NULL,
2852                             style,
2853                             100, 100, 100, 100,
2854                             hwnd_F, 0, GetModuleHandleA(NULL), NULL);
2855     trace("hwnd_C %p\n", hwnd_C);
2856     check_z_order(hwnd_F, 0, hwnd_E, 0, FALSE);
2857     check_z_order(hwnd_E, hwnd_F, hwnd_D, 0, FALSE);
2858     check_z_order(hwnd_D, hwnd_E, hwnd_C, 0, FALSE);
2859     check_z_order(hwnd_C, hwnd_D, 0, hwnd_F, FALSE);
2860 
2861     hwnd_B = CreateWindowExA(WS_EX_TOPMOST, "MainWindowClass", NULL,
2862                             style,
2863                             100, 100, 100, 100,
2864                             hwnd_F, 0, GetModuleHandleA(NULL), NULL);
2865     trace("hwnd_B %p\n", hwnd_B);
2866     check_z_order(hwnd_F, 0, hwnd_E, 0, FALSE);
2867     check_z_order(hwnd_E, hwnd_F, hwnd_D, 0, FALSE);
2868     check_z_order(hwnd_D, hwnd_E, hwnd_C, 0, FALSE);
2869     check_z_order(hwnd_C, hwnd_D, hwnd_B, hwnd_F, FALSE);
2870     check_z_order(hwnd_B, hwnd_C, 0, hwnd_F, TRUE);
2871 
2872     hwnd_A = CreateWindowExA(WS_EX_TOPMOST, "MainWindowClass", NULL,
2873                             style,
2874                             100, 100, 100, 100,
2875                             0, 0, GetModuleHandleA(NULL), NULL);
2876     trace("hwnd_A %p\n", hwnd_A);
2877     check_z_order(hwnd_F, 0, hwnd_E, 0, FALSE);
2878     check_z_order(hwnd_E, hwnd_F, hwnd_D, 0, FALSE);
2879     check_z_order(hwnd_D, hwnd_E, hwnd_C, 0, FALSE);
2880     check_z_order(hwnd_C, hwnd_D, hwnd_B, hwnd_F, FALSE);
2881     check_z_order(hwnd_B, hwnd_C, hwnd_A, hwnd_F, TRUE);
2882     check_z_order(hwnd_A, hwnd_B, 0, 0, TRUE);
2883 
2884     trace("A %p B %p C %p D %p E %p F %p\n", hwnd_A, hwnd_B, hwnd_C, hwnd_D, hwnd_E, hwnd_F);
2885 
2886     /* move hwnd_F and its popups up */
2887     SetWindowPos(hwnd_F, HWND_TOP, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
2888     check_z_order(hwnd_E, 0, hwnd_D, 0, FALSE);
2889     check_z_order(hwnd_D, hwnd_E, hwnd_F, 0, FALSE);
2890     check_z_order(hwnd_F, hwnd_D, hwnd_C, 0, FALSE);
2891     check_z_order(hwnd_C, hwnd_F, hwnd_B, hwnd_F, FALSE);
2892     check_z_order(hwnd_B, hwnd_C, hwnd_A, hwnd_F, TRUE);
2893     check_z_order(hwnd_A, hwnd_B, 0, 0, TRUE);
2894 
2895     /* move hwnd_F and its popups down */
2896 #if 0 /* enable once Wine is fixed to pass this test */
2897     SetWindowPos(hwnd_F, HWND_BOTTOM, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
2898     check_z_order(hwnd_F, 0, hwnd_C, 0, FALSE);
2899     check_z_order(hwnd_C, hwnd_F, hwnd_B, hwnd_F, FALSE);
2900     check_z_order(hwnd_B, hwnd_C, hwnd_E, hwnd_F, FALSE);
2901     check_z_order(hwnd_E, hwnd_B, hwnd_D, 0, FALSE);
2902     check_z_order(hwnd_D, hwnd_E, hwnd_A, 0, FALSE);
2903     check_z_order(hwnd_A, hwnd_D, 0, 0, TRUE);
2904 #endif
2905 
2906     /* make hwnd_C owned by a topmost window */
2907     DestroyWindow( hwnd_C );
2908     hwnd_C = CreateWindowExA(0, "MainWindowClass", NULL,
2909                             style,
2910                             100, 100, 100, 100,
2911                             hwnd_A, 0, GetModuleHandleA(NULL), NULL);
2912     trace("hwnd_C %p\n", hwnd_C);
2913     check_z_order(hwnd_E, 0, hwnd_D, 0, FALSE);
2914     check_z_order(hwnd_D, hwnd_E, hwnd_F, 0, FALSE);
2915     check_z_order(hwnd_F, hwnd_D, hwnd_B, 0, FALSE);
2916     check_z_order(hwnd_B, hwnd_F, hwnd_A, hwnd_F, TRUE);
2917     check_z_order(hwnd_A, hwnd_B, hwnd_C, 0, TRUE);
2918     check_z_order(hwnd_C, hwnd_A, 0, hwnd_A, TRUE);
2919 
2920     DestroyWindow(hwnd_A);
2921     DestroyWindow(hwnd_B);
2922     DestroyWindow(hwnd_C);
2923     DestroyWindow(hwnd_F);
2924 }
2925 
2926 static void test_vis_rgn( HWND hwnd )
2927 {
2928     RECT win_rect, rgn_rect;
2929     HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
2930     HDC hdc;
2931 
2932     ShowWindow(hwnd,SW_SHOW);
2933     hdc = GetDC( hwnd );
2934     ok( GetRandomRgn( hdc, hrgn, SYSRGN ) != 0, "GetRandomRgn failed\n" );
2935     GetWindowRect( hwnd, &win_rect );
2936     GetRgnBox( hrgn, &rgn_rect );
2937     if (is_win9x)
2938     {
2939         trace("win9x, mapping to screen coords\n");
2940         MapWindowPoints( hwnd, 0, (POINT *)&rgn_rect, 2 );
2941     }
2942     trace("win: %s\n", wine_dbgstr_rect(&win_rect));
2943     trace("rgn: %s\n", wine_dbgstr_rect(&rgn_rect));
2944     ok( win_rect.left <= rgn_rect.left, "rgn left %d not inside win rect %d\n",
2945         rgn_rect.left, win_rect.left );
2946     ok( win_rect.top <= rgn_rect.top, "rgn top %d not inside win rect %d\n",
2947         rgn_rect.top, win_rect.top );
2948     ok( win_rect.right >= rgn_rect.right, "rgn right %d not inside win rect %d\n",
2949         rgn_rect.right, win_rect.right );
2950     ok( win_rect.bottom >= rgn_rect.bottom, "rgn bottom %d not inside win rect %d\n",
2951         rgn_rect.bottom, win_rect.bottom );
2952     ReleaseDC( hwnd, hdc );
2953 }
2954 
2955 static LRESULT WINAPI set_focus_on_activate_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
2956 {
2957     if (msg == WM_ACTIVATE && LOWORD(wp) == WA_ACTIVE)
2958     {
2959         HWND child = GetWindow(hwnd, GW_CHILD);
2960         ok(child != 0, "couldn't find child window\n");
2961         SetFocus(child);
2962         ok(GetFocus() == child, "Focus should be on child %p\n", child);
2963         return 0;
2964     }
2965     return DefWindowProcA(hwnd, msg, wp, lp);
2966 }
2967 
2968 static void test_SetFocus(HWND hwnd)
2969 {
2970     HWND child, child2, ret;
2971     WNDPROC old_wnd_proc;
2972 
2973     /* check if we can set focus to non-visible windows */
2974 
2975     ShowWindow(hwnd, SW_SHOW);
2976     SetFocus(0);
2977     SetFocus(hwnd);
2978     ok( GetFocus() == hwnd, "Failed to set focus to visible window %p\n", hwnd );
2979     ok( GetWindowLongA(hwnd,GWL_STYLE) & WS_VISIBLE, "Window %p not visible\n", hwnd );
2980     ShowWindow(hwnd, SW_HIDE);
2981     SetFocus(0);
2982     SetFocus(hwnd);
2983     ok( GetFocus() == hwnd, "Failed to set focus to invisible window %p\n", hwnd );
2984     ok( !(GetWindowLongA(hwnd,GWL_STYLE) & WS_VISIBLE), "Window %p still visible\n", hwnd );
2985     child = CreateWindowExA(0, "static", NULL, WS_CHILD, 0, 0, 0, 0, hwnd, 0, 0, NULL);
2986     assert(child);
2987     SetFocus(child);
2988     ok( GetFocus() == child, "Failed to set focus to invisible child %p\n", child );
2989     ok( !(GetWindowLongA(child,GWL_STYLE) & WS_VISIBLE), "Child %p is visible\n", child );
2990     ShowWindow(child, SW_SHOW);
2991     ok( GetWindowLongA(child,GWL_STYLE) & WS_VISIBLE, "Child %p is not visible\n", child );
2992     ok( GetFocus() == child, "Focus no longer on child %p\n", child );
2993     ShowWindow(child, SW_HIDE);
2994     ok( !(GetWindowLongA(child,GWL_STYLE) & WS_VISIBLE), "Child %p is visible\n", child );
2995     ok( GetFocus() == hwnd, "Focus should be on parent %p, not %p\n", hwnd, GetFocus() );
2996     ShowWindow(child, SW_SHOW);
2997     child2 = CreateWindowExA(0, "static", NULL, WS_CHILD, 0, 0, 0, 0, child, 0, 0, NULL);
2998     assert(child2);
2999     ShowWindow(child2, SW_SHOW);
3000     SetFocus(child2);
3001     ShowWindow(child, SW_HIDE);
3002     ok( !(GetWindowLongA(child,GWL_STYLE) & WS_VISIBLE), "Child %p is visible\n", child );
3003     ok( GetFocus() == child2, "Focus should be on %p, not %p\n", child2, GetFocus() );
3004     ShowWindow(child, SW_SHOW);
3005     SetFocus(child);
3006     ok( GetFocus() == child, "Focus should be on child %p\n", child );
3007     SetWindowPos(child,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_HIDEWINDOW);
3008     ok( GetFocus() == child, "Focus should still be on child %p\n", child );
3009 
3010     ShowWindow(child, SW_HIDE);
3011     SetFocus(hwnd);
3012     ok( GetFocus() == hwnd, "Focus should be on parent %p, not %p\n", hwnd, GetFocus() );
3013     SetWindowPos(child,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW);
3014     ok( GetFocus() == hwnd, "Focus should still be on parent %p, not %p\n", hwnd, GetFocus() );
3015     ShowWindow(child, SW_HIDE);
3016     ok( GetFocus() == hwnd, "Focus should still be on parent %p, not %p\n", hwnd, GetFocus() );
3017 
3018     ShowWindow(hwnd, SW_SHOW);
3019     ShowWindow(child, SW_SHOW);
3020     SetFocus(child);
3021     ok( GetFocus() == child, "Focus should be on child %p\n", child );
3022     EnableWindow(hwnd, FALSE);
3023     ok( GetFocus() == child, "Focus should still be on child %p\n", child );
3024     EnableWindow(hwnd, TRUE);
3025 
3026     ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd);
3027     ShowWindow(hwnd, SW_SHOWMINIMIZED);
3028     ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd);
3029 todo_wine
3030     ok( GetFocus() != child, "Focus should not be on child %p\n", child );
3031     ok( GetFocus() != hwnd, "Focus should not be on parent %p\n", hwnd );
3032     ShowWindow(hwnd, SW_RESTORE);
3033     ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd);
3034     ok( GetFocus() == hwnd, "Focus should be on parent %p\n", hwnd );
3035     ShowWindow(hwnd, SW_SHOWMINIMIZED);
3036     ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd);
3037     ok( GetFocus() != child, "Focus should not be on child %p\n", child );
3038 todo_wine
3039     ok( GetFocus() != hwnd, "Focus should not be on parent %p\n", hwnd );
3040     old_wnd_proc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONG_PTR)set_focus_on_activate_proc);
3041     ShowWindow(hwnd, SW_RESTORE);
3042     ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd);
3043 todo_wine
3044     ok( GetFocus() == child, "Focus should be on child %p, not %p\n", child, GetFocus() );
3045     SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONG_PTR)old_wnd_proc);
3046 
3047     SetFocus( hwnd );
3048     SetParent( child, GetDesktopWindow());
3049     SetParent( child2, child );
3050     ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd);
3051     ok( GetFocus() == hwnd, "Focus should be on parent %p\n", hwnd );
3052     ret = SetFocus( child2 );
3053     ok( ret == 0, "SetFocus %p should fail\n", child2);
3054     ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd);
3055     ok( GetFocus() == hwnd, "Focus should be on parent %p\n", hwnd );
3056     ret = SetFocus( child );
3057     ok( ret == 0, "SetFocus %p should fail\n", child);
3058     ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd);
3059     ok( GetFocus() == hwnd, "Focus should be on parent %p\n", hwnd );
3060     SetWindowLongW( child, GWL_STYLE, WS_POPUP|WS_CHILD );
3061     SetFocus( child2 );
3062     ok( GetActiveWindow() == child, "child window %p should be active\n", child);
3063     ok( GetFocus() == child2, "Focus should be on child2 %p\n", child2 );
3064     SetFocus( hwnd );
3065     ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd);
3066     ok( GetFocus() == hwnd, "Focus should be on parent %p\n", hwnd );
3067     SetFocus( child );
3068     ok( GetActiveWindow() == child, "child window %p should be active\n", child);
3069     ok( GetFocus() == child, "Focus should be on child %p\n", child );
3070 
3071     DestroyWindow( child2 );
3072     DestroyWindow( child );
3073 }
3074 
3075 static void test_SetActiveWindow(HWND hwnd)
3076 {
3077     HWND hwnd2;
3078 
3079     flush_events( TRUE );
3080     ShowWindow(hwnd, SW_HIDE);
3081     SetFocus(0);
3082     SetActiveWindow(0);
3083     check_wnd_state(0, 0, 0, 0);
3084 
3085     /*trace("testing SetActiveWindow %p\n", hwnd);*/
3086 
3087     ShowWindow(hwnd, SW_SHOW);
3088     check_wnd_state(hwnd, hwnd, hwnd, 0);
3089 
3090     hwnd2 = SetActiveWindow(0);
3091     ok(hwnd2 == hwnd, "SetActiveWindow returned %p instead of %p\n", hwnd2, hwnd);
3092     if (!GetActiveWindow())  /* doesn't always work on vista */
3093     {
3094         check_wnd_state(0, 0, 0, 0);
3095         hwnd2 = SetActiveWindow(hwnd);
3096         ok(hwnd2 == 0, "SetActiveWindow returned %p instead of 0\n", hwnd2);
3097     }
3098     check_wnd_state(hwnd, hwnd, hwnd, 0);
3099 
3100     SetWindowPos(hwnd,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_HIDEWINDOW);
3101     check_wnd_state(hwnd, hwnd, hwnd, 0);
3102 
3103     SetWindowPos(hwnd,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_SHOWWINDOW);
3104     check_wnd_state(hwnd, hwnd, hwnd, 0);
3105 
3106     ShowWindow(hwnd, SW_HIDE);
3107     check_wnd_state(0, 0, 0, 0);
3108 
3109     /*trace("testing SetActiveWindow on an invisible window %p\n", hwnd);*/
3110     SetActiveWindow(hwnd);
3111     check_wnd_state(hwnd, hwnd, hwnd, 0);
3112 
3113     ShowWindow(hwnd, SW_SHOW);
3114     check_wnd_state(hwnd, hwnd, hwnd, 0);
3115 
3116     hwnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 0, 0, hwnd, 0, 0, NULL);
3117     check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
3118 
3119     DestroyWindow(hwnd2);
3120     check_wnd_state(hwnd, hwnd, hwnd, 0);
3121 
3122     hwnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 0, 0, hwnd, 0, 0, NULL);
3123     check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
3124 
3125     SetWindowPos(hwnd2,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_HIDEWINDOW);
3126     check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
3127 
3128     DestroyWindow(hwnd2);
3129     check_wnd_state(hwnd, hwnd, hwnd, 0);
3130 }
3131 
3132 struct create_window_thread_params
3133 {
3134     HWND window;
3135     HANDLE window_created;
3136     HANDLE test_finished;
3137 };
3138 
3139 static DWORD WINAPI create_window_thread(void *param)
3140 {
3141     struct create_window_thread_params *p = param;
3142     DWORD res;
3143     BOOL ret;
3144 
3145     p->window = CreateWindowA("static", NULL, WS_POPUP | WS_VISIBLE, 0, 0, 0, 0, 0, 0, 0, 0);
3146 
3147     ret = SetEvent(p->window_created);
3148     ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
3149 
3150     res = WaitForSingleObject(p->test_finished, INFINITE);
3151     ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
3152 
3153     DestroyWindow(p->window);
3154     return 0;
3155 }
3156 
3157 static void test_SetForegroundWindow(HWND hwnd)
3158 {
3159     struct create_window_thread_params thread_params;
3160     HANDLE thread;
3161     DWORD res, tid;
3162     BOOL ret;
3163     HWND hwnd2;
3164     MSG msg;
3165     LONG style;
3166 
3167     flush_events( TRUE );
3168     ShowWindow(hwnd, SW_HIDE);
3169     SetFocus(0);
3170     SetActiveWindow(0);
3171     check_wnd_state(0, 0, 0, 0);
3172 
3173     /*trace("testing SetForegroundWindow %p\n", hwnd);*/
3174 
3175     ShowWindow(hwnd, SW_SHOW);
3176     check_wnd_state(hwnd, hwnd, hwnd, 0);
3177 
3178     hwnd2 = SetActiveWindow(0);
3179     ok(hwnd2 == hwnd, "SetActiveWindow(0) returned %p instead of %p\n", hwnd2, hwnd);
3180     if (GetActiveWindow() == hwnd)  /* doesn't always work on vista */
3181         check_wnd_state(hwnd, hwnd, hwnd, 0);
3182     else
3183         check_wnd_state(0, 0, 0, 0);
3184 
3185     ret = SetForegroundWindow(hwnd);
3186     if (!ret)
3187     {
3188         skip( "SetForegroundWindow not working\n" );
3189         return;
3190     }
3191     check_wnd_state(hwnd, hwnd, hwnd, 0);
3192 
3193     SetLastError(0xdeadbeef);
3194     ret = SetForegroundWindow(0);
3195     ok(!ret, "SetForegroundWindow returned TRUE instead of FALSE\n");
3196     ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE ||
3197        broken(GetLastError() == 0xdeadbeef),  /* win9x */
3198        "got error %d expected ERROR_INVALID_WINDOW_HANDLE\n", GetLastError());
3199     check_wnd_state(hwnd, hwnd, hwnd, 0);
3200 
3201     SetWindowPos(hwnd,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_HIDEWINDOW);
3202     check_wnd_state(hwnd, hwnd, hwnd, 0);
3203 
3204     SetWindowPos(hwnd,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_SHOWWINDOW);
3205     check_wnd_state(hwnd, hwnd, hwnd, 0);
3206 
3207     hwnd2 = GetForegroundWindow();
3208     ok(hwnd2 == hwnd, "Wrong foreground window %p\n", hwnd2);
3209     ret = SetForegroundWindow( GetDesktopWindow() );
3210     ok(ret, "SetForegroundWindow(desktop) error: %d\n", GetLastError());
3211     hwnd2 = GetForegroundWindow();
3212     ok(hwnd2 != hwnd, "Wrong foreground window %p\n", hwnd2);
3213 
3214     ShowWindow(hwnd, SW_HIDE);
3215     check_wnd_state(0, 0, 0, 0);
3216 
3217     /*trace("testing SetForegroundWindow on an invisible window %p\n", hwnd);*/
3218     ret = SetForegroundWindow(hwnd);
3219     ok(ret || broken(!ret), /* win98 */ "SetForegroundWindow returned FALSE instead of TRUE\n");
3220     check_wnd_state(hwnd, hwnd, hwnd, 0);
3221 
3222     ShowWindow(hwnd, SW_SHOW);
3223     check_wnd_state(hwnd, hwnd, hwnd, 0);
3224 
3225     hwnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 0, 0, hwnd, 0, 0, NULL);
3226     check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
3227 
3228     DestroyWindow(hwnd2);
3229     check_wnd_state(hwnd, hwnd, hwnd, 0);
3230 
3231     hwnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 0, 0, hwnd, 0, 0, NULL);
3232     check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
3233 
3234     SetWindowPos(hwnd2,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_HIDEWINDOW);
3235     check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
3236 
3237     DestroyWindow(hwnd2);
3238     check_wnd_state(hwnd, hwnd, hwnd, 0);
3239 
3240     hwnd2 = CreateWindowA("static", NULL, WS_POPUP | WS_VISIBLE, 0, 0, 0, 0, 0, 0, 0, 0);
3241     check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
3242 
3243     thread_params.window_created = CreateEventW(NULL, FALSE, FALSE, NULL);
3244     ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
3245     thread_params.test_finished = CreateEventW(NULL, FALSE, FALSE, NULL);
3246     ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
3247     thread = CreateThread(NULL, 0, create_window_thread, &thread_params, 0, &tid);
3248     ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
3249     res = WaitForSingleObject(thread_params.window_created, INFINITE);
3250     ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
3251     check_wnd_state(hwnd2, thread_params.window, hwnd2, 0);
3252 
3253     SetForegroundWindow(hwnd2);
3254     check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
3255 
3256     while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
3257     if (0) check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
3258     todo_wine ok(GetActiveWindow() == hwnd2, "Expected active window %p, got %p.\n", hwnd2, GetActiveWindow());
3259     todo_wine ok(GetFocus() == hwnd2, "Expected focus window %p, got %p.\n", hwnd2, GetFocus());
3260 
3261     SetForegroundWindow(hwnd);
3262     check_wnd_state(hwnd, hwnd, hwnd, 0);
3263     style = GetWindowLongA(hwnd2, GWL_STYLE) | WS_CHILD;
3264     ok(SetWindowLongA(hwnd2, GWL_STYLE, style), "SetWindowLong failed\n");
3265     ok(SetForegroundWindow(hwnd2), "SetForegroundWindow failed\n");
3266     check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
3267 
3268     SetForegroundWindow(hwnd);
3269     check_wnd_state(hwnd, hwnd, hwnd, 0);
3270     ok(SetWindowLongA(hwnd2, GWL_STYLE, style & (~WS_POPUP)), "SetWindowLong failed\n");
3271     ok(!SetForegroundWindow(hwnd2), "SetForegroundWindow failed\n");
3272     check_wnd_state(hwnd, hwnd, hwnd, 0);
3273 
3274     SetEvent(thread_params.test_finished);
3275     WaitForSingleObject(thread, INFINITE);
3276     CloseHandle(thread_params.test_finished);
3277     CloseHandle(thread_params.window_created);
3278     CloseHandle(thread);
3279     DestroyWindow(hwnd2);
3280 }
3281 
3282 static WNDPROC old_button_proc;
3283 
3284 static LRESULT WINAPI button_hook_proc(HWND button, UINT msg, WPARAM wparam, LPARAM lparam)
3285 {
3286     LRESULT ret;
3287     USHORT key_state;
3288 
3289     key_state = GetKeyState(VK_LBUTTON);
3290     ok(!(key_state & 0x8000), "VK_LBUTTON should not be pressed, state %04x\n", key_state);
3291 
3292     ret = CallWindowProcA(old_button_proc, button, msg, wparam, lparam);
3293 
3294     if (msg == WM_LBUTTONDOWN)
3295     {
3296 	HWND hwnd, capture;
3297 
3298 	check_wnd_state(button, button, button, button);
3299 
3300 	hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL);
3301 	assert(hwnd);
3302 	trace("hwnd %p\n", hwnd);
3303 
3304 	check_wnd_state(button, button, button, button);
3305 
3306 	ShowWindow(hwnd, SW_SHOWNOACTIVATE);
3307 
3308 	check_wnd_state(button, button, button, button);
3309 
3310 	DestroyWindow(hwnd);
3311 
3312 	hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL);
3313 	assert(hwnd);
3314 	trace("hwnd %p\n", hwnd);
3315 
3316 	check_wnd_state(button, button, button, button);
3317 
3318 	/* button wnd proc should release capture on WM_KILLFOCUS if it does
3319 	 * match internal button state.
3320 	 */
3321 	SendMessageA(button, WM_KILLFOCUS, 0, 0);
3322 	check_wnd_state(button, button, button, 0);
3323 
3324 	ShowWindow(hwnd, SW_SHOW);
3325 	check_wnd_state(hwnd, hwnd, hwnd, 0);
3326 
3327 	capture = SetCapture(hwnd);
3328 	ok(capture == 0, "SetCapture() = %p\n", capture);
3329 
3330 	check_wnd_state(hwnd, hwnd, hwnd, hwnd);
3331 
3332 	DestroyWindow(hwnd);
3333 
3334 	check_wnd_state(button, 0, button, 0);
3335     }
3336 
3337     return ret;
3338 }
3339 
3340 static void test_capture_1(void)
3341 {
3342     HWND button, capture;
3343 
3344     capture = GetCapture();
3345     ok(capture == 0, "GetCapture() = %p\n", capture);
3346 
3347     button = CreateWindowExA(0, "button", NULL, WS_POPUP | WS_VISIBLE, 0, 0, 10, 10, 0, 0, 0, NULL);
3348     assert(button);
3349     trace("button %p\n", button);
3350 
3351     old_button_proc = (WNDPROC)SetWindowLongPtrA(button, GWLP_WNDPROC, (LONG_PTR)button_hook_proc);
3352 
3353     SendMessageA(button, WM_LBUTTONDOWN, 0, 0);
3354 
3355     capture = SetCapture(button);
3356     ok(capture == 0, "SetCapture() = %p\n", capture);
3357     check_wnd_state(button, 0, button, button);
3358 
3359     DestroyWindow(button);
3360     /* old active window test depends on previously executed window
3361      * activation tests, and fails under NT4.
3362     check_wnd_state(oldActive, 0, oldFocus, 0);*/
3363 }
3364 
3365 static void test_capture_2(void)
3366 {
3367     HWND button, hwnd, capture, oldFocus, oldActive;
3368 
3369     oldFocus = GetFocus();
3370     oldActive = GetActiveWindow();
3371     check_wnd_state(oldActive, 0, oldFocus, 0);
3372 
3373     button = CreateWindowExA(0, "button", NULL, WS_POPUP | WS_VISIBLE, 0, 0, 10, 10, 0, 0, 0, NULL);
3374     assert(button);
3375     trace("button %p\n", button);
3376 
3377     check_wnd_state(button, button, button, 0);
3378 
3379     capture = SetCapture(button);
3380     ok(capture == 0, "SetCapture() = %p\n", capture);
3381 
3382     check_wnd_state(button, button, button, button);
3383 
3384     /* button wnd proc should ignore WM_KILLFOCUS if it doesn't match
3385      * internal button state.
3386      */
3387     SendMessageA(button, WM_KILLFOCUS, 0, 0);
3388     check_wnd_state(button, button, button, button);
3389 
3390     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL);
3391     assert(hwnd);
3392     trace("hwnd %p\n", hwnd);
3393 
3394     check_wnd_state(button, button, button, button);
3395 
3396     ShowWindow(hwnd, SW_SHOWNOACTIVATE);
3397 
3398     check_wnd_state(button, button, button, button);
3399 
3400     DestroyWindow(hwnd);
3401 
3402     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL);
3403     assert(hwnd);
3404     trace("hwnd %p\n", hwnd);
3405 
3406     check_wnd_state(button, button, button, button);
3407 
3408     ShowWindow(hwnd, SW_SHOW);
3409 
3410     check_wnd_state(hwnd, hwnd, hwnd, button);
3411 
3412     capture = SetCapture(hwnd);
3413     ok(capture == button, "SetCapture() = %p\n", capture);
3414 
3415     check_wnd_state(hwnd, hwnd, hwnd, hwnd);
3416 
3417     DestroyWindow(hwnd);
3418     check_wnd_state(button, button, button, 0);
3419 
3420     DestroyWindow(button);
3421     check_wnd_state(oldActive, 0, oldFocus, 0);
3422 }
3423 
3424 static void test_capture_3(HWND hwnd1, HWND hwnd2)
3425 {
3426     BOOL ret;
3427 
3428     ShowWindow(hwnd1, SW_HIDE);
3429     ShowWindow(hwnd2, SW_HIDE);
3430 
3431     ok(!IsWindowVisible(hwnd1), "%p should be invisible\n", hwnd1);
3432     ok(!IsWindowVisible(hwnd2), "%p should be invisible\n", hwnd2);
3433 
3434     SetCapture(hwnd1);
3435     check_wnd_state(0, 0, 0, hwnd1);
3436 
3437     SetCapture(hwnd2);
3438     check_wnd_state(0, 0, 0, hwnd2);
3439 
3440     ShowWindow(hwnd1, SW_SHOW);
3441     check_wnd_state(hwnd1, hwnd1, hwnd1, hwnd2);
3442 
3443     ret = ReleaseCapture();
3444     ok (ret, "releasecapture did not return TRUE.\n");
3445     ret = ReleaseCapture();
3446     ok (ret, "releasecapture did not return TRUE after second try.\n");
3447 }
3448 
3449 static LRESULT CALLBACK test_capture_4_proc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
3450 {
3451     GUITHREADINFO gti;
3452     HWND cap_wnd, cap_wnd2, set_cap_wnd;
3453     BOOL status;
3454     switch (msg)
3455     {
3456         case WM_CAPTURECHANGED:
3457 
3458             /* now try to release capture from menu. this should fail */
3459             if (pGetGUIThreadInfo)
3460             {
3461                 memset(&gti, 0, sizeof(GUITHREADINFO));
3462                 gti.cbSize = sizeof(GUITHREADINFO);
3463                 status = pGetGUIThreadInfo(GetCurrentThreadId(), &gti);
3464                 ok(status, "GetGUIThreadInfo() failed!\n");
3465                 ok(gti.flags & GUI_INMENUMODE, "Thread info incorrect (flags=%08X)!\n", gti.flags);
3466             }
3467             cap_wnd = GetCapture();
3468 
3469             ok(cap_wnd == (HWND)lParam, "capture window %p does not match lparam %lx\n", cap_wnd, lParam);
3470             todo_wine ok(cap_wnd == hWnd, "capture window %p does not match hwnd %p\n", cap_wnd, hWnd);
3471 
3472             /* check that re-setting the capture for the menu fails */
3473             set_cap_wnd = SetCapture(cap_wnd);
3474             ok(!set_cap_wnd || broken(set_cap_wnd == cap_wnd), /* nt4 */
3475                "SetCapture should have failed!\n");
3476             if (set_cap_wnd)
3477             {
3478                 DestroyWindow(hWnd);
3479                 break;
3480             }
3481 
3482             /* check that SetCapture fails for another window and that it does not touch the error code */
3483             set_cap_wnd = SetCapture(hWnd);
3484             ok(!set_cap_wnd, "SetCapture should have failed!\n");
3485 
3486             /* check that ReleaseCapture fails and does not touch the error code */
3487             status = ReleaseCapture();
3488             ok(!status, "ReleaseCapture should have failed!\n");
3489 
3490             /* check that thread info did not change */
3491             if (pGetGUIThreadInfo)
3492             {
3493                 memset(&gti, 0, sizeof(GUITHREADINFO));
3494                 gti.cbSize = sizeof(GUITHREADINFO);
3495                 status = pGetGUIThreadInfo(GetCurrentThreadId(), &gti);
3496                 ok(status, "GetGUIThreadInfo() failed!\n");
3497                 ok(gti.flags & GUI_INMENUMODE, "Thread info incorrect (flags=%08X)!\n", gti.flags);
3498             }
3499 
3500             /* verify that no capture change took place */
3501             cap_wnd2 = GetCapture();
3502             ok(cap_wnd2 == cap_wnd, "Capture changed!\n");
3503 
3504             /* we are done. kill the window */
3505             DestroyWindow(hWnd);
3506             break;
3507 
3508         default:
3509             return( DefWindowProcA( hWnd, msg, wParam, lParam ) );
3510     }
3511     return 0;
3512 }
3513 
3514 /* Test that no-one can mess around with the current capture while a menu is open */
3515 static void test_capture_4(void)
3516 {
3517     BOOL ret;
3518     HMENU hmenu;
3519     HWND hwnd;
3520     WNDCLASSA wclass;
3521     HINSTANCE hInstance = GetModuleHandleA( NULL );
3522     ATOM aclass;
3523 
3524     if (!pGetGUIThreadInfo)
3525     {
3526         win_skip("GetGUIThreadInfo is not available\n");
3527         return;
3528     }
3529     wclass.lpszClassName = "TestCapture4Class";
3530     wclass.style         = CS_HREDRAW | CS_VREDRAW;
3531     wclass.lpfnWndProc   = test_capture_4_proc;
3532     wclass.hInstance     = hInstance;
3533     wclass.hIcon         = LoadIconA( 0, (LPCSTR)IDI_APPLICATION );
3534     wclass.hCursor       = LoadCursorA( 0, (LPCSTR)IDC_ARROW );
3535     wclass.hbrBackground = (HBRUSH)( COLOR_WINDOW + 1 );
3536     wclass.lpszMenuName  = 0;
3537     wclass.cbClsExtra    = 0;
3538     wclass.cbWndExtra    = 0;
3539     aclass = RegisterClassA( &wclass );
3540     ok( aclass, "RegisterClassA failed with error %d\n", GetLastError());
3541     hwnd = CreateWindowA( wclass.lpszClassName, "MenuTest",
3542                           WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0,
3543                           400, 200, NULL, NULL, hInstance, NULL);
3544     ok(hwnd != NULL, "CreateWindowEx failed with error %d\n", GetLastError());
3545     if (!hwnd) return;
3546     hmenu = CreatePopupMenu();
3547 
3548     ret = AppendMenuA( hmenu, MF_STRING, 1, "winetest2");
3549     ok( ret, "AppendMenuA has failed!\n");
3550 
3551     /* set main window to have initial capture */
3552     SetCapture(hwnd);
3553 
3554     if (is_win9x)
3555     {
3556         win_skip("TrackPopupMenu test crashes on Win9x/WinMe\n");
3557     }
3558     else
3559     {
3560         /* create popup (it will self-destruct) */
3561         ret = TrackPopupMenu(hmenu, TPM_RETURNCMD, 100, 100, 0, hwnd, NULL);
3562         ok( ret == 0, "TrackPopupMenu returned %d expected zero\n", ret);
3563     }
3564 
3565     /* clean up */
3566     DestroyMenu(hmenu);
3567     DestroyWindow(hwnd);
3568 }
3569 
3570 /* PeekMessage wrapper that ignores the messages we don't care about */
3571 static BOOL peek_message( MSG *msg )
3572 {
3573     BOOL ret;
3574     do
3575     {
3576         ret = PeekMessageA(msg, 0, 0, 0, PM_REMOVE);
3577     } while (ret && ignore_message(msg->message));
3578     return ret;
3579 }
3580 
3581 static void test_keyboard_input(HWND hwnd)
3582 {
3583     MSG msg;
3584     BOOL ret;
3585 
3586     flush_events( TRUE );
3587     SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE|SWP_SHOWWINDOW);
3588     UpdateWindow(hwnd);
3589     flush_events( TRUE );
3590 
3591     ok(GetActiveWindow() == hwnd, "wrong active window %p\n", GetActiveWindow());
3592 
3593     SetFocus(hwnd);
3594     ok(GetFocus() == hwnd, "wrong focus window %p\n", GetFocus());
3595 
3596     flush_events( TRUE );
3597 
3598     PostMessageA(hwnd, WM_KEYDOWN, 0, 0);
3599     ret = peek_message(&msg);
3600     ok( ret, "no message available\n");
3601     ok(msg.hwnd == hwnd && msg.message == WM_KEYDOWN, "hwnd %p message %04x\n", msg.hwnd, msg.message);
3602     ret = peek_message(&msg);
3603     ok( !ret, "message %04x available\n", msg.message);
3604 
3605     ok(GetFocus() == hwnd, "wrong focus window %p\n", GetFocus());
3606 
3607     PostThreadMessageA(GetCurrentThreadId(), WM_KEYDOWN, 0, 0);
3608     ret = peek_message(&msg);
3609     ok(ret, "no message available\n");
3610     ok(!msg.hwnd && msg.message == WM_KEYDOWN, "hwnd %p message %04x\n", msg.hwnd, msg.message);
3611     ret = peek_message(&msg);
3612     ok( !ret, "message %04x available\n", msg.message);
3613 
3614     ok(GetFocus() == hwnd, "wrong focus window %p\n", GetFocus());
3615 
3616     keybd_event(VK_SPACE, 0, 0, 0);
3617     if (!peek_message(&msg))
3618     {
3619         skip( "keybd_event didn't work, skipping keyboard test\n" );
3620         return;
3621     }
3622     ok(msg.hwnd == hwnd && msg.message == WM_KEYDOWN, "hwnd %p message %04x\n", msg.hwnd, msg.message);
3623     ret = peek_message(&msg);
3624     ok( !ret, "message %04x available\n", msg.message);
3625 
3626     SetFocus(0);
3627     ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3628 
3629     flush_events( TRUE );
3630 
3631     PostMessageA(hwnd, WM_KEYDOWN, 0, 0);
3632     ret = peek_message(&msg);
3633     ok(ret, "no message available\n");
3634     ok(msg.hwnd == hwnd && msg.message == WM_KEYDOWN, "hwnd %p message %04x\n", msg.hwnd, msg.message);
3635     ret = peek_message(&msg);
3636     ok( !ret, "message %04x available\n", msg.message);
3637 
3638     ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3639 
3640     PostThreadMessageA(GetCurrentThreadId(), WM_KEYDOWN, 0, 0);
3641     ret = peek_message(&msg);
3642     ok(ret, "no message available\n");
3643     ok(!msg.hwnd && msg.message == WM_KEYDOWN, "hwnd %p message %04x\n", msg.hwnd, msg.message);
3644     ret = peek_message(&msg);
3645     ok( !ret, "message %04x available\n", msg.message);
3646 
3647     ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3648 
3649     keybd_event(VK_SPACE, 0, 0, 0);
3650     ret = peek_message(&msg);
3651     ok(ret, "no message available\n");
3652     ok(msg.hwnd == hwnd && msg.message == WM_SYSKEYDOWN, "hwnd %p message %04x\n", msg.hwnd, msg.message);
3653     ret = peek_message(&msg);
3654     ok( !ret, "message %04x available\n", msg.message);
3655 }
3656 
3657 static BOOL wait_for_message( MSG *msg )
3658 {
3659     BOOL ret;
3660 
3661     for (;;)
3662     {
3663         ret = peek_message(msg);
3664         if (ret)
3665         {
3666             if (msg->message == WM_PAINT) DispatchMessageA(msg);
3667             else break;
3668         }
3669         else if (MsgWaitForMultipleObjects( 0, NULL, FALSE, 100, QS_ALLINPUT ) == WAIT_TIMEOUT) break;
3670     }
3671     if (!ret) msg->message = 0;
3672     return ret;
3673 }
3674 
3675 static void test_mouse_input(HWND hwnd)
3676 {
3677     RECT rc;
3678     POINT pt;
3679     int x, y;
3680     HWND popup;
3681     MSG msg;
3682     BOOL ret;
3683     LRESULT res;
3684 
3685     ShowWindow(hwnd, SW_SHOWNORMAL);
3686     UpdateWindow(hwnd);
3687     SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE );
3688 
3689     GetWindowRect(hwnd, &rc);
3690     trace("main window %p: %s\n", hwnd, wine_dbgstr_rect(&rc));
3691 
3692     popup = CreateWindowExA(0, "MainWindowClass", NULL, WS_POPUP,
3693                             rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top,
3694                             hwnd, 0, 0, NULL);
3695     assert(popup != 0);
3696     ShowWindow(popup, SW_SHOW);
3697     UpdateWindow(popup);
3698     SetWindowPos( popup, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE );
3699 
3700     GetWindowRect(popup, &rc);
3701     trace("popup window %p: %s\n", popup, wine_dbgstr_rect(&rc));
3702 
3703     x = rc.left + (rc.right - rc.left) / 2;
3704     y = rc.top + (rc.bottom - rc.top) / 2;
3705     trace("setting cursor to (%d,%d)\n", x, y);
3706 
3707     SetCursorPos(x, y);
3708     GetCursorPos(&pt);
3709     if (x != pt.x || y != pt.y)
3710     {
3711         skip( "failed to set mouse position, skipping mouse input tests\n" );
3712         goto done;
3713     }
3714 
3715     flush_events( TRUE );
3716 
3717     /* Check that setting the same position may generate WM_MOUSEMOVE */
3718     SetCursorPos(x, y);
3719     msg.message = 0;
3720     ret = peek_message(&msg);
3721     if (ret)
3722     {
3723         ok(msg.hwnd == popup && msg.message == WM_MOUSEMOVE, "hwnd %p message %04x\n",
3724            msg.hwnd, msg.message);
3725         ok(msg.pt.x == x && msg.pt.y == y, "wrong message coords (%d,%d)/(%d,%d)\n",
3726            x, y, msg.pt.x, msg.pt.y);
3727     }
3728 
3729     /* force the system to update its internal queue mouse position,
3730      * otherwise it won't generate relative mouse movements below.
3731      */
3732     mouse_event(MOUSEEVENTF_MOVE, -1, -1, 0, 0);
3733     flush_events( TRUE );
3734 
3735     msg.message = 0;
3736     mouse_event(MOUSEEVENTF_MOVE, 1, 1, 0, 0);
3737     flush_events( FALSE );
3738     /* FIXME: SetCursorPos in Wine generates additional WM_MOUSEMOVE message */
3739     while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
3740     {
3741         if (ignore_message(msg.message)) continue;
3742         ok(msg.hwnd == popup && msg.message == WM_MOUSEMOVE,
3743            "hwnd %p message %04x\n", msg.hwnd, msg.message);
3744         DispatchMessageA(&msg);
3745     }
3746     ret = peek_message(&msg);
3747     ok( !ret, "message %04x available\n", msg.message);
3748 
3749     mouse_event(MOUSEEVENTF_MOVE, -1, -1, 0, 0);
3750     ShowWindow(popup, SW_HIDE);
3751     ret = wait_for_message( &msg );
3752     if (ret)
3753         ok(msg.hwnd == hwnd && msg.message == WM_MOUSEMOVE, "hwnd %p message %04x\n", msg.hwnd, msg.message);
3754     flush_events( TRUE );
3755 
3756     mouse_event(MOUSEEVENTF_MOVE, 1, 1, 0, 0);
3757     ShowWindow(hwnd, SW_HIDE);
3758     ret = wait_for_message( &msg );
3759     ok( !ret, "message %04x available\n", msg.message);
3760     flush_events( TRUE );
3761 
3762     /* test mouse clicks */
3763 
3764     ShowWindow(hwnd, SW_SHOW);
3765     SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE );
3766     flush_events( TRUE );
3767     ShowWindow(popup, SW_SHOW);
3768     SetWindowPos( popup, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE );
3769     flush_events( TRUE );
3770 
3771     mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
3772     mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
3773     mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
3774     mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
3775 
3776     ret = wait_for_message( &msg );
3777     if (!ret)
3778     {
3779         skip( "simulating mouse click doesn't work, skipping mouse button tests\n" );
3780         goto done;
3781     }
3782     if (msg.message == WM_MOUSEMOVE)  /* win2k has an extra WM_MOUSEMOVE here */
3783     {
3784         ret = wait_for_message( &msg );
3785         ok(ret, "no message available\n");
3786     }
3787 
3788     ok(msg.hwnd == popup && msg.message == WM_LBUTTONDOWN, "hwnd %p/%p message %04x\n",
3789        msg.hwnd, popup, msg.message);
3790 
3791     ret = wait_for_message( &msg );
3792     ok(ret, "no message available\n");
3793     ok(msg.hwnd == popup && msg.message == WM_LBUTTONUP, "hwnd %p/%p message %04x\n",
3794        msg.hwnd, popup, msg.message);
3795 
3796     ret = wait_for_message( &msg );
3797     ok(ret, "no message available\n");
3798     ok(msg.hwnd == popup && msg.message == WM_LBUTTONDBLCLK, "hwnd %p/%p message %04x\n",
3799        msg.hwnd, popup, msg.message);
3800 
3801     ret = wait_for_message( &msg );
3802     ok(ret, "no message available\n");
3803     ok(msg.hwnd == popup && msg.message == WM_LBUTTONUP, "hwnd %p/%p message %04x\n",
3804        msg.hwnd, popup, msg.message);
3805 
3806     ret = peek_message(&msg);
3807     ok(!ret, "message %04x available\n", msg.message);
3808 
3809     ShowWindow(popup, SW_HIDE);
3810     flush_events( TRUE );
3811 
3812     mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
3813     mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
3814     mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
3815     mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
3816 
3817     ret = wait_for_message( &msg );
3818     ok(ret, "no message available\n");
3819     ok(msg.hwnd == hwnd && msg.message == WM_LBUTTONDOWN, "hwnd %p/%p message %04x\n",
3820        msg.hwnd, hwnd, msg.message);
3821     ret = wait_for_message( &msg );
3822     ok(ret, "no message available\n");
3823     ok(msg.hwnd == hwnd && msg.message == WM_LBUTTONUP, "hwnd %p/%p message %04x\n",
3824        msg.hwnd, hwnd, msg.message);
3825 
3826     test_lbuttondown_flag = TRUE;
3827     SendMessageA(hwnd, WM_COMMAND, (WPARAM)popup, 0);
3828     test_lbuttondown_flag = FALSE;
3829 
3830     ret = wait_for_message( &msg );
3831     ok(ret, "no message available\n");
3832     ok(msg.hwnd == popup && msg.message == WM_LBUTTONDOWN, "hwnd %p/%p message %04x\n",
3833        msg.hwnd, popup, msg.message);
3834     ok(peek_message(&msg), "no message available\n");
3835     ok(msg.hwnd == popup && msg.message == WM_LBUTTONUP, "hwnd %p/%p message %04x\n",
3836        msg.hwnd, popup, msg.message);
3837     ok(peek_message(&msg), "no message available\n");
3838 
3839     /* Test WM_MOUSEACTIVATE */
3840 #define TEST_MOUSEACTIVATE(A,B)                                                          \
3841        res = SendMessageA(hwnd, WM_MOUSEACTIVATE, (WPARAM)hwnd, (LPARAM)MAKELRESULT(A,0));   \
3842        ok(res == B, "WM_MOUSEACTIVATE for %s returned %ld\n", #A, res);
3843 
3844     TEST_MOUSEACTIVATE(HTERROR,MA_ACTIVATE);
3845     TEST_MOUSEACTIVATE(HTTRANSPARENT,MA_ACTIVATE);
3846     TEST_MOUSEACTIVATE(HTNOWHERE,MA_ACTIVATE);
3847     TEST_MOUSEACTIVATE(HTCLIENT,MA_ACTIVATE);
3848     TEST_MOUSEACTIVATE(HTCAPTION,MA_ACTIVATE);
3849     TEST_MOUSEACTIVATE(HTSYSMENU,MA_ACTIVATE);
3850     TEST_MOUSEACTIVATE(HTSIZE,MA_ACTIVATE);
3851     TEST_MOUSEACTIVATE(HTMENU,MA_ACTIVATE);
3852     TEST_MOUSEACTIVATE(HTHSCROLL,MA_ACTIVATE);
3853     TEST_MOUSEACTIVATE(HTVSCROLL,MA_ACTIVATE);
3854     TEST_MOUSEACTIVATE(HTMINBUTTON,MA_ACTIVATE);
3855     TEST_MOUSEACTIVATE(HTMAXBUTTON,MA_ACTIVATE);
3856     TEST_MOUSEACTIVATE(HTLEFT,MA_ACTIVATE);
3857     TEST_MOUSEACTIVATE(HTRIGHT,MA_ACTIVATE);
3858     TEST_MOUSEACTIVATE(HTTOP,MA_ACTIVATE);
3859     TEST_MOUSEACTIVATE(HTTOPLEFT,MA_ACTIVATE);
3860     TEST_MOUSEACTIVATE(HTTOPRIGHT,MA_ACTIVATE);
3861     TEST_MOUSEACTIVATE(HTBOTTOM,MA_ACTIVATE);
3862     TEST_MOUSEACTIVATE(HTBOTTOMLEFT,MA_ACTIVATE);
3863     TEST_MOUSEACTIVATE(HTBOTTOMRIGHT,MA_ACTIVATE);
3864     TEST_MOUSEACTIVATE(HTBORDER,MA_ACTIVATE);
3865     TEST_MOUSEACTIVATE(HTOBJECT,MA_ACTIVATE);
3866     TEST_MOUSEACTIVATE(HTCLOSE,MA_ACTIVATE);
3867     TEST_MOUSEACTIVATE(HTHELP,MA_ACTIVATE);
3868 
3869 done:
3870     /* Clear any messages left behind by WM_MOUSEACTIVATE tests */
3871     flush_events( TRUE );
3872 
3873     DestroyWindow(popup);
3874 }
3875 
3876 static void test_validatergn(HWND hwnd)
3877 {
3878     HWND child;
3879     RECT rc, rc2;
3880     HRGN rgn;
3881     int ret;
3882     child = CreateWindowExA(0, "static", NULL, WS_CHILD| WS_VISIBLE, 10, 10, 10, 10, hwnd, 0, 0, NULL);
3883     ShowWindow(hwnd, SW_SHOW);
3884     UpdateWindow( hwnd);
3885     /* test that ValidateRect validates children*/
3886     InvalidateRect( child, NULL, 1);
3887     GetWindowRect( child, &rc);
3888     MapWindowPoints( NULL, hwnd, (POINT*) &rc, 2);
3889     ret = GetUpdateRect( child, &rc2, 0);
3890     ok( ret == 1, "Expected GetUpdateRect to return non-zero, got %d\n", ret);
3891     ok( rc2.right > rc2.left && rc2.bottom > rc2.top,
3892             "Update rectangle is empty!\n");
3893     ValidateRect( hwnd, &rc);
3894     ret = GetUpdateRect( child, &rc2, 0);
3895     ok( !ret, "Expected GetUpdateRect to return zero, got %d\n", ret);
3896     ok( rc2.left == 0 && rc2.top == 0 && rc2.right == 0 && rc2.bottom == 0,
3897             "Update rectangle %s is not empty!\n", wine_dbgstr_rect(&rc2));
3898 
3899     /* now test ValidateRgn */
3900     InvalidateRect( child, NULL, 1);
3901     GetWindowRect( child, &rc);
3902     MapWindowPoints( NULL, hwnd, (POINT*) &rc, 2);
3903     rgn = CreateRectRgnIndirect( &rc);
3904     ValidateRgn( hwnd, rgn);
3905     ret = GetUpdateRect( child, &rc2, 0);
3906     ok( !ret, "Expected GetUpdateRect to return zero, got %d\n", ret);
3907     ok( rc2.left == 0 && rc2.top == 0 && rc2.right == 0 && rc2.bottom == 0,
3908             "Update rectangle %s is not empty!\n", wine_dbgstr_rect(&rc2));
3909 
3910     DeleteObject( rgn);
3911     DestroyWindow( child );
3912 }
3913 
3914 static void nccalchelper(HWND hwnd, INT x, INT y, RECT *prc)
3915 {
3916     RECT rc;
3917     MoveWindow( hwnd, 0, 0, x, y, 0);
3918     GetWindowRect( hwnd, prc);
3919     rc = *prc;
3920     DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, (LPARAM)prc);
3921     trace("window rect is %s, nccalc rect is %s\n", wine_dbgstr_rect(&rc), wine_dbgstr_rect(prc));
3922 }
3923 
3924 static void test_nccalcscroll(HWND parent)
3925 {
3926     RECT rc1;
3927     INT sbheight = GetSystemMetrics( SM_CYHSCROLL);
3928     INT sbwidth = GetSystemMetrics( SM_CXVSCROLL);
3929     HWND hwnd = CreateWindowExA(0, "static", NULL,
3930             WS_CHILD| WS_VISIBLE | WS_VSCROLL | WS_HSCROLL ,
3931             10, 10, 200, 200, parent, 0, 0, NULL);
3932     ShowWindow( parent, SW_SHOW);
3933     UpdateWindow( parent);
3934 
3935     /* test window too low for a horizontal scroll bar */
3936     nccalchelper( hwnd, 100, sbheight, &rc1);
3937     ok( rc1.bottom - rc1.top == sbheight, "Height should be %d size is %s\n", sbheight,
3938             wine_dbgstr_rect(&rc1));
3939 
3940     /* test window just high enough for a horizontal scroll bar */
3941     nccalchelper( hwnd, 100, sbheight + 1, &rc1);
3942     ok( rc1.bottom - rc1.top == 1, "Height should be 1 size is %s\n", wine_dbgstr_rect(&rc1));
3943 
3944     /* test window too narrow for a vertical scroll bar */
3945     nccalchelper( hwnd, sbwidth - 1, 100, &rc1);
3946     ok( rc1.right - rc1.left == sbwidth - 1 , "Width should be %d size is %s\n", sbwidth - 1,
3947             wine_dbgstr_rect(&rc1));
3948 
3949     /* test window just wide enough for a vertical scroll bar */
3950     nccalchelper( hwnd, sbwidth, 100, &rc1);
3951     ok( rc1.right - rc1.left == 0, "Width should be 0 size is %s\n", wine_dbgstr_rect(&rc1));
3952 
3953     /* same test, but with client edge: not enough width */
3954     SetWindowLongA( hwnd, GWL_EXSTYLE, WS_EX_CLIENTEDGE | GetWindowLongA( hwnd, GWL_EXSTYLE));
3955     nccalchelper( hwnd, sbwidth, 100, &rc1);
3956     ok( rc1.right - rc1.left == sbwidth - 2 * GetSystemMetrics(SM_CXEDGE),
3957             "Width should be %d size is %s\n", sbwidth - 2 * GetSystemMetrics(SM_CXEDGE),
3958             wine_dbgstr_rect(&rc1));
3959 
3960     DestroyWindow( hwnd);
3961 }
3962 
3963 static void test_SetParent(void)
3964 {
3965     HWND desktop = GetDesktopWindow();
3966     HMENU hMenu;
3967     HWND ret, parent, child1, child2, child3, child4, sibling, popup;
3968     BOOL bret;
3969 
3970     parent = CreateWindowExA(0, "static", NULL, WS_OVERLAPPEDWINDOW,
3971 			     100, 100, 200, 200, 0, 0, 0, NULL);
3972     assert(parent != 0);
3973     child1 = CreateWindowExA(0, "static", NULL, WS_CHILD,
3974 			     0, 0, 50, 50, parent, 0, 0, NULL);
3975     assert(child1 != 0);
3976     child2 = CreateWindowExA(0, "static", NULL, WS_POPUP,
3977 			     0, 0, 50, 50, child1, 0, 0, NULL);
3978     assert(child2 != 0);
3979     child3 = CreateWindowExA(0, "static", NULL, WS_CHILD,
3980 			     0, 0, 50, 50, child2, 0, 0, NULL);
3981     assert(child3 != 0);
3982     child4 = CreateWindowExA(0, "static", NULL, WS_POPUP,
3983 			     0, 0, 50, 50, child3, 0, 0, NULL);
3984     assert(child4 != 0);
3985 
3986     trace("parent %p, child1 %p, child2 %p, child3 %p, child4 %p\n",
3987 	   parent, child1, child2, child3, child4);
3988 
3989     check_parents(parent, desktop, 0, 0, 0, parent, parent);
3990     check_parents(child1, parent, parent, parent, 0, parent, parent);
3991     check_parents(child2, desktop, parent, parent, parent, child2, parent);
3992     check_parents(child3, child2, child2, child2, 0, child2, parent);
3993     check_parents(child4, desktop, child2, child2, child2, child4, parent);
3994 
3995     ok(!IsChild(desktop, parent), "wrong parent/child %p/%p\n", desktop, parent);
3996     ok(!IsChild(desktop, child1), "wrong parent/child %p/%p\n", desktop, child1);
3997     ok(!IsChild(desktop, child2), "wrong parent/child %p/%p\n", desktop, child2);
3998     ok(!IsChild(desktop, child3), "wrong parent/child %p/%p\n", desktop, child3);
3999     ok(!IsChild(desktop, child4), "wrong parent/child %p/%p\n", desktop, child4);
4000 
4001     ok(IsChild(parent, child1), "wrong parent/child %p/%p\n", parent, child1);
4002     ok(!IsChild(desktop, child2), "wrong parent/child %p/%p\n", desktop, child2);
4003     ok(!IsChild(parent, child2), "wrong parent/child %p/%p\n", parent, child2);
4004     ok(!IsChild(child1, child2), "wrong parent/child %p/%p\n", child1, child2);
4005     ok(!IsChild(parent, child3), "wrong parent/child %p/%p\n", parent, child3);
4006     ok(IsChild(child2, child3), "wrong parent/child %p/%p\n", child2, child3);
4007     ok(!IsChild(parent, child4), "wrong parent/child %p/%p\n", parent, child4);
4008     ok(!IsChild(child3, child4), "wrong parent/child %p/%p\n", child3, child4);
4009     ok(!IsChild(desktop, child4), "wrong parent/child %p/%p\n", desktop, child4);
4010 
4011     if (!is_win9x) /* Win9x doesn't survive this test */
4012     {
4013         ok(!SetParent(parent, child1), "SetParent should fail\n");
4014         ok(!SetParent(child2, child3), "SetParent should fail\n");
4015         ok(SetParent(child1, parent) != 0, "SetParent should not fail\n");
4016         ret = SetParent(parent, child2);
4017         todo_wine ok( !ret || broken( ret != 0 ), "SetParent should fail\n");
4018         if (ret)  /* nt4, win2k */
4019         {
4020             ret = SetParent(parent, child3);
4021             ok(ret != 0, "SetParent should not fail\n");
4022             ret = SetParent(child2, parent);
4023             ok(!ret, "SetParent should fail\n");
4024             ret = SetParent(parent, child4);
4025             ok(ret != 0, "SetParent should not fail\n");
4026             check_parents(parent, child4, child4, 0, 0, child4, parent);
4027             check_parents(child1, parent, parent, parent, 0, child4, parent);
4028             check_parents(child2, desktop, parent, parent, parent, child2, parent);
4029             check_parents(child3, child2, child2, child2, 0, child2, parent);
4030             check_parents(child4, desktop, child2, child2, child2, child4, parent);
4031         }
4032         else
4033         {
4034             ret = SetParent(parent, child3);
4035             ok(ret != 0, "SetParent should not fail\n");
4036             ret = SetParent(child2, parent);
4037             ok(!ret, "SetParent should fail\n");
4038             ret = SetParent(parent, child4);
4039             ok(!ret, "SetParent should fail\n");
4040             check_parents(parent, child3, child3, 0, 0, child2, parent);
4041             check_parents(child1, parent, parent, parent, 0, child2, parent);
4042             check_parents(child2, desktop, parent, parent, parent, child2, parent);
4043             check_parents(child3, child2, child2, child2, 0, child2, parent);
4044             check_parents(child4, desktop, child2, child2, child2, child4, parent);
4045         }
4046     }
4047     else
4048         skip("Win9x/WinMe crash\n");
4049 
4050     hMenu = CreateMenu();
4051     sibling = CreateWindowExA(0, "static", NULL, WS_OVERLAPPEDWINDOW,
4052 			     100, 100, 200, 200, 0, hMenu, 0, NULL);
4053     assert(sibling != 0);
4054 
4055     ok(SetParent(sibling, parent) != 0, "SetParent should not fail\n");
4056     ok(GetMenu(sibling) == hMenu, "SetParent should not remove menu\n");
4057 
4058     ok(SetParent(parent, desktop) != 0, "SetParent should not fail\n");
4059     ok(SetParent(child4, child3) != 0, "SetParent should not fail\n");
4060     ok(SetParent(child3, child2) != 0, "SetParent should not fail\n");
4061     ok(SetParent(child2, child1) != 0, "SetParent should not fail\n");
4062     ok(!IsChild(child3, child4), "wrong parent/child %p/%p\n", child3, child4);
4063     SetWindowLongW(child4, GWL_STYLE, WS_CHILD);
4064     ok(IsChild(child3, child4), "wrong parent/child %p/%p\n", child3, child4);
4065     ok(IsChild(child2, child4), "wrong parent/child %p/%p\n", child2, child4);
4066     ok(!IsChild(child1, child4), "wrong parent/child %p/%p\n", child1, child4);
4067     SetWindowLongW(child2, GWL_STYLE, WS_CHILD);
4068     ok(IsChild(child1, child4), "wrong parent/child %p/%p\n", child1, child4);
4069     ok(IsChild(parent, child4), "wrong parent/child %p/%p\n", parent, child4);
4070 
4071     ok(DestroyWindow(parent), "DestroyWindow() failed\n");
4072 
4073     ok(!IsWindow(parent), "parent still exists\n");
4074     ok(!IsWindow(sibling), "sibling still exists\n");
4075     ok(!IsWindow(child1), "child1 still exists\n");
4076     ok(!IsWindow(child2), "child2 still exists\n");
4077     ok(!IsWindow(child3), "child3 still exists\n");
4078     ok(!IsWindow(child4), "child4 still exists\n");
4079 
4080     parent = CreateWindowExA(0, "static", NULL, WS_OVERLAPPEDWINDOW,
4081 			     100, 100, 200, 200, 0, 0, 0, NULL);
4082     assert(parent != 0);
4083     child1 = CreateWindowExA(0, "static", NULL, WS_CHILD,
4084 			     0, 0, 50, 50, parent, 0, 0, NULL);
4085     assert(child1 != 0);
4086     popup = CreateWindowExA(0, "static", NULL, WS_POPUP,
4087 			     0, 0, 50, 50, 0, 0, 0, NULL);
4088     assert(popup != 0);
4089 
4090     trace("parent %p, child %p, popup %p\n", parent, child1, popup);
4091 
4092     check_parents(parent, desktop, 0, 0, 0, parent, parent);
4093     check_parents(child1, parent, parent, parent, 0, parent, parent);
4094     check_parents(popup, desktop, 0, 0, 0, popup, popup);
4095 
4096     SetActiveWindow(parent);
4097     SetFocus(parent);
4098     check_active_state(parent, 0, parent);
4099 
4100     ret = SetParent(popup, child1);
4101     ok(ret == desktop, "expected %p, got %p\n", desktop, ret);
4102     check_parents(popup, child1, child1, 0, 0, parent, popup);
4103     check_active_state(popup, 0, popup);
4104 
4105     SetActiveWindow(parent);
4106     SetFocus(popup);
4107     check_active_state(popup, 0, popup);
4108 
4109     EnableWindow(child1, FALSE);
4110     check_active_state(popup, 0, popup);
4111     SetFocus(parent);
4112     check_active_state(parent, 0, parent);
4113     SetFocus(popup);
4114     check_active_state(popup, 0, popup);
4115     EnableWindow(child1, TRUE);
4116 
4117     ShowWindow(child1, SW_MINIMIZE);
4118     SetFocus(parent);
4119     check_active_state(parent, 0, parent);
4120     SetFocus(popup);
4121     check_active_state(popup, 0, popup);
4122     ShowWindow(child1, SW_HIDE);
4123 
4124     SetActiveWindow(parent);
4125     SetFocus(parent);
4126     check_active_state(parent, 0, parent);
4127 
4128     bret = SetForegroundWindow(popup);
4129     ok(bret, "SetForegroundWindow() failed\n");
4130     check_active_state(popup, popup, popup);
4131 
4132     ShowWindow(parent, SW_SHOW);
4133     SetActiveWindow(popup);
4134     ok(DestroyWindow(popup), "DestroyWindow() failed\n");
4135     check_active_state(parent, parent, parent);
4136 
4137     ok(DestroyWindow(parent), "DestroyWindow() failed\n");
4138 
4139     ok(!IsWindow(parent), "parent still exists\n");
4140     ok(!IsWindow(child1), "child1 still exists\n");
4141     ok(!IsWindow(popup), "popup still exists\n");
4142 }
4143 
4144 static LRESULT WINAPI StyleCheckProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
4145 {
4146     LPCREATESTRUCTA lpcs;
4147     LPSTYLESTRUCT lpss;
4148 
4149     switch (msg)
4150     {
4151     case WM_NCCREATE:
4152     case WM_CREATE:
4153         lpcs = (LPCREATESTRUCTA)lparam;
4154         lpss = lpcs->lpCreateParams;
4155         if (lpss)
4156         {
4157             if ((lpcs->dwExStyle & WS_EX_DLGMODALFRAME) ||
4158                 ((!(lpcs->dwExStyle & WS_EX_STATICEDGE)) &&
4159                     (lpcs->style & (WS_DLGFRAME | WS_THICKFRAME))))
4160                 ok(lpcs->dwExStyle & WS_EX_WINDOWEDGE, "Window should have WS_EX_WINDOWEDGE style\n");
4161             else
4162                 ok(!(lpcs->dwExStyle & WS_EX_WINDOWEDGE), "Window shouldn't have WS_EX_WINDOWEDGE style\n");
4163 
4164             ok((lpss->styleOld & ~WS_EX_WINDOWEDGE) == (lpcs->dwExStyle & ~WS_EX_WINDOWEDGE),
4165                 "Ex style (0x%08x) should match what the caller passed to CreateWindowEx (0x%08x)\n",
4166                 lpss->styleOld, lpcs->dwExStyle);
4167 
4168             ok(lpss->styleNew == lpcs->style,
4169                 "Style (0x%08x) should match what the caller passed to CreateWindowEx (0x%08x)\n",
4170                 lpss->styleNew, lpcs->style);
4171         }
4172         break;
4173     }
4174     return DefWindowProcA(hwnd, msg, wparam, lparam);
4175 }
4176 
4177 static ATOM atomStyleCheckClass;
4178 
4179 static void register_style_check_class(void)
4180 {
4181     WNDCLASSA wc =
4182     {
4183         0,
4184         StyleCheckProc,
4185         0,
4186         0,
4187         GetModuleHandleA(NULL),
4188         NULL,
4189         LoadCursorA(0, (LPCSTR)IDC_ARROW),
4190         (HBRUSH)(COLOR_BTNFACE+1),
4191         NULL,
4192         "WineStyleCheck",
4193     };
4194 
4195     atomStyleCheckClass = RegisterClassA(&wc);
4196     assert(atomStyleCheckClass);
4197 }
4198 
4199 static void check_window_style(DWORD dwStyleIn, DWORD dwExStyleIn, DWORD dwStyleOut, DWORD dwExStyleOut)
4200 {
4201     DWORD dwActualStyle;
4202     DWORD dwActualExStyle;
4203     STYLESTRUCT ss;
4204     HWND hwnd;
4205     HWND hwndParent = NULL;
4206 
4207     ss.styleNew = dwStyleIn;
4208     ss.styleOld = dwExStyleIn;
4209 
4210     if (dwStyleIn & WS_CHILD)
4211     {
4212         hwndParent = CreateWindowExA(0, (LPCSTR)MAKEINTATOM(atomStyleCheckClass), NULL,
4213             WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
4214     }
4215 
4216     hwnd = CreateWindowExA(dwExStyleIn, (LPCSTR)MAKEINTATOM(atomStyleCheckClass), NULL,
4217                     dwStyleIn, 0, 0, 0, 0, hwndParent, NULL, NULL, &ss);
4218     assert(hwnd);
4219 
4220     flush_events( TRUE );
4221 
4222     dwActualStyle = GetWindowLongA(hwnd, GWL_STYLE);
4223     dwActualExStyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
4224     ok(dwActualStyle == dwStyleOut, "expected style %#x, got %#x\n", dwStyleOut, dwActualStyle);
4225     ok(dwActualExStyle == dwExStyleOut, "expected ex_style %#x, got %#x\n", dwExStyleOut, dwActualExStyle);
4226 
4227     /* try setting the styles explicitly */
4228     SetWindowLongA( hwnd, GWL_EXSTYLE, dwExStyleIn );
4229     dwActualStyle = GetWindowLongA(hwnd, GWL_STYLE);
4230     dwActualExStyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
4231     /* WS_EX_WINDOWEDGE can't always be changed */
4232     if (dwExStyleIn & WS_EX_DLGMODALFRAME)
4233         dwExStyleOut = dwExStyleIn | WS_EX_WINDOWEDGE;
4234     else if ((dwActualStyle & (WS_DLGFRAME | WS_THICKFRAME)) && !(dwExStyleIn & WS_EX_STATICEDGE))
4235         dwExStyleOut = dwExStyleIn | WS_EX_WINDOWEDGE;
4236     else
4237         dwExStyleOut = dwExStyleIn & ~WS_EX_WINDOWEDGE;
4238     ok(dwActualStyle == dwStyleOut, "expected style %#x, got %#x\n", dwStyleOut, dwActualStyle);
4239     ok(dwActualExStyle == dwExStyleOut, "expected ex_style %#x, got %#x\n", dwExStyleOut, dwActualExStyle);
4240 
4241     SetWindowLongA( hwnd, GWL_STYLE, dwStyleIn );
4242     dwActualStyle = GetWindowLongA(hwnd, GWL_STYLE);
4243     dwActualExStyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
4244     /* WS_CLIPSIBLINGS can't be reset on top-level windows */
4245     if ((dwStyleIn & (WS_CHILD|WS_POPUP)) == WS_CHILD) dwStyleOut = dwStyleIn;
4246     else dwStyleOut = dwStyleIn | WS_CLIPSIBLINGS;
4247     /* WS_EX_WINDOWEDGE can't always be changed */
4248     if (dwExStyleIn & WS_EX_DLGMODALFRAME)
4249         dwExStyleOut = dwExStyleIn | WS_EX_WINDOWEDGE;
4250     else if ((dwActualStyle & (WS_DLGFRAME | WS_THICKFRAME)) && !(dwExStyleIn & WS_EX_STATICEDGE))
4251         dwExStyleOut = dwExStyleIn | WS_EX_WINDOWEDGE;
4252     else
4253         dwExStyleOut = dwExStyleIn & ~WS_EX_WINDOWEDGE;
4254     ok(dwActualStyle == dwStyleOut, "expected style %#x, got %#x\n", dwStyleOut, dwActualStyle);
4255     /* FIXME: Remove the condition below once Wine is fixed */
4256     todo_wine_if (dwActualExStyle != dwExStyleOut)
4257         ok(dwActualExStyle == dwExStyleOut, "expected ex_style %#x, got %#x\n", dwExStyleOut, dwActualExStyle);
4258 
4259     DestroyWindow(hwnd);
4260     if (hwndParent) DestroyWindow(hwndParent);
4261 }
4262 
4263 /* tests what window styles the window manager automatically adds */
4264 static void test_window_styles(void)
4265 {
4266     register_style_check_class();
4267 
4268     check_window_style(0, 0, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE);
4269     check_window_style(WS_DLGFRAME, 0, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE);
4270     check_window_style(WS_THICKFRAME, 0, WS_THICKFRAME|WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE);
4271     check_window_style(WS_DLGFRAME, WS_EX_STATICEDGE, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE|WS_EX_STATICEDGE);
4272     check_window_style(WS_THICKFRAME, WS_EX_STATICEDGE, WS_THICKFRAME|WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE|WS_EX_STATICEDGE);
4273     check_window_style(WS_OVERLAPPEDWINDOW, 0, WS_CLIPSIBLINGS|WS_OVERLAPPEDWINDOW, WS_EX_WINDOWEDGE);
4274     check_window_style(WS_CHILD, 0, WS_CHILD, 0);
4275     check_window_style(WS_CHILD|WS_DLGFRAME, 0, WS_CHILD|WS_DLGFRAME, WS_EX_WINDOWEDGE);
4276     check_window_style(WS_CHILD|WS_THICKFRAME, 0, WS_CHILD|WS_THICKFRAME, WS_EX_WINDOWEDGE);
4277     check_window_style(WS_CHILD|WS_DLGFRAME, WS_EX_STATICEDGE, WS_CHILD|WS_DLGFRAME, WS_EX_STATICEDGE);
4278     check_window_style(WS_CHILD|WS_THICKFRAME, WS_EX_STATICEDGE, WS_CHILD|WS_THICKFRAME, WS_EX_STATICEDGE);
4279     check_window_style(WS_CHILD|WS_CAPTION, 0, WS_CHILD|WS_CAPTION, WS_EX_WINDOWEDGE);
4280     check_window_style(WS_CHILD|WS_CAPTION|WS_SYSMENU, 0, WS_CHILD|WS_CAPTION|WS_SYSMENU, WS_EX_WINDOWEDGE);
4281     check_window_style(WS_CHILD, WS_EX_WINDOWEDGE, WS_CHILD, 0);
4282     check_window_style(WS_CHILD, WS_EX_DLGMODALFRAME, WS_CHILD, WS_EX_WINDOWEDGE|WS_EX_DLGMODALFRAME);
4283     check_window_style(WS_CHILD, WS_EX_DLGMODALFRAME|WS_EX_STATICEDGE, WS_CHILD, WS_EX_STATICEDGE|WS_EX_WINDOWEDGE|WS_EX_DLGMODALFRAME);
4284     check_window_style(WS_CHILD|WS_POPUP, 0, WS_CHILD|WS_POPUP|WS_CLIPSIBLINGS, 0);
4285     check_window_style(WS_CHILD|WS_POPUP|WS_DLGFRAME, 0, WS_CHILD|WS_POPUP|WS_DLGFRAME|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE);
4286     check_window_style(WS_CHILD|WS_POPUP|WS_THICKFRAME, 0, WS_CHILD|WS_POPUP|WS_THICKFRAME|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE);
4287     check_window_style(WS_CHILD|WS_POPUP|WS_DLGFRAME, WS_EX_STATICEDGE, WS_CHILD|WS_POPUP|WS_DLGFRAME|WS_CLIPSIBLINGS, WS_EX_STATICEDGE);
4288     check_window_style(WS_CHILD|WS_POPUP|WS_THICKFRAME, WS_EX_STATICEDGE, WS_CHILD|WS_POPUP|WS_THICKFRAME|WS_CLIPSIBLINGS, WS_EX_STATICEDGE);
4289     check_window_style(WS_CHILD|WS_POPUP, WS_EX_APPWINDOW, WS_CHILD|WS_POPUP|WS_CLIPSIBLINGS, WS_EX_APPWINDOW);
4290     check_window_style(WS_CHILD|WS_POPUP, WS_EX_WINDOWEDGE, WS_CHILD|WS_POPUP|WS_CLIPSIBLINGS, 0);
4291     check_window_style(WS_CHILD, WS_EX_WINDOWEDGE, WS_CHILD, 0);
4292     check_window_style(0, WS_EX_TOOLWINDOW, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE|WS_EX_TOOLWINDOW);
4293     check_window_style(WS_POPUP, 0, WS_POPUP|WS_CLIPSIBLINGS, 0);
4294     check_window_style(WS_POPUP, WS_EX_WINDOWEDGE, WS_POPUP|WS_CLIPSIBLINGS, 0);
4295     check_window_style(WS_POPUP|WS_DLGFRAME, 0, WS_POPUP|WS_DLGFRAME|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE);
4296     check_window_style(WS_POPUP|WS_THICKFRAME, 0, WS_POPUP|WS_THICKFRAME|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE);
4297     check_window_style(WS_POPUP|WS_DLGFRAME, WS_EX_STATICEDGE, WS_POPUP|WS_DLGFRAME|WS_CLIPSIBLINGS, WS_EX_STATICEDGE);
4298     check_window_style(WS_POPUP|WS_THICKFRAME, WS_EX_STATICEDGE, WS_POPUP|WS_THICKFRAME|WS_CLIPSIBLINGS, WS_EX_STATICEDGE);
4299     check_window_style(WS_CAPTION, WS_EX_STATICEDGE, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_STATICEDGE|WS_EX_WINDOWEDGE);
4300     check_window_style(0, WS_EX_APPWINDOW, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_APPWINDOW|WS_EX_WINDOWEDGE);
4301 
4302     if (pGetLayeredWindowAttributes)
4303     {
4304         check_window_style(0, WS_EX_LAYERED, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_LAYERED|WS_EX_WINDOWEDGE);
4305         check_window_style(0, WS_EX_LAYERED|WS_EX_TRANSPARENT, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_LAYERED|WS_EX_TRANSPARENT|WS_EX_WINDOWEDGE);
4306         check_window_style(0, WS_EX_LAYERED|WS_EX_TRANSPARENT|WS_EX_TOOLWINDOW, WS_CLIPSIBLINGS|WS_CAPTION,
4307                                                       WS_EX_LAYERED|WS_EX_TRANSPARENT|WS_EX_TOOLWINDOW|WS_EX_WINDOWEDGE);
4308     }
4309 }
4310 
4311 static HWND root_dialog(HWND hwnd)
4312 {
4313     while ((GetWindowLongA(hwnd, GWL_EXSTYLE) & WS_EX_CONTROLPARENT) &&
4314            (GetWindowLongA(hwnd, GWL_STYLE) & (WS_CHILD|WS_POPUP)) == WS_CHILD)
4315     {
4316         HWND parent = GetParent(hwnd);
4317 
4318         /* simple detector for a window being a dialog */
4319         if (!DefDlgProcA(parent, DM_GETDEFID, 0, 0))
4320             break;
4321 
4322         hwnd = parent;
4323 
4324         if (!(GetWindowLongA(hwnd, GWL_STYLE) & DS_CONTROL))
4325             break;
4326     }
4327 
4328     return hwnd;
4329 }
4330 
4331 static INT_PTR WINAPI empty_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
4332 {
4333     return 0;
4334 }
4335 
4336 static LRESULT expected_id;
4337 
4338 static INT_PTR WINAPI empty_dlg_proc3(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
4339 {
4340     if (msg == WM_INITDIALOG)
4341     {
4342         HWND parent = GetParent(hwnd);
4343         LRESULT id, ret;
4344 
4345         id = DefDlgProcA(parent, DM_GETDEFID, 0, 0);
4346         if (!id || root_dialog(hwnd) == hwnd)
4347             parent = 0;
4348 
4349         id = DefDlgProcA(hwnd, DM_GETDEFID, 0, 0);
4350         if (!parent)
4351             ok(id == MAKELONG(IDOK,DC_HASDEFID), "expected (IDOK,DC_HASDEFID), got %08lx\n", id);
4352         else
4353             ok(id == expected_id, "expected %08lx, got %08lx\n", expected_id, id);
4354 
4355         ret = DefDlgProcA(hwnd, DM_SETDEFID, 0x3333, 0);
4356         ok(ret, "DefDlgProc(DM_SETDEFID) failed\n");
4357         id = DefDlgProcA(hwnd, DM_GETDEFID, 0, 0);
4358         ok(id == MAKELONG(0x3333,DC_HASDEFID), "expected (0x3333,DC_HASDEFID), got %08lx\n", id);
4359 
4360         if (parent)
4361         {
4362             id = DefDlgProcA(parent, DM_GETDEFID, 0, 0);
4363             ok(id == MAKELONG(0x3333,DC_HASDEFID), "expected (0x3333,DC_HASDEFID), got %08lx\n", id);
4364 
4365             expected_id = MAKELONG(0x3333,DC_HASDEFID);
4366         }
4367 
4368         EndDialog(hwnd, 0);
4369     }
4370 
4371     return 0;
4372 }
4373 
4374 struct dialog_param
4375 {
4376     HWND parent, grand_parent;
4377     DLGTEMPLATE *dlg_data;
4378 };
4379 
4380 static INT_PTR WINAPI empty_dlg_proc2(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
4381 {
4382     if (msg == WM_INITDIALOG)
4383     {
4384         DWORD style = GetWindowLongA(hwnd, GWL_STYLE);
4385         struct dialog_param *param = (struct dialog_param *)lparam;
4386         BOOL parent_is_child;
4387         HWND disabled_hwnd;
4388         LRESULT id, ret;
4389 
4390         id = DefDlgProcA(hwnd, DM_GETDEFID, 0, 0);
4391         ok(id == MAKELONG(IDOK,DC_HASDEFID), "expected (IDOK,DC_HASDEFID), got %08lx\n", id);
4392         ret = DefDlgProcA(hwnd, DM_SETDEFID, 0x2222, 0);
4393         ok(ret, "DefDlgProc(DM_SETDEFID) failed\n");
4394         id = DefDlgProcA(hwnd, DM_GETDEFID, 0, 0);
4395         ok(id == MAKELONG(0x2222,DC_HASDEFID), "expected (0x2222,DC_HASDEFID), got %08lx\n", id);
4396 
4397         expected_id = MAKELONG(0x2222,DC_HASDEFID);
4398 
4399         parent_is_child = (GetWindowLongA(param->parent, GWL_STYLE) & (WS_POPUP | WS_CHILD)) == WS_CHILD;
4400 
4401         ok(IsWindowEnabled(hwnd), "wrong state for %p\n", hwnd);
4402         if (parent_is_child)
4403         {
4404             ok(IsWindowEnabled(param->parent), "wrong state for %08x\n", style);
4405             disabled_hwnd = param->grand_parent;
4406         }
4407         else
4408         {
4409             ok(!IsWindowEnabled(param->parent), "wrong state for %08x\n", style);
4410             disabled_hwnd = param->parent;
4411         }
4412 
4413         if (param->grand_parent)
4414         {
4415             if (parent_is_child)
4416                 ok(!IsWindowEnabled(param->grand_parent), "wrong state for %08x\n", style);
4417             else
4418                 ok(IsWindowEnabled(param->grand_parent), "wrong state for %08x\n", style);
4419         }
4420 
4421         DialogBoxIndirectParamA(GetModuleHandleA(NULL), param->dlg_data, disabled_hwnd, empty_dlg_proc3, 0);
4422         ok(IsWindowEnabled(disabled_hwnd), "wrong state for %08x\n", style);
4423 
4424         ok(IsWindowEnabled(hwnd), "wrong state for %p\n", hwnd);
4425         ok(IsWindowEnabled(param->parent), "wrong state for %p\n", param->parent);
4426         if (param->grand_parent)
4427             ok(IsWindowEnabled(param->grand_parent), "wrong state for %p (%08x)\n", param->grand_parent, style);
4428 
4429         DialogBoxIndirectParamA(GetModuleHandleA(NULL), param->dlg_data, hwnd, empty_dlg_proc3, 0);
4430         ok(IsWindowEnabled(hwnd), "wrong state for %p\n", hwnd);
4431         ok(IsWindowEnabled(param->parent), "wrong state for %p\n", param->parent);
4432         if (param->grand_parent)
4433             ok(IsWindowEnabled(param->grand_parent), "wrong state for %p (%08x)\n", param->grand_parent, style);
4434 
4435         param->dlg_data->style |= WS_CHILD;
4436         DialogBoxIndirectParamA(GetModuleHandleA(NULL), param->dlg_data, hwnd, empty_dlg_proc3, 0);
4437         ok(IsWindowEnabled(hwnd), "wrong state for %p (%08x)\n", hwnd, style);
4438 
4439         param->dlg_data->style |= DS_CONTROL;
4440         DialogBoxIndirectParamA(GetModuleHandleA(NULL), param->dlg_data, hwnd, empty_dlg_proc3, 0);
4441         ok(IsWindowEnabled(hwnd), "wrong state for %p (%08x)\n", hwnd, style);
4442 
4443         param->dlg_data->dwExtendedStyle |= WS_EX_CONTROLPARENT;
4444         SetWindowLongA(hwnd, GWL_EXSTYLE, GetWindowLongA(hwnd, GWL_EXSTYLE) | WS_EX_CONTROLPARENT);
4445         SetWindowLongA(hwnd, GWL_STYLE, style & ~DS_CONTROL);
4446         param->dlg_data->style &= ~DS_CONTROL;
4447         DialogBoxIndirectParamA(GetModuleHandleA(NULL), param->dlg_data, hwnd, empty_dlg_proc3, 0);
4448         ok(IsWindowEnabled(hwnd), "wrong state for %p (%08x)\n", hwnd, style);
4449 
4450         SetWindowLongA(hwnd, GWL_STYLE, style | DS_CONTROL);
4451         DialogBoxIndirectParamA(GetModuleHandleA(NULL), param->dlg_data, hwnd, empty_dlg_proc3, 0);
4452         ok(IsWindowEnabled(hwnd), "wrong state for %p (%08x)\n", hwnd, style);
4453 
4454         param->dlg_data->style |= DS_CONTROL;
4455         DialogBoxIndirectParamA(GetModuleHandleA(NULL), param->dlg_data, hwnd, empty_dlg_proc3, 0);
4456         ok(IsWindowEnabled(hwnd), "wrong state for %p (%08x)\n", hwnd, style);
4457 
4458         EndDialog(hwnd, 0);
4459     }
4460     return 0;
4461 }
4462 
4463 static void check_dialog_style(DWORD style_in, DWORD ex_style_in, DWORD style_out, DWORD ex_style_out)
4464 {
4465     struct
4466     {
4467         DLGTEMPLATE dt;
4468         WORD menu_name;
4469         WORD class_id;
4470         WORD class_atom;
4471         WCHAR caption[1];
4472     } dlg_data;
4473     DWORD style, ex_style;
4474     HWND hwnd, grand_parent = 0, parent = 0;
4475     struct dialog_param param;
4476     LRESULT id, ret;
4477 
4478     if (style_in & WS_CHILD)
4479     {
4480         grand_parent = CreateWindowExA(0, "static", NULL, WS_OVERLAPPEDWINDOW,
4481                                 0, 0, 0, 0, NULL, NULL, NULL, NULL);
4482         ok(grand_parent != 0, "grand_parent creation failed\n");
4483     }
4484 
4485     parent = CreateWindowExA(0, "static", NULL, style_in,
4486                              0, 0, 0, 0, grand_parent, NULL, NULL, NULL);
4487     ok(parent != 0, "parent creation failed, style %#x\n", style_in);
4488 
4489     dlg_data.dt.style = style_in;
4490     dlg_data.dt.dwExtendedStyle = ex_style_in;
4491     dlg_data.dt.cdit = 0;
4492     dlg_data.dt.x = 0;
4493     dlg_data.dt.y = 0;
4494     dlg_data.dt.cx = 100;
4495     dlg_data.dt.cy = 100;
4496     dlg_data.menu_name = 0;
4497     dlg_data.class_id = 0;
4498     dlg_data.class_atom = 0;
4499     dlg_data.caption[0] = 0;
4500 
4501     hwnd = CreateDialogIndirectParamA(GetModuleHandleA(NULL), &dlg_data.dt, parent, empty_dlg_proc, 0);
4502     ok(hwnd != 0, "dialog creation failed, style %#x, exstyle %#x\n", style_in, ex_style_in);
4503 
4504     id = DefDlgProcA(hwnd, DM_GETDEFID, 0, 0);
4505     ok(id == MAKELONG(IDOK,DC_HASDEFID), "expected (IDOK,DC_HASDEFID), got %08lx\n", id);
4506     ret = DefDlgProcA(hwnd, DM_SETDEFID, 0x1111, 0);
4507     ok(ret, "DefDlgProc(DM_SETDEFID) failed\n");
4508     id = DefDlgProcA(hwnd, DM_GETDEFID, 0, 0);
4509     ok(id == MAKELONG(0x1111,DC_HASDEFID), "expected (0x1111,DC_HASDEFID), got %08lx\n", id);
4510 
4511     flush_events( TRUE );
4512 
4513     style = GetWindowLongA(hwnd, GWL_STYLE);
4514     ex_style = GetWindowLongA(hwnd, GWL_EXSTYLE);
4515     ok(style == (style_out | DS_3DLOOK), "got %#x\n", style);
4516     ok(ex_style == ex_style_out, "expected ex_style %#x, got %#x\n", ex_style_out, ex_style);
4517 
4518     ok(IsWindowEnabled(parent), "wrong parent state (dialog style %#x)\n", style_in);
4519 
4520     /* try setting the styles explicitly */
4521     SetWindowLongA(hwnd, GWL_EXSTYLE, ex_style_in);
4522     style = GetWindowLongA(hwnd, GWL_STYLE);
4523     ex_style = GetWindowLongA(hwnd, GWL_EXSTYLE);
4524     ok(style == (style_out | DS_3DLOOK), "got %#x\n", style);
4525     /* WS_EX_WINDOWEDGE can't always be changed */
4526     if (ex_style_in & WS_EX_DLGMODALFRAME)
4527         ex_style_out = ex_style_in | WS_EX_WINDOWEDGE;
4528     else if ((style & (WS_DLGFRAME | WS_THICKFRAME)) && !(ex_style_in & WS_EX_STATICEDGE))
4529         ex_style_out = ex_style_in | WS_EX_WINDOWEDGE;
4530     else
4531         ex_style_out = ex_style_in & ~WS_EX_WINDOWEDGE;
4532     ok(ex_style == ex_style_out, "expected ex_style %#x, got %#x\n", ex_style_out, ex_style);
4533 
4534     SetWindowLongA(hwnd, GWL_STYLE, style_in);
4535     style = GetWindowLongA(hwnd, GWL_STYLE);
4536     ex_style = GetWindowLongA(hwnd, GWL_EXSTYLE);
4537     /* WS_CLIPSIBLINGS can't be reset on top-level windows */
4538     if ((style_in & (WS_CHILD | WS_POPUP)) == WS_CHILD) style_out = style_in;
4539     else style_out = style_in | WS_CLIPSIBLINGS;
4540     ok(style == style_out, "expected style %#x, got %#x\n", style_out, style);
4541     /* WS_EX_WINDOWEDGE can't always be changed */
4542     if (ex_style_in & WS_EX_DLGMODALFRAME)
4543         ex_style_out = ex_style_in | WS_EX_WINDOWEDGE;
4544     else if ((style & (WS_DLGFRAME | WS_THICKFRAME)) && !(ex_style_in & WS_EX_STATICEDGE))
4545         ex_style_out = ex_style_in | WS_EX_WINDOWEDGE;
4546     else
4547         ex_style_out = ex_style_in & ~WS_EX_WINDOWEDGE;
4548     /* FIXME: Remove the condition below once Wine is fixed */
4549     todo_wine_if (ex_style != ex_style_out)
4550         ok(ex_style == ex_style_out, "expected ex_style %#x, got %#x\n", ex_style_out, ex_style);
4551 
4552     DestroyWindow(hwnd);
4553 
4554     param.parent = parent;
4555     param.grand_parent = grand_parent;
4556     param.dlg_data = &dlg_data.dt;
4557     DialogBoxIndirectParamA(GetModuleHandleA(NULL), &dlg_data.dt, parent, empty_dlg_proc2, (LPARAM)&param);
4558 
4559     ok(IsWindowEnabled(parent), "wrong parent state (dialog style %#x)\n", style_in);
4560     if (grand_parent)
4561         ok(IsWindowEnabled(grand_parent), "wrong grand parent state (dialog style %#x)\n", style_in);
4562 
4563     DestroyWindow(parent);
4564     DestroyWindow(grand_parent);
4565 }
4566 
4567 static void test_dialog_styles(void)
4568 {
4569     check_dialog_style(0, 0, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4570     check_dialog_style(WS_DLGFRAME, 0, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4571     check_dialog_style(WS_THICKFRAME, 0, WS_THICKFRAME|WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4572     check_dialog_style(WS_DLGFRAME, WS_EX_STATICEDGE, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE|WS_EX_STATICEDGE|WS_EX_CONTROLPARENT);
4573     check_dialog_style(WS_THICKFRAME, WS_EX_STATICEDGE, WS_THICKFRAME|WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE|WS_EX_STATICEDGE|WS_EX_CONTROLPARENT);
4574     check_dialog_style(DS_CONTROL, 0, WS_CLIPSIBLINGS|WS_CAPTION|DS_CONTROL, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4575     check_dialog_style(WS_CAPTION, 0, WS_CAPTION|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4576     check_dialog_style(WS_BORDER, 0, WS_CAPTION|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4577     check_dialog_style(WS_DLGFRAME, 0, WS_CAPTION|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4578     check_dialog_style(WS_BORDER|DS_CONTROL, 0, WS_CAPTION|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4579     check_dialog_style(WS_DLGFRAME|DS_CONTROL, 0, WS_CAPTION|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4580     check_dialog_style(WS_CAPTION|WS_SYSMENU, 0, WS_CAPTION|WS_SYSMENU|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4581     check_dialog_style(WS_SYSMENU, 0, WS_CAPTION|WS_SYSMENU|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4582     check_dialog_style(WS_CAPTION|DS_CONTROL, 0, WS_CAPTION|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4583     check_dialog_style(WS_SYSMENU|DS_CONTROL, 0, WS_CAPTION|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4584     check_dialog_style(WS_CAPTION|WS_SYSMENU|DS_CONTROL, 0, WS_CAPTION|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4585     check_dialog_style(WS_OVERLAPPEDWINDOW, 0, WS_CLIPSIBLINGS|WS_OVERLAPPEDWINDOW, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4586     check_dialog_style(WS_CHILD, 0, WS_CHILD, 0);
4587     check_dialog_style(WS_CHILD|WS_DLGFRAME, 0, WS_CHILD|WS_DLGFRAME, WS_EX_WINDOWEDGE);
4588     check_dialog_style(WS_CHILD|WS_THICKFRAME, 0, WS_CHILD|WS_THICKFRAME, WS_EX_WINDOWEDGE);
4589     check_dialog_style(WS_CHILD|WS_DLGFRAME, WS_EX_STATICEDGE, WS_CHILD|WS_DLGFRAME, WS_EX_STATICEDGE);
4590     check_dialog_style(WS_CHILD|WS_THICKFRAME, WS_EX_STATICEDGE, WS_CHILD|WS_THICKFRAME, WS_EX_STATICEDGE);
4591     check_dialog_style(WS_CHILD|DS_CONTROL, 0, WS_CHILD|DS_CONTROL, WS_EX_CONTROLPARENT);
4592     check_dialog_style(WS_CHILD|WS_CAPTION, 0, WS_CHILD|WS_CAPTION, WS_EX_WINDOWEDGE);
4593     check_dialog_style(WS_CHILD|WS_BORDER, 0, WS_CHILD|WS_BORDER, 0);
4594     check_dialog_style(WS_CHILD|WS_DLGFRAME, 0, WS_CHILD|WS_DLGFRAME, WS_EX_WINDOWEDGE);
4595     check_dialog_style(WS_CHILD|WS_BORDER|DS_CONTROL, 0, WS_CHILD|DS_CONTROL, WS_EX_CONTROLPARENT);
4596     check_dialog_style(WS_CHILD|WS_DLGFRAME|DS_CONTROL, 0, WS_CHILD|DS_CONTROL, WS_EX_CONTROLPARENT);
4597     check_dialog_style(WS_CHILD|WS_CAPTION|WS_SYSMENU, 0, WS_CHILD|WS_CAPTION|WS_SYSMENU, WS_EX_WINDOWEDGE);
4598     check_dialog_style(WS_CHILD|WS_SYSMENU, 0, WS_CHILD|WS_SYSMENU, 0);
4599     check_dialog_style(WS_CHILD|WS_CAPTION|DS_CONTROL, 0, WS_CHILD|DS_CONTROL, WS_EX_CONTROLPARENT);
4600     check_dialog_style(WS_CHILD|WS_SYSMENU|DS_CONTROL, 0, WS_CHILD|DS_CONTROL, WS_EX_CONTROLPARENT);
4601     check_dialog_style(WS_CHILD|WS_CAPTION|WS_SYSMENU|DS_CONTROL, 0, WS_CHILD|DS_CONTROL, WS_EX_CONTROLPARENT);
4602     check_dialog_style(WS_CHILD, WS_EX_WINDOWEDGE, WS_CHILD, 0);
4603     check_dialog_style(WS_CHILD, WS_EX_DLGMODALFRAME, WS_CHILD, WS_EX_WINDOWEDGE|WS_EX_DLGMODALFRAME);
4604     check_dialog_style(WS_CHILD, WS_EX_DLGMODALFRAME|WS_EX_STATICEDGE, WS_CHILD, WS_EX_STATICEDGE|WS_EX_WINDOWEDGE|WS_EX_DLGMODALFRAME);
4605     check_dialog_style(WS_CHILD|WS_POPUP, 0, WS_CHILD|WS_POPUP|WS_CLIPSIBLINGS, 0);
4606     check_dialog_style(WS_CHILD|WS_POPUP|WS_DLGFRAME, 0, WS_CHILD|WS_POPUP|WS_DLGFRAME|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE);
4607     check_dialog_style(WS_CHILD|WS_POPUP|WS_THICKFRAME, 0, WS_CHILD|WS_POPUP|WS_THICKFRAME|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE);
4608     check_dialog_style(WS_CHILD|WS_POPUP|WS_DLGFRAME, WS_EX_STATICEDGE, WS_CHILD|WS_POPUP|WS_DLGFRAME|WS_CLIPSIBLINGS, WS_EX_STATICEDGE);
4609     check_dialog_style(WS_CHILD|WS_POPUP|WS_THICKFRAME, WS_EX_STATICEDGE, WS_CHILD|WS_POPUP|WS_THICKFRAME|WS_CLIPSIBLINGS, WS_EX_STATICEDGE);
4610     check_dialog_style(WS_CHILD|WS_POPUP|DS_CONTROL, 0, WS_CHILD|WS_POPUP|WS_CLIPSIBLINGS|DS_CONTROL, WS_EX_CONTROLPARENT);
4611     check_dialog_style(WS_CHILD|WS_POPUP|WS_CAPTION, 0, WS_CHILD|WS_POPUP|WS_CAPTION|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE);
4612     check_dialog_style(WS_CHILD|WS_POPUP|WS_BORDER, 0, WS_CHILD|WS_POPUP|WS_BORDER|WS_CLIPSIBLINGS, 0);
4613     check_dialog_style(WS_CHILD|WS_POPUP|WS_DLGFRAME, 0, WS_CHILD|WS_POPUP|WS_DLGFRAME|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE);
4614     check_dialog_style(WS_CHILD|WS_POPUP|WS_BORDER|DS_CONTROL, 0, WS_CHILD|WS_POPUP|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT);
4615     check_dialog_style(WS_CHILD|WS_POPUP|WS_DLGFRAME|DS_CONTROL, 0, WS_CHILD|WS_POPUP|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT);
4616     check_dialog_style(WS_CHILD|WS_POPUP|WS_CAPTION|WS_SYSMENU, 0, WS_CHILD|WS_POPUP|WS_CAPTION|WS_SYSMENU|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE);
4617     check_dialog_style(WS_CHILD|WS_POPUP|WS_SYSMENU, 0, WS_CHILD|WS_POPUP|WS_SYSMENU|WS_CLIPSIBLINGS, 0);
4618     check_dialog_style(WS_CHILD|WS_POPUP|WS_CAPTION|DS_CONTROL, 0, WS_CHILD|WS_POPUP|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT);
4619     check_dialog_style(WS_CHILD|WS_POPUP|WS_SYSMENU|DS_CONTROL, 0, WS_CHILD|WS_POPUP|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT);
4620     check_dialog_style(WS_CHILD|WS_POPUP|WS_CAPTION|WS_SYSMENU|DS_CONTROL, 0, WS_CHILD|WS_POPUP|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT);
4621     check_dialog_style(WS_CHILD|WS_POPUP, WS_EX_APPWINDOW, WS_CHILD|WS_POPUP|WS_CLIPSIBLINGS, WS_EX_APPWINDOW);
4622     check_dialog_style(WS_CHILD|WS_POPUP, WS_EX_WINDOWEDGE, WS_CHILD|WS_POPUP|WS_CLIPSIBLINGS, 0);
4623     check_dialog_style(WS_CHILD, WS_EX_WINDOWEDGE, WS_CHILD, 0);
4624     check_dialog_style(0, WS_EX_TOOLWINDOW, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE|WS_EX_TOOLWINDOW|WS_EX_CONTROLPARENT);
4625     check_dialog_style(WS_POPUP, 0, WS_POPUP|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT);
4626     check_dialog_style(WS_POPUP, WS_EX_WINDOWEDGE, WS_POPUP|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT);
4627     check_dialog_style(WS_POPUP|WS_DLGFRAME, 0, WS_POPUP|WS_DLGFRAME|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4628     check_dialog_style(WS_POPUP|WS_THICKFRAME, 0, WS_POPUP|WS_THICKFRAME|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4629     check_dialog_style(WS_POPUP|WS_DLGFRAME, WS_EX_STATICEDGE, WS_POPUP|WS_DLGFRAME|WS_CLIPSIBLINGS, WS_EX_STATICEDGE|WS_EX_CONTROLPARENT);
4630     check_dialog_style(WS_POPUP|WS_THICKFRAME, WS_EX_STATICEDGE, WS_POPUP|WS_THICKFRAME|WS_CLIPSIBLINGS, WS_EX_STATICEDGE|WS_EX_CONTROLPARENT);
4631     check_dialog_style(WS_POPUP|DS_CONTROL, 0, WS_POPUP|WS_CLIPSIBLINGS|DS_CONTROL, WS_EX_CONTROLPARENT);
4632     check_dialog_style(WS_POPUP|WS_CAPTION, 0, WS_POPUP|WS_CAPTION|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4633     check_dialog_style(WS_POPUP|WS_BORDER, 0, WS_POPUP|WS_BORDER|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT);
4634     check_dialog_style(WS_POPUP|WS_DLGFRAME, 0, WS_POPUP|WS_DLGFRAME|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4635     check_dialog_style(WS_POPUP|WS_BORDER|DS_CONTROL, 0, WS_POPUP|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT);
4636     check_dialog_style(WS_POPUP|WS_DLGFRAME|DS_CONTROL, 0, WS_POPUP|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT);
4637     check_dialog_style(WS_POPUP|WS_CAPTION|WS_SYSMENU, 0, WS_POPUP|WS_CAPTION|WS_SYSMENU|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4638     check_dialog_style(WS_POPUP|WS_SYSMENU, 0, WS_POPUP|WS_SYSMENU|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT);
4639     check_dialog_style(WS_POPUP|WS_CAPTION|DS_CONTROL, 0, WS_POPUP|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT);
4640     check_dialog_style(WS_POPUP|WS_SYSMENU|DS_CONTROL, 0, WS_POPUP|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT);
4641     check_dialog_style(WS_POPUP|WS_CAPTION|WS_SYSMENU|DS_CONTROL, 0, WS_POPUP|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT);
4642     check_dialog_style(WS_CAPTION, WS_EX_STATICEDGE, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_STATICEDGE|WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4643     check_dialog_style(0, WS_EX_APPWINDOW, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_APPWINDOW|WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4644 
4645     if (pGetLayeredWindowAttributes)
4646     {
4647         check_dialog_style(0, WS_EX_LAYERED, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_LAYERED|WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4648         check_dialog_style(0, WS_EX_LAYERED|WS_EX_TRANSPARENT, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_LAYERED|WS_EX_TRANSPARENT|WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4649         check_dialog_style(0, WS_EX_LAYERED|WS_EX_TRANSPARENT|WS_EX_TOOLWINDOW, WS_CLIPSIBLINGS|WS_CAPTION,
4650                               WS_EX_LAYERED|WS_EX_TRANSPARENT|WS_EX_TOOLWINDOW|WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4651     }
4652 }
4653 
4654 struct dlg_parent_param
4655 {
4656     HWND ga_parent;
4657     HWND gwl_parent;
4658     HWND get_parent;
4659     HWND owner;
4660     HWND root;
4661     HWND ga_root_owner;
4662 };
4663 
4664 static INT_PTR WINAPI parent_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
4665 {
4666     if (msg == WM_INITDIALOG) {
4667         struct dlg_parent_param *param = (void*)lparam;
4668         check_parents(hwnd, param->ga_parent, param->gwl_parent, param->get_parent, param->owner,
4669                       param->root ? param->root : hwnd, param->ga_root_owner ? param->ga_root_owner : hwnd);
4670 
4671         ok(!IsWindowEnabled(param->gwl_parent), "parent is not disabled\n");
4672         EndDialog(hwnd, 2);
4673         ok(IsWindowEnabled(param->gwl_parent), "parent is not enabled\n");
4674     }
4675 
4676     return 0;
4677 }
4678 
4679 static INT_PTR WINAPI reparent_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
4680 {
4681     if (msg == WM_INITDIALOG) {
4682         ok(!IsWindowEnabled(GetParent(hwnd)), "parent is not disabled\n");
4683         SetParent(hwnd, (HWND)lparam);
4684     }
4685 
4686     return 0;
4687 }
4688 
4689 static INT_PTR WINAPI reparent_owned_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
4690 {
4691     if (msg == WM_INITDIALOG) {
4692         HWND new_parent = (HWND)lparam;
4693         HWND owner = GetWindow(hwnd, GW_OWNER);
4694         ok(!IsWindowEnabled(owner), "owner is not disabled\n");
4695         SetWindowLongA(hwnd, GWL_STYLE, GetWindowLongA(hwnd, GWL_STYLE) | WS_CHILD);
4696         SetParent(hwnd, new_parent);
4697         ok(GetParent(hwnd) == new_parent, "GetParent(hwnd) = %p, expected %p\n", GetParent(hwnd), new_parent);
4698         PostMessageA(hwnd, WM_QUIT, 0, 0);
4699     }
4700 
4701     return 0;
4702 }
4703 
4704 static LRESULT WINAPI reparent_dialog_owner_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
4705 {
4706     if (msg == WM_ENTERIDLE) {
4707         HWND dialog = (HWND)lparam;
4708         HWND owner = GetParent(dialog);
4709         /* EndDialog will enable owner */
4710         EnableWindow(owner, FALSE);
4711         EndDialog(dialog, 2);
4712         ok(IsWindowEnabled(owner), "owner is not enabled\n");
4713         /* ...but it won't be enabled on dialog exit */
4714         EnableWindow(owner, FALSE);
4715     }
4716     return DefWindowProcA( hwnd, msg, wparam, lparam );
4717 }
4718 
4719 static LRESULT WINAPI post_quit_dialog_owner_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
4720 {
4721     if (msg == WM_ENTERIDLE) {
4722         HWND dialog = (HWND)lparam;
4723         PostMessageA(dialog, WM_QUIT, 0, 0);
4724     }
4725     return DefWindowProcA( hwnd, msg, wparam, lparam );
4726 }
4727 
4728 static LRESULT WINAPI destroy_dialog_owner_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
4729 {
4730     if (msg == WM_ENTERIDLE) {
4731         HWND dialog = (HWND)lparam;
4732         DestroyWindow(dialog);
4733     }
4734     return DefWindowProcA( hwnd, msg, wparam, lparam );
4735 }
4736 
4737 static void test_dialog_parent(void)
4738 {
4739     HWND dialog, parent, child, child2, other, desktop = GetDesktopWindow();
4740     struct dlg_parent_param param;
4741     INT_PTR ret;
4742     struct
4743     {
4744         DLGTEMPLATE dt;
4745         WORD menu_name;
4746         WORD class_id;
4747         WORD class_atom;
4748         WCHAR caption[1];
4749     } dlg_data;
4750 
4751     dlg_data.dt.dwExtendedStyle = 0;
4752     dlg_data.dt.cdit = 0;
4753     dlg_data.dt.x = 0;
4754     dlg_data.dt.y = 0;
4755     dlg_data.dt.cx = 100;
4756     dlg_data.dt.cy = 100;
4757     dlg_data.menu_name = 0;
4758     dlg_data.class_id = 0;
4759     dlg_data.class_atom = 0;
4760     dlg_data.caption[0] = 0;
4761 
4762     parent = CreateWindowExA(0, "static", NULL, WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
4763     /* Create a child without WS_CHILD flag. It's a valid owner window. */
4764     child = CreateWindowExA(0, "static", NULL, WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
4765     SetParent(child, parent);
4766     /* Regular child. If passed as an owner, its parent will be true owner window. */
4767     child2 = CreateWindowExA(0, "static", NULL, WS_CHILD, 0, 0, 0, 0, child, NULL, NULL, NULL);
4768 
4769     trace("parent %p child %p child2 %p desktop %p\n", parent, child, child2, desktop);
4770 
4771     /* When dialog is created with WS_CHILD style, its parent depends on function used to create it. */
4772     dlg_data.dt.style = WS_CHILD;
4773 
4774     /* CreateDialogIndirectParam uses passed parent as dialog parent. */
4775     dialog = CreateDialogIndirectParamA(GetModuleHandleA(NULL), &dlg_data.dt, child2, empty_dlg_proc, 0);
4776     ok(dialog != 0, "dialog creation failed\n");
4777     check_parents(dialog, child2, child2, child2, NULL, parent, child);
4778 
4779     ok(IsWindowEnabled(child2), "child2 is disabled\n");
4780     EnableWindow(child2, FALSE);
4781     EndDialog(dialog, 0);
4782     ok(IsWindowEnabled(child2), "child2 is not enabled\n");
4783     DestroyWindow(dialog);
4784 
4785     /* DialogBoxIndirectParam uses the first parent of passed owner that's not a child window as dialog
4786      * parent (like in case of dialog with owner). */
4787     param.ga_parent = param.gwl_parent = param.get_parent = child;
4788     param.owner = NULL;
4789     param.root = parent;
4790     param.ga_root_owner = child;
4791     ret = DialogBoxIndirectParamA(GetModuleHandleA(NULL), &dlg_data.dt, child2, parent_dlg_proc, (LPARAM)&param);
4792     ok(ret == 2, "DialogBoxIndirectParam returned %ld\n", ret);
4793 
4794     /* Dialogs without WS_CHILD behave as expected, they use passed owner just like CreateWindow does. */
4795     dlg_data.dt.style = WS_OVERLAPPEDWINDOW;
4796 
4797     dialog = CreateDialogIndirectParamA(GetModuleHandleA(NULL), &dlg_data.dt, child2, empty_dlg_proc, 0);
4798     ok(dialog != 0, "dialog creation failed\n");
4799     check_parents(dialog, desktop, child, NULL, child, dialog, dialog);
4800 
4801     ok(IsWindowEnabled(child), "child is disabled\n");
4802     EnableWindow(child, FALSE);
4803     EndDialog(dialog, 0);
4804     ok(IsWindowEnabled(child), "child is not enabled\n");
4805     DestroyWindow(dialog);
4806 
4807     param.ga_parent = desktop;
4808     param.gwl_parent = child;
4809     param.get_parent = NULL;
4810     param.owner = child;
4811     param.root = param.ga_root_owner = NULL;
4812     ret = DialogBoxIndirectParamA(GetModuleHandleA(NULL), &dlg_data.dt, child2, parent_dlg_proc, (LPARAM)&param);
4813     ok(ret == 2, "DialogBoxIndirectParam returned %ld\n", ret);
4814 
4815     other = CreateWindowExA(0, "static", NULL, WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
4816     SetWindowLongPtrA(child, GWLP_WNDPROC, (ULONG_PTR)reparent_dialog_owner_proc);
4817 
4818     /* When dialog is created with WS_CHILD|WS_POPUP style, we have an owner. */
4819     dlg_data.dt.style = WS_CHILD|WS_POPUP;
4820 
4821     dialog = CreateDialogIndirectParamA(GetModuleHandleA(NULL), &dlg_data.dt, child2, empty_dlg_proc, 0);
4822     ok(dialog != 0, "dialog creation failed\n");
4823     check_parents(dialog, desktop, child, child, child, dialog, child);
4824 
4825     ok(IsWindowEnabled(child), "child is disabled\n");
4826     EnableWindow(child, FALSE);
4827     EndDialog(dialog, 0);
4828     ok(IsWindowEnabled(child), "child is not enabled\n");
4829     DestroyWindow(dialog);
4830 
4831     param.ga_parent = desktop;
4832     param.gwl_parent = param.get_parent = child;
4833     param.owner = child;
4834     param.root = NULL;
4835     param.ga_root_owner = child;
4836     ret = DialogBoxIndirectParamA(GetModuleHandleA(NULL), &dlg_data.dt, child2, parent_dlg_proc, (LPARAM)&param);
4837     ok(ret == 2, "DialogBoxIndirectParam returned %ld\n", ret);
4838 
4839     /* If we change parent in WM_INITDIALOG for WS_CHILD dialog WM_ENTERIDLE is still sent to the original
4840      * parent. EndDialog will enable the new parent. */
4841     EnableWindow(child, TRUE);
4842     EnableWindow(other, FALSE);
4843     dlg_data.dt.style = WS_CHILD;
4844     ret = DialogBoxIndirectParamA(GetModuleHandleA(NULL), &dlg_data.dt, child2, reparent_dlg_proc, (LPARAM)other);
4845     ok(ret == 2, "DialogBoxIndirectParam returned %ld\n", ret);
4846     ok(!IsWindowEnabled(other), "other is not disabled\n");
4847     ok(!IsWindowEnabled(child), "child is not disabled\n");
4848     ok(IsWindowEnabled(child2), "child2 is not enabled\n");
4849     EnableWindow(child, TRUE);
4850 
4851     /* If we change parent and style in WM_INITDIALOG for dialog with an owner to make it true child
4852      * (thus GetParent() will return the new parent instead of an owner), WM_ENTERIDLE is still sent
4853      * to the original parent. EndDialog will enable the new parent. */
4854     EnableWindow(other, FALSE);
4855     dlg_data.dt.style = WS_OVERLAPPED;
4856     ret = DialogBoxIndirectParamA(GetModuleHandleA(NULL), &dlg_data.dt, child2, reparent_owned_dlg_proc, (LPARAM)other);
4857     ok(ret == 1, "DialogBoxIndirectParam returned %ld\n", ret);
4858     ok(!IsWindowEnabled(other), "other is not disabled\n");
4859     ok(!IsWindowEnabled(child), "child is not disabled\n");
4860     ok(IsWindowEnabled(child2), "child2 is not enabled\n");
4861     EnableWindow(child, TRUE);
4862     EnableWindow(other, TRUE);
4863 
4864     /* Quit dialog message loop by sending WM_QUIT message. Dialog owner is not enabled. */
4865     SetWindowLongPtrA(child, GWLP_WNDPROC, (ULONG_PTR)post_quit_dialog_owner_proc);
4866     ret = DialogBoxIndirectParamA(GetModuleHandleA(NULL), &dlg_data.dt, other, empty_dlg_proc, 0);
4867     ok(ret == 1, "DialogBoxIndirectParam returned %ld\n", ret);
4868     ok(!IsWindowEnabled(other), "other is enabled\n");
4869     EnableWindow(other, TRUE);
4870 
4871     /* Quit dialog message loop by destroying the window. Dialog owner is not enabled. */
4872     SetWindowLongPtrA(child, GWLP_WNDPROC, (ULONG_PTR)destroy_dialog_owner_proc);
4873     ret = DialogBoxIndirectParamA(GetModuleHandleA(NULL), &dlg_data.dt, other, empty_dlg_proc, 0);
4874     ok(ret == 1, "DialogBoxIndirectParam returned %ld\n", ret);
4875     ok(!IsWindowEnabled(other), "other is enabled\n");
4876     EnableWindow(other, TRUE);
4877 
4878     DestroyWindow(parent);
4879 }
4880 
4881 static void test_scrollwindow( HWND hwnd)
4882 {
4883     HDC hdc;
4884     RECT rc, rc2, rc3;
4885     COLORREF colr;
4886 
4887     ShowWindow( hwnd, SW_SHOW);
4888     UpdateWindow( hwnd);
4889     flush_events( TRUE );
4890     GetClientRect( hwnd, &rc);
4891     hdc = GetDC( hwnd);
4892     /* test ScrollWindow(Ex) with no clip rectangle */
4893     /* paint the lower half of the window black */
4894     rc2 = rc;
4895     rc2.top = ( rc2.top + rc2.bottom) / 2;
4896     FillRect( hdc, &rc2, GetStockObject(BLACK_BRUSH));
4897     /* paint the upper half of the window white */
4898     rc2.bottom = rc2.top;
4899     rc2.top =0;
4900     FillRect( hdc, &rc2, GetStockObject(WHITE_BRUSH));
4901     /* scroll lower half up */
4902     rc2 = rc;
4903     rc2.top = ( rc2.top + rc2.bottom) / 2;
4904     ScrollWindowEx( hwnd, 0, - rc2.top, &rc2, NULL, NULL, NULL, SW_ERASE);
4905     flush_events(FALSE);
4906     /* expected: black should have scrolled to the upper half */
4907     colr = GetPixel( hdc, (rc2.left+rc2.right)/ 2,  rc2.bottom / 4 );
4908     ok ( colr == 0, "pixel should be black, color is %08x\n", colr);
4909     /* Repeat that test of ScrollWindow(Ex) now with clip rectangle */
4910     /* paint the lower half of the window black */
4911     rc2 = rc;
4912     rc2.top = ( rc2.top + rc2.bottom) / 2;
4913     FillRect( hdc, &rc2, GetStockObject(BLACK_BRUSH));
4914     /* paint the upper half of the window white */
4915     rc2.bottom = rc2.top;
4916     rc2.top =0;
4917     FillRect( hdc, &rc2, GetStockObject(WHITE_BRUSH));
4918     /* scroll lower half up */
4919     rc2 = rc;
4920     rc2.top = ( rc2.top + rc2.bottom) / 2;
4921     rc3 = rc;
4922     rc3.left = rc3.right / 4;
4923     rc3.right -= rc3.right / 4;
4924     ScrollWindowEx( hwnd, 0, - rc2.top, &rc2, &rc3, NULL, NULL, SW_ERASE);
4925     flush_events(FALSE);
4926     /* expected: black should have scrolled to the upper half */
4927     colr = GetPixel( hdc, (rc2.left+rc2.right)/ 2,  rc2.bottom / 4 );
4928     ok ( colr == 0, "pixel should be black, color is %08x\n", colr);
4929 
4930     /* clean up */
4931     ReleaseDC( hwnd, hdc);
4932 }
4933 
4934 static void test_scrollvalidate( HWND parent)
4935 {
4936     HDC hdc;
4937     HRGN hrgn=CreateRectRgn(0,0,0,0);
4938     HRGN exprgn, tmprgn, clipping;
4939     RECT rc, rcu, cliprc;
4940     /* create two overlapping child windows. The visual region
4941      * of hwnd1 is clipped by the overlapping part of
4942      * hwnd2 because of the WS_CLIPSIBLING style */
4943     HWND hwnd1, hwnd2;
4944 
4945     clipping = CreateRectRgn(0,0,0,0);
4946     tmprgn = CreateRectRgn(0,0,0,0);
4947     exprgn = CreateRectRgn(0,0,0,0);
4948     hwnd2 = CreateWindowExA(0, "static", NULL,
4949             WS_CHILD| WS_VISIBLE | WS_CLIPSIBLINGS | WS_BORDER ,
4950             75, 30, 100, 100, parent, 0, 0, NULL);
4951     hwnd1 = CreateWindowExA(0, "static", NULL,
4952             WS_CHILD| WS_VISIBLE | WS_CLIPSIBLINGS | WS_BORDER ,
4953             25, 50, 100, 100, parent, 0, 0, NULL);
4954     ShowWindow( parent, SW_SHOW);
4955     UpdateWindow( parent);
4956     GetClientRect( hwnd1, &rc);
4957     cliprc=rc;
4958     SetRectRgn( clipping, 10, 10, 90, 90);
4959     hdc = GetDC( hwnd1);
4960     /* for a visual touch */
4961     TextOutA( hdc, 0,10, "0123456789", 10);
4962     ScrollDC( hdc, -10, -5, &rc, &cliprc, hrgn, &rcu);
4963     if (winetest_debug > 0) dump_region(hrgn);
4964     /* create a region with what is expected */
4965     SetRectRgn( exprgn, 39,0,49,74);
4966     SetRectRgn( tmprgn, 88,79,98,93);
4967     CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
4968     SetRectRgn( tmprgn, 0,93,98,98);
4969     CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
4970     ok( EqualRgn( exprgn, hrgn), "wrong update region\n");
4971     trace("update rect is %s\n", wine_dbgstr_rect(&rcu));
4972     /* now with clipping region */
4973     SelectClipRgn( hdc, clipping);
4974     ScrollDC( hdc, -10, -5, &rc, &cliprc, hrgn, &rcu);
4975     if (winetest_debug > 0) dump_region(hrgn);
4976     /* create a region with what is expected */
4977     SetRectRgn( exprgn, 39,10,49,74);
4978     SetRectRgn( tmprgn, 80,79,90,85);
4979     CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
4980     SetRectRgn( tmprgn, 10,85,90,90);
4981     CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
4982     ok( EqualRgn( exprgn, hrgn), "wrong update region\n");
4983     trace("update rect is %s\n", wine_dbgstr_rect(&rcu));
4984     ReleaseDC( hwnd1, hdc);
4985 
4986     /* test scrolling a rect by more than its size */
4987     DestroyWindow( hwnd2);
4988     ValidateRect( hwnd1, NULL);
4989     SetRect( &rc, 40,40, 50,50);
4990     InvalidateRect( hwnd1, &rc, 1);
4991     ScrollWindowEx( hwnd1, -20, 0, &rc, NULL, hrgn, &rcu,
4992       SW_SCROLLCHILDREN | SW_INVALIDATE);
4993     if (winetest_debug > 0) dump_region(hrgn);
4994     SetRectRgn( exprgn, 20, 40, 30, 50);
4995     SetRectRgn( tmprgn, 40, 40, 50, 50);
4996     CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
4997     ok( EqualRgn( exprgn, hrgn), "wrong update region\n");
4998     ok( rcu.left == 20 && rcu.top == 40 && rcu.right == 50 && rcu.bottom == 50,
4999         "unexpected update rect: %s\n", wine_dbgstr_rect(&rcu));
5000 
5001     /* test scrolling a window with an update region */
5002     ValidateRect( hwnd1, NULL);
5003     SetRect( &rc, 40,40, 50,50);
5004     InvalidateRect( hwnd1, &rc, 1);
5005     GetClientRect( hwnd1, &rc);
5006     cliprc=rc;
5007     ScrollWindowEx( hwnd1, -10, 0, &rc, &cliprc, hrgn, &rcu,
5008       SW_SCROLLCHILDREN | SW_INVALIDATE);
5009     if (winetest_debug > 0) dump_region(hrgn);
5010     SetRectRgn( exprgn, 88,0,98,98);
5011     SetRectRgn( tmprgn, 30, 40, 50, 50);
5012     CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
5013     ok( EqualRgn( exprgn, hrgn), "wrong update region\n");
5014 
5015     /* clear an update region */
5016     UpdateWindow( hwnd1 );
5017 
5018     SetRect( &rc, 0,40, 100,60);
5019     SetRect( &cliprc, 0,0, 100,100);
5020     ScrollWindowEx( hwnd1, 0, -25, &rc, &cliprc, hrgn, &rcu, SW_INVALIDATE);
5021     if (winetest_debug > 0) dump_region( hrgn );
5022     SetRectRgn( exprgn, 0, 40, 98, 60 );
5023     ok( EqualRgn( exprgn, hrgn), "wrong update region in excessive scroll\n");
5024 
5025     /* now test ScrollWindowEx with a combination of
5026      * WS_CLIPCHILDREN style and SW_SCROLLCHILDREN flag */
5027     /* make hwnd2 the child of hwnd1 */
5028     hwnd2 = CreateWindowExA(0, "static", NULL,
5029             WS_CHILD| WS_VISIBLE | WS_BORDER ,
5030             50, 50, 100, 100, hwnd1, 0, 0, NULL);
5031     SetWindowLongA( hwnd1, GWL_STYLE, GetWindowLongA( hwnd1, GWL_STYLE) & ~WS_CLIPSIBLINGS);
5032     GetClientRect( hwnd1, &rc);
5033     cliprc=rc;
5034 
5035     /* WS_CLIPCHILDREN and SW_SCROLLCHILDREN */
5036     SetWindowLongA( hwnd1, GWL_STYLE, GetWindowLongA( hwnd1, GWL_STYLE) | WS_CLIPCHILDREN );
5037     ValidateRect( hwnd1, NULL);
5038     ValidateRect( hwnd2, NULL);
5039     ScrollWindowEx( hwnd1, -10, -10, &rc, &cliprc, hrgn, &rcu,
5040       SW_SCROLLCHILDREN | SW_INVALIDATE);
5041     if (winetest_debug > 0) dump_region(hrgn);
5042     SetRectRgn( exprgn, 88,0,98,88);
5043     SetRectRgn( tmprgn, 0,88,98,98);
5044     CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
5045     ok( EqualRgn( exprgn, hrgn), "wrong update region\n");
5046 
5047     /* SW_SCROLLCHILDREN */
5048     SetWindowLongA( hwnd1, GWL_STYLE, GetWindowLongA( hwnd1, GWL_STYLE) & ~WS_CLIPCHILDREN );
5049     ValidateRect( hwnd1, NULL);
5050     ValidateRect( hwnd2, NULL);
5051     ScrollWindowEx( hwnd1, -10, -10, &rc, &cliprc, hrgn, &rcu, SW_SCROLLCHILDREN | SW_INVALIDATE);
5052     if (winetest_debug > 0) dump_region(hrgn);
5053     /* expected region is the same as in previous test */
5054     ok( EqualRgn( exprgn, hrgn), "wrong update region\n");
5055 
5056     /* no SW_SCROLLCHILDREN */
5057     SetWindowLongA( hwnd1, GWL_STYLE, GetWindowLongA( hwnd1, GWL_STYLE) & ~WS_CLIPCHILDREN );
5058     ValidateRect( hwnd1, NULL);
5059     ValidateRect( hwnd2, NULL);
5060     ScrollWindowEx( hwnd1, -10, -10, &rc, &cliprc, hrgn, &rcu, SW_INVALIDATE);
5061     if (winetest_debug > 0) dump_region(hrgn);
5062     /* expected region is the same as in previous test */
5063     ok( EqualRgn( exprgn, hrgn), "wrong update region\n");
5064 
5065     /* WS_CLIPCHILDREN and no SW_SCROLLCHILDREN */
5066     SetWindowLongA( hwnd1, GWL_STYLE, GetWindowLongA( hwnd1, GWL_STYLE) | WS_CLIPCHILDREN );
5067     ValidateRect( hwnd1, NULL);
5068     ValidateRect( hwnd2, NULL);
5069     ScrollWindowEx( hwnd1, -10, -10, &rc, &cliprc, hrgn, &rcu, SW_INVALIDATE);
5070     if (winetest_debug > 0) dump_region(hrgn);
5071     SetRectRgn( exprgn, 88,0,98,20);
5072     SetRectRgn( tmprgn, 20,20,98,30);
5073     CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
5074     SetRectRgn( tmprgn, 20,30,30,88);
5075     CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
5076     SetRectRgn( tmprgn, 0,88,30,98);
5077     CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
5078     ok( EqualRgn( exprgn, hrgn), "wrong update region\n");
5079 
5080     /* clean up */
5081     DeleteObject( hrgn);
5082     DeleteObject( exprgn);
5083     DeleteObject( tmprgn);
5084     DestroyWindow( hwnd1);
5085     DestroyWindow( hwnd2);
5086 }
5087 
5088 /* couple of tests of return values of scrollbar functions
5089  * called on a scrollbarless window */
5090 static void test_scroll(void)
5091 {
5092     BOOL ret;
5093     INT min, max;
5094     SCROLLINFO si;
5095     HWND hwnd = CreateWindowExA(0, "Static", "Wine test window",
5096         WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP,
5097         100, 100, 200, 200, 0, 0, 0, NULL);
5098     /* horizontal */
5099     ret = GetScrollRange( hwnd, SB_HORZ, &min, &max);
5100     if (!ret)  /* win9x */
5101     {
5102         win_skip( "GetScrollRange doesn't work\n" );
5103         DestroyWindow( hwnd);
5104         return;
5105     }
5106     ok( min == 0, "minimum scroll pos is %d (should be zero)\n", min);
5107     ok( max == 0, "maximum scroll pos is %d (should be zero)\n", min);
5108     si.cbSize = sizeof( si);
5109     si.fMask = SIF_PAGE;
5110     si.nPage = 0xdeadbeef;
5111     ret = GetScrollInfo( hwnd, SB_HORZ, &si);
5112     ok( !ret, "GetScrollInfo returns %d (should be zero)\n", ret);
5113     ok( si.nPage == 0xdeadbeef, "unexpected value for nPage is %d\n", si.nPage);
5114     /* vertical */
5115     ret = GetScrollRange( hwnd, SB_VERT, &min, &max);
5116     ok( ret, "GetScrollRange returns FALSE\n");
5117     ok( min == 0, "minimum scroll pos is %d (should be zero)\n", min);
5118     ok( max == 0, "maximum scroll pos is %d (should be zero)\n", min);
5119     si.cbSize = sizeof( si);
5120     si.fMask = SIF_PAGE;
5121     si.nPage = 0xdeadbeef;
5122     ret = GetScrollInfo( hwnd, SB_VERT, &si);
5123     ok( !ret, "GetScrollInfo returns %d (should be zero)\n", ret);
5124     ok( si.nPage == 0xdeadbeef, "unexpected value for nPage is %d\n", si.nPage);
5125     /* clean up */
5126     DestroyWindow( hwnd);
5127 }
5128 
5129 static void test_scrolldc( HWND parent)
5130 {
5131     HDC hdc;
5132     HRGN exprgn, tmprgn, hrgn;
5133     RECT rc, rc2, rcu, cliprc;
5134     HWND hwnd1;
5135     COLORREF colr;
5136 
5137     hrgn = CreateRectRgn(0,0,0,0);
5138     tmprgn = CreateRectRgn(0,0,0,0);
5139     exprgn = CreateRectRgn(0,0,0,0);
5140 
5141     hwnd1 = CreateWindowExA(0, "static", NULL,
5142             WS_CHILD| WS_VISIBLE,
5143             25, 50, 100, 100, parent, 0, 0, NULL);
5144     ShowWindow( parent, SW_SHOW);
5145     UpdateWindow( parent);
5146     flush_events( TRUE );
5147     GetClientRect( hwnd1, &rc);
5148     hdc = GetDC( hwnd1);
5149     /* paint the upper half of the window black */
5150     rc2 = rc;
5151     rc2.bottom = ( rc.top + rc.bottom) /2;
5152     FillRect( hdc, &rc2, GetStockObject(BLACK_BRUSH));
5153     /* clip region is the lower half */
5154     cliprc=rc;
5155     cliprc.top = (rc.top + rc.bottom) /2;
5156     /* test whether scrolled pixels are properly clipped */
5157     colr = GetPixel( hdc, (rc.left+rc.right)/2, ( rc.top + rc.bottom) /2 - 1);
5158     ok ( colr == 0, "pixel should be black, color is %08x\n", colr);
5159     /* this scroll should not cause any visible changes */
5160     ScrollDC( hdc, 5, -20, &rc, &cliprc, hrgn, &rcu);
5161     colr = GetPixel( hdc, (rc.left+rc.right)/2, ( rc.top + rc.bottom) /2 - 1);
5162     ok ( colr == 0, "pixel should be black, color is %08x\n", colr);
5163     /* test with NULL clip rect */
5164     ScrollDC( hdc, 20, -20, &rc, NULL, hrgn, &rcu);
5165     /*FillRgn(hdc, hrgn, GetStockObject(WHITE_BRUSH));*/
5166     trace("update rect: %s\n", wine_dbgstr_rect(&rcu));
5167     if (winetest_debug > 0) dump_region(hrgn);
5168     SetRect(&rc2, 0, 0, 100, 100);
5169     ok(EqualRect(&rcu, &rc2), "rects do not match %s / %s\n", wine_dbgstr_rect(&rcu),
5170        wine_dbgstr_rect(&rc2));
5171 
5172     SetRectRgn( exprgn, 0, 0, 20, 80);
5173     SetRectRgn( tmprgn, 0, 80, 100, 100);
5174     CombineRgn(exprgn, exprgn, tmprgn, RGN_OR);
5175     if (winetest_debug > 0) dump_region(exprgn);
5176     ok(EqualRgn(exprgn, hrgn), "wrong update region\n");
5177     /* test clip rect > scroll rect */
5178     FillRect( hdc, &rc, GetStockObject(WHITE_BRUSH));
5179     rc2=rc;
5180     InflateRect( &rc2, -(rc.right-rc.left)/4, -(rc.bottom-rc.top)/4);
5181     FillRect( hdc, &rc2, GetStockObject(BLACK_BRUSH));
5182     ScrollDC( hdc, 10, 10, &rc2, &rc, hrgn, &rcu);
5183     SetRectRgn( exprgn, 25, 25, 75, 35);
5184     SetRectRgn( tmprgn, 25, 35, 35, 75);
5185     CombineRgn(exprgn, exprgn, tmprgn, RGN_OR);
5186     ok(EqualRgn(exprgn, hrgn), "wrong update region\n");
5187     trace("update rect: %s\n", wine_dbgstr_rect(&rcu));
5188     if (winetest_debug > 0) dump_region(hrgn);
5189 
5190     /* clean up */
5191     DeleteObject(hrgn);
5192     DeleteObject(exprgn);
5193     DeleteObject(tmprgn);
5194     DestroyWindow(hwnd1);
5195 }
5196 
5197 static void test_params(void)
5198 {
5199     HWND hwnd;
5200     INT rc;
5201 
5202     ok(!IsWindow(0), "IsWindow(0)\n");
5203     ok(!IsWindow(HWND_BROADCAST), "IsWindow(HWND_BROADCAST)\n");
5204     ok(!IsWindow(HWND_TOPMOST), "IsWindow(HWND_TOPMOST)\n");
5205 
5206     /* Just a param check */
5207     if (pGetMonitorInfoA)
5208     {
5209         SetLastError(0xdeadbeef);
5210         rc = GetWindowTextA(hwndMain2, NULL, 1024);
5211         ok( rc==0, "GetWindowText: rc=%d err=%d\n",rc,GetLastError());
5212     }
5213     else
5214     {
5215         /* Skips actually on Win95 and NT4 */
5216         win_skip("Test would crash on Win95\n");
5217     }
5218 
5219     SetLastError(0xdeadbeef);
5220     hwnd=CreateWindowA("LISTBOX", "TestList",
5221                       (LBS_STANDARD & ~LBS_SORT),
5222                       0, 0, 100, 100,
5223                       NULL, (HMENU)1, NULL, 0);
5224 
5225     ok(!hwnd || broken(hwnd != NULL), /* w2k3 sp2 */
5226        "CreateWindow with invalid menu handle should fail\n");
5227     if (!hwnd)
5228         ok(GetLastError() == ERROR_INVALID_MENU_HANDLE || /* NT */
5229            GetLastError() == 0xdeadbeef, /* Win9x */
5230            "wrong last error value %d\n", GetLastError());
5231 }
5232 
5233 static void test_AWRwindow(LPCSTR class, LONG style, LONG exStyle, BOOL menu)
5234 {
5235     HWND hwnd = 0;
5236 
5237     hwnd = CreateWindowExA(exStyle, class, class, style,
5238 			  110, 100,
5239 			  225, 200,
5240 			  0,
5241 			  menu ? hmenu : 0,
5242 			  0, 0);
5243     if (!hwnd) {
5244 	trace("Failed to create window class=%s, style=0x%08x, exStyle=0x%08x\n", class, style, exStyle);
5245         return;
5246     }
5247     ShowWindow(hwnd, SW_SHOW);
5248 
5249     test_nonclient_area(hwnd);
5250 
5251     SetMenu(hwnd, 0);
5252     DestroyWindow(hwnd);
5253 }
5254 
5255 static BOOL AWR_init(void)
5256 {
5257     WNDCLASSA class;
5258 
5259     class.style         = CS_HREDRAW | CS_VREDRAW;
5260     class.lpfnWndProc     = DefWindowProcA;
5261     class.cbClsExtra    = 0;
5262     class.cbWndExtra    = 0;
5263     class.hInstance     = 0;
5264     class.hIcon         = LoadIconA(0, (LPCSTR)IDI_APPLICATION);
5265     class.hCursor       = LoadCursorA(0, (LPCSTR)IDC_ARROW);
5266     class.hbrBackground = 0;
5267     class.lpszMenuName  = 0;
5268     class.lpszClassName = szAWRClass;
5269 
5270     if (!RegisterClassA(&class)) {
5271 	ok(FALSE, "RegisterClass failed\n");
5272 	return FALSE;
5273     }
5274 
5275     hmenu = CreateMenu();
5276     if (!hmenu)
5277 	return FALSE;
5278     ok(hmenu != 0, "Failed to create menu\n");
5279     ok(AppendMenuA(hmenu, MF_STRING, 1, "Test!"), "Failed to create menu item\n");
5280 
5281     return TRUE;
5282 }
5283 
5284 
5285 static void test_AWR_window_size(BOOL menu)
5286 {
5287     static const DWORD styles[] = {
5288         WS_POPUP, WS_MAXIMIZE, WS_BORDER, WS_DLGFRAME, WS_CAPTION, WS_SYSMENU,
5289         WS_THICKFRAME, WS_MINIMIZEBOX, WS_MAXIMIZEBOX, WS_HSCROLL, WS_VSCROLL
5290     };
5291     static const DWORD exStyles[] = {
5292 	WS_EX_CLIENTEDGE, WS_EX_TOOLWINDOW, WS_EX_WINDOWEDGE, WS_EX_APPWINDOW,
5293 	WS_EX_DLGMODALFRAME, WS_EX_DLGMODALFRAME | WS_EX_STATICEDGE
5294     };
5295 
5296     unsigned int i;
5297 
5298     /* A exhaustive check of all the styles takes too long
5299      * so just do a (hopefully representative) sample
5300      */
5301     for (i = 0; i < COUNTOF(styles); ++i)
5302         test_AWRwindow(szAWRClass, styles[i], 0, menu);
5303     for (i = 0; i < COUNTOF(exStyles); ++i) {
5304         test_AWRwindow(szAWRClass, WS_POPUP, exStyles[i], menu);
5305         test_AWRwindow(szAWRClass, WS_THICKFRAME, exStyles[i], menu);
5306     }
5307 }
5308 
5309 static void test_AWR_flags(void)
5310 {
5311     static const DWORD styles[] = { WS_POPUP, WS_BORDER, WS_DLGFRAME, WS_THICKFRAME };
5312     static const DWORD exStyles[] = { WS_EX_CLIENTEDGE, WS_EX_TOOLWINDOW, WS_EX_WINDOWEDGE,
5313                                       WS_EX_APPWINDOW, WS_EX_DLGMODALFRAME, WS_EX_STATICEDGE };
5314 
5315     DWORD i, j, k, style, exstyle;
5316     RECT rect, rect2;
5317 
5318     for (i = 0; i < (1 << COUNTOF(styles)); i++)
5319     {
5320         for (k = style = 0; k < COUNTOF(styles); k++) if (i & (1 << k)) style |= styles[k];
5321 
5322         for (j = 0; j < (1 << COUNTOF(exStyles)); j++)
5323         {
5324             for (k = exstyle = 0; k < COUNTOF(exStyles); k++) if (j & (1 << k)) exstyle |= exStyles[k];
5325             SetRect( &rect, 100, 100, 200, 200 );
5326             rect2 = rect;
5327             AdjustWindowRectEx( &rect, style, FALSE, exstyle );
5328             wine_AdjustWindowRectEx( &rect2, style, FALSE, exstyle );
5329             ok( EqualRect( &rect, &rect2 ), "rects do not match: win %s wine %s\n",
5330                 wine_dbgstr_rect( &rect ), wine_dbgstr_rect( &rect2 ));
5331         }
5332     }
5333 }
5334 #undef COUNTOF
5335 
5336 #define SHOWSYSMETRIC(SM) trace(#SM "=%d\n", GetSystemMetrics(SM))
5337 
5338 static void test_AdjustWindowRect(void)
5339 {
5340     if (!AWR_init())
5341 	return;
5342 
5343     SHOWSYSMETRIC(SM_CYCAPTION);
5344     SHOWSYSMETRIC(SM_CYSMCAPTION);
5345     SHOWSYSMETRIC(SM_CYMENU);
5346     SHOWSYSMETRIC(SM_CXEDGE);
5347     SHOWSYSMETRIC(SM_CYEDGE);
5348     SHOWSYSMETRIC(SM_CXVSCROLL);
5349     SHOWSYSMETRIC(SM_CYHSCROLL);
5350     SHOWSYSMETRIC(SM_CXFRAME);
5351     SHOWSYSMETRIC(SM_CYFRAME);
5352     SHOWSYSMETRIC(SM_CXDLGFRAME);
5353     SHOWSYSMETRIC(SM_CYDLGFRAME);
5354     SHOWSYSMETRIC(SM_CXBORDER);
5355     SHOWSYSMETRIC(SM_CYBORDER);
5356 
5357     test_AWR_window_size(FALSE);
5358     test_AWR_window_size(TRUE);
5359     test_AWR_flags();
5360 
5361     DestroyMenu(hmenu);
5362 }
5363 #undef SHOWSYSMETRIC
5364 
5365 
5366 /* Global variables to trigger exit from loop */
5367 static int redrawComplete, WMPAINT_count;
5368 
5369 static LRESULT WINAPI redraw_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
5370 {
5371     switch (msg)
5372     {
5373     case WM_PAINT:
5374         trace("doing WM_PAINT %d\n", WMPAINT_count);
5375         WMPAINT_count++;
5376         if (WMPAINT_count > 10 && redrawComplete == 0) {
5377             PAINTSTRUCT ps;
5378             BeginPaint(hwnd, &ps);
5379             EndPaint(hwnd, &ps);
5380             return 1;
5381         }
5382         return 0;
5383     }
5384     return DefWindowProcA(hwnd, msg, wparam, lparam);
5385 }
5386 
5387 /* Ensure we exit from RedrawNow regardless of invalidated area */
5388 static void test_redrawnow(void)
5389 {
5390    WNDCLASSA cls;
5391    HWND hwndMain;
5392 
5393    cls.style = CS_DBLCLKS;
5394    cls.lpfnWndProc = redraw_window_procA;
5395    cls.cbClsExtra = 0;
5396    cls.cbWndExtra = 0;
5397    cls.hInstance = GetModuleHandleA(0);
5398    cls.hIcon = 0;
5399    cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
5400    cls.hbrBackground = GetStockObject(WHITE_BRUSH);
5401    cls.lpszMenuName = NULL;
5402    cls.lpszClassName = "RedrawWindowClass";
5403 
5404    if(!RegisterClassA(&cls)) {
5405        trace("Register failed %d\n", GetLastError());
5406        return;
5407    }
5408 
5409    hwndMain = CreateWindowA("RedrawWindowClass", "Main Window", WS_OVERLAPPEDWINDOW,
5410                             CW_USEDEFAULT, 0, 100, 100, NULL, NULL, 0, NULL);
5411 
5412    ok( WMPAINT_count == 0, "Multiple unexpected WM_PAINT calls %d\n", WMPAINT_count);
5413    ShowWindow(hwndMain, SW_SHOW);
5414    ok( WMPAINT_count == 0, "Multiple unexpected WM_PAINT calls %d\n", WMPAINT_count);
5415    RedrawWindow(hwndMain, NULL,NULL,RDW_UPDATENOW | RDW_ALLCHILDREN);
5416    ok( WMPAINT_count == 1 || broken(WMPAINT_count == 0), /* sometimes on win9x */
5417        "Multiple unexpected WM_PAINT calls %d\n", WMPAINT_count);
5418    redrawComplete = TRUE;
5419    ok( WMPAINT_count < 10, "RedrawWindow (RDW_UPDATENOW) never completed (%d)\n", WMPAINT_count);
5420 
5421    /* clean up */
5422    DestroyWindow( hwndMain);
5423 }
5424 
5425 struct parentdc_stat {
5426     RECT client;
5427     RECT clip;
5428     RECT paint;
5429 };
5430 
5431 struct parentdc_test {
5432    struct parentdc_stat main, main_todo;
5433    struct parentdc_stat child1, child1_todo;
5434    struct parentdc_stat child2, child2_todo;
5435 };
5436 
5437 static LRESULT WINAPI parentdc_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
5438 {
5439     RECT rc;
5440     PAINTSTRUCT ps;
5441 
5442     struct parentdc_stat *t = (struct parentdc_stat *)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
5443 
5444     switch (msg)
5445     {
5446     case WM_PAINT:
5447         GetClientRect(hwnd, &rc);
5448         t->client = rc;
5449         GetWindowRect(hwnd, &rc);
5450         trace("WM_PAINT: hwnd %p, client rect %s, window rect %s\n", hwnd,
5451               wine_dbgstr_rect(&t->client), wine_dbgstr_rect(&rc));
5452         BeginPaint(hwnd, &ps);
5453         t->paint = ps.rcPaint;
5454         GetClipBox(ps.hdc, &rc);
5455         t->clip = rc;
5456         trace("clip rect %s, paint rect %s\n", wine_dbgstr_rect(&rc),
5457               wine_dbgstr_rect(&ps.rcPaint));
5458         EndPaint(hwnd, &ps);
5459         return 0;
5460     }
5461     return DefWindowProcA(hwnd, msg, wparam, lparam);
5462 }
5463 
5464 static void zero_parentdc_stat(struct parentdc_stat *t)
5465 {
5466     SetRectEmpty(&t->client);
5467     SetRectEmpty(&t->clip);
5468     SetRectEmpty(&t->paint);
5469 }
5470 
5471 static void zero_parentdc_test(struct parentdc_test *t)
5472 {
5473     zero_parentdc_stat(&t->main);
5474     zero_parentdc_stat(&t->child1);
5475     zero_parentdc_stat(&t->child2);
5476 }
5477 
5478 #define parentdc_field_ok(t, w, r, f, got) \
5479   ok (t.w.r.f==got.w.r.f, "window " #w ", rect " #r ", field " #f \
5480       ": expected %d, got %d\n", \
5481       t.w.r.f, got.w.r.f)
5482 
5483 #define parentdc_todo_field_ok(t, w, r, f, got) \
5484   todo_wine_if (t.w##_todo.r.f) \
5485       parentdc_field_ok(t, w, r, f, got);
5486 
5487 #define parentdc_rect_ok(t, w, r, got) \
5488   parentdc_todo_field_ok(t, w, r, left, got); \
5489   parentdc_todo_field_ok(t, w, r, top, got); \
5490   parentdc_todo_field_ok(t, w, r, right, got); \
5491   parentdc_todo_field_ok(t, w, r, bottom, got);
5492 
5493 #define parentdc_win_ok(t, w, got) \
5494   parentdc_rect_ok(t, w, client, got); \
5495   parentdc_rect_ok(t, w, clip, got); \
5496   parentdc_rect_ok(t, w, paint, got);
5497 
5498 #define parentdc_ok(t, got) \
5499   parentdc_win_ok(t, main, got); \
5500   parentdc_win_ok(t, child1, got); \
5501   parentdc_win_ok(t, child2, got);
5502 
5503 static void test_csparentdc(void)
5504 {
5505    WNDCLASSA clsMain, cls;
5506    HWND hwndMain, hwnd1, hwnd2;
5507    RECT rc;
5508 
5509    struct parentdc_test test_answer;
5510 
5511 #define nothing_todo {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}
5512    const struct parentdc_test test1 =
5513    {
5514         {{0, 0, 150, 150}, {0, 0, 150, 150}, {0, 0, 150, 150}}, nothing_todo,
5515         {{0, 0, 40, 40}, {-20, -20, 130, 130}, {0, 0, 40, 40}}, {{0, 0, 0, 0}, {1, 1, 1, 1}, {0, 0, 0, 0}},
5516         {{0, 0, 40, 40}, {-40, -40, 110, 110}, {0, 0, 40, 40}}, {{0, 0, 0, 0}, {1, 1, 1, 1}, {0, 0, 0, 0}},
5517    };
5518 
5519    const struct parentdc_test test2 =
5520    {
5521         {{0, 0, 150, 150}, {0, 0, 50, 50}, {0, 0, 50, 50}}, nothing_todo,
5522         {{0, 0, 40, 40}, {-20, -20, 30, 30}, {0, 0, 30, 30}}, {{0, 0, 0, 0}, {1, 1, 0, 0}, {0, 0, 0, 0}},
5523         {{0, 0, 40, 40}, {-40, -40, 10, 10}, {0, 0, 10, 10}}, {{0, 0, 0, 0}, {1, 1, 0, 0}, {0, 0, 0, 0}},
5524    };
5525 
5526    const struct parentdc_test test3 =
5527    {
5528         {{0, 0, 150, 150}, {0, 0, 10, 10}, {0, 0, 10, 10}}, nothing_todo,
5529         {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, nothing_todo,
5530         {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, nothing_todo,
5531    };
5532 
5533    const struct parentdc_test test4 =
5534    {
5535         {{0, 0, 150, 150}, {40, 40, 50, 50}, {40, 40, 50, 50}}, nothing_todo,
5536         {{0, 0, 40, 40}, {20, 20, 30, 30}, {20, 20, 30, 30}}, nothing_todo,
5537         {{0, 0, 40, 40}, {0, 0, 10, 10}, {0, 0, 10, 10}}, nothing_todo,
5538    };
5539 
5540    const struct parentdc_test test5 =
5541    {
5542         {{0, 0, 150, 150}, {20, 20, 60, 60}, {20, 20, 60, 60}}, nothing_todo,
5543         {{0, 0, 40, 40}, {-20, -20, 130, 130}, {0, 0, 40, 40}}, {{0, 0, 0, 0}, {1, 1, 1, 1}, {0, 0, 0, 0}},
5544         {{0, 0, 40, 40}, {-20, -20, 20, 20}, {0, 0, 20, 20}}, {{0, 0, 0, 0}, {1, 1, 0, 0}, {0, 0, 0, 0}},
5545    };
5546 
5547    const struct parentdc_test test6 =
5548    {
5549         {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, nothing_todo,
5550         {{0, 0, 40, 40}, {0, 0, 10, 10}, {0, 0, 10, 10}}, nothing_todo,
5551         {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, nothing_todo,
5552    };
5553 
5554    const struct parentdc_test test7 =
5555    {
5556         {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, nothing_todo,
5557         {{0, 0, 40, 40}, {-20, -20, 130, 130}, {0, 0, 40, 40}}, {{0, 0, 0, 0}, {1, 1, 1, 1}, {0, 0, 0, 0}},
5558         {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, nothing_todo,
5559    };
5560 #undef nothing_todo
5561 
5562    clsMain.style = CS_DBLCLKS;
5563    clsMain.lpfnWndProc = parentdc_window_procA;
5564    clsMain.cbClsExtra = 0;
5565    clsMain.cbWndExtra = 0;
5566    clsMain.hInstance = GetModuleHandleA(0);
5567    clsMain.hIcon = 0;
5568    clsMain.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
5569    clsMain.hbrBackground = GetStockObject(WHITE_BRUSH);
5570    clsMain.lpszMenuName = NULL;
5571    clsMain.lpszClassName = "ParentDcMainWindowClass";
5572 
5573    if(!RegisterClassA(&clsMain)) {
5574        trace("Register failed %d\n", GetLastError());
5575        return;
5576    }
5577 
5578    cls.style = CS_DBLCLKS | CS_PARENTDC;
5579    cls.lpfnWndProc = parentdc_window_procA;
5580    cls.cbClsExtra = 0;
5581    cls.cbWndExtra = 0;
5582    cls.hInstance = GetModuleHandleA(0);
5583    cls.hIcon = 0;
5584    cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
5585    cls.hbrBackground = GetStockObject(WHITE_BRUSH);
5586    cls.lpszMenuName = NULL;
5587    cls.lpszClassName = "ParentDcWindowClass";
5588 
5589    if(!RegisterClassA(&cls)) {
5590        trace("Register failed %d\n", GetLastError());
5591        return;
5592    }
5593 
5594    SetRect(&rc, 0, 0, 150, 150);
5595    AdjustWindowRectEx(&rc, WS_OVERLAPPEDWINDOW, FALSE, 0);
5596    hwndMain = CreateWindowA("ParentDcMainWindowClass", "Main Window", WS_OVERLAPPEDWINDOW,
5597                             CW_USEDEFAULT, 0, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, 0, NULL);
5598    SetWindowLongPtrA(hwndMain, GWLP_USERDATA, (DWORD_PTR)&test_answer.main);
5599    hwnd1 = CreateWindowA("ParentDcWindowClass", "Child Window 1", WS_CHILD,
5600                             20, 20, 40, 40, hwndMain, NULL, 0, NULL);
5601    SetWindowLongPtrA(hwnd1, GWLP_USERDATA, (DWORD_PTR)&test_answer.child1);
5602    hwnd2 = CreateWindowA("ParentDcWindowClass", "Child Window 2", WS_CHILD,
5603                             40, 40, 40, 40, hwndMain, NULL, 0, NULL);
5604    SetWindowLongPtrA(hwnd2, GWLP_USERDATA, (DWORD_PTR)&test_answer.child2);
5605    ShowWindow(hwndMain, SW_SHOW);
5606    ShowWindow(hwnd1, SW_SHOW);
5607    ShowWindow(hwnd2, SW_SHOW);
5608    SetWindowPos(hwndMain, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
5609    flush_events( TRUE );
5610 
5611    zero_parentdc_test(&test_answer);
5612    InvalidateRect(hwndMain, NULL, TRUE);
5613    flush_events( TRUE );
5614    parentdc_ok(test1, test_answer);
5615 
5616    zero_parentdc_test(&test_answer);
5617    SetRect(&rc, 0, 0, 50, 50);
5618    InvalidateRect(hwndMain, &rc, TRUE);
5619    flush_events( TRUE );
5620    parentdc_ok(test2, test_answer);
5621 
5622    zero_parentdc_test(&test_answer);
5623    SetRect(&rc, 0, 0, 10, 10);
5624    InvalidateRect(hwndMain, &rc, TRUE);
5625    flush_events( TRUE );
5626    parentdc_ok(test3, test_answer);
5627 
5628    zero_parentdc_test(&test_answer);
5629    SetRect(&rc, 40, 40, 50, 50);
5630    InvalidateRect(hwndMain, &rc, TRUE);
5631    flush_events( TRUE );
5632    parentdc_ok(test4, test_answer);
5633 
5634    zero_parentdc_test(&test_answer);
5635    SetRect(&rc, 20, 20, 60, 60);
5636    InvalidateRect(hwndMain, &rc, TRUE);
5637    flush_events( TRUE );
5638    parentdc_ok(test5, test_answer);
5639 
5640    zero_parentdc_test(&test_answer);
5641    SetRect(&rc, 0, 0, 10, 10);
5642    InvalidateRect(hwnd1, &rc, TRUE);
5643    flush_events( TRUE );
5644    parentdc_ok(test6, test_answer);
5645 
5646    zero_parentdc_test(&test_answer);
5647    SetRect(&rc, -5, -5, 65, 65);
5648    InvalidateRect(hwnd1, &rc, TRUE);
5649    flush_events( TRUE );
5650    parentdc_ok(test7, test_answer);
5651 
5652    DestroyWindow(hwndMain);
5653    DestroyWindow(hwnd1);
5654    DestroyWindow(hwnd2);
5655 }
5656 
5657 static LRESULT WINAPI def_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
5658 {
5659     return DefWindowProcA(hwnd, msg, wparam, lparam);
5660 }
5661 
5662 static LRESULT WINAPI def_window_procW(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
5663 {
5664     return DefWindowProcW(hwnd, msg, wparam, lparam);
5665 }
5666 
5667 static void test_IsWindowUnicode(void)
5668 {
5669     static const char ansi_class_nameA[] = "ansi class name";
5670     static const WCHAR ansi_class_nameW[] = {'a','n','s','i',' ','c','l','a','s','s',' ','n','a','m','e',0};
5671     static const char unicode_class_nameA[] = "unicode class name";
5672     static const WCHAR unicode_class_nameW[] = {'u','n','i','c','o','d','e',' ','c','l','a','s','s',' ','n','a','m','e',0};
5673     WNDCLASSA classA;
5674     WNDCLASSW classW;
5675     HWND hwnd;
5676     ATOM atom;
5677 
5678     memset(&classW, 0, sizeof(classW));
5679     classW.hInstance = GetModuleHandleA(0);
5680     classW.lpfnWndProc = def_window_procW;
5681     classW.lpszClassName = unicode_class_nameW;
5682     if (!RegisterClassW(&classW)) return; /* this catches Win9x as well */
5683 
5684     memset(&classA, 0, sizeof(classA));
5685     classA.hInstance = GetModuleHandleA(0);
5686     classA.lpfnWndProc = def_window_procA;
5687     classA.lpszClassName = ansi_class_nameA;
5688     atom = RegisterClassA(&classA);
5689     assert(atom);
5690 
5691     /* unicode class: window proc */
5692     hwnd = CreateWindowExW(0, unicode_class_nameW, NULL, WS_POPUP,
5693                            0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL);
5694     assert(hwnd);
5695 
5696     ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n");
5697     SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (ULONG_PTR)def_window_procA);
5698     ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n");
5699     SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (ULONG_PTR)def_window_procW);
5700     ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n");
5701 
5702     DestroyWindow(hwnd);
5703 
5704     hwnd = CreateWindowExA(0, unicode_class_nameA, NULL, WS_POPUP,
5705                            0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL);
5706     assert(hwnd);
5707 
5708     ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n");
5709     SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (ULONG_PTR)def_window_procA);
5710     ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n");
5711     SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (ULONG_PTR)def_window_procW);
5712     ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n");
5713 
5714     DestroyWindow(hwnd);
5715 
5716     /* ansi class: window proc */
5717     hwnd = CreateWindowExW(0, ansi_class_nameW, NULL, WS_POPUP,
5718                            0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL);
5719     assert(hwnd);
5720 
5721     ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n");
5722     SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (ULONG_PTR)def_window_procW);
5723     ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n");
5724     SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (ULONG_PTR)def_window_procA);
5725     ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n");
5726 
5727     DestroyWindow(hwnd);
5728 
5729     hwnd = CreateWindowExA(0, ansi_class_nameA, NULL, WS_POPUP,
5730                            0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL);
5731     assert(hwnd);
5732 
5733     ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n");
5734     SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (ULONG_PTR)def_window_procW);
5735     ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n");
5736     SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (ULONG_PTR)def_window_procA);
5737     ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n");
5738 
5739     DestroyWindow(hwnd);
5740 
5741     /* unicode class: class proc */
5742     hwnd = CreateWindowExW(0, unicode_class_nameW, NULL, WS_POPUP,
5743                            0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL);
5744     assert(hwnd);
5745 
5746     ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n");
5747     SetClassLongPtrA(hwnd, GCLP_WNDPROC, (ULONG_PTR)def_window_procA);
5748     ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n");
5749     /* do not restore class window proc back to unicode */
5750 
5751     DestroyWindow(hwnd);
5752 
5753     hwnd = CreateWindowExA(0, unicode_class_nameA, NULL, WS_POPUP,
5754                            0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL);
5755     assert(hwnd);
5756 
5757     ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n");
5758     SetClassLongPtrW(hwnd, GCLP_WNDPROC, (ULONG_PTR)def_window_procW);
5759     ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n");
5760 
5761     DestroyWindow(hwnd);
5762 
5763     /* ansi class: class proc */
5764     hwnd = CreateWindowExW(0, ansi_class_nameW, NULL, WS_POPUP,
5765                            0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL);
5766     assert(hwnd);
5767 
5768     ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n");
5769     SetClassLongPtrW(hwnd, GCLP_WNDPROC, (ULONG_PTR)def_window_procW);
5770     ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n");
5771     /* do not restore class window proc back to ansi */
5772 
5773     DestroyWindow(hwnd);
5774 
5775     hwnd = CreateWindowExA(0, ansi_class_nameA, NULL, WS_POPUP,
5776                            0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL);
5777     assert(hwnd);
5778 
5779     ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n");
5780     SetClassLongPtrA(hwnd, GCLP_WNDPROC, (ULONG_PTR)def_window_procA);
5781     ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n");
5782 
5783     DestroyWindow(hwnd);
5784 }
5785 
5786 static LRESULT CALLBACK minmax_wnd_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
5787 {
5788     MINMAXINFO *minmax;
5789 
5790     if (msg != WM_GETMINMAXINFO)
5791         return DefWindowProcA(hwnd, msg, wp, lp);
5792 
5793     minmax = (MINMAXINFO *)lp;
5794 
5795     if ((GetWindowLongA(hwnd, GWL_STYLE) & WS_CHILD))
5796     {
5797         minmax->ptReserved.x = 0;
5798         minmax->ptReserved.y = 0;
5799         minmax->ptMaxSize.x = 400;
5800         minmax->ptMaxSize.y = 400;
5801         minmax->ptMaxPosition.x = 300;
5802         minmax->ptMaxPosition.y = 300;
5803         minmax->ptMaxTrackSize.x = 200;
5804         minmax->ptMaxTrackSize.y = 200;
5805         minmax->ptMinTrackSize.x = 100;
5806         minmax->ptMinTrackSize.y = 100;
5807     }
5808     else
5809         DefWindowProcA(hwnd, msg, wp, lp);
5810     return 1;
5811 }
5812 
5813 static int expected_cx, expected_cy;
5814 static RECT expected_rect, broken_rect;
5815 
5816 static LRESULT CALLBACK winsizes_wnd_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
5817 {
5818     switch(msg)
5819     {
5820     case WM_GETMINMAXINFO:
5821     {
5822         RECT rect;
5823         GetWindowRect( hwnd, &rect );
5824         ok( !rect.left && !rect.top && !rect.right && !rect.bottom, "wrong rect %s\n",
5825             wine_dbgstr_rect( &rect ));
5826         return DefWindowProcA(hwnd, msg, wp, lp);
5827     }
5828     case WM_NCCREATE:
5829     case WM_CREATE:
5830     {
5831         CREATESTRUCTA *cs = (CREATESTRUCTA *)lp;
5832         RECT rect;
5833         GetWindowRect( hwnd, &rect );
5834         trace( "hwnd %p msg %x size %dx%d rect %s\n", hwnd, msg, cs->cx, cs->cy,
5835                wine_dbgstr_rect( &rect ));
5836         ok( cs->cx == expected_cx || broken(cs->cx == (short)expected_cx),
5837             "wrong x size %d/%d\n", cs->cx, expected_cx );
5838         ok( cs->cy == expected_cy || broken(cs->cy == (short)expected_cy),
5839             "wrong y size %d/%d\n", cs->cy, expected_cy );
5840         ok( (rect.right - rect.left == expected_rect.right - expected_rect.left &&
5841              rect.bottom - rect.top == expected_rect.bottom - expected_rect.top) ||
5842             (rect.right - rect.left == min( 65535, expected_rect.right - expected_rect.left ) &&
5843              rect.bottom - rect.top == min( 65535, expected_rect.bottom - expected_rect.top )) ||
5844             broken( rect.right - rect.left == broken_rect.right - broken_rect.left &&
5845                     rect.bottom - rect.top == broken_rect.bottom - broken_rect.top) ||
5846             broken( rect.right - rect.left == (short)broken_rect.right - (short)broken_rect.left &&
5847                     rect.bottom - rect.top == (short)broken_rect.bottom - (short)broken_rect.top),
5848             "wrong rect %s / %s\n", wine_dbgstr_rect( &rect ), wine_dbgstr_rect( &expected_rect ));
5849         return DefWindowProcA(hwnd, msg, wp, lp);
5850     }
5851     case WM_NCCALCSIZE:
5852     {
5853         RECT rect, *r = (RECT *)lp;
5854         GetWindowRect( hwnd, &rect );
5855         ok( EqualRect( &rect, r ), "passed rect %s doesn't match window rect %s\n",
5856             wine_dbgstr_rect( r ), wine_dbgstr_rect( &rect ));
5857         return DefWindowProcA(hwnd, msg, wp, lp);
5858     }
5859     default:
5860         return DefWindowProcA(hwnd, msg, wp, lp);
5861     }
5862 }
5863 
5864 static void test_CreateWindow(void)
5865 {
5866     WNDCLASSA cls;
5867     HWND hwnd, parent;
5868     HMENU hmenu;
5869     RECT rc, rc_minmax;
5870     MINMAXINFO minmax;
5871     BOOL res;
5872 
5873 #define expect_menu(window, menu) \
5874     SetLastError(0xdeadbeef); \
5875     res = (GetMenu(window) == (HMENU)menu); \
5876     ok(res, "GetMenu error %d\n", GetLastError())
5877 
5878 #define expect_style(window, style)\
5879     ok((ULONG)GetWindowLongA(window, GWL_STYLE) == (style), "expected style %x != %x\n", (LONG)(style), GetWindowLongA(window, GWL_STYLE))
5880 
5881 #define expect_ex_style(window, ex_style)\
5882     ok((ULONG)GetWindowLongA(window, GWL_EXSTYLE) == (ex_style), "expected ex_style %x != %x\n", (LONG)(ex_style), GetWindowLongA(window, GWL_EXSTYLE))
5883 
5884 #define expect_gle_broken_9x(gle)\
5885     ok(GetLastError() == gle ||\
5886        broken(GetLastError() == 0xdeadbeef),\
5887        "IsMenu set error %d\n", GetLastError())
5888 
5889     hmenu = CreateMenu();
5890     assert(hmenu != 0);
5891     parent = GetDesktopWindow();
5892     assert(parent != 0);
5893 
5894     SetLastError(0xdeadbeef);
5895     res = IsMenu(hmenu);
5896     ok(res, "IsMenu error %d\n", GetLastError());
5897 
5898     /* WS_CHILD */
5899     SetLastError(0xdeadbeef);
5900     hwnd = CreateWindowExA(WS_EX_APPWINDOW, "static", NULL, WS_CHILD,
5901                            0, 0, 100, 100, parent, (HMENU)1, 0, NULL);
5902     ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError());
5903     expect_menu(hwnd, 1);
5904     expect_style(hwnd, WS_CHILD);
5905     expect_ex_style(hwnd, WS_EX_APPWINDOW);
5906     DestroyWindow(hwnd);
5907 
5908     SetLastError(0xdeadbeef);
5909     hwnd = CreateWindowExA(WS_EX_APPWINDOW, "static", NULL, WS_CHILD | WS_CAPTION,
5910                            0, 0, 100, 100, parent, (HMENU)1, 0, NULL);
5911     ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError());
5912     expect_menu(hwnd, 1);
5913     expect_style(hwnd, WS_CHILD | WS_CAPTION);
5914     expect_ex_style(hwnd, WS_EX_APPWINDOW | WS_EX_WINDOWEDGE);
5915     DestroyWindow(hwnd);
5916 
5917     SetLastError(0xdeadbeef);
5918     hwnd = CreateWindowExA(0, "static", NULL, WS_CHILD,
5919                            0, 0, 100, 100, parent, (HMENU)1, 0, NULL);
5920     ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError());
5921     expect_menu(hwnd, 1);
5922     expect_style(hwnd, WS_CHILD);
5923     expect_ex_style(hwnd, 0);
5924     DestroyWindow(hwnd);
5925 
5926     SetLastError(0xdeadbeef);
5927     hwnd = CreateWindowExA(0, "static", NULL, WS_CHILD | WS_CAPTION,
5928                            0, 0, 100, 100, parent, (HMENU)1, 0, NULL);
5929     ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError());
5930     expect_menu(hwnd, 1);
5931     expect_style(hwnd, WS_CHILD | WS_CAPTION);
5932     expect_ex_style(hwnd, WS_EX_WINDOWEDGE);
5933     DestroyWindow(hwnd);
5934 
5935     /* WS_POPUP */
5936     SetLastError(0xdeadbeef);
5937     hwnd = CreateWindowExA(WS_EX_APPWINDOW, "static", NULL, WS_POPUP,
5938                            0, 0, 100, 100, parent, hmenu, 0, NULL);
5939     ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError());
5940     expect_menu(hwnd, hmenu);
5941     expect_style(hwnd, WS_POPUP | WS_CLIPSIBLINGS);
5942     expect_ex_style(hwnd, WS_EX_APPWINDOW);
5943     DestroyWindow(hwnd);
5944     SetLastError(0xdeadbeef);
5945     ok(!IsMenu(hmenu), "IsMenu should fail\n");
5946     expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE);
5947 
5948     hmenu = CreateMenu();
5949     assert(hmenu != 0);
5950     SetLastError(0xdeadbeef);
5951     hwnd = CreateWindowExA(WS_EX_APPWINDOW, "static", NULL, WS_POPUP | WS_CAPTION,
5952                            0, 0, 100, 100, parent, hmenu, 0, NULL);
5953     ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError());
5954     expect_menu(hwnd, hmenu);
5955     expect_style(hwnd, WS_POPUP | WS_CAPTION | WS_CLIPSIBLINGS);
5956     expect_ex_style(hwnd, WS_EX_APPWINDOW | WS_EX_WINDOWEDGE);
5957     DestroyWindow(hwnd);
5958     SetLastError(0xdeadbeef);
5959     ok(!IsMenu(hmenu), "IsMenu should fail\n");
5960     expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE);
5961 
5962     hmenu = CreateMenu();
5963     assert(hmenu != 0);
5964     SetLastError(0xdeadbeef);
5965     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP,
5966                            0, 0, 100, 100, parent, hmenu, 0, NULL);
5967     ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError());
5968     expect_menu(hwnd, hmenu);
5969     expect_style(hwnd, WS_POPUP | WS_CLIPSIBLINGS);
5970     expect_ex_style(hwnd, 0);
5971     DestroyWindow(hwnd);
5972     SetLastError(0xdeadbeef);
5973     ok(!IsMenu(hmenu), "IsMenu should fail\n");
5974     expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE);
5975 
5976     hmenu = CreateMenu();
5977     assert(hmenu != 0);
5978     SetLastError(0xdeadbeef);
5979     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_CAPTION,
5980                            0, 0, 100, 100, parent, hmenu, 0, NULL);
5981     ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError());
5982     expect_menu(hwnd, hmenu);
5983     expect_style(hwnd, WS_POPUP | WS_CAPTION | WS_CLIPSIBLINGS);
5984     expect_ex_style(hwnd, WS_EX_WINDOWEDGE);
5985     DestroyWindow(hwnd);
5986     SetLastError(0xdeadbeef);
5987     ok(!IsMenu(hmenu), "IsMenu should fail\n");
5988     expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE);
5989 
5990     /* WS_CHILD | WS_POPUP */
5991     SetLastError(0xdeadbeef);
5992     hwnd = CreateWindowExA(WS_EX_APPWINDOW, "static", NULL, WS_CHILD | WS_POPUP,
5993                            0, 0, 100, 100, parent, (HMENU)1, 0, NULL);
5994     ok(!hwnd || broken(hwnd != 0 /* Win9x */), "CreateWindowEx should fail\n");
5995     expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE);
5996     if (hwnd)
5997         DestroyWindow(hwnd);
5998 
5999     hmenu = CreateMenu();
6000     assert(hmenu != 0);
6001     SetLastError(0xdeadbeef);
6002     hwnd = CreateWindowExA(WS_EX_APPWINDOW, "static", NULL, WS_CHILD | WS_POPUP,
6003                            0, 0, 100, 100, parent, hmenu, 0, NULL);
6004     ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError());
6005     expect_menu(hwnd, hmenu);
6006     expect_style(hwnd, WS_CHILD | WS_POPUP | WS_CLIPSIBLINGS);
6007     expect_ex_style(hwnd, WS_EX_APPWINDOW);
6008     DestroyWindow(hwnd);
6009     SetLastError(0xdeadbeef);
6010     ok(!IsMenu(hmenu), "IsMenu should fail\n");
6011     expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE);
6012 
6013     SetLastError(0xdeadbeef);
6014     hwnd = CreateWindowExA(WS_EX_APPWINDOW, "static", NULL, WS_CHILD | WS_POPUP | WS_CAPTION,
6015                            0, 0, 100, 100, parent, (HMENU)1, 0, NULL);
6016     ok(!hwnd || broken(hwnd != 0 /* Win9x */), "CreateWindowEx should fail\n");
6017     expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE);
6018     if (hwnd)
6019         DestroyWindow(hwnd);
6020 
6021     hmenu = CreateMenu();
6022     assert(hmenu != 0);
6023     SetLastError(0xdeadbeef);
6024     hwnd = CreateWindowExA(WS_EX_APPWINDOW, "static", NULL, WS_CHILD | WS_POPUP | WS_CAPTION,
6025                            0, 0, 100, 100, parent, hmenu, 0, NULL);
6026     ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError());
6027     expect_menu(hwnd, hmenu);
6028     expect_style(hwnd, WS_CHILD | WS_POPUP | WS_CAPTION | WS_CLIPSIBLINGS);
6029     expect_ex_style(hwnd, WS_EX_APPWINDOW | WS_EX_WINDOWEDGE);
6030     DestroyWindow(hwnd);
6031     SetLastError(0xdeadbeef);
6032     ok(!IsMenu(hmenu), "IsMenu should fail\n");
6033     expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE);
6034 
6035     SetLastError(0xdeadbeef);
6036     hwnd = CreateWindowExA(0, "static", NULL, WS_CHILD | WS_POPUP,
6037                            0, 0, 100, 100, parent, (HMENU)1, 0, NULL);
6038     ok(!hwnd || broken(hwnd != 0 /* Win9x */), "CreateWindowEx should fail\n");
6039     expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE);
6040     if (hwnd)
6041         DestroyWindow(hwnd);
6042 
6043     hmenu = CreateMenu();
6044     assert(hmenu != 0);
6045     SetLastError(0xdeadbeef);
6046     hwnd = CreateWindowExA(0, "static", NULL, WS_CHILD | WS_POPUP,
6047                            0, 0, 100, 100, parent, hmenu, 0, NULL);
6048     ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError());
6049     expect_menu(hwnd, hmenu);
6050     expect_style(hwnd, WS_CHILD | WS_POPUP | WS_CLIPSIBLINGS);
6051     expect_ex_style(hwnd, 0);
6052     DestroyWindow(hwnd);
6053     SetLastError(0xdeadbeef);
6054     ok(!IsMenu(hmenu), "IsMenu should fail\n");
6055     expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE);
6056 
6057     SetLastError(0xdeadbeef);
6058     hwnd = CreateWindowExA(0, "static", NULL, WS_CHILD | WS_POPUP | WS_CAPTION,
6059                            0, 0, 100, 100, parent, (HMENU)1, 0, NULL);
6060     ok(!hwnd || broken(hwnd != 0 /* Win9x */), "CreateWindowEx should fail\n");
6061     expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE);
6062     if (hwnd)
6063         DestroyWindow(hwnd);
6064 
6065     hmenu = CreateMenu();
6066     assert(hmenu != 0);
6067     SetLastError(0xdeadbeef);
6068     hwnd = CreateWindowExA(0, "static", NULL, WS_CHILD | WS_POPUP | WS_CAPTION,
6069                            0, 0, 100, 100, parent, hmenu, 0, NULL);
6070     ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError());
6071     expect_menu(hwnd, hmenu);
6072     expect_style(hwnd, WS_CHILD | WS_POPUP | WS_CAPTION | WS_CLIPSIBLINGS);
6073     expect_ex_style(hwnd, WS_EX_WINDOWEDGE);
6074     DestroyWindow(hwnd);
6075     SetLastError(0xdeadbeef);
6076     ok(!IsMenu(hmenu), "IsMenu should fail\n");
6077     expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE);
6078 
6079     /* test child window sizing */
6080     cls.style = 0;
6081     cls.lpfnWndProc = minmax_wnd_proc;
6082     cls.cbClsExtra = 0;
6083     cls.cbWndExtra = 0;
6084     cls.hInstance = GetModuleHandleA(NULL);
6085     cls.hIcon = 0;
6086     cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
6087     cls.hbrBackground = GetStockObject(WHITE_BRUSH);
6088     cls.lpszMenuName = NULL;
6089     cls.lpszClassName = "MinMax_WndClass";
6090     RegisterClassA(&cls);
6091 
6092     SetLastError(0xdeadbeef);
6093     parent = CreateWindowExA(0, "MinMax_WndClass", NULL, WS_CAPTION | WS_SYSMENU | WS_THICKFRAME,
6094                            0, 0, 100, 100, 0, 0, 0, NULL);
6095     ok(parent != 0, "CreateWindowEx error %d\n", GetLastError());
6096     expect_menu(parent, 0);
6097     expect_style(parent, WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_CLIPSIBLINGS);
6098     expect_ex_style(parent, WS_EX_WINDOWEDGE);
6099 
6100     memset(&minmax, 0, sizeof(minmax));
6101     SendMessageA(parent, WM_GETMINMAXINFO, 0, (LPARAM)&minmax);
6102     SetRect(&rc_minmax, 0, 0, minmax.ptMaxSize.x, minmax.ptMaxSize.y);
6103     ok(IsRectEmpty(&rc_minmax), "ptMaxSize is not empty\n");
6104     SetRect(&rc_minmax, 0, 0, minmax.ptMaxTrackSize.x, minmax.ptMaxTrackSize.y);
6105     ok(IsRectEmpty(&rc_minmax), "ptMaxTrackSize is not empty\n");
6106 
6107     GetWindowRect(parent, &rc);
6108     ok(!IsRectEmpty(&rc), "parent window rect is empty\n");
6109     GetClientRect(parent, &rc);
6110     ok(!IsRectEmpty(&rc), "parent client rect is empty\n");
6111 
6112     InflateRect(&rc, 200, 200);
6113     trace("creating child with rect %s\n", wine_dbgstr_rect(&rc));
6114 
6115     SetLastError(0xdeadbeef);
6116     hwnd = CreateWindowExA(0, "MinMax_WndClass", NULL, WS_CHILD | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME,
6117                           rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top,
6118                           parent, (HMENU)1, 0, NULL);
6119     ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError());
6120     expect_menu(hwnd, 1);
6121     expect_style(hwnd, WS_CHILD | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME);
6122     expect_ex_style(hwnd, WS_EX_WINDOWEDGE);
6123 
6124     memset(&minmax, 0, sizeof(minmax));
6125     SendMessageA(hwnd, WM_GETMINMAXINFO, 0, (LPARAM)&minmax);
6126     SetRect(&rc_minmax, 0, 0, minmax.ptMaxTrackSize.x, minmax.ptMaxTrackSize.y);
6127 
6128     GetWindowRect(hwnd, &rc);
6129     OffsetRect(&rc, -rc.left, -rc.top);
6130     ok(EqualRect(&rc, &rc_minmax), "rects don't match: %s and %s\n", wine_dbgstr_rect(&rc),
6131        wine_dbgstr_rect(&rc_minmax));
6132     DestroyWindow(hwnd);
6133 
6134     cls.lpfnWndProc = winsizes_wnd_proc;
6135     cls.lpszClassName = "Sizes_WndClass";
6136     RegisterClassA(&cls);
6137 
6138     expected_cx = expected_cy = 200000;
6139     SetRect( &expected_rect, 0, 0, 200000, 200000 );
6140     broken_rect = expected_rect;
6141     hwnd = CreateWindowExA(0, "Sizes_WndClass", NULL, WS_CHILD, 300000, 300000, 200000, 200000, parent, 0, 0, NULL);
6142     ok( hwnd != 0, "creation failed err %u\n", GetLastError());
6143     GetClientRect( hwnd, &rc );
6144     ok( rc.right == 200000 || rc.right == 65535 || broken(rc.right == (short)200000),
6145         "invalid rect right %u\n", rc.right );
6146     ok( rc.bottom == 200000 || rc.bottom == 65535 || broken(rc.bottom == (short)200000),
6147         "invalid rect bottom %u\n", rc.bottom );
6148     DestroyWindow(hwnd);
6149 
6150     expected_cx = expected_cy = -10;
6151     SetRectEmpty(&expected_rect);
6152     SetRect( &broken_rect, 0, 0, -10, -10 );
6153     hwnd = CreateWindowExA(0, "Sizes_WndClass", NULL, WS_CHILD, -20, -20, -10, -10, parent, 0, 0, NULL);
6154     ok( hwnd != 0, "creation failed err %u\n", GetLastError());
6155     GetClientRect( hwnd, &rc );
6156     ok( rc.right == 0, "invalid rect right %u\n", rc.right );
6157     ok( rc.bottom == 0, "invalid rect bottom %u\n", rc.bottom );
6158     DestroyWindow(hwnd);
6159 
6160     expected_cx = expected_cy = -200000;
6161     SetRectEmpty(&expected_rect);
6162     SetRect( &broken_rect, 0, 0, -200000, -200000 );
6163     hwnd = CreateWindowExA(0, "Sizes_WndClass", NULL, WS_CHILD, -300000, -300000, -200000, -200000, parent, 0, 0, NULL);
6164     ok( hwnd != 0, "creation failed err %u\n", GetLastError());
6165     GetClientRect( hwnd, &rc );
6166     ok( rc.right == 0, "invalid rect right %u\n", rc.right );
6167     ok( rc.bottom == 0, "invalid rect bottom %u\n", rc.bottom );
6168     DestroyWindow(hwnd);
6169 
6170     /* we need a parent at 0,0 so that child coordinates match */
6171     DestroyWindow(parent);
6172     parent = CreateWindowExA(0, "MinMax_WndClass", NULL, WS_POPUP, 0, 0, 100, 100, 0, 0, 0, NULL);
6173     ok(parent != 0, "CreateWindowEx error %d\n", GetLastError());
6174 
6175     expected_cx = 100;
6176     expected_cy = 0x7fffffff;
6177     SetRect( &expected_rect, 10, 10, 110, 0x7fffffff );
6178     SetRect( &broken_rect, 10, 10, 110, 0x7fffffffU + 10 );
6179     hwnd = CreateWindowExA(0, "Sizes_WndClass", NULL, WS_CHILD, 10, 10, 100, 0x7fffffff, parent, 0, 0, NULL);
6180     ok( hwnd != 0, "creation failed err %u\n", GetLastError());
6181     GetClientRect( hwnd, &rc );
6182     ok( rc.right == 100, "invalid rect right %u\n", rc.right );
6183     ok( rc.bottom == 0x7fffffff - 10 || rc.bottom ==65535 || broken(rc.bottom == 0),
6184         "invalid rect bottom %u\n", rc.bottom );
6185     DestroyWindow(hwnd);
6186 
6187     expected_cx = 0x7fffffff;
6188     expected_cy = 0x7fffffff;
6189     SetRect( &expected_rect, 20, 10, 0x7fffffff, 0x7fffffff );
6190     SetRect( &broken_rect, 20, 10, 0x7fffffffU + 20, 0x7fffffffU + 10 );
6191     hwnd = CreateWindowExA(0, "Sizes_WndClass", NULL, WS_CHILD, 20, 10, 0x7fffffff, 0x7fffffff, parent, 0, 0, NULL);
6192     ok( hwnd != 0, "creation failed err %u\n", GetLastError());
6193     GetClientRect( hwnd, &rc );
6194     ok( rc.right == 0x7fffffff - 20 || rc.right == 65535 || broken(rc.right == 0),
6195         "invalid rect right %u\n", rc.right );
6196     ok( rc.bottom == 0x7fffffff - 10 || rc.right == 65535 || broken(rc.bottom == 0),
6197         "invalid rect bottom %u\n", rc.bottom );
6198     DestroyWindow(hwnd);
6199 
6200     /* top level window */
6201     expected_cx = expected_cy = 200000;
6202     SetRect( &expected_rect, 0, 0, GetSystemMetrics(SM_CXMAXTRACK), GetSystemMetrics(SM_CYMAXTRACK) );
6203     hwnd = CreateWindowExA(0, "Sizes_WndClass", NULL, WS_OVERLAPPEDWINDOW, 300000, 300000, 200000, 200000, 0, 0, 0, NULL);
6204     ok( hwnd != 0, "creation failed err %u\n", GetLastError());
6205     GetClientRect( hwnd, &rc );
6206     ok( rc.right <= expected_cx, "invalid rect right %u\n", rc.right );
6207     ok( rc.bottom <= expected_cy, "invalid rect bottom %u\n", rc.bottom );
6208     DestroyWindow(hwnd);
6209 
6210     if (pGetLayout && pSetLayout)
6211     {
6212         HDC hdc = GetDC( parent );
6213         pSetLayout( hdc, LAYOUT_RTL );
6214         if (pGetLayout( hdc ))
6215         {
6216             ReleaseDC( parent, hdc );
6217             DestroyWindow( parent );
6218             SetLastError( 0xdeadbeef );
6219             parent = CreateWindowExA(WS_EX_APPWINDOW | WS_EX_LAYOUTRTL, "static", NULL, WS_POPUP,
6220                                     0, 0, 100, 100, 0, 0, 0, NULL);
6221             ok( parent != 0, "creation failed err %u\n", GetLastError());
6222             expect_ex_style( parent, WS_EX_APPWINDOW | WS_EX_LAYOUTRTL );
6223             hwnd = CreateWindowExA(0, "static", NULL, WS_CHILD, 0, 0, 20, 20, parent, 0, 0, NULL);
6224             ok( hwnd != 0, "creation failed err %u\n", GetLastError());
6225             expect_ex_style( hwnd, WS_EX_LAYOUTRTL );
6226             DestroyWindow( hwnd );
6227             hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0, 0, 20, 20, parent, 0, 0, NULL);
6228             ok( hwnd != 0, "creation failed err %u\n", GetLastError());
6229             expect_ex_style( hwnd, 0 );
6230             DestroyWindow( hwnd );
6231             SetWindowLongW( parent, GWL_EXSTYLE, WS_EX_APPWINDOW | WS_EX_LAYOUTRTL | WS_EX_NOINHERITLAYOUT );
6232             hwnd = CreateWindowExA(0, "static", NULL, WS_CHILD, 0, 0, 20, 20, parent, 0, 0, NULL);
6233             ok( hwnd != 0, "creation failed err %u\n", GetLastError());
6234             expect_ex_style( hwnd, 0 );
6235             DestroyWindow( hwnd );
6236 
6237             if (pGetProcessDefaultLayout && pSetProcessDefaultLayout)
6238             {
6239                 DWORD layout;
6240 
6241                 SetLastError( 0xdeadbeef );
6242                 ok( !pGetProcessDefaultLayout( NULL ), "GetProcessDefaultLayout succeeded\n" );
6243                 ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
6244                 SetLastError( 0xdeadbeef );
6245                 res = pGetProcessDefaultLayout( &layout );
6246                 ok( res, "GetProcessDefaultLayout failed err %u\n", GetLastError ());
6247                 ok( layout == 0, "GetProcessDefaultLayout wrong layout %x\n", layout );
6248                 SetLastError( 0xdeadbeef );
6249                 res = pSetProcessDefaultLayout( 7 );
6250                 ok( res, "SetProcessDefaultLayout failed err %u\n", GetLastError ());
6251                 res = pGetProcessDefaultLayout( &layout );
6252                 ok( res, "GetProcessDefaultLayout failed err %u\n", GetLastError ());
6253                 ok( layout == 7, "GetProcessDefaultLayout wrong layout %x\n", layout );
6254                 SetLastError( 0xdeadbeef );
6255                 res = pSetProcessDefaultLayout( LAYOUT_RTL );
6256                 ok( res, "SetProcessDefaultLayout failed err %u\n", GetLastError ());
6257                 res = pGetProcessDefaultLayout( &layout );
6258                 ok( res, "GetProcessDefaultLayout failed err %u\n", GetLastError ());
6259                 ok( layout == LAYOUT_RTL, "GetProcessDefaultLayout wrong layout %x\n", layout );
6260                 hwnd = CreateWindowExA(WS_EX_APPWINDOW, "static", NULL, WS_POPUP,
6261                                       0, 0, 100, 100, 0, 0, 0, NULL);
6262                 ok( hwnd != 0, "creation failed err %u\n", GetLastError());
6263                 expect_ex_style( hwnd, WS_EX_APPWINDOW | WS_EX_LAYOUTRTL );
6264                 DestroyWindow( hwnd );
6265                 hwnd = CreateWindowExA(WS_EX_APPWINDOW, "static", NULL, WS_POPUP,
6266                                       0, 0, 100, 100, parent, 0, 0, NULL);
6267                 ok( hwnd != 0, "creation failed err %u\n", GetLastError());
6268                 expect_ex_style( hwnd, WS_EX_APPWINDOW );
6269                 DestroyWindow( hwnd );
6270                 pSetProcessDefaultLayout( 0 );
6271             }
6272             else win_skip( "SetProcessDefaultLayout not supported\n" );
6273         }
6274         else win_skip( "SetLayout not supported\n" );
6275     }
6276     else win_skip( "SetLayout not available\n" );
6277 
6278     DestroyWindow(parent);
6279 
6280     UnregisterClassA("MinMax_WndClass", GetModuleHandleA(NULL));
6281     UnregisterClassA("Sizes_WndClass", GetModuleHandleA(NULL));
6282 
6283 #undef expect_gle_broken_9x
6284 #undef expect_menu
6285 #undef expect_style
6286 #undef expect_ex_style
6287 }
6288 
6289 /* function that remembers whether the system the test is running on sets the
6290  * last error for user32 functions to make the tests stricter */
6291 static int check_error(DWORD actual, DWORD expected)
6292 {
6293     static int sets_last_error = -1;
6294     if (sets_last_error == -1)
6295         sets_last_error = (actual != 0xdeadbeef);
6296     return (!sets_last_error && (actual == 0xdeadbeef)) || (actual == expected);
6297 }
6298 
6299 static void test_SetWindowLong(void)
6300 {
6301     LONG_PTR retval;
6302     WNDPROC old_window_procW;
6303 
6304     SetLastError(0xdeadbeef);
6305     retval = SetWindowLongPtrA(NULL, GWLP_WNDPROC, 0);
6306     ok(!retval, "SetWindowLongPtr on invalid window handle should have returned 0 instead of 0x%lx\n", retval);
6307     ok(check_error(GetLastError(), ERROR_INVALID_WINDOW_HANDLE),
6308         "SetWindowLongPtr should have set error to ERROR_INVALID_WINDOW_HANDLE instead of %d\n", GetLastError());
6309 
6310     SetLastError(0xdeadbeef);
6311     retval = SetWindowLongPtrA(hwndMain, 0xdeadbeef, 0);
6312     ok(!retval, "SetWindowLongPtr on invalid index should have returned 0 instead of 0x%lx\n", retval);
6313     ok(check_error(GetLastError(), ERROR_INVALID_INDEX),
6314         "SetWindowLongPtr should have set error to ERROR_INVALID_INDEX instead of %d\n", GetLastError());
6315 
6316     SetLastError(0xdeadbeef);
6317     retval = SetWindowLongPtrA(hwndMain, GWLP_WNDPROC, 0);
6318     ok((WNDPROC)retval == main_window_procA || broken(!retval), /* win9x */
6319         "SetWindowLongPtr on invalid window proc should have returned address of main_window_procA instead of 0x%lx\n", retval);
6320     ok(GetLastError() == 0xdeadbeef, "SetWindowLongPtr shouldn't have set the last error, instead of setting it to %d\n", GetLastError());
6321     retval = GetWindowLongPtrA(hwndMain, GWLP_WNDPROC);
6322     ok((WNDPROC)retval == main_window_procA,
6323         "SetWindowLongPtr on invalid window proc shouldn't have changed the value returned by GetWindowLongPtr, instead of changing it to 0x%lx\n", retval);
6324     ok(!IsWindowUnicode(hwndMain), "hwndMain shouldn't be Unicode\n");
6325 
6326     old_window_procW = (WNDPROC)GetWindowLongPtrW(hwndMain, GWLP_WNDPROC);
6327     SetLastError(0xdeadbeef);
6328     retval = SetWindowLongPtrW(hwndMain, GWLP_WNDPROC, 0);
6329     if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
6330     {
6331         ok(GetLastError() == 0xdeadbeef, "SetWindowLongPtr shouldn't have set the last error, instead of setting it to %d\n", GetLastError());
6332         ok(retval != 0, "SetWindowLongPtr error %d\n", GetLastError());
6333         ok((WNDPROC)retval == old_window_procW,
6334             "SetWindowLongPtr on invalid window proc shouldn't have changed the value returned by GetWindowLongPtr, instead of changing it to 0x%lx\n", retval);
6335         ok(IsWindowUnicode(hwndMain), "hwndMain should now be Unicode\n");
6336 
6337         /* set it back to ANSI */
6338         SetWindowLongPtrA(hwndMain, GWLP_WNDPROC, 0);
6339     }
6340 }
6341 
6342 static LRESULT WINAPI check_style_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
6343 {
6344     const STYLESTRUCT *expected = (STYLESTRUCT *)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
6345     const STYLESTRUCT *got = (STYLESTRUCT *)lParam;
6346 
6347     if (message == WM_STYLECHANGING && wParam == GWL_STYLE)
6348     {
6349         ok(got->styleOld == expected[0].styleOld, "expected old style %#x, got %#x\n",
6350             expected[0].styleOld, got->styleOld);
6351         ok(got->styleNew == expected[0].styleNew, "expected new style %#x, got %#x\n",
6352             expected[0].styleNew, got->styleNew);
6353     }
6354     else if (message == WM_STYLECHANGED && wParam == GWL_STYLE)
6355     {
6356         ok(got->styleOld == expected[1].styleOld, "expected old style %#x, got %#x\n",
6357             expected[1].styleOld, got->styleOld);
6358         ok(got->styleNew == expected[1].styleNew, "expected new style %#x, got %#x\n",
6359             expected[1].styleNew, got->styleNew);
6360     }
6361 
6362     return DefWindowProcA(hwnd, message, wParam, lParam);
6363 }
6364 
6365 static void test_set_window_style(void)
6366 {
6367     LONG expected_style, new_style, old_style;
6368     STYLESTRUCT expected_stylestruct[2];
6369     unsigned int i;
6370     WNDCLASSA cls;
6371     HWND hwnd;
6372 
6373     static const struct
6374     {
6375         LONG creation_style;
6376         LONG style;
6377     }
6378     tests[] =
6379     {
6380         { WS_MINIMIZE | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
6381           WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX },
6382         { WS_MINIMIZE | WS_CLIPSIBLINGS | WS_CAPTION,
6383           WS_CLIPSIBLINGS | WS_CAPTION },
6384         { WS_MAXIMIZE | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
6385           WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX },
6386         { WS_MAXIMIZE | WS_CLIPSIBLINGS | WS_CAPTION,
6387           WS_CLIPSIBLINGS | WS_CAPTION },
6388         { WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
6389           WS_MINIMIZE | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX },
6390         { WS_CLIPSIBLINGS | WS_CAPTION,
6391           WS_MINIMIZE | WS_CLIPSIBLINGS | WS_CAPTION },
6392         { WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
6393           WS_MAXIMIZE | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX },
6394         { WS_CLIPSIBLINGS | WS_CAPTION,
6395           WS_MAXIMIZE | WS_CLIPSIBLINGS | WS_CAPTION },
6396     };
6397 
6398     memset(&cls, 0, sizeof(cls));
6399     cls.lpfnWndProc = check_style_wnd_proc;
6400     cls.hInstance = GetModuleHandleA(0);
6401     cls.lpszClassName = "TestSetWindowStylesClass";
6402     ok(RegisterClassA(&cls), "RegisterClass failed\n");
6403 
6404     for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
6405     {
6406         expected_style = tests[i].style;
6407         if (tests[i].creation_style & WS_MINIMIZE)
6408             expected_style |= WS_MINIMIZE;
6409 
6410         expected_stylestruct[0].styleOld = tests[i].creation_style;
6411         expected_stylestruct[0].styleNew = tests[i].style;
6412         expected_stylestruct[1].styleOld = tests[i].creation_style;
6413         expected_stylestruct[1].styleNew = expected_style;
6414 
6415         hwnd = CreateWindowA(cls.lpszClassName, "Test set styles",
6416                              tests[i].creation_style, 100, 100, 200, 200, 0, 0, 0, NULL);
6417         ok(hwnd != 0, "CreateWindow failed\n");
6418         SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)&expected_stylestruct);
6419 
6420         old_style = SetWindowLongA(hwnd, GWL_STYLE, tests[i].style);
6421         ok(old_style == tests[i].creation_style, "expected old style %#x, got %#x\n",
6422             tests[i].creation_style, old_style);
6423         new_style = GetWindowLongA(hwnd, GWL_STYLE);
6424         ok(new_style == expected_style, "expected new style %#x, got %#x\n",
6425             expected_style, new_style);
6426 
6427         SetWindowLongPtrA(hwnd, GWLP_USERDATA, 0);
6428         DestroyWindow(hwnd);
6429     }
6430 
6431     UnregisterClassA(cls.lpszClassName, cls.hInstance);
6432 }
6433 
6434 static void test_ShowWindow(void)
6435 {
6436     HWND hwnd;
6437     DWORD style;
6438     RECT rcMain, rc, rcMinimized;
6439     LPARAM ret;
6440 
6441     SetRect(&rcMain, 120, 120, 210, 210);
6442 
6443     hwnd = CreateWindowExA(0, "MainWindowClass", NULL,
6444                           WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
6445                           WS_MAXIMIZEBOX | WS_POPUP,
6446                           rcMain.left, rcMain.top,
6447                           rcMain.right - rcMain.left, rcMain.bottom - rcMain.top,
6448                           0, 0, 0, NULL);
6449     assert(hwnd);
6450 
6451     style = GetWindowLongA(hwnd, GWL_STYLE);
6452     ok(!(style & WS_DISABLED), "window should not be disabled\n");
6453     ok(!(style & WS_VISIBLE), "window should not be visible\n");
6454     ok(!(style & WS_MINIMIZE), "window should not be minimized\n");
6455     ok(!(style & WS_MAXIMIZE), "window should not be maximized\n");
6456     GetWindowRect(hwnd, &rc);
6457     ok(EqualRect(&rcMain, &rc), "expected %s, got %s\n", wine_dbgstr_rect(&rcMain),
6458        wine_dbgstr_rect(&rc));
6459 
6460     ret = ShowWindow(hwnd, SW_SHOW);
6461     ok(!ret, "not expected ret: %lu\n", ret);
6462     style = GetWindowLongA(hwnd, GWL_STYLE);
6463     ok(!(style & WS_DISABLED), "window should not be disabled\n");
6464     ok(style & WS_VISIBLE, "window should be visible\n");
6465     ok(!(style & WS_MINIMIZE), "window should not be minimized\n");
6466     ok(!(style & WS_MAXIMIZE), "window should not be maximized\n");
6467     GetWindowRect(hwnd, &rc);
6468     ok(EqualRect(&rcMain, &rc), "expected %s, got %s\n", wine_dbgstr_rect(&rcMain),
6469        wine_dbgstr_rect(&rc));
6470 
6471     ret = ShowWindow(hwnd, SW_MINIMIZE);
6472     ok(ret, "not expected ret: %lu\n", ret);
6473     style = GetWindowLongA(hwnd, GWL_STYLE);
6474     ok(!(style & WS_DISABLED), "window should not be disabled\n");
6475     ok(style & WS_VISIBLE, "window should be visible\n");
6476     ok(style & WS_MINIMIZE, "window should be minimized\n");
6477     ok(!(style & WS_MAXIMIZE), "window should not be maximized\n");
6478     GetWindowRect(hwnd, &rcMinimized);
6479     ok(!EqualRect(&rcMain, &rcMinimized), "rects shouldn't match\n");
6480     /* shouldn't be able to resize minimized windows */
6481     ret = SetWindowPos(hwnd, 0, 0, 0,
6482                        (rcMinimized.right - rcMinimized.left) * 2,
6483                        (rcMinimized.bottom - rcMinimized.top) * 2,
6484                        SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
6485     ok(ret, "not expected ret: %lu\n", ret);
6486     GetWindowRect(hwnd, &rc);
6487     ok(EqualRect(&rc, &rcMinimized), "rects should match\n");
6488 
6489     ShowWindow(hwnd, SW_RESTORE);
6490     ok(ret, "not expected ret: %lu\n", ret);
6491     style = GetWindowLongA(hwnd, GWL_STYLE);
6492     ok(!(style & WS_DISABLED), "window should not be disabled\n");
6493     ok(style & WS_VISIBLE, "window should be visible\n");
6494     ok(!(style & WS_MINIMIZE), "window should not be minimized\n");
6495     ok(!(style & WS_MAXIMIZE), "window should not be maximized\n");
6496     GetWindowRect(hwnd, &rc);
6497     ok(EqualRect(&rcMain, &rc), "expected %s, got %s\n", wine_dbgstr_rect(&rcMain),
6498        wine_dbgstr_rect(&rc));
6499 
6500     ret = EnableWindow(hwnd, FALSE);
6501     ok(!ret, "not expected ret: %lu\n", ret);
6502     style = GetWindowLongA(hwnd, GWL_STYLE);
6503     ok(style & WS_DISABLED, "window should be disabled\n");
6504 
6505     ret = DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
6506     ok(!ret, "not expected ret: %lu\n", ret);
6507     style = GetWindowLongA(hwnd, GWL_STYLE);
6508     ok(style & WS_DISABLED, "window should be disabled\n");
6509     ok(style & WS_VISIBLE, "window should be visible\n");
6510     ok(!(style & WS_MINIMIZE), "window should not be minimized\n");
6511     ok(!(style & WS_MAXIMIZE), "window should not be maximized\n");
6512     GetWindowRect(hwnd, &rc);
6513     ok(EqualRect(&rcMain, &rc), "expected %s, got %s\n", wine_dbgstr_rect(&rcMain),
6514        wine_dbgstr_rect(&rc));
6515 
6516     ret = DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
6517     ok(!ret, "not expected ret: %lu\n", ret);
6518     style = GetWindowLongA(hwnd, GWL_STYLE);
6519     ok(style & WS_DISABLED, "window should be disabled\n");
6520     ok(style & WS_VISIBLE, "window should be visible\n");
6521     ok(!(style & WS_MINIMIZE), "window should not be minimized\n");
6522     ok(!(style & WS_MAXIMIZE), "window should not be maximized\n");
6523     GetWindowRect(hwnd, &rc);
6524     ok(EqualRect(&rcMain, &rc), "expected %s, got %s\n", wine_dbgstr_rect(&rcMain),
6525        wine_dbgstr_rect(&rc));
6526 
6527     ret = ShowWindow(hwnd, SW_MINIMIZE);
6528     ok(ret, "not expected ret: %lu\n", ret);
6529     style = GetWindowLongA(hwnd, GWL_STYLE);
6530     ok(style & WS_DISABLED, "window should be disabled\n");
6531     ok(style & WS_VISIBLE, "window should be visible\n");
6532     ok(style & WS_MINIMIZE, "window should be minimized\n");
6533     ok(!(style & WS_MAXIMIZE), "window should not be maximized\n");
6534     GetWindowRect(hwnd, &rc);
6535     ok(!EqualRect(&rcMain, &rc), "rects shouldn't match\n");
6536 
6537     ret = DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);
6538     ok(!ret, "not expected ret: %lu\n", ret);
6539     style = GetWindowLongA(hwnd, GWL_STYLE);
6540     ok(style & WS_DISABLED, "window should be disabled\n");
6541     ok(style & WS_VISIBLE, "window should be visible\n");
6542     ok(style & WS_MINIMIZE, "window should be minimized\n");
6543     ok(!(style & WS_MAXIMIZE), "window should not be maximized\n");
6544     GetWindowRect(hwnd, &rc);
6545     ok(!EqualRect(&rcMain, &rc), "rects shouldn't match\n");
6546 
6547     ret = ShowWindow(hwnd, SW_RESTORE);
6548     ok(ret, "not expected ret: %lu\n", ret);
6549     style = GetWindowLongA(hwnd, GWL_STYLE);
6550     ok(style & WS_DISABLED, "window should be disabled\n");
6551     ok(style & WS_VISIBLE, "window should be visible\n");
6552     ok(!(style & WS_MINIMIZE), "window should not be minimized\n");
6553     ok(!(style & WS_MAXIMIZE), "window should not be maximized\n");
6554     GetWindowRect(hwnd, &rc);
6555     ok(EqualRect(&rcMain, &rc), "expected %s, got %s\n", wine_dbgstr_rect(&rcMain),
6556        wine_dbgstr_rect(&rc));
6557 
6558     ret = DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0);
6559     ok(!ret, "not expected ret: %lu\n", ret);
6560     ok(IsWindow(hwnd), "window should exist\n");
6561 
6562     ret = EnableWindow(hwnd, TRUE);
6563     ok(ret, "not expected ret: %lu\n", ret);
6564 
6565     ret = DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0);
6566     ok(!ret, "not expected ret: %lu\n", ret);
6567     ok(!IsWindow(hwnd), "window should not exist\n");
6568 }
6569 
6570 static DWORD CALLBACK gettext_msg_thread( LPVOID arg )
6571 {
6572     HWND hwnd = arg;
6573     char buf[32];
6574     INT buf_len;
6575 
6576     /* test GetWindowTextA */
6577     num_gettext_msgs = 0;
6578     memset( buf, 0, sizeof(buf) );
6579     buf_len = GetWindowTextA( hwnd, buf, sizeof(buf) );
6580     ok( buf_len != 0, "expected a nonempty window text\n" );
6581     ok( !strcmp(buf, "another_caption"), "got wrong window text '%s'\n", buf );
6582     ok( num_gettext_msgs == 1, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
6583 
6584     return 0;
6585 }
6586 
6587 static DWORD CALLBACK settext_msg_thread( LPVOID arg )
6588 {
6589     HWND hwnd = arg;
6590     BOOL success;
6591 
6592     /* test SetWindowTextA */
6593     num_settext_msgs = 0;
6594     success = SetWindowTextA( hwnd, "thread_caption" );
6595     ok( success, "SetWindowTextA failed\n" );
6596     ok( num_settext_msgs == 1, "got %u WM_SETTEXT messages\n", num_settext_msgs );
6597 
6598     return 0;
6599 }
6600 
6601 static void test_gettext(void)
6602 {
6603     DWORD tid, num_msgs;
6604     WCHAR bufW[32];
6605     HANDLE thread;
6606     BOOL success;
6607     char buf[32];
6608     INT buf_len;
6609     HWND hwnd, hwnd2;
6610     LRESULT r;
6611     MSG msg;
6612 
6613     hwnd = CreateWindowExA( 0, "MainWindowClass", "caption", WS_POPUP, 0, 0, 0, 0, 0, 0, 0, NULL );
6614     ok( hwnd != 0, "CreateWindowExA error %d\n", GetLastError() );
6615 
6616     /* test GetWindowTextA */
6617     num_gettext_msgs = 0;
6618     memset( buf, 0, sizeof(buf) );
6619     buf_len = GetWindowTextA( hwnd, buf, sizeof(buf) );
6620     ok( buf_len != 0, "expected a nonempty window text\n" );
6621     ok( !strcmp(buf, "caption"), "got wrong window text '%s'\n", buf );
6622     ok( num_gettext_msgs == 1, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
6623 
6624     /* other process window */
6625     strcpy( buf, "a" );
6626     buf_len = GetWindowTextA( GetDesktopWindow(), buf, sizeof(buf) );
6627     ok( buf_len == 0, "expected a nonempty window text\n" );
6628     ok( *buf == 0, "got wrong window text '%s'\n", buf );
6629 
6630     strcpy( buf, "blah" );
6631     buf_len = GetWindowTextA( GetDesktopWindow(), buf, 0 );
6632     ok( buf_len == 0, "expected a nonempty window text\n" );
6633     ok( !strcmp(buf, "blah"), "got wrong window text '%s'\n", buf );
6634 
6635     bufW[0] = 0xcc;
6636     buf_len = GetWindowTextW( GetDesktopWindow(), bufW, 0 );
6637     ok( buf_len == 0, "expected a nonempty window text\n" );
6638     ok( bufW[0] == 0xcc, "got %x\n", bufW[0] );
6639 
6640     g_wm_gettext_override.enabled = TRUE;
6641 
6642     num_gettext_msgs = 0;
6643     memset( buf, 0xcc, sizeof(buf) );
6644     g_wm_gettext_override.buff = buf;
6645     buf_len = GetWindowTextA( hwnd, buf, sizeof(buf) );
6646     ok( buf_len == 0, "got %d\n", buf_len );
6647     ok( *buf == 0, "got %x\n", *buf );
6648     ok( num_gettext_msgs == 1, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
6649 
6650     num_gettext_msgs = 0;
6651     strcpy( buf, "blah" );
6652     g_wm_gettext_override.buff = buf;
6653     buf_len = GetWindowTextA( hwnd, buf, 0 );
6654     ok( buf_len == 0, "got %d\n", buf_len );
6655     ok( !strcmp(buf, "blah"), "got %s\n", buf );
6656     ok( num_gettext_msgs == 0, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
6657 
6658     g_wm_gettext_override.enabled = FALSE;
6659 
6660     /* same for W window */
6661     hwnd2 = CreateWindowExW( 0, mainclassW, NULL, WS_POPUP, 0, 0, 0, 0, 0, 0, 0, NULL );
6662     ok( hwnd2 != 0, "CreateWindowExA error %d\n", GetLastError() );
6663 
6664     g_wm_gettext_override.enabled = TRUE;
6665 
6666     num_gettext_msgs = 0;
6667     memset( bufW, 0xcc, sizeof(bufW) );
6668     g_wm_gettext_override.buffW = bufW;
6669     buf_len = GetWindowTextW( hwnd2, bufW, sizeof(bufW)/sizeof(WCHAR) );
6670     ok( buf_len == 0, "got %d\n", buf_len );
6671     ok( *bufW == 0, "got %x\n", *bufW );
6672     ok( num_gettext_msgs == 1, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
6673 
6674     num_gettext_msgs = 0;
6675     memset( bufW, 0xcc, sizeof(bufW) );
6676     g_wm_gettext_override.buffW = bufW;
6677     buf_len = GetWindowTextW( hwnd2, bufW, 0 );
6678     ok( buf_len == 0, "got %d\n", buf_len );
6679     ok( *bufW == 0xcccc, "got %x\n", *bufW );
6680     ok( num_gettext_msgs == 0, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
6681 
6682     g_wm_gettext_override.enabled = FALSE;
6683 
6684     DestroyWindow( hwnd2 );
6685 
6686     /* test WM_GETTEXT */
6687     num_gettext_msgs = 0;
6688     memset( buf, 0, sizeof(buf) );
6689     r = SendMessageA( hwnd, WM_GETTEXT, sizeof(buf), (LONG_PTR)buf );
6690     ok( r != 0, "expected a nonempty window text\n" );
6691     ok( !strcmp(buf, "caption"), "got wrong window text '%s'\n", buf );
6692     ok( num_gettext_msgs == 1, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
6693 
6694     /* test SetWindowTextA */
6695     num_settext_msgs = 0;
6696     success = SetWindowTextA( hwnd, "new_caption" );
6697     ok( success, "SetWindowTextA failed\n" );
6698     ok( num_settext_msgs == 1, "got %u WM_SETTEXT messages\n", num_settext_msgs );
6699 
6700     num_gettext_msgs = 0;
6701     memset( buf, 0, sizeof(buf) );
6702     buf_len = GetWindowTextA( hwnd, buf, sizeof(buf) );
6703     ok( buf_len != 0, "expected a nonempty window text\n" );
6704     ok( !strcmp(buf, "new_caption"), "got wrong window text '%s'\n", buf );
6705     ok( num_gettext_msgs == 1, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
6706 
6707     /* test WM_SETTEXT */
6708     num_settext_msgs = 0;
6709     r = SendMessageA( hwnd, WM_SETTEXT, 0, (ULONG_PTR)"another_caption" );
6710     ok( r != 0, "WM_SETTEXT failed\n" );
6711     ok( num_settext_msgs == 1, "got %u WM_SETTEXT messages\n", num_settext_msgs );
6712 
6713     num_gettext_msgs = 0;
6714     memset( buf, 0, sizeof(buf) );
6715     buf_len = GetWindowTextA( hwnd, buf, sizeof(buf) );
6716     ok( buf_len != 0, "expected a nonempty window text\n" );
6717     ok( !strcmp(buf, "another_caption"), "got wrong window text '%s'\n", buf );
6718     ok( num_gettext_msgs == 1, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
6719 
6720     while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE ))
6721         DispatchMessageA( &msg );
6722 
6723     /* test interthread GetWindowTextA */
6724     num_msgs = 0;
6725     thread = CreateThread( NULL, 0, gettext_msg_thread, hwnd, 0, &tid );
6726     ok(thread != NULL, "CreateThread failed, error %d\n", GetLastError());
6727     while (MsgWaitForMultipleObjects( 1, &thread, FALSE, INFINITE, QS_SENDMESSAGE ) != WAIT_OBJECT_0)
6728     {
6729         while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE ))
6730             DispatchMessageA( &msg );
6731         num_msgs++;
6732     }
6733     CloseHandle( thread );
6734     ok( num_msgs >= 1, "got %u wakeups from MsgWaitForMultipleObjects\n", num_msgs );
6735 
6736     /* test interthread SetWindowText */
6737     num_msgs = 0;
6738     thread = CreateThread( NULL, 0, settext_msg_thread, hwnd, 0, &tid );
6739     ok(thread != NULL, "CreateThread failed, error %d\n", GetLastError());
6740     while (MsgWaitForMultipleObjects( 1, &thread, FALSE, INFINITE, QS_SENDMESSAGE ) != WAIT_OBJECT_0)
6741     {
6742         while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE ))
6743             DispatchMessageA( &msg );
6744         num_msgs++;
6745     }
6746     CloseHandle( thread );
6747     ok( num_msgs >= 1, "got %u wakeups from MsgWaitForMultipleObjects\n", num_msgs );
6748 
6749     num_gettext_msgs = 0;
6750     memset( buf, 0, sizeof(buf) );
6751     buf_len = GetWindowTextA( hwnd, buf, sizeof(buf) );
6752     ok( buf_len != 0, "expected a nonempty window text\n" );
6753     ok( !strcmp(buf, "thread_caption"), "got wrong window text '%s'\n", buf );
6754     ok( num_gettext_msgs == 1, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
6755 
6756     /* seems to crash on every modern Windows version */
6757     if (0)
6758     {
6759     r = SendMessageA( hwnd, WM_GETTEXT, 0x10, 0x1000);
6760     ok( r == 0, "settext should return zero\n");
6761 
6762     r = SendMessageA( hwnd, WM_GETTEXT, 0x10000, 0);
6763     ok( r == 0, "settext should return zero (%ld)\n", r);
6764 
6765     r = SendMessageA( hwnd, WM_GETTEXT, 0xff000000, 0x1000);
6766     ok( r == 0, "settext should return zero (%ld)\n", r);
6767 
6768     r = SendMessageA( hwnd, WM_GETTEXT, 0x1000, 0xff000000);
6769     ok( r == 0, "settext should return zero (%ld)\n", r);
6770     }
6771 
6772     DestroyWindow(hwnd);
6773 }
6774 
6775 
6776 static void test_GetUpdateRect(void)
6777 {
6778     MSG msg;
6779     BOOL ret, parent_wm_paint, grandparent_wm_paint;
6780     RECT rc1, rc2;
6781     HWND hgrandparent, hparent, hchild;
6782     WNDCLASSA cls;
6783     static const char classNameA[] = "GetUpdateRectClass";
6784 
6785     hgrandparent = CreateWindowA("static", "grandparent", WS_OVERLAPPEDWINDOW,
6786                                  0, 0, 100, 100, NULL, NULL, 0, NULL);
6787 
6788     hparent = CreateWindowA("static", "parent", WS_CHILD|WS_VISIBLE,
6789                             0, 0, 100, 100, hgrandparent, NULL, 0, NULL);
6790 
6791     hchild = CreateWindowA("static", "child", WS_CHILD|WS_VISIBLE,
6792                             10, 10, 30, 30, hparent, NULL, 0, NULL);
6793 
6794     ShowWindow(hgrandparent, SW_SHOW);
6795     UpdateWindow(hgrandparent);
6796     flush_events( TRUE );
6797 
6798     ShowWindow(hchild, SW_HIDE);
6799     SetRectEmpty(&rc2);
6800     ret = GetUpdateRect(hgrandparent, &rc1, FALSE);
6801     ok(!ret, "GetUpdateRect returned not empty region\n");
6802     ok(EqualRect(&rc1, &rc2), "rects do not match %s / %s\n", wine_dbgstr_rect(&rc1),
6803        wine_dbgstr_rect(&rc2));
6804 
6805     SetRect(&rc2, 10, 10, 40, 40);
6806     ret = GetUpdateRect(hparent, &rc1, FALSE);
6807     ok(ret, "GetUpdateRect returned empty region\n");
6808     ok(EqualRect(&rc1, &rc2), "rects do not match %s / %s\n", wine_dbgstr_rect(&rc1),
6809        wine_dbgstr_rect(&rc2));
6810 
6811     parent_wm_paint = FALSE;
6812     grandparent_wm_paint = FALSE;
6813     while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
6814     {
6815         if (msg.message == WM_PAINT)
6816         {
6817             if (msg.hwnd == hgrandparent) grandparent_wm_paint = TRUE;
6818             if (msg.hwnd == hparent) parent_wm_paint = TRUE;
6819         }
6820         DispatchMessageA(&msg);
6821     }
6822     ok(parent_wm_paint, "WM_PAINT should have been received in parent\n");
6823     ok(!grandparent_wm_paint, "WM_PAINT should NOT have been received in grandparent\n");
6824 
6825     DestroyWindow(hgrandparent);
6826 
6827     cls.style = 0;
6828     cls.lpfnWndProc = DefWindowProcA;
6829     cls.cbClsExtra = 0;
6830     cls.cbWndExtra = 0;
6831     cls.hInstance = GetModuleHandleA(0);
6832     cls.hIcon = 0;
6833     cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
6834     cls.hbrBackground = GetStockObject(WHITE_BRUSH);
6835     cls.lpszMenuName = NULL;
6836     cls.lpszClassName = classNameA;
6837 
6838     if(!RegisterClassA(&cls)) {
6839        trace("Register failed %d\n", GetLastError());
6840        return;
6841     }
6842 
6843     hgrandparent = CreateWindowA(classNameA, "grandparent", WS_OVERLAPPEDWINDOW,
6844                                  0, 0, 100, 100, NULL, NULL, 0, NULL);
6845 
6846     hparent = CreateWindowA(classNameA, "parent", WS_CHILD|WS_VISIBLE,
6847                             0, 0, 100, 100, hgrandparent, NULL, 0, NULL);
6848 
6849     hchild = CreateWindowA(classNameA, "child", WS_CHILD|WS_VISIBLE,
6850                             10, 10, 30, 30, hparent, NULL, 0, NULL);
6851 
6852     ShowWindow(hgrandparent, SW_SHOW);
6853     UpdateWindow(hgrandparent);
6854     flush_events( TRUE );
6855 
6856     ret = GetUpdateRect(hgrandparent, &rc1, FALSE);
6857     ok(!ret, "GetUpdateRect returned not empty region\n");
6858 
6859     ShowWindow(hchild, SW_HIDE);
6860 
6861     SetRectEmpty(&rc2);
6862     ret = GetUpdateRect(hgrandparent, &rc1, FALSE);
6863     ok(!ret, "GetUpdateRect returned not empty region\n");
6864     ok(EqualRect(&rc1, &rc2), "rects do not match %s / %s\n", wine_dbgstr_rect(&rc1),
6865        wine_dbgstr_rect(&rc2));
6866 
6867     SetRect(&rc2, 10, 10, 40, 40);
6868     ret = GetUpdateRect(hparent, &rc1, FALSE);
6869     ok(ret, "GetUpdateRect returned empty region\n");
6870     ok(EqualRect(&rc1, &rc2), "rects do not match %s / %s\n", wine_dbgstr_rect(&rc1),
6871        wine_dbgstr_rect(&rc2));
6872 
6873     parent_wm_paint = FALSE;
6874     grandparent_wm_paint = FALSE;
6875     while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
6876     {
6877         if (msg.message == WM_PAINT)
6878         {
6879             if (msg.hwnd == hgrandparent) grandparent_wm_paint = TRUE;
6880             if (msg.hwnd == hparent) parent_wm_paint = TRUE;
6881         }
6882         DispatchMessageA(&msg);
6883     }
6884     ok(parent_wm_paint, "WM_PAINT should have been received in parent\n");
6885     ok(!grandparent_wm_paint, "WM_PAINT should NOT have been received in grandparent\n");
6886 
6887     DestroyWindow(hgrandparent);
6888 }
6889 
6890 
6891 static LRESULT CALLBACK TestExposedRegion_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
6892 {
6893     if(msg == WM_PAINT)
6894     {
6895         PAINTSTRUCT ps;
6896         RECT updateRect;
6897         DWORD waitResult;
6898         HWND win;
6899         const int waitTime = 2000;
6900 
6901         BeginPaint(hwnd, &ps);
6902 
6903         /* create and destroy window to create an exposed region on this window */
6904         win = CreateWindowA("static", "win", WS_VISIBLE,
6905                              10,10,50,50, NULL, NULL, 0, NULL);
6906         DestroyWindow(win);
6907 
6908         waitResult = MsgWaitForMultipleObjects( 0, NULL, FALSE, waitTime, QS_PAINT );
6909 
6910         ValidateRect(hwnd, NULL);
6911         EndPaint(hwnd, &ps);
6912 
6913         if(waitResult != WAIT_TIMEOUT)
6914         {
6915             GetUpdateRect(hwnd, &updateRect, FALSE);
6916             ok(IsRectEmpty(&updateRect), "Exposed rect should be empty\n");
6917         }
6918 
6919         return 1;
6920     }
6921     return DefWindowProcA(hwnd, msg, wParam, lParam);
6922 }
6923 
6924 static void test_Expose(void)
6925 {
6926     WNDCLASSA cls;
6927     HWND mw;
6928 
6929     memset(&cls, 0, sizeof(WNDCLASSA));
6930     cls.lpfnWndProc = TestExposedRegion_WndProc;
6931     cls.hbrBackground = GetStockObject(WHITE_BRUSH);
6932     cls.lpszClassName = "TestExposeClass";
6933     RegisterClassA(&cls);
6934 
6935     mw = CreateWindowA("TestExposeClass", "MainWindow", WS_VISIBLE|WS_OVERLAPPEDWINDOW,
6936                             0, 0, 200, 100, NULL, NULL, 0, NULL);
6937 
6938     UpdateWindow(mw);
6939     DestroyWindow(mw);
6940 }
6941 
6942 static LRESULT CALLBACK TestNCRedraw_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
6943 {
6944     static UINT ncredrawflags;
6945     PAINTSTRUCT ps;
6946 
6947     switch(msg)
6948     {
6949     case WM_CREATE:
6950         ncredrawflags = *(UINT *) (((CREATESTRUCTA *)lParam)->lpCreateParams);
6951         return 0;
6952     case WM_NCPAINT:
6953         RedrawWindow(hwnd, NULL, NULL, ncredrawflags);
6954         break;
6955     case WM_PAINT:
6956         BeginPaint(hwnd, &ps);
6957         EndPaint(hwnd, &ps);
6958         return 0;
6959     }
6960     return DefWindowProcA(hwnd, msg, wParam, lParam);
6961 }
6962 
6963 static void run_NCRedrawLoop(UINT flags)
6964 {
6965     HWND hwnd;
6966     MSG msg;
6967 
6968     UINT loopcount = 0;
6969 
6970     hwnd = CreateWindowA("TestNCRedrawClass", "MainWindow",
6971                          WS_OVERLAPPEDWINDOW, 0, 0, 200, 100,
6972                          NULL, NULL, 0, &flags);
6973     ShowWindow(hwnd, SW_SHOW);
6974     UpdateWindow(hwnd);
6975     flush_events( FALSE );
6976     while (PeekMessageA(&msg, hwnd, 0, 0, PM_REMOVE))
6977     {
6978         if (msg.message == WM_PAINT) loopcount++;
6979         if (loopcount >= 100) break;
6980         TranslateMessage(&msg);
6981         DispatchMessageA(&msg);
6982         MsgWaitForMultipleObjects(0, NULL, FALSE, 100, QS_ALLINPUT);
6983     }
6984     todo_wine_if (flags == (RDW_INVALIDATE | RDW_FRAME))
6985         ok(loopcount < 100, "Detected infinite WM_PAINT loop (%x).\n", flags);
6986     DestroyWindow(hwnd);
6987 }
6988 
6989 static void test_NCRedraw(void)
6990 {
6991     WNDCLASSA wndclass;
6992 
6993     wndclass.lpszClassName = "TestNCRedrawClass";
6994     wndclass.style = CS_HREDRAW | CS_VREDRAW;
6995     wndclass.lpfnWndProc = TestNCRedraw_WndProc;
6996     wndclass.cbClsExtra = 0;
6997     wndclass.cbWndExtra = 0;
6998     wndclass.hInstance = 0;
6999     wndclass.hIcon = LoadIconA(0, (LPCSTR)IDI_APPLICATION);
7000     wndclass.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
7001     wndclass.hbrBackground = GetStockObject(WHITE_BRUSH);
7002     wndclass.lpszMenuName = NULL;
7003 
7004     RegisterClassA(&wndclass);
7005 
7006     run_NCRedrawLoop(RDW_INVALIDATE | RDW_FRAME);
7007     run_NCRedrawLoop(RDW_INVALIDATE);
7008 }
7009 
7010 static void test_GetWindowModuleFileName(void)
7011 {
7012     HWND hwnd;
7013     HINSTANCE hinst;
7014     UINT ret1, ret2;
7015     char buf1[MAX_PATH], buf2[MAX_PATH];
7016 
7017     if (!pGetWindowModuleFileNameA)
7018     {
7019         win_skip("GetWindowModuleFileNameA is not available\n");
7020         return;
7021     }
7022 
7023     hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0,0,0,0, 0, 0, 0, NULL);
7024     assert(hwnd);
7025 
7026     hinst = (HINSTANCE)GetWindowLongPtrA(hwnd, GWLP_HINSTANCE);
7027     ok(hinst == 0 || broken(hinst == GetModuleHandleA(NULL)), /* win9x */ "expected 0, got %p\n", hinst);
7028 
7029     buf1[0] = 0;
7030     SetLastError(0xdeadbeef);
7031     ret1 = GetModuleFileNameA(hinst, buf1, sizeof(buf1));
7032     ok(ret1, "GetModuleFileName error %u\n", GetLastError());
7033 
7034     buf2[0] = 0;
7035     SetLastError(0xdeadbeef);
7036     ret2 = pGetWindowModuleFileNameA(hwnd, buf2, sizeof(buf2));
7037     ok(ret2 || broken(!ret2), /* nt4 sp 3 */
7038        "GetWindowModuleFileNameA error %u\n", GetLastError());
7039 
7040     if (ret2)
7041     {
7042         ok(ret1 == ret2 || broken(ret2 == ret1 + 1), /* win98 */ "%u != %u\n", ret1, ret2);
7043         ok(!strcmp(buf1, buf2), "%s != %s\n", buf1, buf2);
7044     }
7045     hinst = GetModuleHandleA(NULL);
7046 
7047     SetLastError(0xdeadbeef);
7048     ret2 = GetModuleFileNameA(hinst, buf2, ret1 - 2);
7049     ok(ret2 == ret1 - 2 || broken(ret2 == ret1 - 3), /* win98 */
7050        "expected %u, got %u\n", ret1 - 2, ret2);
7051     ok(GetLastError() == 0xdeadbeef /* XP */ ||
7052        GetLastError() == ERROR_INSUFFICIENT_BUFFER, /* win2k3, vista */
7053        "expected 0xdeadbeef or ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
7054 
7055     SetLastError(0xdeadbeef);
7056     ret2 = GetModuleFileNameA(hinst, buf2, 0);
7057     ok(!ret2, "GetModuleFileName should return 0\n");
7058     ok(GetLastError() == 0xdeadbeef /* XP */ ||
7059        GetLastError() == ERROR_INSUFFICIENT_BUFFER, /* win2k3, vista */
7060        "expected 0xdeadbeef or ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
7061 
7062     SetLastError(0xdeadbeef);
7063     ret2 = pGetWindowModuleFileNameA(hwnd, buf2, ret1 - 2);
7064     ok(ret2 == ret1 - 2 || broken(ret2 == ret1 - 3) /* win98 */ || broken(!ret2), /* nt4 sp3 */
7065        "expected %u, got %u\n", ret1 - 2, ret2);
7066     ok(GetLastError() == 0xdeadbeef /* XP */ ||
7067        GetLastError() == ERROR_INSUFFICIENT_BUFFER, /* win2k3, vista */
7068        "expected 0xdeadbeef or ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
7069 
7070     SetLastError(0xdeadbeef);
7071     ret2 = pGetWindowModuleFileNameA(hwnd, buf2, 0);
7072     ok(!ret2, "expected 0, got %u\n", ret2);
7073     ok(GetLastError() == 0xdeadbeef /* XP */ ||
7074        GetLastError() == ERROR_INSUFFICIENT_BUFFER, /* win2k3, vista */
7075        "expected 0xdeadbeef or ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
7076 
7077     DestroyWindow(hwnd);
7078 
7079     buf2[0] = 0;
7080     hwnd = (HWND)0xdeadbeef;
7081     SetLastError(0xdeadbeef);
7082     ret1 = pGetWindowModuleFileNameA(hwnd, buf1, sizeof(buf1));
7083     ok(!ret1, "expected 0, got %u\n", ret1);
7084     ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || broken(GetLastError() == 0xdeadbeef), /* win9x */
7085        "expected ERROR_INVALID_WINDOW_HANDLE, got %u\n", GetLastError());
7086 
7087     hwnd = FindWindowA("Shell_TrayWnd", NULL);
7088     ok(IsWindow(hwnd) || broken(!hwnd), "got invalid tray window %p\n", hwnd);
7089     SetLastError(0xdeadbeef);
7090     ret1 = pGetWindowModuleFileNameA(hwnd, buf1, sizeof(buf1));
7091     ok(!ret1 || broken(ret1), /* win98 */ "expected 0, got %u\n", ret1);
7092 
7093     if (!ret1)  /* inter-process GetWindowModuleFileName works on win9x, so don't test the desktop there */
7094     {
7095         ret1 = GetModuleFileNameA(0, buf1, sizeof(buf1));
7096         hwnd = GetDesktopWindow();
7097         ok(IsWindow(hwnd), "got invalid desktop window %p\n", hwnd);
7098         SetLastError(0xdeadbeef);
7099         ret2 = pGetWindowModuleFileNameA(hwnd, buf2, sizeof(buf2));
7100         ok(!ret2 ||
7101            ret1 == ret2 || /* vista */
7102            broken(ret2),  /* some win98 return user.exe as file name */
7103            "expected 0 or %u, got %u %s\n", ret1, ret2, buf2);
7104     }
7105 }
7106 
7107 static void test_hwnd_message(void)
7108 {
7109     static const WCHAR mainwindowclassW[] = {'M','a','i','n','W','i','n','d','o','w','C','l','a','s','s',0};
7110     static const WCHAR message_windowW[] = {'m','e','s','s','a','g','e',' ','w','i','n','d','o','w',0};
7111 
7112     HWND parent = 0, hwnd, found;
7113     RECT rect;
7114 
7115     /* HWND_MESSAGE is not supported below w2k, but win9x return != 0
7116        on CreateWindowExA and crash later in the test.
7117        Use UNICODE here to fail on win9x */
7118     hwnd = CreateWindowExW(0, mainwindowclassW, message_windowW, WS_CAPTION | WS_VISIBLE,
7119                            100, 100, 200, 200, HWND_MESSAGE, 0, 0, NULL);
7120     if (!hwnd)
7121     {
7122         win_skip("CreateWindowExW with parent HWND_MESSAGE failed\n");
7123         return;
7124     }
7125 
7126     ok( !GetParent(hwnd), "GetParent should return 0 for message only windows\n" );
7127     if (pGetAncestor)
7128     {
7129         char buffer[100];
7130         HWND root, desktop = GetDesktopWindow();
7131 
7132         parent = pGetAncestor(hwnd, GA_PARENT);
7133         ok(parent != 0, "GetAncestor(GA_PARENT) should not return 0 for message windows\n");
7134         ok(parent != desktop, "GetAncestor(GA_PARENT) should not return desktop for message windows\n");
7135         root = pGetAncestor(hwnd, GA_ROOT);
7136         ok(root == hwnd, "GetAncestor(GA_ROOT) should return hwnd for message windows\n");
7137         ok( !pGetAncestor(parent, GA_PARENT) || broken(pGetAncestor(parent, GA_PARENT) != 0), /* win2k */
7138             "parent shouldn't have parent %p\n", pGetAncestor(parent, GA_PARENT) );
7139         trace("parent %p root %p desktop %p\n", parent, root, desktop);
7140         if (!GetClassNameA( parent, buffer, sizeof(buffer) )) buffer[0] = 0;
7141         ok( !lstrcmpiA( buffer, "Message" ), "wrong parent class '%s'\n", buffer );
7142         GetWindowRect( parent, &rect );
7143         ok( rect.left == 0 && rect.right == 100 && rect.top == 0 && rect.bottom == 100,
7144             "wrong parent rect %s\n", wine_dbgstr_rect( &rect ));
7145     }
7146     GetWindowRect( hwnd, &rect );
7147     ok( rect.left == 100 && rect.right == 300 && rect.top == 100 && rect.bottom == 300,
7148         "wrong window rect %s\n", wine_dbgstr_rect( &rect ));
7149 
7150     /* test FindWindow behavior */
7151 
7152     found = FindWindowExA( 0, 0, 0, "message window" );
7153     ok( found == hwnd, "didn't find message window %p/%p\n", found, hwnd );
7154     SetLastError(0xdeadbeef);
7155     found = FindWindowExA( GetDesktopWindow(), 0, 0, "message window" );
7156     ok( found == 0, "found message window %p/%p\n", found, hwnd );
7157     ok( GetLastError() == 0xdeadbeef, "expected deadbeef, got %d\n", GetLastError() );
7158     if (parent)
7159     {
7160         found = FindWindowExA( parent, 0, 0, "message window" );
7161         ok( found == hwnd, "didn't find message window %p/%p\n", found, hwnd );
7162     }
7163 
7164     /* test IsChild behavior */
7165 
7166     if (parent) ok( !IsChild( parent, hwnd ), "HWND_MESSAGE is child of top window\n" );
7167 
7168     /* test IsWindowVisible behavior */
7169 
7170     ok( !IsWindowVisible( hwnd ), "HWND_MESSAGE window is visible\n" );
7171     if (parent) ok( !IsWindowVisible( parent ), "HWND_MESSAGE parent is visible\n" );
7172 
7173     DestroyWindow(hwnd);
7174 }
7175 
7176 static void test_layered_window(void)
7177 {
7178     HWND hwnd;
7179     COLORREF key = 0;
7180     BYTE alpha = 0;
7181     DWORD flags = 0;
7182     POINT pt = { 0, 0 };
7183     SIZE sz = { 200, 200 };
7184     HDC hdc;
7185     HBITMAP hbm;
7186     BOOL ret;
7187 
7188     if (!pGetLayeredWindowAttributes || !pSetLayeredWindowAttributes || !pUpdateLayeredWindow)
7189     {
7190         win_skip( "layered windows not supported\n" );
7191         return;
7192     }
7193 
7194     hdc = CreateCompatibleDC( 0 );
7195     hbm = CreateCompatibleBitmap( hdc, 200, 200 );
7196     SelectObject( hdc, hbm );
7197 
7198     hwnd = CreateWindowExA(0, "MainWindowClass", "message window", WS_CAPTION,
7199                            100, 100, 200, 200, 0, 0, 0, NULL);
7200     assert( hwnd );
7201     SetLastError( 0xdeadbeef );
7202     ret = pUpdateLayeredWindow( hwnd, 0, NULL, &sz, hdc, &pt, 0, NULL, ULW_OPAQUE );
7203     ok( !ret, "UpdateLayeredWindow should fail on non-layered window\n" );
7204     ok( GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError() );
7205     ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags );
7206     ok( !ret, "GetLayeredWindowAttributes should fail on non-layered window\n" );
7207     ret = pSetLayeredWindowAttributes( hwnd, 0, 0, LWA_ALPHA );
7208     ok( !ret, "SetLayeredWindowAttributes should fail on non-layered window\n" );
7209     SetWindowLongA( hwnd, GWL_EXSTYLE, GetWindowLongA(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED );
7210     ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags );
7211     ok( !ret, "GetLayeredWindowAttributes should fail on layered but not initialized window\n" );
7212     ret = pUpdateLayeredWindow( hwnd, 0, NULL, &sz, hdc, &pt, 0, NULL, ULW_OPAQUE );
7213     ok( ret, "UpdateLayeredWindow should succeed on layered window\n" );
7214     ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags );
7215     ok( !ret, "GetLayeredWindowAttributes should fail on layered but not initialized window\n" );
7216     ret = pSetLayeredWindowAttributes( hwnd, 0x123456, 44, LWA_ALPHA );
7217     ok( ret, "SetLayeredWindowAttributes should succeed on layered window\n" );
7218     ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags );
7219     ok( ret, "GetLayeredWindowAttributes should succeed on layered window\n" );
7220     ok( key == 0x123456 || key == 0, "wrong color key %x\n", key );
7221     ok( alpha == 44, "wrong alpha %u\n", alpha );
7222     ok( flags == LWA_ALPHA, "wrong flags %x\n", flags );
7223     SetLastError( 0xdeadbeef );
7224     ret = pUpdateLayeredWindow( hwnd, 0, NULL, &sz, hdc, &pt, 0, NULL, ULW_OPAQUE );
7225     ok( !ret, "UpdateLayeredWindow should fail on layered but initialized window\n" );
7226     ok( GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError() );
7227 
7228     /* clearing WS_EX_LAYERED resets attributes */
7229     SetWindowLongA( hwnd, GWL_EXSTYLE, GetWindowLongA(hwnd, GWL_EXSTYLE) & ~WS_EX_LAYERED );
7230     SetLastError( 0xdeadbeef );
7231     ret = pUpdateLayeredWindow( hwnd, 0, NULL, &sz, hdc, &pt, 0, NULL, ULW_OPAQUE );
7232     ok( !ret, "UpdateLayeredWindow should fail on non-layered window\n" );
7233     ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags );
7234     ok( !ret, "GetLayeredWindowAttributes should fail on no longer layered window\n" );
7235     SetWindowLongA( hwnd, GWL_EXSTYLE, GetWindowLongA(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED );
7236     ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags );
7237     ok( !ret, "GetLayeredWindowAttributes should fail on layered but not initialized window\n" );
7238     ret = pUpdateLayeredWindow( hwnd, 0, NULL, &sz, hdc, &pt, 0, NULL, ULW_OPAQUE );
7239     ok( ret, "UpdateLayeredWindow should succeed on layered window\n" );
7240     ret = pUpdateLayeredWindow( hwnd, 0, NULL, &sz, hdc, &pt, 0, NULL, ULW_OPAQUE | ULW_EX_NORESIZE );
7241     ok( !ret, "UpdateLayeredWindow should fail with ex flag\n" );
7242     ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
7243     if (pUpdateLayeredWindowIndirect)
7244     {
7245         UPDATELAYEREDWINDOWINFO info;
7246         info.cbSize   = sizeof(info);
7247         info.hdcDst   = 0;
7248         info.pptDst   = NULL;
7249         info.psize    = &sz;
7250         info.hdcSrc   = hdc;
7251         info.pptSrc   = &pt;
7252         info.crKey    = 0;
7253         info.pblend   = NULL;
7254         info.dwFlags  = ULW_OPAQUE | ULW_EX_NORESIZE;
7255         info.prcDirty = NULL;
7256         ret = pUpdateLayeredWindowIndirect( hwnd, &info );
7257         ok( ret, "UpdateLayeredWindowIndirect should succeed on layered window\n" );
7258         sz.cx--;
7259         SetLastError(0);
7260         ret = pUpdateLayeredWindowIndirect( hwnd, &info );
7261         ok( !ret, "UpdateLayeredWindowIndirect should fail\n" );
7262         /* particular error code differs from version to version, could be ERROR_INCORRECT_SIZE,
7263            ERROR_MR_MID_NOT_FOUND or ERROR_GEN_FAILURE (Win8/Win10) */
7264         ok( GetLastError() != 0, "wrong error %u\n", GetLastError() );
7265         info.dwFlags  = ULW_OPAQUE;
7266         ret = pUpdateLayeredWindowIndirect( hwnd, &info );
7267         ok( ret, "UpdateLayeredWindowIndirect should succeed on layered window\n" );
7268         sz.cx++;
7269         info.dwFlags  = ULW_OPAQUE | 0xf00;
7270         ret = pUpdateLayeredWindowIndirect( hwnd, &info );
7271         ok( !ret, "UpdateLayeredWindowIndirect should fail\n" );
7272         ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
7273         info.cbSize--;
7274         info.dwFlags  = ULW_OPAQUE;
7275         ret = pUpdateLayeredWindowIndirect( hwnd, &info );
7276         ok( !ret, "UpdateLayeredWindowIndirect should fail\n" );
7277         ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
7278         ret = pUpdateLayeredWindowIndirect( hwnd, NULL );
7279         ok( !ret, "UpdateLayeredWindowIndirect should fail\n" );
7280         ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
7281     }
7282 
7283     ret = pSetLayeredWindowAttributes( hwnd, 0x654321, 22, LWA_COLORKEY | LWA_ALPHA );
7284     ok( ret, "SetLayeredWindowAttributes should succeed on layered window\n" );
7285     ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags );
7286     ok( ret, "GetLayeredWindowAttributes should succeed on layered window\n" );
7287     ok( key == 0x654321, "wrong color key %x\n", key );
7288     ok( alpha == 22, "wrong alpha %u\n", alpha );
7289     ok( flags == (LWA_COLORKEY | LWA_ALPHA), "wrong flags %x\n", flags );
7290     SetLastError( 0xdeadbeef );
7291     ret = pUpdateLayeredWindow( hwnd, 0, NULL, &sz, hdc, &pt, 0, NULL, ULW_OPAQUE );
7292     ok( !ret, "UpdateLayeredWindow should fail on layered but initialized window\n" );
7293     ok( GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError() );
7294 
7295     ret = pSetLayeredWindowAttributes( hwnd, 0x888888, 33, LWA_COLORKEY );
7296     ok( ret, "SetLayeredWindowAttributes should succeed on layered window\n" );
7297     alpha = 0;
7298     ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags );
7299     ok( ret, "GetLayeredWindowAttributes should succeed on layered window\n" );
7300     ok( key == 0x888888, "wrong color key %x\n", key );
7301     /* alpha not changed on vista if LWA_ALPHA is not set */
7302     ok( alpha == 22 || alpha == 33, "wrong alpha %u\n", alpha );
7303     ok( flags == LWA_COLORKEY, "wrong flags %x\n", flags );
7304 
7305     /* color key may or may not be changed without LWA_COLORKEY */
7306     ret = pSetLayeredWindowAttributes( hwnd, 0x999999, 44, 0 );
7307     ok( ret, "SetLayeredWindowAttributes should succeed on layered window\n" );
7308     alpha = 0;
7309     ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags );
7310     ok( ret, "GetLayeredWindowAttributes should succeed on layered window\n" );
7311     ok( key == 0x888888 || key == 0x999999, "wrong color key %x\n", key );
7312     ok( alpha == 22 || alpha == 44, "wrong alpha %u\n", alpha );
7313     ok( flags == 0, "wrong flags %x\n", flags );
7314 
7315     /* default alpha and color key is 0 */
7316     SetWindowLongA( hwnd, GWL_EXSTYLE, GetWindowLongA(hwnd, GWL_EXSTYLE) & ~WS_EX_LAYERED );
7317     SetWindowLongA( hwnd, GWL_EXSTYLE, GetWindowLongA(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED );
7318     ret = pSetLayeredWindowAttributes( hwnd, 0x222222, 55, 0 );
7319     ok( ret, "SetLayeredWindowAttributes should succeed on layered window\n" );
7320     ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags );
7321     ok( ret, "GetLayeredWindowAttributes should succeed on layered window\n" );
7322     ok( key == 0 || key == 0x222222, "wrong color key %x\n", key );
7323     ok( alpha == 0 || alpha == 55, "wrong alpha %u\n", alpha );
7324     ok( flags == 0, "wrong flags %x\n", flags );
7325 
7326     DestroyWindow( hwnd );
7327     DeleteDC( hdc );
7328     DeleteObject( hbm );
7329 }
7330 
7331 static MONITORINFO mi;
7332 
7333 static LRESULT CALLBACK fullscreen_wnd_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
7334 {
7335     switch (msg)
7336     {
7337         case WM_NCCREATE:
7338         {
7339             CREATESTRUCTA *cs = (CREATESTRUCTA *)lp;
7340             ok(cs->x == mi.rcMonitor.left && cs->y == mi.rcMonitor.top &&
7341                cs->cx == mi.rcMonitor.right && cs->cy == mi.rcMonitor.bottom,
7342                "expected %s, got (%d,%d)-(%d,%d)\n", wine_dbgstr_rect(&mi.rcMonitor),
7343                cs->x, cs->y, cs->cx, cs->cy);
7344             break;
7345         }
7346         case WM_GETMINMAXINFO:
7347         {
7348             MINMAXINFO *minmax = (MINMAXINFO *)lp;
7349             ok(minmax->ptMaxPosition.x <= mi.rcMonitor.left, "%d <= %d\n", minmax->ptMaxPosition.x, mi.rcMonitor.left);
7350             ok(minmax->ptMaxPosition.y <= mi.rcMonitor.top, "%d <= %d\n", minmax->ptMaxPosition.y, mi.rcMonitor.top);
7351             ok(minmax->ptMaxSize.x >= mi.rcMonitor.right, "%d >= %d\n", minmax->ptMaxSize.x, mi.rcMonitor.right);
7352             ok(minmax->ptMaxSize.y >= mi.rcMonitor.bottom, "%d >= %d\n", minmax->ptMaxSize.y, mi.rcMonitor.bottom);
7353             break;
7354         }
7355     }
7356     return DefWindowProcA(hwnd, msg, wp, lp);
7357 }
7358 
7359 static void test_fullscreen(void)
7360 {
7361     static const DWORD t_style[] = {
7362         WS_OVERLAPPED, WS_POPUP, WS_CHILD, WS_THICKFRAME, WS_DLGFRAME
7363     };
7364     static const DWORD t_ex_style[] = {
7365         0, WS_EX_APPWINDOW, WS_EX_TOOLWINDOW
7366     };
7367     WNDCLASSA cls;
7368     HWND hwnd;
7369     int i, j;
7370     POINT pt;
7371     RECT rc;
7372     HMONITOR hmon;
7373     LRESULT ret;
7374 
7375     if (!pGetMonitorInfoA || !pMonitorFromPoint)
7376     {
7377         win_skip("GetMonitorInfoA or MonitorFromPoint are not available on this platform\n");
7378         return;
7379     }
7380 
7381     pt.x = pt.y = 0;
7382     SetLastError(0xdeadbeef);
7383     hmon = pMonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY);
7384     ok(hmon != 0, "MonitorFromPoint error %u\n", GetLastError());
7385 
7386     mi.cbSize = sizeof(mi);
7387     SetLastError(0xdeadbeef);
7388     ret = pGetMonitorInfoA(hmon, &mi);
7389     ok(ret, "GetMonitorInfo error %u\n", GetLastError());
7390     trace("monitor %s, work %s\n", wine_dbgstr_rect(&mi.rcMonitor), wine_dbgstr_rect(&mi.rcWork));
7391 
7392     cls.style = 0;
7393     cls.lpfnWndProc = fullscreen_wnd_proc;
7394     cls.cbClsExtra = 0;
7395     cls.cbWndExtra = 0;
7396     cls.hInstance = GetModuleHandleA(NULL);
7397     cls.hIcon = 0;
7398     cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
7399     cls.hbrBackground = GetStockObject(WHITE_BRUSH);
7400     cls.lpszMenuName = NULL;
7401     cls.lpszClassName = "fullscreen_class";
7402     RegisterClassA(&cls);
7403 
7404     for (i = 0; i < sizeof(t_style)/sizeof(t_style[0]); i++)
7405     {
7406         DWORD style, ex_style;
7407 
7408         /* avoid a WM interaction */
7409         assert(!(t_style[i] & WS_VISIBLE));
7410 
7411         for (j = 0; j < sizeof(t_ex_style)/sizeof(t_ex_style[0]); j++)
7412         {
7413             int fixup;
7414 
7415             style = t_style[i];
7416             ex_style = t_ex_style[j];
7417 
7418             hwnd = CreateWindowExA(ex_style, "fullscreen_class", NULL, style,
7419                                    mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom,
7420                                    GetDesktopWindow(), 0, GetModuleHandleA(NULL), NULL);
7421             ok(hwnd != 0, "%d: CreateWindowExA(%#x/%#x) failed\n", i, ex_style, style);
7422             GetWindowRect(hwnd, &rc);
7423             trace("%#x/%#x: window rect %s\n", ex_style, style, wine_dbgstr_rect(&rc));
7424             ok(rc.left <= mi.rcMonitor.left && rc.top <= mi.rcMonitor.top &&
7425                rc.right >= mi.rcMonitor.right && rc.bottom >= mi.rcMonitor.bottom,
7426                "%#x/%#x: window rect %s\n", ex_style, style, wine_dbgstr_rect(&rc));
7427             DestroyWindow(hwnd);
7428 
7429             style = t_style[i] | WS_MAXIMIZE;
7430             hwnd = CreateWindowExA(ex_style, "fullscreen_class", NULL, style,
7431                                    mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom,
7432                                    GetDesktopWindow(), 0, GetModuleHandleA(NULL), NULL);
7433             ok(hwnd != 0, "%d: CreateWindowExA(%#x/%#x) failed\n", i, ex_style, style);
7434             GetWindowRect(hwnd, &rc);
7435             trace("%#x/%#x: window rect %s\n", ex_style, style, wine_dbgstr_rect(&rc));
7436             ok(rc.left <= mi.rcMonitor.left && rc.top <= mi.rcMonitor.top &&
7437                rc.right >= mi.rcMonitor.right && rc.bottom >= mi.rcMonitor.bottom,
7438                "%#x/%#x: window rect %s\n", ex_style, style, wine_dbgstr_rect(&rc));
7439             DestroyWindow(hwnd);
7440 
7441             style = t_style[i] | WS_MAXIMIZE | WS_CAPTION;
7442             hwnd = CreateWindowExA(ex_style, "fullscreen_class", NULL, style,
7443                                    mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom,
7444                                    GetDesktopWindow(), 0, GetModuleHandleA(NULL), NULL);
7445             ok(hwnd != 0, "%d: CreateWindowExA(%#x/%#x) failed\n", i, ex_style, style);
7446             GetWindowRect(hwnd, &rc);
7447             trace("%#x/%#x: window rect %s\n", ex_style, style, wine_dbgstr_rect(&rc));
7448             ok(rc.left <= mi.rcMonitor.left && rc.top <= mi.rcMonitor.top &&
7449                rc.right >= mi.rcMonitor.right && rc.bottom >= mi.rcMonitor.bottom,
7450                "%#x/%#x: window rect %s\n", ex_style, style, wine_dbgstr_rect(&rc));
7451             DestroyWindow(hwnd);
7452 
7453             style = t_style[i] | WS_CAPTION | WS_MAXIMIZEBOX;
7454             hwnd = CreateWindowExA(ex_style, "fullscreen_class", NULL, style,
7455                                    mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom,
7456                                    GetDesktopWindow(), 0, GetModuleHandleA(NULL), NULL);
7457             ok(hwnd != 0, "%d: CreateWindowExA(%#x/%#x) failed\n", i, ex_style, style);
7458             GetWindowRect(hwnd, &rc);
7459             trace("%#x/%#x: window rect %s\n", ex_style, style, wine_dbgstr_rect(&rc));
7460             ok(rc.left <= mi.rcMonitor.left && rc.top <= mi.rcMonitor.top &&
7461                rc.right >= mi.rcMonitor.right && rc.bottom >= mi.rcMonitor.bottom,
7462                "%#x/%#x: window rect %s\n", ex_style, style, wine_dbgstr_rect(&rc));
7463             DestroyWindow(hwnd);
7464 
7465             style = t_style[i] | WS_MAXIMIZE | WS_CAPTION | WS_MAXIMIZEBOX;
7466             hwnd = CreateWindowExA(ex_style, "fullscreen_class", NULL, style,
7467                                    mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom,
7468                                    GetDesktopWindow(), 0, GetModuleHandleA(NULL), NULL);
7469             ok(hwnd != 0, "%d: CreateWindowExA(%#x/%#x) failed\n", i, ex_style, style);
7470             GetWindowRect(hwnd, &rc);
7471             trace("%#x/%#x: window rect %s\n", ex_style, style, wine_dbgstr_rect(&rc));
7472             /* Windows makes a maximized window slightly larger (to hide the borders?) */
7473             fixup = min(abs(rc.left), abs(rc.top));
7474             InflateRect(&rc, -fixup, -fixup);
7475             ok(rc.left >= mi.rcMonitor.left && rc.top >= mi.rcMonitor.top &&
7476                rc.right <= mi.rcMonitor.right && rc.bottom <= mi.rcMonitor.bottom,
7477                "%#x/%#x: window rect %s must be in %s\n", ex_style, style, wine_dbgstr_rect(&rc),
7478                wine_dbgstr_rect(&mi.rcMonitor));
7479             DestroyWindow(hwnd);
7480 
7481             style = t_style[i] | WS_MAXIMIZE | WS_MAXIMIZEBOX;
7482             hwnd = CreateWindowExA(ex_style, "fullscreen_class", NULL, style,
7483                                    mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom,
7484                                    GetDesktopWindow(), 0, GetModuleHandleA(NULL), NULL);
7485             ok(hwnd != 0, "%d: CreateWindowExA(%#x/%#x) failed\n", i, ex_style, style);
7486             GetWindowRect(hwnd, &rc);
7487             trace("%#x/%#x: window rect %s\n", ex_style, style, wine_dbgstr_rect(&rc));
7488             /* Windows makes a maximized window slightly larger (to hide the borders?) */
7489             fixup = min(abs(rc.left), abs(rc.top));
7490             InflateRect(&rc, -fixup, -fixup);
7491             if (style & (WS_CHILD | WS_POPUP))
7492                 ok(rc.left <= mi.rcMonitor.left && rc.top <= mi.rcMonitor.top &&
7493                    rc.right >= mi.rcMonitor.right && rc.bottom >= mi.rcMonitor.bottom,
7494                    "%#x/%#x: window rect %s\n", ex_style, style, wine_dbgstr_rect(&rc));
7495             else
7496                 ok(rc.left >= mi.rcMonitor.left && rc.top >= mi.rcMonitor.top &&
7497                    rc.right <= mi.rcMonitor.right && rc.bottom <= mi.rcMonitor.bottom,
7498                    "%#x/%#x: window rect %s\n", ex_style, style, wine_dbgstr_rect(&rc));
7499             DestroyWindow(hwnd);
7500         }
7501     }
7502 
7503     UnregisterClassA("fullscreen_class", GetModuleHandleA(NULL));
7504 }
7505 
7506 static BOOL test_thick_child_got_minmax;
7507 static const char * test_thick_child_name;
7508 static LONG test_thick_child_style;
7509 static LONG test_thick_child_exStyle;
7510 
7511 static LRESULT WINAPI test_thick_child_size_winproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
7512 {
7513     MINMAXINFO* minmax;
7514     int expectedMinTrackX;
7515     int expectedMinTrackY;
7516     int actualMinTrackX;
7517     int actualMinTrackY;
7518     int expectedMaxTrackX;
7519     int expectedMaxTrackY;
7520     int actualMaxTrackX;
7521     int actualMaxTrackY;
7522     int expectedMaxSizeX;
7523     int expectedMaxSizeY;
7524     int actualMaxSizeX;
7525     int actualMaxSizeY;
7526     int expectedPosX;
7527     int expectedPosY;
7528     int actualPosX;
7529     int actualPosY;
7530     LONG adjustedStyle;
7531     RECT rect;
7532     switch (msg)
7533     {
7534         case WM_GETMINMAXINFO:
7535         {
7536             minmax = (MINMAXINFO *)lparam;
7537             trace("hwnd %p, WM_GETMINMAXINFO, %08lx, %08lx\n", hwnd, wparam, lparam);
7538             dump_minmax_info( minmax );
7539 
7540             test_thick_child_got_minmax = TRUE;
7541 
7542 
7543             adjustedStyle = test_thick_child_style;
7544             if ((adjustedStyle & WS_CAPTION) == WS_CAPTION)
7545                 adjustedStyle &= ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
7546             GetClientRect(GetParent(hwnd), &rect);
7547             AdjustWindowRectEx(&rect, adjustedStyle, FALSE, test_thick_child_exStyle);
7548 
7549             if (test_thick_child_style & (WS_DLGFRAME | WS_BORDER))
7550             {
7551                 expectedMinTrackX = GetSystemMetrics(SM_CXMINTRACK);
7552                 expectedMinTrackY = GetSystemMetrics(SM_CYMINTRACK);
7553             }
7554             else
7555             {
7556                 expectedMinTrackX = -2 * rect.left;
7557                 expectedMinTrackY = -2 * rect.top;
7558             }
7559             actualMinTrackX =  minmax->ptMinTrackSize.x;
7560             actualMinTrackY =  minmax->ptMinTrackSize.y;
7561 
7562             ok(actualMinTrackX == expectedMinTrackX && actualMinTrackY == expectedMinTrackY,
7563                 "expected minTrack %dx%d, actual minTrack %dx%d for %s\n",
7564                 expectedMinTrackX, expectedMinTrackY, actualMinTrackX, actualMinTrackY,
7565                 test_thick_child_name);
7566 
7567             actualMaxTrackX = minmax->ptMaxTrackSize.x;
7568             actualMaxTrackY = minmax->ptMaxTrackSize.y;
7569             expectedMaxTrackX = GetSystemMetrics(SM_CXMAXTRACK);
7570             expectedMaxTrackY = GetSystemMetrics(SM_CYMAXTRACK);
7571             ok(actualMaxTrackX == expectedMaxTrackX &&  actualMaxTrackY == expectedMaxTrackY,
7572                 "expected maxTrack %dx%d, actual maxTrack %dx%d for %s\n",
7573                  expectedMaxTrackX, expectedMaxTrackY, actualMaxTrackX, actualMaxTrackY,
7574                 test_thick_child_name);
7575 
7576             expectedMaxSizeX = rect.right - rect.left;
7577             expectedMaxSizeY = rect.bottom - rect.top;
7578             actualMaxSizeX = minmax->ptMaxSize.x;
7579             actualMaxSizeY = minmax->ptMaxSize.y;
7580 
7581             ok(actualMaxSizeX == expectedMaxSizeX &&  actualMaxSizeY == expectedMaxSizeY,
7582                 "expected maxSize %dx%d, actual maxSize %dx%d for %s\n",
7583                 expectedMaxSizeX, expectedMaxSizeY, actualMaxSizeX, actualMaxSizeY,
7584                 test_thick_child_name);
7585 
7586 
7587             expectedPosX = rect.left;
7588             expectedPosY = rect.top;
7589             actualPosX = minmax->ptMaxPosition.x;
7590             actualPosY = minmax->ptMaxPosition.y;
7591             ok(actualPosX == expectedPosX && actualPosY == expectedPosY,
7592                 "expected maxPosition (%d/%d), actual maxPosition (%d/%d) for %s\n",
7593                 expectedPosX, expectedPosY, actualPosX, actualPosY, test_thick_child_name);
7594 
7595             break;
7596         }
7597     }
7598 
7599     return DefWindowProcA(hwnd, msg, wparam, lparam);
7600 }
7601 
7602 #define NUMBER_OF_THICK_CHILD_TESTS 16
7603 static void test_thick_child_size(HWND parentWindow)
7604 {
7605     BOOL success;
7606     RECT childRect;
7607     RECT adjustedParentRect;
7608     HWND childWindow;
7609     LONG childWidth;
7610     LONG childHeight;
7611     LONG expectedWidth;
7612     LONG expectedHeight;
7613     WNDCLASSA cls;
7614     static const char className[] = "THICK_CHILD_CLASS";
7615     int i;
7616     LONG adjustedStyle;
7617     static const LONG styles[NUMBER_OF_THICK_CHILD_TESTS] = {
7618         WS_CHILD | WS_VISIBLE | WS_THICKFRAME,
7619         WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME,
7620         WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME | WS_BORDER,
7621         WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_BORDER,
7622         WS_CHILD | WS_VISIBLE | WS_THICKFRAME,
7623         WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME,
7624         WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME | WS_BORDER,
7625         WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_BORDER,
7626         WS_CHILD | WS_VISIBLE | WS_THICKFRAME,
7627         WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME,
7628         WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME | WS_BORDER,
7629         WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_BORDER,
7630         WS_CHILD | WS_VISIBLE | WS_THICKFRAME,
7631         WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME,
7632         WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME | WS_BORDER,
7633         WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_BORDER,
7634     };
7635 
7636     static const LONG exStyles[NUMBER_OF_THICK_CHILD_TESTS] = {
7637         0,
7638         0,
7639         0,
7640         0,
7641         WS_EX_DLGMODALFRAME,
7642         WS_EX_DLGMODALFRAME,
7643         WS_EX_DLGMODALFRAME,
7644         WS_EX_DLGMODALFRAME,
7645         WS_EX_STATICEDGE,
7646         WS_EX_STATICEDGE,
7647         WS_EX_STATICEDGE,
7648         WS_EX_STATICEDGE,
7649         WS_EX_STATICEDGE | WS_EX_DLGMODALFRAME,
7650         WS_EX_STATICEDGE | WS_EX_DLGMODALFRAME,
7651         WS_EX_STATICEDGE | WS_EX_DLGMODALFRAME,
7652         WS_EX_STATICEDGE | WS_EX_DLGMODALFRAME,
7653     };
7654     static const char *styleName[NUMBER_OF_THICK_CHILD_TESTS] = {
7655         "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME",
7656         "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME",
7657         "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME | WS_BORDER",
7658         "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_BORDER",
7659         "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME, exstyle= WS_EX_DLGMODALFRAME",
7660         "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME exstyle= WS_EX_DLGMODALFRAME",
7661         "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME | WS_BORDER exstyle= WS_EX_DLGMODALFRAME",
7662         "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_BORDER exstyle= WS_EX_DLGMODALFRAME",
7663         "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME exstyle= WS_EX_STATICEDGE",
7664         "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME exstyle= WS_EX_STATICEDGE",
7665         "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME | WS_BORDER exstyle= WS_EX_STATICEDGE",
7666         "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_BORDER exstyle= WS_EX_STATICEDGE",
7667         "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME, exstyle= WS_EX_STATICEDGE | WS_EX_DLGMODALFRAME",
7668         "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME exstyle= WS_EX_STATICEDGE | WS_EX_DLGMODALFRAME",
7669         "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME | WS_BORDER exstyle= WS_EX_STATICEDGE | WS_EX_DLGMODALFRAME",
7670         "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_BORDER exstyle= WS_EX_STATICEDGE | WS_EX_DLGMODALFRAME",
7671     };
7672 
7673     cls.style = 0;
7674     cls.lpfnWndProc = test_thick_child_size_winproc;
7675     cls.cbClsExtra = 0;
7676     cls.cbWndExtra = 0;
7677     cls.hInstance = GetModuleHandleA(0);
7678     cls.hIcon = 0;
7679     cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
7680     cls.hbrBackground = GetStockObject(WHITE_BRUSH);
7681     cls.lpszMenuName = NULL;
7682     cls.lpszClassName = className;
7683     SetLastError(0xdeadbeef);
7684     success = RegisterClassA(&cls);
7685     ok(success,"RegisterClassA failed, error: %u\n", GetLastError());
7686 
7687     for(i = 0; i < NUMBER_OF_THICK_CHILD_TESTS; i++)
7688     {
7689         test_thick_child_name = styleName[i];
7690         test_thick_child_style = styles[i];
7691         test_thick_child_exStyle = exStyles[i];
7692         test_thick_child_got_minmax = FALSE;
7693 
7694         SetLastError(0xdeadbeef);
7695         childWindow = CreateWindowExA( exStyles[i], className, "", styles[i],  0, 0, 0, 0, parentWindow, 0,  GetModuleHandleA(0),  NULL );
7696         ok(childWindow != NULL, "Failed to create child window, error: %u\n", GetLastError());
7697 
7698         ok(test_thick_child_got_minmax, "Got no WM_GETMINMAXINFO\n");
7699 
7700         SetLastError(0xdeadbeef);
7701         success = GetWindowRect(childWindow, &childRect);
7702         ok(success,"GetWindowRect call failed, error: %u\n", GetLastError());
7703         childWidth = childRect.right - childRect.left;
7704         childHeight = childRect.bottom - childRect.top;
7705 
7706         adjustedStyle = styles[i];
7707         if ((adjustedStyle & WS_CAPTION) == WS_CAPTION)
7708             adjustedStyle &= ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
7709         GetClientRect(GetParent(childWindow), &adjustedParentRect);
7710         AdjustWindowRectEx(&adjustedParentRect, adjustedStyle, FALSE, test_thick_child_exStyle);
7711 
7712 
7713         if (test_thick_child_style & (WS_DLGFRAME | WS_BORDER))
7714         {
7715             expectedWidth = GetSystemMetrics(SM_CXMINTRACK);
7716             expectedHeight = GetSystemMetrics(SM_CYMINTRACK);
7717         }
7718         else
7719         {
7720             expectedWidth = -2 * adjustedParentRect.left;
7721             expectedHeight = -2 * adjustedParentRect.top;
7722         }
7723 
7724         ok((childWidth == expectedWidth) && (childHeight == expectedHeight),
7725             "size of window (%s) is wrong: expected size %dx%d != actual size %dx%d\n",
7726             test_thick_child_name, expectedWidth, expectedHeight, childWidth, childHeight);
7727 
7728         SetLastError(0xdeadbeef);
7729         success = DestroyWindow(childWindow);
7730         ok(success,"DestroyWindow call failed, error: %u\n", GetLastError());
7731     }
7732     ok(UnregisterClassA(className, GetModuleHandleA(NULL)),"UnregisterClass call failed\n");
7733 }
7734 
7735 static void test_handles( HWND full_hwnd )
7736 {
7737     HWND hwnd = full_hwnd;
7738     BOOL ret;
7739     RECT rect;
7740 
7741     SetLastError( 0xdeadbeef );
7742     ret = GetWindowRect( hwnd, &rect );
7743     ok( ret, "GetWindowRect failed for %p err %u\n", hwnd, GetLastError() );
7744 
7745 #ifdef _WIN64
7746     if ((ULONG_PTR)full_hwnd >> 32)
7747         hwnd = (HWND)((ULONG_PTR)full_hwnd & ~0u);
7748     else
7749         hwnd = (HWND)((ULONG_PTR)full_hwnd | ((ULONG_PTR)~0u << 32));
7750     SetLastError( 0xdeadbeef );
7751     ret = GetWindowRect( hwnd, &rect );
7752     ok( ret, "GetWindowRect failed for %p err %u\n", hwnd, GetLastError() );
7753 
7754     hwnd = (HWND)(((ULONG_PTR)full_hwnd & ~0u) | ((ULONG_PTR)0x1234 << 32));
7755     SetLastError( 0xdeadbeef );
7756     ret = GetWindowRect( hwnd, &rect );
7757     ok( ret, "GetWindowRect failed for %p err %u\n", hwnd, GetLastError() );
7758 
7759     hwnd = (HWND)(((ULONG_PTR)full_hwnd & 0xffff) | ((ULONG_PTR)0x9876 << 16));
7760     SetLastError( 0xdeadbeef );
7761     ret = GetWindowRect( hwnd, &rect );
7762     ok( !ret, "GetWindowRect succeeded for %p\n", hwnd );
7763     ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
7764 
7765     hwnd = (HWND)(((ULONG_PTR)full_hwnd & 0xffff) | ((ULONG_PTR)0x12345678 << 16));
7766     SetLastError( 0xdeadbeef );
7767     ret = GetWindowRect( hwnd, &rect );
7768     ok( !ret, "GetWindowRect succeeded for %p\n", hwnd );
7769     ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
7770 #endif
7771 }
7772 
7773 static void test_winregion(void)
7774 {
7775     HWND hwnd;
7776     RECT r;
7777     int ret, width;
7778     HRGN hrgn;
7779 
7780     if (!pGetWindowRgnBox)
7781     {
7782         win_skip("GetWindowRgnBox not supported\n");
7783         return;
7784     }
7785 
7786     hwnd = CreateWindowExA(0, "static", NULL, WS_VISIBLE, 10, 10, 10, 10, NULL, 0, 0, NULL);
7787     /* NULL prect */
7788     SetLastError(0xdeadbeef);
7789     ret = pGetWindowRgnBox(hwnd, NULL);
7790     ok( ret == ERROR, "Expected ERROR, got %d\n", ret);
7791     ok( GetLastError() == 0xdeadbeef, "Expected , got %d\n", GetLastError());
7792 
7793     hrgn = CreateRectRgn(2, 3, 10, 15);
7794     ok( hrgn != NULL, "Region creation failed\n");
7795     if (hrgn)
7796     {
7797         SetWindowRgn(hwnd, hrgn, FALSE);
7798 
7799         SetLastError(0xdeadbeef);
7800         ret = pGetWindowRgnBox(hwnd, NULL);
7801         ok( ret == ERROR, "Expected ERROR, got %d\n", ret);
7802         ok( GetLastError() == 0xdeadbeef, "Expected , got %d\n", GetLastError());
7803 
7804         SetRectEmpty(&r);
7805         ret = pGetWindowRgnBox(hwnd, &r);
7806         ok( ret == SIMPLEREGION, "Expected SIMPLEREGION, got %d\n", ret);
7807         ok( r.left == 2 && r.top == 3 && r.right == 10 && r.bottom == 15,
7808            "Expected (2,3)-(10,15), got %s\n", wine_dbgstr_rect( &r ));
7809         if (pMirrorRgn)
7810         {
7811             hrgn = CreateRectRgn(2, 3, 10, 15);
7812             ret = pMirrorRgn( hwnd, hrgn );
7813             ok( ret == TRUE, "MirrorRgn failed %u\n", ret );
7814             SetRectEmpty(&r);
7815             GetWindowRect( hwnd, &r );
7816             width = r.right - r.left;
7817             SetRectEmpty(&r);
7818             ret = GetRgnBox( hrgn, &r );
7819             ok( ret == SIMPLEREGION, "GetRgnBox failed %u\n", ret );
7820             ok( r.left == width - 10 && r.top == 3 && r.right == width - 2 && r.bottom == 15,
7821                 "Wrong rectangle %s for width %d\n", wine_dbgstr_rect( &r ), width );
7822         }
7823         else win_skip( "MirrorRgn not supported\n" );
7824     }
7825     DestroyWindow(hwnd);
7826 }
7827 
7828 static void test_rtl_layout(void)
7829 {
7830     HWND parent, child;
7831     RECT r;
7832     POINT pt;
7833 
7834     if (!pSetProcessDefaultLayout)
7835     {
7836         win_skip( "SetProcessDefaultLayout not supported\n" );
7837         return;
7838     }
7839 
7840     parent = CreateWindowExA(WS_EX_LAYOUTRTL, "static", NULL, WS_POPUP, 100, 100, 300, 300, NULL, 0, 0, NULL);
7841     child = CreateWindowExA(0, "static", NULL, WS_CHILD, 10, 10, 20, 20, parent, 0, 0, NULL);
7842 
7843     GetWindowRect( parent, &r );
7844     ok( r.left == 100 && r.right == 400, "wrong rect %s\n", wine_dbgstr_rect( &r ));
7845     GetClientRect( parent, &r );
7846     ok( r.left == 0 && r.right == 300, "wrong rect %s\n", wine_dbgstr_rect( &r ));
7847     GetClientRect( child, &r );
7848     ok( r.left == 0 && r.right == 20, "wrong rect %s\n", wine_dbgstr_rect( &r ));
7849     MapWindowPoints( child, parent, (POINT *)&r, 2 );
7850     ok( r.left == 10 && r.right == 30, "wrong rect %s\n", wine_dbgstr_rect( &r ));
7851     GetWindowRect( child, &r );
7852     ok( r.left == 370 && r.right == 390, "wrong rect %s\n", wine_dbgstr_rect( &r ));
7853     MapWindowPoints( NULL, parent, (POINT *)&r, 2 );
7854     ok( r.left == 10 && r.right == 30, "wrong rect %s\n", wine_dbgstr_rect( &r ));
7855     GetWindowRect( child, &r );
7856     MapWindowPoints( NULL, parent, (POINT *)&r, 1 );
7857     MapWindowPoints( NULL, parent, (POINT *)&r + 1, 1 );
7858     ok( r.left == 30 && r.right == 10, "wrong rect %s\n", wine_dbgstr_rect( &r ));
7859     pt.x = pt.y = 12;
7860     MapWindowPoints( child, parent, &pt, 1 );
7861     ok( pt.x == 22 && pt.y == 22, "wrong point %d,%d\n", pt.x, pt.y );
7862     SetWindowPos( parent, 0, 0, 0, 250, 250, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE );
7863     GetWindowRect( parent, &r );
7864     ok( r.left == 100 && r.right == 350, "wrong rect %s\n", wine_dbgstr_rect( &r ));
7865     GetWindowRect( child, &r );
7866     ok( r.left == 320 && r.right == 340, "wrong rect %s\n", wine_dbgstr_rect( &r ));
7867     SetWindowLongW( parent, GWL_EXSTYLE, 0 );
7868     GetWindowRect( child, &r );
7869     ok( r.left == 320 && r.right == 340, "wrong rect %s\n", wine_dbgstr_rect( &r ));
7870     MapWindowPoints( NULL, parent, (POINT *)&r, 2 );
7871     ok( r.left == 220 && r.right == 240, "wrong rect %s\n", wine_dbgstr_rect( &r ));
7872     SetWindowLongW( parent, GWL_EXSTYLE, WS_EX_LAYOUTRTL );
7873     GetWindowRect( child, &r );
7874     ok( r.left == 320 && r.right == 340, "wrong rect %s\n", wine_dbgstr_rect( &r ));
7875     MapWindowPoints( NULL, parent, (POINT *)&r, 2 );
7876     ok( r.left == 10 && r.right == 30, "wrong rect %s\n", wine_dbgstr_rect( &r ));
7877     SetWindowPos( child, 0, 0, 0, 30, 30, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE );
7878     GetWindowRect( child, &r );
7879     ok( r.left == 310 && r.right == 340, "wrong rect %s\n", wine_dbgstr_rect( &r ));
7880     MapWindowPoints( NULL, parent, (POINT *)&r, 2 );
7881     ok( r.left == 10 && r.right == 40, "wrong rect %s\n", wine_dbgstr_rect( &r ));
7882     DestroyWindow( child );
7883     DestroyWindow( parent );
7884 }
7885 
7886 static void test_FlashWindow(void)
7887 {
7888     HWND hwnd;
7889     BOOL ret;
7890     if (!pFlashWindow)
7891     {
7892         win_skip( "FlashWindow not supported\n" );
7893         return;
7894     }
7895 
7896     hwnd = CreateWindowExA( 0, "MainWindowClass", "FlashWindow", WS_POPUP,
7897                             0, 0, 0, 0, 0, 0, 0, NULL );
7898     ok( hwnd != 0, "CreateWindowExA error %d\n", GetLastError() );
7899 
7900     SetLastError( 0xdeadbeef );
7901     ret = pFlashWindow( NULL, TRUE );
7902     ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
7903         "FlashWindow returned with %d\n", GetLastError() );
7904 
7905     DestroyWindow( hwnd );
7906 
7907     SetLastError( 0xdeadbeef );
7908     ret = pFlashWindow( hwnd, TRUE );
7909     ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
7910         "FlashWindow returned with %d\n", GetLastError() );
7911 }
7912 
7913 static void test_FlashWindowEx(void)
7914 {
7915     HWND hwnd;
7916     FLASHWINFO finfo;
7917     BOOL prev, ret;
7918 
7919     if (!pFlashWindowEx)
7920     {
7921         win_skip( "FlashWindowEx not supported\n" );
7922         return;
7923     }
7924 
7925     hwnd = CreateWindowExA( 0, "MainWindowClass", "FlashWindow", WS_POPUP,
7926                             0, 0, 0, 0, 0, 0, 0, NULL );
7927     ok( hwnd != 0, "CreateWindowExA error %d\n", GetLastError() );
7928 
7929     finfo.cbSize = sizeof(FLASHWINFO);
7930     finfo.dwFlags = FLASHW_TIMER;
7931     finfo.uCount = 3;
7932     finfo.dwTimeout = 200;
7933     finfo.hwnd = NULL;
7934     SetLastError(0xdeadbeef);
7935     ret = pFlashWindowEx(&finfo);
7936     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7937        "FlashWindowEx returned with %d\n", GetLastError());
7938 
7939     finfo.hwnd = hwnd;
7940     SetLastError(0xdeadbeef);
7941     ret = pFlashWindowEx(NULL);
7942     ok(!ret && GetLastError() == ERROR_NOACCESS,
7943        "FlashWindowEx returned with %d\n", GetLastError());
7944 
7945     SetLastError(0xdeadbeef);
7946     ret = pFlashWindowEx(&finfo);
7947     todo_wine ok(!ret, "previous window state should not be active\n");
7948 
7949     finfo.cbSize = sizeof(FLASHWINFO) - 1;
7950     SetLastError(0xdeadbeef);
7951     ret = pFlashWindowEx(&finfo);
7952     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7953        "FlashWindowEx succeeded\n");
7954 
7955     finfo.cbSize = sizeof(FLASHWINFO) + 1;
7956     SetLastError(0xdeadbeef);
7957     ret = pFlashWindowEx(&finfo);
7958     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7959        "FlashWindowEx succeeded\n");
7960     finfo.cbSize = sizeof(FLASHWINFO);
7961 
7962     DestroyWindow( hwnd );
7963 
7964     SetLastError(0xdeadbeef);
7965     ret = pFlashWindowEx(&finfo);
7966     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7967        "FlashWindowEx returned with %d\n", GetLastError());
7968 
7969     ok(finfo.cbSize == sizeof(FLASHWINFO), "FlashWindowEx modified cdSize to %x\n", finfo.cbSize);
7970     ok(finfo.hwnd == hwnd, "FlashWindowEx modified hwnd to %p\n", finfo.hwnd);
7971     ok(finfo.dwFlags == FLASHW_TIMER, "FlashWindowEx modified dwFlags to %x\n", finfo.dwFlags);
7972     ok(finfo.uCount == 3, "FlashWindowEx modified uCount to %x\n", finfo.uCount);
7973     ok(finfo.dwTimeout == 200, "FlashWindowEx modified dwTimeout to %x\n", finfo.dwTimeout);
7974 
7975     hwnd = CreateWindowExA( 0, "MainWindowClass", "FlashWindow", WS_VISIBLE | WS_POPUPWINDOW,
7976                             0, 0, 0, 0, 0, 0, 0, NULL );
7977     ok( hwnd != 0, "CreateWindowExA error %d\n", GetLastError() );
7978     finfo.hwnd = hwnd;
7979 
7980     SetLastError(0xdeadbeef);
7981     ret = pFlashWindowEx(NULL);
7982     ok(!ret && GetLastError() == ERROR_NOACCESS,
7983        "FlashWindowEx returned with %d\n", GetLastError());
7984 
7985     SetLastError(0xdeadbeef);
7986     prev = pFlashWindowEx(&finfo);
7987 
7988     ok(finfo.cbSize == sizeof(FLASHWINFO), "FlashWindowEx modified cdSize to %x\n", finfo.cbSize);
7989     ok(finfo.hwnd == hwnd, "FlashWindowEx modified hwnd to %p\n", finfo.hwnd);
7990     ok(finfo.dwFlags == FLASHW_TIMER, "FlashWindowEx modified dwFlags to %x\n", finfo.dwFlags);
7991     ok(finfo.uCount == 3, "FlashWindowEx modified uCount to %x\n", finfo.uCount);
7992     ok(finfo.dwTimeout == 200, "FlashWindowEx modified dwTimeout to %x\n", finfo.dwTimeout);
7993 
7994     finfo.dwFlags = FLASHW_STOP;
7995     SetLastError(0xdeadbeef);
7996     ret = pFlashWindowEx(&finfo);
7997     ok(prev != ret, "previous window state should be different\n");
7998 
7999     DestroyWindow( hwnd );
8000 }
8001 
8002 static void test_FindWindowEx(void)
8003 {
8004     HWND hwnd, found;
8005 
8006     hwnd = CreateWindowExA( 0, "MainWindowClass", "caption", WS_POPUP, 0,0,0,0, 0, 0, 0, NULL );
8007     ok( hwnd != 0, "CreateWindowExA error %d\n", GetLastError() );
8008 
8009     num_gettext_msgs = 0;
8010     found = FindWindowExA( 0, 0, "MainWindowClass", "" );
8011     ok( found == NULL, "expected a NULL hwnd\n" );
8012     ok( num_gettext_msgs == 0, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
8013 
8014     num_gettext_msgs = 0;
8015     found = FindWindowExA( 0, 0, "MainWindowClass", NULL );
8016     ok( found == hwnd, "found is %p, expected a valid hwnd\n", found );
8017     ok( num_gettext_msgs == 0, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
8018 
8019     num_gettext_msgs = 0;
8020     found = FindWindowExA( 0, 0, "MainWindowClass", "caption" );
8021     ok( found == hwnd, "found is %p, expected a valid hwnd\n", found );
8022     ok( num_gettext_msgs == 0, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
8023 
8024     DestroyWindow( hwnd );
8025 
8026     hwnd = CreateWindowExA( 0, "MainWindowClass", NULL, WS_POPUP, 0,0,0,0, 0, 0, 0, NULL );
8027     ok( hwnd != 0, "CreateWindowExA error %d\n", GetLastError() );
8028 
8029     num_gettext_msgs = 0;
8030     found = FindWindowExA( 0, 0, "MainWindowClass", "" );
8031     ok( found == hwnd, "found is %p, expected a valid hwnd\n", found );
8032     ok( num_gettext_msgs == 0, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
8033 
8034     num_gettext_msgs = 0;
8035     found = FindWindowExA( 0, 0, "MainWindowClass", NULL );
8036     ok( found == hwnd, "found is %p, expected a valid hwnd\n", found );
8037     ok( num_gettext_msgs == 0, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
8038 
8039     DestroyWindow( hwnd );
8040 
8041     /* test behaviour with a window title that is an empty character */
8042     found = FindWindowExA( 0, 0, "Shell_TrayWnd", "" );
8043     ok( found != NULL, "found is NULL, expected a valid hwnd\n" );
8044     found = FindWindowExA( 0, 0, "Shell_TrayWnd", NULL );
8045     ok( found != NULL, "found is NULL, expected a valid hwnd\n" );
8046 }
8047 
8048 static void test_GetLastActivePopup(void)
8049 {
8050     HWND hwndOwner, hwndPopup1, hwndPopup2;
8051 
8052     hwndOwner = CreateWindowExA(0, "MainWindowClass", NULL,
8053                                 WS_VISIBLE | WS_POPUPWINDOW,
8054                                 100, 100, 200, 200,
8055                                 NULL, 0, GetModuleHandleA(NULL), NULL);
8056     hwndPopup1 = CreateWindowExA(0, "MainWindowClass", NULL,
8057                                  WS_VISIBLE | WS_POPUPWINDOW,
8058                                  100, 100, 200, 200,
8059                                  hwndOwner, 0, GetModuleHandleA(NULL), NULL);
8060     hwndPopup2 = CreateWindowExA(0, "MainWindowClass", NULL,
8061                                  WS_VISIBLE | WS_POPUPWINDOW,
8062                                  100, 100, 200, 200,
8063                                  hwndPopup1, 0, GetModuleHandleA(NULL), NULL);
8064     ok( GetLastActivePopup(hwndOwner) == hwndPopup2, "wrong last active popup\n" );
8065     DestroyWindow( hwndPopup2 );
8066     DestroyWindow( hwndPopup1 );
8067     DestroyWindow( hwndOwner );
8068 }
8069 
8070 static LRESULT WINAPI my_httrasparent_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
8071 {
8072     if (msg == WM_NCHITTEST) return HTTRANSPARENT;
8073     return DefWindowProcA(hwnd, msg, wp, lp);
8074 }
8075 
8076 static LRESULT WINAPI my_window_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
8077 {
8078     return DefWindowProcA(hwnd, msg, wp, lp);
8079 }
8080 
8081 static void create_window_tree(HWND parent, HWND *window, int size)
8082 {
8083     static const DWORD style[] = { 0, WS_VISIBLE, WS_DISABLED, WS_VISIBLE | WS_DISABLED };
8084     int i, pos;
8085 
8086     memset(window, 0, size * sizeof(window[0]));
8087 
8088     pos = 0;
8089     for (i = 0; i < sizeof(style)/sizeof(style[0]); i++)
8090     {
8091         assert(pos < size);
8092         window[pos] = CreateWindowExA(0, "my_window", NULL, style[i] | WS_CHILD,
8093                                      0, 0, 100, 100, parent, 0, 0, NULL);
8094         ok(window[pos] != 0, "CreateWindowEx failed\n");
8095         pos++;
8096         assert(pos < size);
8097         window[pos] = CreateWindowExA(WS_EX_TRANSPARENT, "my_window", NULL, style[i] | WS_CHILD,
8098                                      0, 0, 100, 100, parent, 0, 0, NULL);
8099         ok(window[pos] != 0, "CreateWindowEx failed\n");
8100         pos++;
8101 
8102         assert(pos < size);
8103         window[pos] = CreateWindowExA(0, "my_httrasparent", NULL, style[i] | WS_CHILD,
8104                                      0, 0, 100, 100, parent, 0, 0, NULL);
8105         ok(window[pos] != 0, "CreateWindowEx failed\n");
8106         pos++;
8107         assert(pos < size);
8108         window[pos] = CreateWindowExA(WS_EX_TRANSPARENT, "my_httrasparent", NULL, style[i] | WS_CHILD,
8109                                      0, 0, 100, 100, parent, 0, 0, NULL);
8110         ok(window[pos] != 0, "CreateWindowEx failed\n");
8111         pos++;
8112 
8113         assert(pos < size);
8114         window[pos] = CreateWindowExA(0, "my_button", NULL, style[i] | WS_CHILD | BS_GROUPBOX,
8115                                      0, 0, 100, 100, parent, 0, 0, NULL);
8116         ok(window[pos] != 0, "CreateWindowEx failed\n");
8117         pos++;
8118         assert(pos < size);
8119         window[pos] = CreateWindowExA(WS_EX_TRANSPARENT, "my_button", NULL, style[i] | WS_CHILD | BS_GROUPBOX,
8120                                      0, 0, 100, 100, parent, 0, 0, NULL);
8121         ok(window[pos] != 0, "CreateWindowEx failed\n");
8122         pos++;
8123         assert(pos < size);
8124         window[pos] = CreateWindowExA(0, "my_button", NULL, style[i] | WS_CHILD | BS_PUSHBUTTON,
8125                                      0, 0, 100, 100, parent, 0, 0, NULL);
8126         ok(window[pos] != 0, "CreateWindowEx failed\n");
8127         pos++;
8128         assert(pos < size);
8129         window[pos] = CreateWindowExA(WS_EX_TRANSPARENT, "my_button", NULL, style[i] | WS_CHILD | BS_PUSHBUTTON,
8130                                      0, 0, 100, 100, parent, 0, 0, NULL);
8131         ok(window[pos] != 0, "CreateWindowEx failed\n");
8132         pos++;
8133 
8134         assert(pos < size);
8135         window[pos] = CreateWindowExA(0, "Button", NULL, style[i] | WS_CHILD | BS_GROUPBOX,
8136                                      0, 0, 100, 100, parent, 0, 0, NULL);
8137         ok(window[pos] != 0, "CreateWindowEx failed\n");
8138         pos++;
8139         assert(pos < size);
8140         window[pos] = CreateWindowExA(WS_EX_TRANSPARENT, "Button", NULL, style[i] | WS_CHILD | BS_GROUPBOX,
8141                                      0, 0, 100, 100, parent, 0, 0, NULL);
8142         ok(window[pos] != 0, "CreateWindowEx failed\n");
8143         pos++;
8144         assert(pos < size);
8145         window[pos] = CreateWindowExA(0, "Button", NULL, style[i] | WS_CHILD | BS_PUSHBUTTON,
8146                                      0, 0, 100, 100, parent, 0, 0, NULL);
8147         ok(window[pos] != 0, "CreateWindowEx failed\n");
8148         pos++;
8149         assert(pos < size);
8150         window[pos] = CreateWindowExA(WS_EX_TRANSPARENT, "Button", NULL, style[i] | WS_CHILD | BS_PUSHBUTTON,
8151                                      0, 0, 100, 100, parent, 0, 0, NULL);
8152         ok(window[pos] != 0, "CreateWindowEx failed\n");
8153         pos++;
8154 
8155         assert(pos < size);
8156         window[pos] = CreateWindowExA(0, "Static", NULL, style[i] | WS_CHILD,
8157                                      0, 0, 100, 100, parent, 0, 0, NULL);
8158         ok(window[pos] != 0, "CreateWindowEx failed\n");
8159         pos++;
8160         assert(pos < size);
8161         window[pos] = CreateWindowExA(WS_EX_TRANSPARENT, "Static", NULL, style[i] | WS_CHILD,
8162                                      0, 0, 100, 100, parent, 0, 0, NULL);
8163         ok(window[pos] != 0, "CreateWindowEx failed\n");
8164         pos++;
8165     }
8166 }
8167 
8168 struct window_attributes
8169 {
8170     char class_name[128];
8171     BOOL is_visible, is_enabled, is_groupbox, is_httransparent, is_extransparent;
8172 };
8173 
8174 static void get_window_attributes(HWND hwnd, struct window_attributes *attrs)
8175 {
8176     DWORD style, ex_style, hittest;
8177 
8178     style = GetWindowLongA(hwnd, GWL_STYLE);
8179     ex_style = GetWindowLongA(hwnd, GWL_EXSTYLE);
8180     attrs->class_name[0] = 0;
8181     GetClassNameA(hwnd, attrs->class_name, sizeof(attrs->class_name));
8182     hittest = SendMessageA(hwnd, WM_NCHITTEST, 0, 0);
8183 
8184     attrs->is_visible = (style & WS_VISIBLE) != 0;
8185     attrs->is_enabled = (style & WS_DISABLED) == 0;
8186     attrs->is_groupbox = !lstrcmpiA(attrs->class_name, "Button") && (style & BS_TYPEMASK) == BS_GROUPBOX;
8187     attrs->is_httransparent = hittest == HTTRANSPARENT;
8188     attrs->is_extransparent = (ex_style & WS_EX_TRANSPARENT) != 0;
8189 }
8190 
8191 static int window_to_index(HWND hwnd, HWND *window, int size)
8192 {
8193     int i;
8194 
8195     for (i = 0; i < size; i++)
8196     {
8197         if (!window[i]) break;
8198         if (window[i] == hwnd) return i;
8199     }
8200     return -1;
8201 }
8202 
8203 static void test_child_window_from_point(void)
8204 {
8205     static const int real_child_pos[] = { 14,15,16,17,18,19,20,21,24,25,26,27,42,43,
8206                                           44,45,46,47,48,49,52,53,54,55,51,50,23,22,-1 };
8207     static const int real_child_pos_nt4[] = { 14,15,16,17,20,21,24,25,26,27,42,43,44,45,
8208                                               48,49,52,53,54,55,51,50,47,46,23,22,19,18,-1 };
8209     WNDCLASSA cls;
8210     HWND hwnd, parent, window[100];
8211     POINT pt;
8212     int found_invisible, found_disabled, found_groupbox, found_httransparent, found_extransparent;
8213     int ret, i;
8214 
8215     ret = GetClassInfoA(0, "Button", &cls);
8216     ok(ret, "GetClassInfo(Button) failed\n");
8217     cls.lpszClassName = "my_button";
8218     ret = RegisterClassA(&cls);
8219     ok(ret, "RegisterClass(my_button) failed\n");
8220 
8221     cls.lpszClassName = "my_httrasparent";
8222     cls.lpfnWndProc = my_httrasparent_proc;
8223     ret = RegisterClassA(&cls);
8224     ok(ret, "RegisterClass(my_httrasparent) failed\n");
8225 
8226     cls.lpszClassName = "my_window";
8227     cls.lpfnWndProc = my_window_proc;
8228     ret = RegisterClassA(&cls);
8229     ok(ret, "RegisterClass(my_window) failed\n");
8230 
8231     parent = CreateWindowExA(0, "MainWindowClass", NULL,
8232                             WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_VISIBLE,
8233                             100, 100, 200, 200,
8234                             0, 0, GetModuleHandleA(NULL), NULL);
8235     ok(parent != 0, "CreateWindowEx failed\n");
8236     trace("parent %p\n", parent);
8237 
8238     create_window_tree(parent, window, sizeof(window)/sizeof(window[0]));
8239 
8240     found_invisible = 0;
8241     found_disabled = 0;
8242     found_groupbox = 0;
8243     found_httransparent = 0;
8244     found_extransparent = 0;
8245 
8246     /* FIXME: also test WindowFromPoint, ChildWindowFromPoint, ChildWindowFromPointEx */
8247     for (i = 0; i < sizeof(real_child_pos)/sizeof(real_child_pos[0]); i++)
8248     {
8249         struct window_attributes attrs;
8250 
8251         pt.x = pt.y = 50;
8252         hwnd = RealChildWindowFromPoint(parent, pt);
8253         ok(hwnd != 0, "RealChildWindowFromPoint failed\n");
8254         ret = window_to_index(hwnd, window, sizeof(window)/sizeof(window[0]));
8255         /* FIXME: remove once Wine is fixed */
8256         todo_wine_if (ret != real_child_pos[i])
8257             ok(ret == real_child_pos[i] || broken(ret == real_child_pos_nt4[i]), "expected %d, got %d\n", real_child_pos[i], ret);
8258 
8259         get_window_attributes(hwnd, &attrs);
8260         if (!attrs.is_visible) found_invisible++;
8261         if (!attrs.is_enabled) found_disabled++;
8262         if (attrs.is_groupbox) found_groupbox++;
8263         if (attrs.is_httransparent) found_httransparent++;
8264         if (attrs.is_extransparent) found_extransparent++;
8265 
8266         if (ret != real_child_pos[i] && ret != -1)
8267         {
8268             trace("found hwnd %p (%s), is_visible %d, is_enabled %d, is_groupbox %d, is_httransparent %d, is_extransparent %d\n",
8269                   hwnd, attrs.class_name, attrs.is_visible, attrs.is_enabled, attrs.is_groupbox, attrs.is_httransparent, attrs.is_extransparent);
8270             get_window_attributes(window[real_child_pos[i]], &attrs);
8271             trace("expected hwnd %p (%s), is_visible %d, is_enabled %d, is_groupbox %d, is_httransparent %d, is_extransparent %d\n",
8272                   window[real_child_pos[i]], attrs.class_name, attrs.is_visible, attrs.is_enabled, attrs.is_groupbox, attrs.is_httransparent, attrs.is_extransparent);
8273         }
8274         if (ret == -1)
8275         {
8276             ok(hwnd == parent, "expected %p, got %p\n", parent, hwnd);
8277             break;
8278         }
8279         DestroyWindow(hwnd);
8280     }
8281 
8282     DestroyWindow(parent);
8283 
8284     ok(!found_invisible, "found %d invisible windows\n", found_invisible);
8285     ok(found_disabled, "found %d disabled windows\n", found_disabled);
8286 todo_wine
8287     ok(found_groupbox == 4, "found %d groupbox windows\n", found_groupbox);
8288     ok(found_httransparent, "found %d httransparent windows\n", found_httransparent);
8289 todo_wine
8290     ok(found_extransparent, "found %d extransparent windows\n", found_extransparent);
8291 
8292     ret = UnregisterClassA("my_button", cls.hInstance);
8293     ok(ret, "UnregisterClass(my_button) failed\n");
8294     ret = UnregisterClassA("my_httrasparent", cls.hInstance);
8295     ok(ret, "UnregisterClass(my_httrasparent) failed\n");
8296     ret = UnregisterClassA("my_window", cls.hInstance);
8297     ok(ret, "UnregisterClass(my_window) failed\n");
8298 }
8299 
8300 static void simulate_click(int x, int y)
8301 {
8302     INPUT input[2];
8303     UINT events_no;
8304 
8305     SetCursorPos(x, y);
8306     memset(input, 0, sizeof(input));
8307     input[0].type = INPUT_MOUSE;
8308     U(input[0]).mi.dx = x;
8309     U(input[0]).mi.dy = y;
8310     U(input[0]).mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
8311     input[1].type = INPUT_MOUSE;
8312     U(input[1]).mi.dx = x;
8313     U(input[1]).mi.dy = y;
8314     U(input[1]).mi.dwFlags = MOUSEEVENTF_LEFTUP;
8315     events_no = SendInput(2, input, sizeof(input[0]));
8316     ok(events_no == 2, "SendInput returned %d\n", events_no);
8317 }
8318 
8319 static WNDPROC def_static_proc;
8320 static BOOL got_hittest;
8321 static LRESULT WINAPI static_hook_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
8322 {
8323     if(msg == WM_NCHITTEST)
8324         got_hittest = TRUE;
8325     if(msg == WM_LBUTTONDOWN)
8326         ok(0, "unexpected call\n");
8327 
8328     return def_static_proc(hwnd, msg, wp, lp);
8329 }
8330 
8331 static void window_from_point_proc(HWND parent)
8332 {
8333     HANDLE start_event, end_event;
8334     HANDLE win, child_static, child_button;
8335     BOOL got_click;
8336     DWORD ret;
8337     POINT pt;
8338     MSG msg;
8339 
8340     start_event = OpenEventA(EVENT_ALL_ACCESS, FALSE, "test_wfp_start");
8341     ok(start_event != 0, "OpenEvent failed\n");
8342     end_event = OpenEventA(EVENT_ALL_ACCESS, FALSE, "test_wfp_end");
8343     ok(end_event != 0, "OpenEvent failed\n");
8344 
8345     child_static = CreateWindowExA(0, "static", "static", WS_CHILD | WS_VISIBLE,
8346             0, 0, 100, 100, parent, 0, NULL, NULL);
8347     ok(child_static != 0, "CreateWindowEx failed\n");
8348     pt.x = pt.y = 150;
8349     win = WindowFromPoint(pt);
8350     ok(win == parent, "WindowFromPoint returned %p, expected %p\n", win, parent);
8351 
8352     child_button = CreateWindowExA(0, "button", "button", WS_CHILD | WS_VISIBLE,
8353             100, 0, 100, 100, parent, 0, NULL, NULL);
8354     ok(child_button != 0, "CreateWindowEx failed\n");
8355     pt.x = 250;
8356     win = WindowFromPoint(pt);
8357     ok(win == child_button, "WindowFromPoint returned %p, expected %p\n", win, child_button);
8358 
8359     /* without this window simulate click test keeps sending WM_NCHITTEST
8360      * message to child_static in an infinite loop */
8361     win = CreateWindowExA(0, "button", "button", WS_CHILD | WS_VISIBLE,
8362             0, 0, 100, 100, parent, 0, NULL, NULL);
8363     ok(win != 0, "CreateWindowEx failed\n");
8364     def_static_proc = (void*)SetWindowLongPtrA(child_static,
8365             GWLP_WNDPROC, (LONG_PTR)static_hook_proc);
8366     flush_events(TRUE);
8367     SetEvent(start_event);
8368 
8369     got_hittest = FALSE;
8370     got_click = FALSE;
8371     while(!got_click && wait_for_message(&msg)) {
8372         if(msg.message == WM_LBUTTONUP) {
8373             ok(msg.hwnd == win, "msg.hwnd = %p, expected %p\n", msg.hwnd, win);
8374             got_click = TRUE;
8375         }
8376         DispatchMessageA(&msg);
8377     }
8378     ok(got_hittest, "transparent window didn't get WM_NCHITTEST message\n");
8379     ok(got_click, "button under static window didn't get WM_LBUTTONUP\n");
8380 
8381     ret = WaitForSingleObject(end_event, 5000);
8382     ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", ret);
8383 
8384     CloseHandle(start_event);
8385     CloseHandle(end_event);
8386 }
8387 
8388 static void test_window_from_point(const char *argv0)
8389 {
8390     HWND hwnd, child, win;
8391     POINT pt;
8392     PROCESS_INFORMATION info;
8393     STARTUPINFOA startup;
8394     char cmd[MAX_PATH];
8395     HANDLE start_event, end_event;
8396 
8397     hwnd = CreateWindowExA(0, "MainWindowClass", NULL, WS_POPUP | WS_VISIBLE,
8398             100, 100, 200, 100, 0, 0, NULL, NULL);
8399     ok(hwnd != 0, "CreateWindowEx failed\n");
8400 
8401     pt.x = pt.y = 150;
8402     win = WindowFromPoint(pt);
8403     pt.x = 250;
8404     if(win == hwnd)
8405         win = WindowFromPoint(pt);
8406     if(win != hwnd) {
8407         skip("there's another window covering test window\n");
8408         DestroyWindow(hwnd);
8409         return;
8410     }
8411 
8412     child = CreateWindowExA(0, "static", "static", WS_CHILD | WS_VISIBLE,
8413             0, 0, 100, 100, hwnd, 0, NULL, NULL);
8414     ok(child != 0, "CreateWindowEx failed\n");
8415     pt.x = pt.y = 150;
8416     win = WindowFromPoint(pt);
8417     ok(win == hwnd, "WindowFromPoint returned %p, expected %p\n", win, hwnd);
8418     DestroyWindow(child);
8419 
8420     child = CreateWindowExA(0, "button", "button", WS_CHILD | WS_VISIBLE,
8421                 0, 0, 100, 100, hwnd, 0, NULL, NULL);
8422     ok(child != 0, "CreateWindowEx failed\n");
8423     win = WindowFromPoint(pt);
8424     ok(win == child, "WindowFromPoint returned %p, expected %p\n", win, child);
8425     DestroyWindow(child);
8426 
8427     start_event = CreateEventA(NULL, FALSE, FALSE, "test_wfp_start");
8428     ok(start_event != 0, "CreateEvent failed\n");
8429     end_event = CreateEventA(NULL, FALSE, FALSE, "test_wfp_end");
8430     ok(start_event != 0, "CreateEvent failed\n");
8431 
8432     sprintf(cmd, "%s win create_children %p\n", argv0, hwnd);
8433     memset(&startup, 0, sizeof(startup));
8434     startup.cb = sizeof(startup);
8435     ok(CreateProcessA(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL,
8436                 &startup, &info), "CreateProcess failed.\n");
8437     ok(wait_for_event(start_event, 1000), "didn't get start_event\n");
8438 
8439     child = GetWindow(hwnd, GW_CHILD);
8440     win = WindowFromPoint(pt);
8441     ok(win == child, "WindowFromPoint returned %p, expected %p\n", win, child);
8442 
8443     simulate_click(150, 150);
8444     flush_events(TRUE);
8445 
8446     child = GetWindow(child, GW_HWNDNEXT);
8447     pt.x = 250;
8448     win = WindowFromPoint(pt);
8449     ok(win == child, "WindowFromPoint returned %p, expected %p\n", win, child);
8450 
8451     SetEvent(end_event);
8452     winetest_wait_child_process(info.hProcess);
8453     CloseHandle(start_event);
8454     CloseHandle(end_event);
8455     CloseHandle(info.hProcess);
8456     CloseHandle(info.hThread);
8457 
8458     DestroyWindow(hwnd);
8459 }
8460 
8461 static void test_map_points(void)
8462 {
8463     BOOL ret;
8464     POINT p;
8465     HWND wnd, wnd0, dwnd;
8466     INT n;
8467     DWORD err;
8468     POINT pos = { 100, 200 };
8469     int width = 150;
8470     int height = 150;
8471     RECT window_rect;
8472     RECT client_rect;
8473 
8474     /* Create test windows */
8475     wnd = CreateWindowA("static", "test1", WS_POPUP, pos.x, pos.y, width, height, NULL, NULL, NULL, NULL);
8476     ok(wnd != NULL, "Failed %p\n", wnd);
8477     wnd0 = CreateWindowA("static", "test2", WS_POPUP, 0, 0, width, height, NULL, NULL, NULL, NULL);
8478     ok(wnd0 != NULL, "Failed %p\n", wnd);
8479     dwnd = CreateWindowA("static", "test3", 0, 200, 300, 150, 150, NULL, NULL, NULL, NULL);
8480     DestroyWindow(dwnd);
8481     ok(dwnd != NULL, "Failed %p\n", dwnd);
8482 
8483     /* Verify window rect and client rect (they should have the same width and height) */
8484     GetWindowRect(wnd, &window_rect);
8485     ok(window_rect.left == pos.x, "left is %d instead of %d\n", window_rect.left, pos.x);
8486     ok(window_rect.top == pos.y, "top is %d instead of %d\n", window_rect.top, pos.y);
8487     ok(window_rect.right == pos.x + width, "right is %d instead of %d\n", window_rect.right, pos.x + width);
8488     ok(window_rect.bottom == pos.y + height, "bottom is %d instead of %d\n", window_rect.bottom, pos.y + height);
8489     GetClientRect(wnd, &client_rect);
8490     ok(client_rect.left == 0, "left is %d instead of 0\n", client_rect.left);
8491     ok(client_rect.top == 0, "top is %d instead of 0\n", client_rect.top);
8492     ok(client_rect.right == width, "right is %d instead of %d\n", client_rect.right, width);
8493     ok(client_rect.bottom == height, "bottom is %d instead of %d\n", client_rect.bottom, height);
8494 
8495     /* Test MapWindowPoints */
8496 
8497     /* MapWindowPoints(NULL or wnd, NULL or wnd, NULL, 1); crashes on Windows */
8498 
8499     SetLastError(0xdeadbeef);
8500     n = MapWindowPoints(NULL, NULL, NULL, 0);
8501     err = GetLastError();
8502     ok(n == 0, "Got %d, expected %d\n", n, 0);
8503     ok(err == 0xdeadbeef, "Got %x, expected %x\n", err, 0xdeadbeef);
8504 
8505     SetLastError(0xdeadbeef);
8506     n = MapWindowPoints(wnd, wnd, NULL, 0);
8507     err = GetLastError();
8508     ok(n == 0, "Got %d, expected %d\n", n, 0);
8509     ok(err == 0xdeadbeef, "Got %x, expected %x\n", err, 0xdeadbeef);
8510 
8511     n = MapWindowPoints(wnd, NULL, NULL, 0);
8512     ok(n == MAKELONG(window_rect.left, window_rect.top), "Got %x, expected %x\n",
8513        n, MAKELONG(window_rect.left, window_rect.top));
8514 
8515     n = MapWindowPoints(NULL, wnd, NULL, 0);
8516     ok(n == MAKELONG(-window_rect.left, -window_rect.top), "Got %x, expected %x\n",
8517        n, MAKELONG(-window_rect.left, -window_rect.top));
8518 
8519     SetLastError(0xdeadbeef);
8520     p.x = p.y = 100;
8521     n = MapWindowPoints(dwnd, NULL, &p, 1);
8522     err = GetLastError();
8523     ok(n == 0, "Got %d, expected %d\n", n, 0);
8524     ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100);
8525     ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE);
8526 
8527     SetLastError(0xdeadbeef);
8528     p.x = p.y = 100;
8529     n = MapWindowPoints(dwnd, wnd, &p, 1);
8530     err = GetLastError();
8531     ok(n == 0, "Got %d, expected %d\n", n, 0);
8532     ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100);
8533     ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE);
8534 
8535     SetLastError(0xdeadbeef);
8536     p.x = p.y = 100;
8537     n = MapWindowPoints(NULL, dwnd, &p, 1);
8538     err = GetLastError();
8539     ok(n == 0, "Got %d, expected %d\n", n, 0);
8540     ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100);
8541     ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE);
8542 
8543     SetLastError(0xdeadbeef);
8544     p.x = p.y = 100;
8545     n = MapWindowPoints(wnd, dwnd, &p, 1);
8546     err = GetLastError();
8547     ok(n == 0, "Got %d, expected %d\n", n, 0);
8548     ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100);
8549     ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE);
8550 
8551     SetLastError(0xdeadbeef);
8552     p.x = p.y = 100;
8553     n = MapWindowPoints(dwnd, dwnd, &p, 1);
8554     err = GetLastError();
8555     ok(n == 0, "Got %d, expected %d\n", n, 0);
8556     ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100);
8557     ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE);
8558 
8559     SetLastError(0xdeadbeef);
8560     p.x = p.y = 100;
8561     n = MapWindowPoints(NULL, NULL, &p, 1);
8562     err = GetLastError();
8563     ok(n == 0, "Got %d, expected %d\n", n, 0);
8564     ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100);
8565     ok(err == 0xdeadbeef, "Got %x, expected %x\n", err, 0xdeadbeef);
8566 
8567     SetLastError(0xdeadbeef);
8568     p.x = p.y = 100;
8569     n = MapWindowPoints(wnd, wnd, &p, 1);
8570     err = GetLastError();
8571     ok(n == 0, "Got %d, expected %d\n", n, 0);
8572     ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100);
8573     ok(err == 0xdeadbeef, "Got %x, expected %x\n", err, 0xdeadbeef);
8574 
8575     p.x = p.y = 100;
8576     n = MapWindowPoints(wnd, NULL, &p, 1);
8577     ok(n == MAKELONG(window_rect.left, window_rect.top), "Got %x, expected %x\n",
8578        n, MAKELONG(window_rect.left, window_rect.top));
8579     ok((p.x == (window_rect.left + 100)) && (p.y == (window_rect.top + 100)), "Failed got (%d, %d), expected (%d, %d)\n",
8580        p.x, p.y, window_rect.left + 100, window_rect.top + 100);
8581 
8582     p.x = p.y = 100;
8583     n = MapWindowPoints(NULL, wnd, &p, 1);
8584     ok(n == MAKELONG(-window_rect.left, -window_rect.top), "Got %x, expected %x\n",
8585        n, MAKELONG(-window_rect.left, -window_rect.top));
8586     ok((p.x == (-window_rect.left + 100)) && (p.y == (-window_rect.top + 100)), "Failed got (%d, %d), expected (%d, %d)\n",
8587        p.x, p.y, -window_rect.left + 100, -window_rect.top + 100);
8588 
8589     SetLastError(0xdeadbeef);
8590     p.x = p.y = 0;
8591     n = MapWindowPoints(wnd0, NULL, &p, 1);
8592     err = GetLastError();
8593     ok(n == 0, "Got %x,  expected 0\n", n);
8594     ok((p.x == 0) && (p.y == 0), "Failed got (%d, %d), expected (0, 0)\n", p.x, p.y);
8595     ok(err == 0xdeadbeef, "Got %x, expected %x\n", err, 0xdeadbeef);
8596 
8597     SetLastError(0xdeadbeef);
8598     p.x = p.y = 0;
8599     n = MapWindowPoints(NULL, wnd0, &p, 1);
8600     err = GetLastError();
8601     ok(n == 0, "Got %x,  expected 0\n", n);
8602     ok((p.x == 0) && (p.y == 0), "Failed got (%d, %d), expected (0, 0)\n", p.x, p.y);
8603     ok(err == 0xdeadbeef, "Got %x, expected %x\n", err, 0xdeadbeef);
8604 
8605     /* Test ClientToScreen */
8606 
8607     /* ClientToScreen(wnd, NULL); crashes on Windows */
8608 
8609     SetLastError(0xdeadbeef);
8610     ret = ClientToScreen(NULL, NULL);
8611     err = GetLastError();
8612     ok(!ret, "Should fail\n");
8613     ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE);
8614 
8615     SetLastError(0xdeadbeef);
8616     p.x = p.y = 100;
8617     ret = ClientToScreen(NULL, &p);
8618     err = GetLastError();
8619     ok(!ret, "Should fail\n");
8620     ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100);
8621     ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE);
8622 
8623     SetLastError(0xdeadbeef);
8624     p.x = p.y = 100;
8625     ret = ClientToScreen(dwnd, &p);
8626     err = GetLastError();
8627     ok(!ret, "Should fail\n");
8628     ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100);
8629     ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE);
8630 
8631     p.x = p.y = 100;
8632     ret = ClientToScreen(wnd, &p);
8633     ok(ret, "Failed with error %u\n", GetLastError());
8634     ok((p.x == (window_rect.left + 100)) && (p.y == (window_rect.top + 100)), "Failed got (%d, %d), expected (%d, %d)\n",
8635        p.x, p.y, window_rect.left + 100, window_rect.top + 100);
8636 
8637     p.x = p.y = 0;
8638     ret = ClientToScreen(wnd0, &p);
8639     ok(ret, "Failed with error %u\n", GetLastError());
8640     ok((p.x == 0) && (p.y == 0), "Failed got (%d, %d), expected (0, 0)\n", p.x, p.y);
8641 
8642     /* Test ScreenToClient */
8643 
8644     /* ScreenToClient(wnd, NULL); crashes on Windows */
8645 
8646     SetLastError(0xdeadbeef);
8647     ret = ScreenToClient(NULL, NULL);
8648     err = GetLastError();
8649     ok(!ret, "Should fail\n");
8650     ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE);
8651 
8652     SetLastError(0xdeadbeef);
8653     p.x = p.y = 100;
8654     ret = ScreenToClient(NULL, &p);
8655     err = GetLastError();
8656     ok(!ret, "Should fail\n");
8657     ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100);
8658     ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE);
8659 
8660     SetLastError(0xdeadbeef);
8661     p.x = p.y = 100;
8662     ret = ScreenToClient(dwnd, &p);
8663     err = GetLastError();
8664     ok(!ret, "Should fail\n");
8665     ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100);
8666     ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE);
8667 
8668     p.x = p.y = 100;
8669     ret = ScreenToClient(wnd, &p);
8670     ok(ret, "Failed with error %u\n", GetLastError());
8671     ok((p.x == (-window_rect.left + 100)) && (p.y == (-window_rect.top + 100)), "Failed got(%d, %d), expected (%d, %d)\n",
8672        p.x, p.y, -window_rect.left + 100, -window_rect.top + 100);
8673 
8674     p.x = p.y = 0;
8675     ret = ScreenToClient(wnd0, &p);
8676     ok(ret, "Failed with error %u\n", GetLastError());
8677     ok((p.x == 0) && (p.y == 0), "Failed got (%d, %d), expected (0, 0)\n", p.x, p.y);
8678 
8679     DestroyWindow(wnd);
8680     DestroyWindow(wnd0);
8681 }
8682 
8683 static void test_update_region(void)
8684 {
8685     HWND hwnd, parent, child;
8686     HRGN  rgn1, rgn2;
8687     const RECT rc = {15, 15, 40, 40};
8688     const POINT wnd_orig = {30, 20};
8689     const POINT child_orig = {10, 5};
8690 
8691     parent = CreateWindowExA(0, "MainWindowClass", NULL,
8692                 WS_VISIBLE | WS_CLIPCHILDREN,
8693                 0, 0, 300, 150, NULL, NULL, GetModuleHandleA(0), 0);
8694     hwnd = CreateWindowExA(0, "MainWindowClass", NULL,
8695                 WS_VISIBLE | WS_CLIPCHILDREN | WS_CHILD,
8696                 0, 0, 200, 100, parent, NULL, GetModuleHandleA(0), 0);
8697     child = CreateWindowExA(0, "MainWindowClass", NULL,
8698                 WS_VISIBLE | WS_CHILD,
8699                 child_orig.x, child_orig.y,  100, 50,
8700                 hwnd, NULL, GetModuleHandleA(0), 0);
8701     assert(parent && hwnd && child);
8702 
8703     ValidateRgn(parent, NULL);
8704     ValidateRgn(hwnd, NULL);
8705     InvalidateRect(hwnd, &rc, FALSE);
8706     ValidateRgn(child, NULL);
8707 
8708     rgn1 = CreateRectRgn(0, 0, 0, 0);
8709     ok(GetUpdateRgn(parent, rgn1, FALSE) == NULLREGION,
8710             "has invalid area after ValidateRgn(NULL)\n");
8711     GetUpdateRgn(hwnd, rgn1, FALSE);
8712     rgn2 = CreateRectRgnIndirect(&rc);
8713     ok(EqualRgn(rgn1, rgn2), "assigned and retrieved update regions are different\n");
8714     ok(GetUpdateRgn(child, rgn2, FALSE) == NULLREGION,
8715             "has invalid area after ValidateRgn(NULL)\n");
8716 
8717     SetWindowPos(hwnd, 0, wnd_orig.x, wnd_orig.y,  0, 0,
8718             SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE);
8719 
8720     /* parent now has non-simple update region, it consist of
8721      * two rects, that was exposed after hwnd moving ... */
8722     SetRectRgn(rgn1, 0, 0, 200, wnd_orig.y);
8723     SetRectRgn(rgn2, 0, 0, wnd_orig.x, 100);
8724     CombineRgn(rgn1, rgn1, rgn2, RGN_OR);
8725     /* ... and mapped hwnd's invalid area, that hwnd has before moving */
8726     SetRectRgn(rgn2, rc.left + wnd_orig.x, rc.top + wnd_orig.y,
8727             rc.right + wnd_orig.x, rc.bottom + wnd_orig.y);
8728     CombineRgn(rgn1, rgn1, rgn2, RGN_OR);
8729     GetUpdateRgn(parent, rgn2, FALSE);
8730 todo_wine
8731     ok(EqualRgn(rgn1, rgn2), "wrong update region\n");
8732 
8733     /* hwnd has the same invalid region as before moving */
8734     SetRectRgn(rgn1, rc.left, rc.top, rc.right, rc.bottom);
8735     GetUpdateRgn(hwnd, rgn2, FALSE);
8736     ok(EqualRgn(rgn1, rgn2), "wrong update region\n");
8737 
8738     /* hwnd's invalid area maps to child during moving */
8739     SetRectRgn(rgn1, rc.left - child_orig.x , rc.top - child_orig.y,
8740             rc.right - child_orig.x, rc.bottom - child_orig.y);
8741     GetUpdateRgn(child, rgn2, FALSE);
8742 todo_wine
8743     ok(EqualRgn(rgn1, rgn2), "wrong update region\n");
8744 
8745     DeleteObject(rgn1);
8746     DeleteObject(rgn2);
8747     DestroyWindow(parent);
8748 }
8749 
8750 static void test_window_without_child_style(void)
8751 {
8752     HWND hwnd;
8753 
8754     hwnd = CreateWindowExA(0, "edit", NULL, WS_VISIBLE|WS_CHILD,
8755             0, 0, 50, 50, hwndMain, NULL, 0, NULL);
8756     ok(hwnd != NULL, "CreateWindow failed\n");
8757 
8758     ok(SetWindowLongA(hwnd, GWL_STYLE, GetWindowLongA(hwnd, GWL_STYLE) & (~WS_CHILD)),
8759             "can't remove WS_CHILD style\n");
8760 
8761     SetActiveWindow(hwndMain);
8762     PostMessageW(hwnd, WM_LBUTTONUP, 0, 0);
8763     SendMessageW(hwnd, WM_NCLBUTTONDOWN, HTCAPTION, 0);
8764     check_active_state(hwnd, hwnd, hwnd);
8765     flush_events(TRUE);
8766 
8767     DestroyWindow(hwnd);
8768 }
8769 
8770 
8771 struct smresult_thread_data
8772 {
8773     HWND main_hwnd;
8774     HWND thread_hwnd;
8775     HANDLE thread_started;
8776     HANDLE thread_got_wm_app;
8777     HANDLE main_in_wm_app_1;
8778     HANDLE thread_replied;
8779 };
8780 
8781 
8782 static LRESULT WINAPI smresult_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
8783 {
8784     switch (msg)
8785     {
8786     case WM_APP:
8787     {
8788         struct smresult_thread_data *data = (struct smresult_thread_data*)lparam;
8789 
8790         ok(hwnd == data->thread_hwnd, "unexpected hwnd %p\n", hwnd);
8791 
8792         SendNotifyMessageA(data->main_hwnd, WM_APP+1, 0, lparam);
8793 
8794         /* Don't return until the main thread is processing our sent message. */
8795         ok(WaitForSingleObject(data->main_in_wm_app_1, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
8796 
8797         /* Break the PeekMessage loop so we can notify the main thread after we return. */
8798         SetEvent(data->thread_got_wm_app);
8799 
8800         return 0x240408ea;
8801     }
8802     case WM_APP+1:
8803     {
8804         struct smresult_thread_data *data = (struct smresult_thread_data*)lparam;
8805         LRESULT res;
8806 
8807         ok(hwnd == data->main_hwnd, "unexpected hwnd %p\n", hwnd);
8808 
8809         /* Ask the thread to reply to our WM_APP message. */
8810         SetEvent(data->main_in_wm_app_1);
8811 
8812         /* Wait until the thread has sent a reply. */
8813         ok(WaitForSingleObject(data->thread_replied, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
8814 
8815         /* Send another message while we have a reply queued for the current one. */
8816         res = SendMessageA(data->thread_hwnd, WM_APP+2, 0, lparam);
8817         ok(res == 0x449b0190, "unexpected result %lx\n", res);
8818 
8819         return 0;
8820     }
8821     case WM_APP+2:
8822     {
8823         struct smresult_thread_data *data = (struct smresult_thread_data*)lparam;
8824 
8825         ok(hwnd == data->thread_hwnd, "unexpected hwnd %p\n", hwnd);
8826 
8827         /* Don't return until we know the main thread is processing sent messages. */
8828         SendMessageA(data->main_hwnd, WM_NULL, 0, 0);
8829 
8830         return 0x449b0190;
8831     }
8832     case WM_CLOSE:
8833         PostQuitMessage(0);
8834         break;
8835     }
8836     return DefWindowProcA(hwnd, msg, wparam, lparam);
8837 }
8838 
8839 static DWORD WINAPI smresult_thread_proc(void *param)
8840 {
8841     MSG msg;
8842     struct smresult_thread_data *data = param;
8843 
8844     data->thread_hwnd = CreateWindowExA(0, "SmresultClass", "window caption text", WS_OVERLAPPEDWINDOW,
8845                                       100, 100, 200, 200, 0, 0, 0, NULL);
8846     ok(data->thread_hwnd != 0, "Failed to create overlapped window\n");
8847 
8848     SetEvent(data->thread_started);
8849 
8850     /* Loop until we've processed WM_APP. */
8851     while (WaitForSingleObject(data->thread_got_wm_app, 0) != WAIT_OBJECT_0)
8852     {
8853         if (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
8854         {
8855             TranslateMessage(&msg);
8856             DispatchMessageA(&msg);
8857         }
8858         else
8859         {
8860             MsgWaitForMultipleObjects(1, &data->thread_got_wm_app, FALSE, INFINITE, QS_SENDMESSAGE);
8861         }
8862     }
8863 
8864     /* Notify the main thread that we replied to its WM_APP message. */
8865     SetEvent(data->thread_replied);
8866 
8867     while (GetMessageA(&msg, 0, 0, 0))
8868     {
8869         TranslateMessage(&msg);
8870         DispatchMessageA(&msg);
8871     }
8872 
8873     return 0;
8874 }
8875 
8876 static void test_smresult(void)
8877 {
8878     WNDCLASSA cls;
8879     HANDLE hThread;
8880     DWORD tid;
8881     struct smresult_thread_data data;
8882     BOOL ret;
8883     LRESULT res;
8884 
8885     cls.style = CS_DBLCLKS;
8886     cls.lpfnWndProc = smresult_wndproc;
8887     cls.cbClsExtra = 0;
8888     cls.cbWndExtra = 0;
8889     cls.hInstance = GetModuleHandleA(0);
8890     cls.hIcon = 0;
8891     cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
8892     cls.hbrBackground = GetStockObject(WHITE_BRUSH);
8893     cls.lpszMenuName = NULL;
8894     cls.lpszClassName = "SmresultClass";
8895 
8896     ret = RegisterClassA(&cls);
8897     ok(ret, "RegisterClassA failed\n");
8898 
8899     data.thread_started = CreateEventA(NULL, TRUE, FALSE, NULL);
8900     ok(data.thread_started != NULL, "CreateEventA failed\n");
8901 
8902     data.thread_got_wm_app = CreateEventA(NULL, TRUE, FALSE, NULL);
8903     ok(data.thread_got_wm_app != NULL, "CreateEventA failed\n");
8904 
8905     data.main_in_wm_app_1 = CreateEventA(NULL, TRUE, FALSE, NULL);
8906     ok(data.main_in_wm_app_1 != NULL, "CreateEventA failed\n");
8907 
8908     data.thread_replied = CreateEventA(NULL, TRUE, FALSE, NULL);
8909     ok(data.thread_replied != NULL, "CreateEventA failed\n");
8910 
8911     data.main_hwnd = CreateWindowExA(0, "SmresultClass", "window caption text", WS_OVERLAPPEDWINDOW,
8912                                       100, 100, 200, 200, 0, 0, 0, NULL);
8913 
8914     hThread = CreateThread(NULL, 0, smresult_thread_proc, &data, 0, &tid);
8915     ok(hThread != NULL, "CreateThread failed, error %d\n", GetLastError());
8916 
8917     ok(WaitForSingleObject(data.thread_started, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
8918 
8919     res = SendMessageA(data.thread_hwnd, WM_APP, 0, (LPARAM)&data);
8920     ok(res == 0x240408ea, "unexpected result %lx\n", res);
8921 
8922     SendMessageA(data.thread_hwnd, WM_CLOSE, 0, 0);
8923 
8924     DestroyWindow(data.main_hwnd);
8925 
8926     ok(WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
8927 
8928     CloseHandle(data.thread_started);
8929     CloseHandle(data.thread_got_wm_app);
8930     CloseHandle(data.main_in_wm_app_1);
8931     CloseHandle(data.thread_replied);
8932 }
8933 
8934 static void test_GetMessagePos(void)
8935 {
8936     HWND button;
8937     DWORD pos;
8938     MSG msg;
8939 
8940     button = CreateWindowExA(0, "button", "button", WS_VISIBLE,
8941             100, 100, 100, 100, 0, 0, 0, NULL);
8942     ok(button != 0, "CreateWindowExA failed\n");
8943 
8944     SetCursorPos(120, 140);
8945     flush_events(TRUE);
8946     pos = GetMessagePos();
8947     ok(pos == MAKELONG(120, 140), "pos = %08x\n", pos);
8948 
8949     SetCursorPos(340, 320);
8950     pos = GetMessagePos();
8951     ok(pos == MAKELONG(120, 140), "pos = %08x\n", pos);
8952 
8953     SendMessageW(button, WM_APP, 0, 0);
8954     pos = GetMessagePos();
8955     ok(pos == MAKELONG(120, 140), "pos = %08x\n", pos);
8956 
8957     PostMessageA(button, WM_APP, 0, 0);
8958     GetMessageA(&msg, button, 0, 0);
8959     ok(msg.message == WM_APP, "msg.message = %x\n", msg.message);
8960     pos = GetMessagePos();
8961     ok(pos == MAKELONG(340, 320), "pos = %08x\n", pos);
8962 
8963     PostMessageA(button, WM_APP, 0, 0);
8964     SetCursorPos(350, 330);
8965     GetMessageA(&msg, button, 0, 0);
8966     ok(msg.message == WM_APP, "msg.message = %x\n", msg.message);
8967     pos = GetMessagePos();
8968     ok(pos == MAKELONG(340, 320), "pos = %08x\n", pos);
8969 
8970     PostMessageA(button, WM_APP, 0, 0);
8971     SetCursorPos(320, 340);
8972     PostMessageA(button, WM_APP+1, 0, 0);
8973     pos = GetMessagePos();
8974     ok(pos == MAKELONG(340, 320), "pos = %08x\n", pos);
8975     GetMessageA(&msg, button, 0, 0);
8976     ok(msg.message == WM_APP, "msg.message = %x\n", msg.message);
8977     pos = GetMessagePos();
8978     ok(pos == MAKELONG(350, 330), "pos = %08x\n", pos);
8979     GetMessageA(&msg, button, 0, 0);
8980     ok(msg.message == WM_APP+1, "msg.message = %x\n", msg.message);
8981     pos = GetMessagePos();
8982     ok(pos == MAKELONG(320, 340), "pos = %08x\n", pos);
8983 
8984     SetTimer(button, 1, 250, NULL);
8985     SetCursorPos(330, 350);
8986     GetMessageA(&msg, button, 0, 0);
8987     while (msg.message == WM_PAINT)
8988     {
8989         UpdateWindow( button );
8990         GetMessageA(&msg, button, 0, 0);
8991     }
8992     ok(msg.message == WM_TIMER, "msg.message = %x\n", msg.message);
8993     pos = GetMessagePos();
8994     ok(pos == MAKELONG(330, 350), "pos = %08x\n", pos);
8995     KillTimer(button, 1);
8996 
8997     DestroyWindow(button);
8998 }
8999 
9000 #define SET_FOREGROUND_STEAL_1          0x01
9001 #define SET_FOREGROUND_SET_1            0x02
9002 #define SET_FOREGROUND_STEAL_2          0x04
9003 #define SET_FOREGROUND_SET_2            0x08
9004 #define SET_FOREGROUND_INJECT           0x10
9005 
9006 struct set_foreground_thread_params
9007 {
9008     UINT msg_quit, msg_command;
9009     HWND window1, window2, thread_window;
9010     HANDLE command_executed;
9011 };
9012 
9013 static DWORD WINAPI set_foreground_thread(void *params)
9014 {
9015     struct set_foreground_thread_params *p = params;
9016     MSG msg;
9017 
9018     p->thread_window = CreateWindowExA(0, "static", "thread window", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
9019             0, 0, 10, 10, 0, 0, 0, NULL);
9020     SetEvent(p->command_executed);
9021 
9022     while(GetMessageA(&msg, 0, 0, 0))
9023     {
9024         if (msg.message == p->msg_quit)
9025             break;
9026 
9027         if (msg.message == p->msg_command)
9028         {
9029             if (msg.wParam & SET_FOREGROUND_STEAL_1)
9030             {
9031                 SetForegroundWindow(p->thread_window);
9032                 check_wnd_state(p->thread_window, p->thread_window, p->thread_window, 0);
9033             }
9034             if (msg.wParam & SET_FOREGROUND_INJECT)
9035             {
9036                 SendNotifyMessageA(p->window1, WM_ACTIVATEAPP, 0, 0);
9037             }
9038             if (msg.wParam & SET_FOREGROUND_SET_1)
9039             {
9040                 SetForegroundWindow(p->window1);
9041                 check_wnd_state(0, p->window1, 0, 0);
9042             }
9043             if (msg.wParam & SET_FOREGROUND_STEAL_2)
9044             {
9045                 SetForegroundWindow(p->thread_window);
9046                 check_wnd_state(p->thread_window, p->thread_window, p->thread_window, 0);
9047             }
9048             if (msg.wParam & SET_FOREGROUND_SET_2)
9049             {
9050                 SetForegroundWindow(p->window2);
9051                 check_wnd_state(0, p->window2, 0, 0);
9052             }
9053 
9054             SetEvent(p->command_executed);
9055             continue;
9056         }
9057 
9058         TranslateMessage(&msg);
9059         DispatchMessageA(&msg);
9060     }
9061 
9062     DestroyWindow(p->thread_window);
9063     return 0;
9064 }
9065 
9066 static void test_activateapp(HWND window1)
9067 {
9068     HWND window2, test_window;
9069     HANDLE thread;
9070     struct set_foreground_thread_params thread_params;
9071     DWORD tid;
9072     MSG msg;
9073 
9074     window2 = CreateWindowExA(0, "static", "window 2", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
9075             300, 0, 10, 10, 0, 0, 0, NULL);
9076     thread_params.msg_quit = WM_USER;
9077     thread_params.msg_command = WM_USER + 1;
9078     thread_params.window1 = window1;
9079     thread_params.window2 = window2;
9080     thread_params.command_executed = CreateEventW(NULL, FALSE, FALSE, NULL);
9081 
9082     thread = CreateThread(NULL, 0, set_foreground_thread, &thread_params, 0, &tid);
9083     WaitForSingleObject(thread_params.command_executed, INFINITE);
9084 
9085     SetForegroundWindow(window1);
9086     check_wnd_state(window1, window1, window1, 0);
9087     while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
9088 
9089     /* Steal foreground: WM_ACTIVATEAPP(0) is delivered. */
9090     app_activated = app_deactivated = FALSE;
9091     PostThreadMessageA(tid, thread_params.msg_command, SET_FOREGROUND_STEAL_1, 0);
9092     WaitForSingleObject(thread_params.command_executed, INFINITE);
9093     test_window = GetForegroundWindow();
9094     ok(test_window == thread_params.thread_window, "Expected foreground window %p, got %p\n",
9095             thread_params.thread_window, test_window);
9096     /* Active and Focus window are sometimes 0 on KDE. Ignore them.
9097      * check_wnd_state(window1, thread_params.thread_window, window1, 0); */
9098     ok(!app_activated, "Received WM_ACTIVATEAPP(1), did not expect it.\n");
9099     ok(!app_deactivated, "Received WM_ACTIVATEAPP(0), did not expect it.\n");
9100     while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
9101     check_wnd_state(0, thread_params.thread_window, 0, 0);
9102     test_window = GetForegroundWindow();
9103     ok(test_window == thread_params.thread_window, "Expected foreground window %p, got %p\n",
9104             thread_params.thread_window, test_window);
9105     ok(!app_activated, "Received WM_ACTIVATEAPP(1), did not expect it.\n");
9106     /* This message is reliable on Windows and inside a virtual desktop.
9107      * It is unreliable on KDE (50/50) and never arrives on FVWM.
9108      * ok(app_deactivated, "Expected WM_ACTIVATEAPP(0), did not receive it.\n"); */
9109 
9110     /* Set foreground: WM_ACTIVATEAPP (1) is delivered. */
9111     app_activated = app_deactivated = FALSE;
9112     PostThreadMessageA(tid, thread_params.msg_command, SET_FOREGROUND_SET_1, 0);
9113     WaitForSingleObject(thread_params.command_executed, INFINITE);
9114     check_wnd_state(0, 0, 0, 0);
9115     test_window = GetForegroundWindow();
9116     ok(!test_window, "Expected foreground window 0, got %p\n", test_window);
9117     ok(!app_activated, "Received WM_ACTIVATEAPP(!= 0), did not expect it.\n");
9118     ok(!app_deactivated, "Received WM_ACTIVATEAPP(0), did not expect it.\n");
9119     while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
9120     check_wnd_state(window1, window1, window1, 0);
9121     test_window = GetForegroundWindow();
9122     ok(test_window == window1, "Expected foreground window %p, got %p\n",
9123             window1, test_window);
9124     ok(app_activated, "Expected WM_ACTIVATEAPP(1), did not receive it.\n");
9125     ok(!app_deactivated, "Received WM_ACTIVATEAPP(0), did not expect it.\n");
9126 
9127     /* Steal foreground then set it back: No messages are delivered. */
9128     app_activated = app_deactivated = FALSE;
9129     PostThreadMessageA(tid, thread_params.msg_command, SET_FOREGROUND_STEAL_1 | SET_FOREGROUND_SET_1, 0);
9130     WaitForSingleObject(thread_params.command_executed, INFINITE);
9131     test_window = GetForegroundWindow();
9132     ok(test_window == window1, "Expected foreground window %p, got %p\n",
9133             window1, test_window);
9134     check_wnd_state(window1, window1, window1, 0);
9135     ok(!app_activated, "Received WM_ACTIVATEAPP(1), did not expect it.\n");
9136     ok(!app_deactivated, "Received WM_ACTIVATEAPP(0), did not expect it.\n");
9137     while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
9138     test_window = GetForegroundWindow();
9139     ok(test_window == window1, "Expected foreground window %p, got %p\n",
9140             window1, test_window);
9141     check_wnd_state(window1, window1, window1, 0);
9142     ok(!app_activated, "Received WM_ACTIVATEAPP(1), did not expect it.\n");
9143     ok(!app_deactivated, "Received WM_ACTIVATEAPP(0), did not expect it.\n");
9144 
9145     /* This is not implemented with a plain WM_ACTIVATEAPP filter. */
9146     app_activated = app_deactivated = FALSE;
9147     PostThreadMessageA(tid, thread_params.msg_command, SET_FOREGROUND_STEAL_1
9148             | SET_FOREGROUND_INJECT | SET_FOREGROUND_SET_1, 0);
9149     WaitForSingleObject(thread_params.command_executed, INFINITE);
9150     test_window = GetForegroundWindow();
9151     ok(test_window == window1, "Expected foreground window %p, got %p\n",
9152             window1, test_window);
9153     check_wnd_state(window1, window1, window1, 0);
9154     ok(!app_activated, "Received WM_ACTIVATEAPP(1), did not expect it.\n");
9155     ok(!app_deactivated, "Received WM_ACTIVATEAPP(0), did not expect it.\n");
9156     while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
9157     test_window = GetForegroundWindow();
9158     ok(test_window == window1, "Expected foreground window %p, got %p\n",
9159             window1, test_window);
9160     check_wnd_state(window1, window1, window1, 0);
9161     ok(!app_activated, "Received WM_ACTIVATEAPP(1), did not expect it.\n");
9162     ok(app_deactivated, "Expected WM_ACTIVATEAPP(0), did not receive it.\n");
9163 
9164     SetForegroundWindow(thread_params.thread_window);
9165 
9166     /* Set foreground then remove: Both messages are delivered. */
9167     app_activated = app_deactivated = FALSE;
9168     PostThreadMessageA(tid, thread_params.msg_command, SET_FOREGROUND_SET_1 | SET_FOREGROUND_STEAL_2, 0);
9169     WaitForSingleObject(thread_params.command_executed, INFINITE);
9170     test_window = GetForegroundWindow();
9171     ok(test_window == thread_params.thread_window, "Expected foreground window %p, got %p\n",
9172             thread_params.thread_window, test_window);
9173     check_wnd_state(0, thread_params.thread_window, 0, 0);
9174     ok(!app_activated, "Received WM_ACTIVATEAPP(1), did not expect it.\n");
9175     ok(!app_deactivated, "Received WM_ACTIVATEAPP(0), did not expect it.\n");
9176     while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
9177     test_window = GetForegroundWindow();
9178     ok(test_window == thread_params.thread_window, "Expected foreground window %p, got %p\n",
9179             thread_params.thread_window, test_window);
9180     /* Active and focus are window1 on wine because the internal WM_WINE_SETACTIVEWINDOW(0)
9181      * message is never generated. GetCapture() returns 0 though, so we'd get a test success
9182      * in todo_wine in the line below.
9183      * todo_wine check_wnd_state(0, thread_params.thread_window, 0, 0); */
9184     ok(app_activated, "Expected WM_ACTIVATEAPP(1), did not receive it.\n");
9185     todo_wine ok(app_deactivated, "Expected WM_ACTIVATEAPP(0), did not receive it.\n");
9186 
9187     SetForegroundWindow(window1);
9188     test_window = GetForegroundWindow();
9189     ok(test_window == window1, "Expected foreground window %p, got %p\n",
9190             window1, test_window);
9191     check_wnd_state(window1, window1, window1, 0);
9192 
9193     /* Switch to a different window from the same thread? No messages. */
9194     app_activated = app_deactivated = FALSE;
9195     PostThreadMessageA(tid, thread_params.msg_command, SET_FOREGROUND_STEAL_1 | SET_FOREGROUND_SET_2, 0);
9196     WaitForSingleObject(thread_params.command_executed, INFINITE);
9197     test_window = GetForegroundWindow();
9198     ok(test_window == window1, "Expected foreground window %p, got %p\n",
9199             window1, test_window);
9200     check_wnd_state(window1, window1, window1, 0);
9201     ok(!app_activated, "Received WM_ACTIVATEAPP(1), did not expect it.\n");
9202     ok(!app_deactivated, "Received WM_ACTIVATEAPP(0), did not expect it.\n");
9203     while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
9204     test_window = GetForegroundWindow();
9205     ok(test_window == window2, "Expected foreground window %p, got %p\n",
9206             window2, test_window);
9207     check_wnd_state(window2, window2, window2, 0);
9208     ok(!app_activated, "Received WM_ACTIVATEAPP(1), did not expect it.\n");
9209     ok(!app_deactivated, "Received WM_ACTIVATEAPP(0), did not expect it.\n");
9210 
9211     PostThreadMessageA(tid, thread_params.msg_quit, 0, 0);
9212     WaitForSingleObject(thread, INFINITE);
9213 
9214     CloseHandle(thread_params.command_executed);
9215     DestroyWindow(window2);
9216 }
9217 
9218 static LRESULT WINAPI winproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
9219 {
9220     if(!hwnd) {
9221         int *count = (int*)lparam;
9222         (*count)++;
9223     }
9224     return 0;
9225 }
9226 
9227 static LRESULT WINAPI winproc_convA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
9228 {
9229     if(msg == WM_SETTEXT)
9230     {
9231         const char *text = (const char*)lparam;
9232 
9233         ok(!wparam, "wparam = %08lx\n", wparam);
9234         ok(!strcmp(text, "text"), "WM_SETTEXT lparam = %s\n", text);
9235         return 1;
9236     }
9237     return 0;
9238 }
9239 
9240 static const WCHAR textW[] = {'t','e','x','t',0};
9241 static LRESULT WINAPI winproc_convW(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
9242 {
9243     if(msg == WM_SETTEXT)
9244     {
9245         const WCHAR *text = (const WCHAR*)lparam;
9246 
9247         ok(!wparam, "wparam = %08lx\n", wparam);
9248         ok(!lstrcmpW(text, textW), "WM_SETTEXT lparam = %s\n", wine_dbgstr_w(text));
9249         return 1;
9250     }
9251     return 0;
9252 }
9253 
9254 static void test_winproc_handles(const char *argv0)
9255 {
9256     static const WCHAR winproc_testW[] = {'w','i','n','p','r','o','c','_','t','e','s','t',0};
9257 
9258     HINSTANCE hinst = GetModuleHandleA(NULL);
9259     WNDCLASSA wnd_classA;
9260     WNDCLASSW wnd_classW;
9261     int count, ret;
9262     PROCESS_INFORMATION info;
9263     STARTUPINFOA startup;
9264     char cmd[MAX_PATH];
9265 
9266     memset(&wnd_classA, 0, sizeof(wnd_classA));
9267     wnd_classA.lpszClassName = "winproc_test";
9268     wnd_classA.lpfnWndProc = winproc;
9269     ret = RegisterClassA(&wnd_classA);
9270     ok(ret, "RegisterClass failed with error %d\n", GetLastError());
9271 
9272     ret = GetClassInfoW(hinst, winproc_testW, &wnd_classW);
9273     ok(ret, "GetClassInfoW failed with error %d\n", GetLastError());
9274     ok(wnd_classA.lpfnWndProc != wnd_classW.lpfnWndProc,
9275             "winproc pointers should not be identical\n");
9276 
9277     count = 0;
9278     CallWindowProcA(wnd_classW.lpfnWndProc, 0, 0, 0, (LPARAM)&count);
9279     ok(count == 1, "winproc should be called once (%d)\n", count);
9280     count = 0;
9281     CallWindowProcW(wnd_classW.lpfnWndProc, 0, 0, 0, (LPARAM)&count);
9282     ok(count == 1, "winproc should be called once (%d)\n", count);
9283 
9284     ret = UnregisterClassW(winproc_testW, hinst);
9285     ok(ret, "UnregisterClass failed with error %d\n", GetLastError());
9286 
9287     /* crashes on 64-bit windows because lpfnWndProc handle is already freed */
9288     if (sizeof(void*) == 4)
9289     {
9290         count = 0;
9291         CallWindowProcA(wnd_classW.lpfnWndProc, 0, 0, 0, (LPARAM)&count);
9292         todo_wine ok(!count, "winproc should not be called (%d)\n", count);
9293         CallWindowProcW(wnd_classW.lpfnWndProc, 0, 0, 0, (LPARAM)&count);
9294         todo_wine ok(!count, "winproc should not be called (%d)\n", count);
9295     }
9296 
9297     sprintf(cmd, "%s win winproc_limit", argv0);
9298     memset(&startup, 0, sizeof(startup));
9299     startup.cb = sizeof(startup);
9300     ok(CreateProcessA(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL,
9301                 &startup, &info), "CreateProcess failed.\n");
9302     winetest_wait_child_process(info.hProcess);
9303     CloseHandle(info.hProcess);
9304     CloseHandle(info.hThread);
9305 }
9306 
9307 static void test_winproc_limit(void)
9308 {
9309     WNDPROC winproc_handle;
9310     LONG_PTR ret;
9311     HWND hwnd;
9312     int i;
9313 
9314     hwnd = CreateWindowExA(0, "static", "test", WS_POPUP, 0, 0, 0, 0, 0, 0, 0, 0);
9315     ok(hwnd != 0, "CreateWindowEx failed\n");
9316 
9317     ok(SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONG_PTR)winproc),
9318             "SetWindowLongPtr failed\n");
9319     winproc_handle = (WNDPROC)GetWindowLongPtrW(hwnd, GWLP_WNDPROC);
9320     ok(winproc_handle != winproc, "winproc pointers should not be identical\n");
9321 
9322     /* run out of winproc slots */
9323     for(i = 2; i<0xffff; i++)
9324     {
9325         ok(SetWindowLongPtrA(hwnd, GWLP_WNDPROC, i), "SetWindowLongPtr failed (%d)\n", i);
9326         if(GetWindowLongPtrW(hwnd, GWLP_WNDPROC) == i)
9327             break;
9328     }
9329     ok(i != 0xffff, "unable to run out of winproc slots\n");
9330 
9331     ret = SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONG_PTR)winproc_convA);
9332     ok(ret, "SetWindowLongPtr failed with error %d\n", GetLastError());
9333     ok(SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"text"), "WM_SETTEXT failed\n");
9334     ok(SendMessageW(hwnd, WM_SETTEXT, 0, (LPARAM)textW), "WM_SETTEXT with conversion failed\n");
9335 
9336     ret = SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR)winproc_convW);
9337     ok(ret, "SetWindowLongPtr failed with error %d\n", GetLastError());
9338     ok(SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"text"), "WM_SETTEXT failed\n");
9339     ok(SendMessageW(hwnd, WM_SETTEXT, 0, (LPARAM)textW), "WM_SETTEXT with conversion failed\n");
9340 
9341     /* Show that there's no message conversion when CallWindowProc is used */
9342     ok(CallWindowProcA(winproc_convW, hwnd, WM_SETTEXT, 0, (LPARAM)textW) == 1,
9343             "winproc_convW returned error\n");
9344     ok(CallWindowProcW(winproc_convW, hwnd, WM_SETTEXT, 0, (LPARAM)textW) == 1,
9345             "winproc_convW returned error\n");
9346 
9347     i = 0;
9348     CallWindowProcA(winproc_handle, 0, 0, 0, (LPARAM)&i);
9349     ok(i == 1, "winproc should be called once (%d)\n", i);
9350     i = 0;
9351     CallWindowProcW(winproc_handle, 0, 0, 0, (LPARAM)&i);
9352     ok(i == 1, "winproc should be called once (%d)\n", i);
9353 
9354     DestroyWindow(hwnd);
9355 
9356     i = 0;
9357     CallWindowProcA(winproc_handle, 0, 0, 0, (LPARAM)&i);
9358     ok(i == 1, "winproc should be called once (%d)\n", i);
9359     i = 0;
9360     CallWindowProcW(winproc_handle, 0, 0, 0, (LPARAM)&i);
9361     ok(i == 1, "winproc should be called once (%d)\n", i);
9362 }
9363 
9364 static void test_deferwindowpos(void)
9365 {
9366     HDWP hdwp, hdwp2;
9367     BOOL ret;
9368 
9369     hdwp = BeginDeferWindowPos(0);
9370     ok(hdwp != NULL, "got %p\n", hdwp);
9371 
9372     ret = EndDeferWindowPos(NULL);
9373     ok(!ret, "got %d\n", ret);
9374 
9375     hdwp2 = DeferWindowPos(NULL, NULL, NULL, 0, 0, 10, 10, 0);
9376 todo_wine
9377     ok(hdwp2 == NULL && ((GetLastError() == ERROR_INVALID_DWP_HANDLE) ||
9378         broken(GetLastError() == ERROR_INVALID_WINDOW_HANDLE) /* before win8 */), "got %p, error %d\n", hdwp2, GetLastError());
9379 
9380     hdwp2 = DeferWindowPos((HDWP)0xdead, GetDesktopWindow(), NULL, 0, 0, 10, 10, 0);
9381 todo_wine
9382     ok(hdwp2 == NULL && ((GetLastError() == ERROR_INVALID_DWP_HANDLE) ||
9383         broken(GetLastError() == ERROR_INVALID_WINDOW_HANDLE) /* before win8 */), "got %p, error %d\n", hdwp2, GetLastError());
9384 
9385     hdwp2 = DeferWindowPos(hdwp, NULL, NULL, 0, 0, 10, 10, 0);
9386     ok(hdwp2 == NULL && GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "got %p, error %d\n", hdwp2, GetLastError());
9387 
9388     hdwp2 = DeferWindowPos(hdwp, GetDesktopWindow(), NULL, 0, 0, 10, 10, 0);
9389     ok(hdwp2 == NULL && GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "got %p, error %d\n", hdwp2, GetLastError());
9390 
9391     hdwp2 = DeferWindowPos(hdwp, (HWND)0xdead, NULL, 0, 0, 10, 10, 0);
9392     ok(hdwp2 == NULL && GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "got %p, error %d\n", hdwp2, GetLastError());
9393 
9394     ret = EndDeferWindowPos(hdwp);
9395     ok(ret, "got %d\n", ret);
9396 }
9397 
9398 START_TEST(win)
9399 {
9400     char **argv;
9401     int argc = winetest_get_mainargs( &argv );
9402     HMODULE user32 = GetModuleHandleA( "user32.dll" );
9403     HMODULE gdi32 = GetModuleHandleA("gdi32.dll");
9404     pGetAncestor = (void *)GetProcAddress( user32, "GetAncestor" );
9405     pGetWindowInfo = (void *)GetProcAddress( user32, "GetWindowInfo" );
9406     pGetWindowModuleFileNameA = (void *)GetProcAddress( user32, "GetWindowModuleFileNameA" );
9407     pGetLayeredWindowAttributes = (void *)GetProcAddress( user32, "GetLayeredWindowAttributes" );
9408     pSetLayeredWindowAttributes = (void *)GetProcAddress( user32, "SetLayeredWindowAttributes" );
9409     pUpdateLayeredWindow = (void *)GetProcAddress( user32, "UpdateLayeredWindow" );
9410     pUpdateLayeredWindowIndirect = (void *)GetProcAddress( user32, "UpdateLayeredWindowIndirect" );
9411     pGetMonitorInfoA = (void *)GetProcAddress( user32,  "GetMonitorInfoA" );
9412     pMonitorFromPoint = (void *)GetProcAddress( user32,  "MonitorFromPoint" );
9413     pGetWindowRgnBox = (void *)GetProcAddress( user32, "GetWindowRgnBox" );
9414     pGetGUIThreadInfo = (void *)GetProcAddress( user32, "GetGUIThreadInfo" );
9415     pGetProcessDefaultLayout = (void *)GetProcAddress( user32, "GetProcessDefaultLayout" );
9416     pSetProcessDefaultLayout = (void *)GetProcAddress( user32, "SetProcessDefaultLayout" );
9417     pFlashWindow = (void *)GetProcAddress( user32, "FlashWindow" );
9418     pFlashWindowEx = (void *)GetProcAddress( user32, "FlashWindowEx" );
9419     pGetLayout = (void *)GetProcAddress( gdi32, "GetLayout" );
9420     pSetLayout = (void *)GetProcAddress( gdi32, "SetLayout" );
9421     pMirrorRgn = (void *)GetProcAddress( gdi32, "MirrorRgn" );
9422 
9423     if (argc==4 && !strcmp(argv[2], "create_children"))
9424     {
9425         HWND hwnd;
9426 
9427         sscanf(argv[3], "%p", &hwnd);
9428         window_from_point_proc(hwnd);
9429         return;
9430     }
9431 
9432     if (argc==3 && !strcmp(argv[2], "winproc_limit"))
9433     {
9434         test_winproc_limit();
9435         return;
9436     }
9437 
9438     if (!RegisterWindowClasses()) assert(0);
9439 
9440     hwndMain = CreateWindowExA(/*WS_EX_TOOLWINDOW*/ 0, "MainWindowClass", "Main window",
9441                                WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
9442                                WS_MAXIMIZEBOX | WS_POPUP | WS_VISIBLE,
9443                                100, 100, 200, 200,
9444                                0, 0, GetModuleHandleA(NULL), NULL);
9445     assert( hwndMain );
9446 
9447     if(!SetForegroundWindow(hwndMain)) {
9448         /* workaround for foreground lock timeout */
9449         simulate_click(101, 101);
9450         ok(SetForegroundWindow(hwndMain), "SetForegroundWindow failed\n");
9451     }
9452 
9453     SetLastError(0xdeafbeef);
9454     GetWindowLongPtrW(GetDesktopWindow(), GWLP_WNDPROC);
9455     is_win9x = (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED);
9456 
9457     hhook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId());
9458     if (!hhook) win_skip( "Cannot set CBT hook, skipping some tests\n" );
9459 
9460     /* make sure that these tests are executed first */
9461     test_FindWindowEx();
9462     test_SetParent();
9463 
9464     hwndMain2 = CreateWindowExA(/*WS_EX_TOOLWINDOW*/ 0, "MainWindowClass", "Main window 2",
9465                                 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
9466                                 WS_MAXIMIZEBOX | WS_POPUP,
9467                                 100, 100, 200, 200,
9468                                 0, 0, GetModuleHandleA(NULL), NULL);
9469     assert( hwndMain2 );
9470 
9471     our_pid = GetWindowThreadProcessId(hwndMain, NULL);
9472 
9473     /* Add the tests below this line */
9474     test_child_window_from_point();
9475     test_window_from_point(argv[0]);
9476     test_thick_child_size(hwndMain);
9477     test_fullscreen();
9478     test_hwnd_message();
9479     test_nonclient_area(hwndMain);
9480     test_params();
9481     test_GetWindowModuleFileName();
9482     test_capture_1();
9483     test_capture_2();
9484     test_capture_3(hwndMain, hwndMain2);
9485     test_capture_4();
9486     test_rtl_layout();
9487     test_FlashWindow();
9488     test_FlashWindowEx();
9489 
9490     test_CreateWindow();
9491     test_parent_owner();
9492     test_enum_thread_windows();
9493 
9494     test_mdi();
9495     test_icons();
9496     test_SetWindowPos(hwndMain, hwndMain2);
9497     test_SetMenu(hwndMain);
9498     test_SetFocus(hwndMain);
9499     test_SetActiveWindow(hwndMain);
9500     test_NCRedraw();
9501 
9502     test_children_zorder(hwndMain);
9503     test_popup_zorder(hwndMain2, hwndMain, WS_POPUP);
9504     test_popup_zorder(hwndMain2, hwndMain, 0);
9505     test_GetLastActivePopup();
9506     test_keyboard_input(hwndMain);
9507     test_mouse_input(hwndMain);
9508     test_validatergn(hwndMain);
9509     test_nccalcscroll( hwndMain);
9510     test_scrollwindow( hwndMain);
9511     test_scrollvalidate( hwndMain);
9512     test_scrolldc( hwndMain);
9513     test_scroll();
9514     test_IsWindowUnicode();
9515     test_vis_rgn(hwndMain);
9516 
9517     test_AdjustWindowRect();
9518     test_window_styles();
9519     test_dialog_styles();
9520     test_dialog_parent();
9521     test_redrawnow();
9522     test_csparentdc();
9523     test_SetWindowLong();
9524     test_set_window_style();
9525     test_ShowWindow();
9526     test_gettext();
9527     test_GetUpdateRect();
9528     test_Expose();
9529     test_layered_window();
9530 
9531     test_SetForegroundWindow(hwndMain);
9532     test_shell_window();
9533     test_handles( hwndMain );
9534     test_winregion();
9535     test_map_points();
9536     test_update_region();
9537     test_window_without_child_style();
9538     test_smresult();
9539     test_GetMessagePos();
9540 
9541     test_activateapp(hwndMain);
9542     test_winproc_handles(argv[0]);
9543     test_deferwindowpos();
9544 
9545     /* add the tests above this line */
9546     if (hhook) UnhookWindowsHookEx(hhook);
9547 
9548     DestroyWindow(hwndMain2);
9549     DestroyWindow(hwndMain);
9550 }
9551