ReactOS  0.4.14-dev-604-gcfdd483
win.c
Go to the documentation of this file.
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 
62 static HHOOK hhook;
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 
102 {
103  DWORD end_time = GetTickCount() + timeout;
104  MSG msg;
105 
106  do {
108  return TRUE;
109  while(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
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  }
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() &&
153  ok_(file, line)(foreground == GetForegroundWindow(), "GetForegroundWindow() = %p\n", GetForegroundWindow());
154  ok_(file, line)(focus == GetFocus(), "GetFocus() = %p\n", GetFocus());
155  ok_(file, line)(capture == GetCapture(), "GetCapture() = %p\n", GetCapture());
156 }
157 
158 /* same as above but without capture test */
159 #define check_active_state(a,b,c) check_active_state_(__FILE__,__LINE__,a,b,c)
160 static void check_active_state_(const char *file, int line,
161  HWND active, HWND foreground, HWND focus)
162 {
163  ok_(file, line)(active == GetActiveWindow(), "GetActiveWindow() = %p\n", GetActiveWindow());
164  /* only check foreground if it belongs to the current thread */
165  /* foreground can be moved to a different app pretty much at any time */
166  if (foreground && GetForegroundWindow() &&
169  ok_(file, line)(foreground == GetForegroundWindow(), "GetForegroundWindow() = %p\n", GetForegroundWindow());
170  ok_(file, line)(focus == GetFocus(), "GetFocus() = %p\n", GetFocus());
171 }
172 
174 {
175  /* these are always ignored */
176  return (message >= 0xc000 ||
177  message == WM_GETICON ||
178  message == WM_GETOBJECT ||
179  message == WM_TIMER ||
180  message == WM_SYSTIMER ||
181  message == WM_TIMECHANGE ||
183 }
184 
186 {
187  (*(LPINT)lParam)++;
188  trace("EnumChildProc on %p\n", hwndChild);
189  if (*(LPINT)lParam > 1) return FALSE;
190  return TRUE;
191 }
192 
193 /* will search for the given window */
195 {
196  trace("EnumChildProc1 on %p\n", hwndChild);
197  if ((HWND)lParam == hwndChild) return FALSE;
198  return TRUE;
199 }
200 
202 {
203  HWND ret = CreateWindowExA(0, "ToolWindowClass", "Tool window 1", style,
204  0, 0, 100, 100, parent, 0, 0, NULL );
205  ok( ret != 0, "Creation failed\n" );
206  return ret;
207 }
208 
209 /* test parent and owner values for various combinations */
210 static void test_parent_owner(void)
211 {
212  LONG style;
213  HWND test, owner, ret;
214  HWND desktop = GetDesktopWindow();
216  INT numChildren;
217 
218  trace( "main window %p main2 %p desktop %p child %p\n", hwndMain, hwndMain2, desktop, child );
219 
220  /* child without parent, should fail */
221  SetLastError(0xdeadbeef);
222  test = CreateWindowExA(0, "ToolWindowClass", "Tool window 1",
223  WS_CHILD, 0, 0, 100, 100, 0, 0, 0, NULL );
224  ok( !test, "WS_CHILD without parent created\n" );
226  broken(GetLastError() == 0xdeadbeef), /* win9x */
227  "CreateWindowExA error %u\n", GetLastError() );
228 
229  /* desktop window */
230  check_parents( desktop, 0, 0, 0, 0, 0, 0 );
231  style = GetWindowLongA( desktop, GWL_STYLE );
232  ok( !SetWindowLongA( desktop, GWL_STYLE, WS_POPUP ), "Set GWL_STYLE on desktop succeeded\n" );
233  ok( !SetWindowLongA( desktop, GWL_STYLE, 0 ), "Set GWL_STYLE on desktop succeeded\n" );
234  ok( GetWindowLongA( desktop, GWL_STYLE ) == style, "Desktop style changed\n" );
235 
236  /* normal child window */
238  trace( "created child %p\n", test );
247  DestroyWindow( test );
248 
249  /* normal child window with WS_MAXIMIZE */
251  DestroyWindow( test );
252 
253  /* normal child window with WS_THICKFRAME */
255  DestroyWindow( test );
256 
257  /* popup window with WS_THICKFRAME */
259  DestroyWindow( test );
260 
261  /* child of desktop */
262  test = create_tool_window( WS_CHILD, desktop );
263  trace( "created child of desktop %p\n", test );
264  check_parents( test, desktop, 0, desktop, 0, test, desktop );
266  check_parents( test, desktop, 0, 0, 0, test, test );
268  check_parents( test, desktop, 0, 0, 0, test, test );
269  DestroyWindow( test );
270 
271  /* child of desktop with WS_MAXIMIZE */
273  DestroyWindow( test );
274 
275  /* child of desktop with WS_MINIMIZE */
277  DestroyWindow( test );
278 
279  /* child of child */
281  trace( "created child of child %p\n", test );
284  check_parents( test, child, child, 0, 0, hwndMain, test );
286  check_parents( test, child, child, 0, 0, hwndMain, test );
287  DestroyWindow( test );
288 
289  /* child of child with WS_MAXIMIZE */
291  DestroyWindow( test );
292 
293  /* child of child with WS_MINIMIZE */
295  DestroyWindow( test );
296 
297  /* not owned top-level window */
298  test = create_tool_window( 0, 0 );
299  trace( "created top-level %p\n", test );
300  check_parents( test, desktop, 0, 0, 0, test, test );
302  check_parents( test, desktop, 0, 0, 0, test, test );
304  check_parents( test, desktop, 0, desktop, 0, test, desktop );
305  DestroyWindow( test );
306 
307  /* not owned top-level window with WS_MAXIMIZE */
309  DestroyWindow( test );
310 
311  /* owned top-level window */
313  trace( "created owned top-level %p\n", test );
314  check_parents( test, desktop, hwndMain, 0, hwndMain, test, test );
318  check_parents( test, desktop, hwndMain, desktop, hwndMain, test, desktop );
319  DestroyWindow( test );
320 
321  /* owned top-level window with WS_MAXIMIZE */
323  DestroyWindow( test );
324 
325  /* not owned popup */
327  trace( "created popup %p\n", test );
328  check_parents( test, desktop, 0, 0, 0, test, test );
330  check_parents( test, desktop, 0, desktop, 0, test, desktop );
332  check_parents( test, desktop, 0, 0, 0, test, test );
333  DestroyWindow( test );
334 
335  /* not owned popup with WS_MAXIMIZE */
337  DestroyWindow( test );
338 
339  /* owned popup */
341  trace( "created owned popup %p\n", test );
344  check_parents( test, desktop, hwndMain, desktop, hwndMain, test, desktop );
346  check_parents( test, desktop, hwndMain, 0, hwndMain, test, test );
347  DestroyWindow( test );
348 
349  /* owned popup with WS_MAXIMIZE */
351  DestroyWindow( test );
352 
353  /* top-level window owned by child (same as owned by top-level) */
354  test = create_tool_window( 0, child );
355  trace( "created top-level owned by child %p\n", test );
356  check_parents( test, desktop, hwndMain, 0, hwndMain, test, test );
357  DestroyWindow( test );
358 
359  /* top-level window owned by child (same as owned by top-level) with WS_MAXIMIZE */
361  DestroyWindow( test );
362 
363  /* popup owned by desktop (same as not owned) */
364  test = create_tool_window( WS_POPUP, desktop );
365  trace( "created popup owned by desktop %p\n", test );
366  check_parents( test, desktop, 0, 0, 0, test, test );
367  DestroyWindow( test );
368 
369  /* popup owned by desktop (same as not owned) with WS_MAXIMIZE */
371  DestroyWindow( test );
372 
373  /* popup owned by child (same as owned by top-level) */
375  trace( "created popup owned by child %p\n", test );
377  DestroyWindow( test );
378 
379  /* popup owned by child (same as owned by top-level) with WS_MAXIMIZE */
381  DestroyWindow( test );
382 
383  /* not owned popup with WS_CHILD (same as WS_POPUP only) */
385  trace( "created WS_CHILD popup %p\n", test );
386  check_parents( test, desktop, 0, 0, 0, test, test );
387  DestroyWindow( test );
388 
389  /* not owned popup with WS_CHILD | WS_MAXIMIZE (same as WS_POPUP only) */
391  DestroyWindow( test );
392 
393  /* owned popup with WS_CHILD (same as WS_POPUP only) */
395  trace( "created owned WS_CHILD popup %p\n", test );
397  DestroyWindow( test );
398 
399  /* owned popup with WS_CHILD (same as WS_POPUP only) with WS_MAXIMIZE */
401  DestroyWindow( test );
402 
403  /******************** parent changes *************************/
404  trace( "testing parent changes\n" );
405 
406  /* desktop window */
407  check_parents( desktop, 0, 0, 0, 0, 0, 0 );
408  if (0)
409  {
410  /* this test succeeds on NT but crashes on win9x systems */
412  ok( !ret, "Set GWL_HWNDPARENT succeeded on desktop\n" );
413  check_parents( desktop, 0, 0, 0, 0, 0, 0 );
414  ok( !SetParent( desktop, hwndMain ), "SetParent succeeded on desktop\n" );
415  check_parents( desktop, 0, 0, 0, 0, 0, 0 );
416  }
417  /* normal child window */
419  trace( "created child %p\n", test );
420 
422  ok( ret == hwndMain, "GWL_HWNDPARENT return value %p expected %p\n", ret, hwndMain );
424 
426  ok( ret == hwndMain2, "GWL_HWNDPARENT return value %p expected %p\n", ret, hwndMain2 );
428 
430  ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
431  check_parents( test, desktop, 0, desktop, 0, test, desktop );
432 
433  /* window is now child of desktop so GWLP_HWNDPARENT changes owner from now on */
434  if (!is_win9x)
435  {
437  ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
438  check_parents( test, desktop, 0, desktop, 0, test, desktop );
439  }
440  else
441  win_skip("Test creates circular window tree under Win9x/WinMe\n" );
442 
444  ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
445  check_parents( test, desktop, child, desktop, child, test, desktop );
446 
448  ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
449  check_parents( test, desktop, 0, desktop, 0, test, desktop );
450  DestroyWindow( test );
451 
452  /* not owned top-level window */
453  test = create_tool_window( 0, 0 );
454  trace( "created top-level %p\n", test );
455 
457  ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
458  check_parents( test, desktop, hwndMain2, 0, hwndMain2, test, test );
459 
461  ok( ret == hwndMain2, "GWL_HWNDPARENT return value %p expected %p\n", ret, hwndMain2 );
462  check_parents( test, desktop, child, 0, child, test, test );
463 
465  ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
466  check_parents( test, desktop, 0, 0, 0, test, test );
467  DestroyWindow( test );
468 
469  /* not owned popup */
471  trace( "created popup %p\n", test );
472 
474  ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
476 
478  ok( ret == hwndMain2, "GWL_HWNDPARENT return value %p expected %p\n", ret, hwndMain2 );
479  check_parents( test, desktop, child, child, child, test, hwndMain );
480 
482  ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
483  check_parents( test, desktop, 0, 0, 0, test, test );
484  DestroyWindow( test );
485 
486  /* normal child window */
488  trace( "created child %p\n", test );
489 
490  ret = SetParent( test, desktop );
491  ok( ret == hwndMain, "SetParent return value %p expected %p\n", ret, hwndMain );
492  check_parents( test, desktop, 0, desktop, 0, test, desktop );
493 
494  ret = SetParent( test, child );
495  ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
497 
498  ret = SetParent( test, hwndMain2 );
499  ok( ret == child, "SetParent return value %p expected %p\n", ret, child );
501  DestroyWindow( test );
502 
503  /* not owned top-level window */
504  test = create_tool_window( 0, 0 );
505  trace( "created top-level %p\n", test );
506 
507  ret = SetParent( test, child );
508  ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
509  check_parents( test, child, child, 0, 0, hwndMain, test );
510 
511  if (!is_win9x)
512  {
513  ShowWindow( test, SW_SHOW );
514  ret = SetParent( test, test );
515  ok( ret == NULL, "SetParent return value %p expected %p\n", ret, NULL );
516  ok( GetWindowLongA( test, GWL_STYLE ) & WS_VISIBLE, "window is not visible after SetParent\n" );
517  check_parents( test, child, child, 0, 0, hwndMain, test );
518  }
519  else
520  win_skip( "Test crashes on Win9x/WinMe\n" );
521  DestroyWindow( test );
522 
523  /* owned popup */
525  trace( "created owned popup %p\n", test );
526 
527  ret = SetParent( test, child );
528  ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
530 
532  ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
534  DestroyWindow( test );
535 
536  /**************** test owner destruction *******************/
537 
538  /* owned child popup */
539  owner = create_tool_window( 0, 0 );
540  test = create_tool_window( WS_POPUP, owner );
541  trace( "created owner %p and popup %p\n", owner, test );
542  ret = SetParent( test, child );
543  ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
544  check_parents( test, child, child, owner, owner, hwndMain, owner );
545  /* window is now child of 'child' but owned by 'owner' */
546  DestroyWindow( owner );
547  ok( IsWindow(test), "Window %p destroyed by owner destruction\n", test );
548  /* Win98 doesn't pass this test. It doesn't allow a destroyed owner,
549  * while Win95, Win2k, WinXP do.
550  */
551  /*check_parents( test, child, child, owner, owner, hwndMain, owner );*/
552  ok( !IsWindow(owner), "Owner %p not destroyed\n", owner );
554 
555  /* owned top-level popup */
556  owner = create_tool_window( 0, 0 );
557  test = create_tool_window( WS_POPUP, owner );
558  trace( "created owner %p and popup %p\n", owner, test );
559  check_parents( test, desktop, owner, owner, owner, test, owner );
560  DestroyWindow( owner );
561  ok( !IsWindow(test), "Window %p not destroyed by owner destruction\n", test );
562 
563  /* top-level popup owned by child */
566  trace( "created owner %p and popup %p\n", owner, test );
568  ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
569  check_parents( test, desktop, owner, owner, owner, test, hwndMain2 );
570  DestroyWindow( owner );
571  ok( IsWindow(test), "Window %p destroyed by owner destruction\n", test );
572  ok( !IsWindow(owner), "Owner %p not destroyed\n", owner );
573  /* Win98 doesn't pass this test. It doesn't allow a destroyed owner,
574  * while Win95, Win2k, WinXP do.
575  */
576  /*check_parents( test, desktop, owner, owner, owner, test, owner );*/
578 
579  /* final cleanup */
581 
582 
583  owner = create_tool_window( WS_OVERLAPPED, 0 );
584  test = create_tool_window( WS_POPUP, desktop );
585 
586  ok( !GetWindow( test, GW_OWNER ), "Wrong owner window\n" );
587  numChildren = 0;
588  ok( !EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
589  "EnumChildWindows should have returned FALSE\n" );
590  ok( numChildren == 0, "numChildren should be 0 got %d\n", numChildren );
591 
593  ret = SetParent( test, owner );
594  ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
595 
596  numChildren = 0;
597  ok( EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
598  "EnumChildWindows should have returned TRUE\n" );
599  ok( numChildren == 1, "numChildren should be 1 got %d\n", numChildren );
600 
601  child = create_tool_window( WS_CHILD, owner );
602  numChildren = 0;
603  ok( !EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
604  "EnumChildWindows should have returned FALSE\n" );
605  ok( numChildren == 2, "numChildren should be 2 got %d\n", numChildren );
606  DestroyWindow( child );
607 
609  ok( GetWindow( child, GW_OWNER ) == owner, "Wrong owner window\n" );
610  numChildren = 0;
611  ok( EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
612  "EnumChildWindows should have returned TRUE\n" );
613  ok( numChildren == 1, "numChildren should be 1 got %d\n", numChildren );
614 
615  ret = SetParent( child, owner );
616  ok( GetWindow( child, GW_OWNER ) == owner, "Wrong owner window\n" );
617  ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
618  numChildren = 0;
619  ok( !EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
620  "EnumChildWindows should have returned FALSE\n" );
621  ok( numChildren == 2, "numChildren should be 2 got %d\n", numChildren );
622 
623  ret = SetParent( child, NULL );
624  ok( GetWindow( child, GW_OWNER ) == owner, "Wrong owner window\n" );
625  ok( ret == owner, "SetParent return value %p expected %p\n", ret, owner );
626  numChildren = 0;
627  ok( EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
628  "EnumChildWindows should have returned TRUE\n" );
629  ok( numChildren == 1, "numChildren should be 1 got %d\n", numChildren );
630 
631  /* even GW_OWNER == owner it's still a desktop's child */
633  "EnumChildWindows should have found %p and returned FALSE\n", child );
634 
635  DestroyWindow( child );
637 
639  "EnumChildWindows should have found %p and returned FALSE\n", child );
640 
641  DestroyWindow( child );
642  DestroyWindow( test );
643  DestroyWindow( owner );
644 
645  /* Test that owner window takes into account WS_CHILD flag even if parent is set by SetParent. */
646  owner = create_tool_window( WS_VISIBLE | WS_OVERLAPPEDWINDOW, desktop );
647  SetParent(owner, hwndMain);
648  check_parents( owner, hwndMain, hwndMain, NULL, NULL, hwndMain, owner );
650  check_parents( test, desktop, owner, NULL, owner, test, test );
651  DestroyWindow( owner );
652  DestroyWindow( test );
653 
654  owner = create_tool_window( WS_VISIBLE | WS_CHILD, desktop );
655  SetParent(owner, hwndMain);
658  check_parents( test, desktop, hwndMain, NULL, hwndMain, test, test );
659  DestroyWindow( owner );
660  DestroyWindow( test );
661 
662  owner = create_tool_window( WS_VISIBLE | WS_POPUP | WS_CHILD, desktop );
663  SetParent(owner, hwndMain);
664  check_parents( owner, hwndMain, hwndMain, NULL, NULL, hwndMain, owner );
666  check_parents( test, desktop, owner, NULL, owner, test, test );
667  DestroyWindow( owner );
668  DestroyWindow( test );
669 }
670 
672 {
673  (*(LPINT)lParam)++;
674  if (*(LPINT)lParam > 2) return FALSE;
675  return TRUE;
676 }
677 static DWORD CALLBACK enum_thread( void *arg )
678 {
679  INT count;
680  HWND hwnd[3];
681  BOOL ret;
682  MSG msg;
683 
684  if (pGetGUIThreadInfo)
685  {
687  info.cbSize = sizeof(info);
688  ret = pGetGUIThreadInfo( GetCurrentThreadId(), &info );
689  ok( ret || broken(!ret), /* win9x */
690  "GetGUIThreadInfo failed without message queue\n" );
691  SetLastError( 0xdeadbeef );
692  info.cbSize = sizeof(info) + 1;
693  ret = pGetGUIThreadInfo( GetCurrentThreadId(), &info );
694  ok( !ret, "GetGUIThreadInfo succeeded with wrong size\n" );
696  broken(GetLastError() == 0xdeadbeef), /* win9x */
697  "wrong error %u\n", GetLastError() );
698  }
699 
700  PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ); /* make sure we have a message queue */
701 
702  count = 0;
704  ok( ret, "EnumThreadWindows should have returned TRUE\n" );
705  ok( count == 0, "count should be 0 got %d\n", count );
706 
707  hwnd[0] = CreateWindowExA(0, "ToolWindowClass", "Tool window 1", WS_POPUP,
708  0, 0, 100, 100, 0, 0, 0, NULL );
709  count = 0;
711  ok( ret, "EnumThreadWindows should have returned TRUE\n" );
712  if (count != 2) /* Vista gives us two windows for the price of one */
713  {
714  ok( count == 1, "count should be 1 got %d\n", count );
715  hwnd[2] = CreateWindowExA(0, "ToolWindowClass", "Tool window 2", WS_POPUP,
716  0, 0, 100, 100, 0, 0, 0, NULL );
717  }
718  else hwnd[2] = 0;
719 
720  hwnd[1] = CreateWindowExA(0, "ToolWindowClass", "Tool window 3", WS_POPUP,
721  0, 0, 100, 100, 0, 0, 0, NULL );
722  count = 0;
724  ok( !ret, "EnumThreadWindows should have returned FALSE\n" );
725  ok( count == 3, "count should be 3 got %d\n", count );
726 
727  if (hwnd[2]) DestroyWindow(hwnd[2]);
728  DestroyWindow(hwnd[1]);
729  DestroyWindow(hwnd[0]);
730  return 0;
731 }
732 
733 /* test EnumThreadWindows in a separate thread */
734 static void test_enum_thread_windows(void)
735 {
736  DWORD id;
737  HANDLE handle = CreateThread( NULL, 0, enum_thread, 0, 0, &id );
738  ok( !WaitForSingleObject( handle, 10000 ), "wait failed\n" );
739  CloseHandle( handle );
740 }
741 
743 {
744  BOOL enabled; /* when 1 bypasses default procedure */
745  char *buff; /* expected text buffer pointer */
746  WCHAR *buffW; /* same, for W test */
748 
750 {
751  switch (msg)
752  {
753  case WM_GETMINMAXINFO:
754  {
755  SetWindowLongPtrA(hwnd, GWLP_USERDATA, 0x20031021);
756  break;
757  }
759  {
760  WINDOWPOS *winpos = (WINDOWPOS *)lparam;
761  if (!(winpos->flags & SWP_NOMOVE))
762  {
763  ok(winpos->x >= -32768 && winpos->x <= 32767, "bad winpos->x %d\n", winpos->x);
764  ok(winpos->y >= -32768 && winpos->y <= 32767, "bad winpos->y %d\n", winpos->y);
765  }
766  /* Win9x does not fixup cx/xy for WM_WINDOWPOSCHANGING */
767  if (!(winpos->flags & SWP_NOSIZE) && !is_win9x)
768  {
769  ok((winpos->cx >= 0 && winpos->cx <= 32767) ||
770  winpos->cx == 32768, /* win7 doesn't truncate */
771  "bad winpos->cx %d\n", winpos->cx);
772  ok((winpos->cy >= 0 && winpos->cy <= 32767) ||
773  winpos->cy == 40000, /* win7 doesn't truncate */
774  "bad winpos->cy %d\n", winpos->cy);
775  }
776  break;
777  }
778  case WM_WINDOWPOSCHANGED:
780  {
781  RECT rc1, rc2;
782  WINDOWPOS *winpos = (WINDOWPOS *)lparam;
783  ok(winpos->x >= -32768 && winpos->x <= 32767, "bad winpos->x %d\n", winpos->x);
784  ok(winpos->y >= -32768 && winpos->y <= 32767, "bad winpos->y %d\n", winpos->y);
785 
786  ok((winpos->cx >= 0 && winpos->cx <= 32767) ||
787  winpos->cx == 32768, /* win7 doesn't truncate */
788  "bad winpos->cx %d\n", winpos->cx);
789  ok((winpos->cy >= 0 && winpos->cy <= 32767) ||
790  winpos->cy == 40000, /* win7 doesn't truncate */
791  "bad winpos->cy %d\n", winpos->cy);
792 
793  GetWindowRect(hwnd, &rc1);
794  SetRect(&rc2, winpos->x, winpos->y, winpos->x + winpos->cx, winpos->y + winpos->cy);
795  /* note: winpos coordinates are relative to parent */
797  if (0)
798  {
799  /* Uncomment this once the test succeeds in all cases */
800  ok(EqualRect(&rc1, &rc2), "rects do not match %s / %s\n", wine_dbgstr_rect(&rc1),
802 
805  MapWindowPoints(0, hwnd, (LPPOINT)&rc1, 2);
806  ok(EqualRect(&rc1, &rc2), "rects do not match %s / %s\n", wine_dbgstr_rect(&rc1),
808  }
809  break;
810  }
811  case WM_NCCREATE:
812  {
813  BOOL got_getminmaxinfo = GetWindowLongPtrA(hwnd, GWLP_USERDATA) == 0x20031021;
815 
816  if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
817  ok(got_getminmaxinfo, "main: WM_GETMINMAXINFO should have been received before WM_NCCREATE\n");
818  else
819  ok(!got_getminmaxinfo, "main: WM_GETMINMAXINFO should NOT have been received before WM_NCCREATE\n");
820  break;
821  }
822  case WM_COMMAND:
824  {
826  flush_events( FALSE );
827  }
828  break;
829  case WM_GETTEXT:
831  if (g_wm_gettext_override.enabled)
832  {
833  char *text = (char*)lparam;
834  ok(g_wm_gettext_override.buff == text, "expected buffer %p, got %p\n", g_wm_gettext_override.buff, text);
835  ok(*text == 0, "expected empty string buffer %x\n", *text);
836  return 0;
837  }
838  break;
839  case WM_SETTEXT:
841  break;
842  case WM_ACTIVATEAPP:
843  if (wparam) app_activated = TRUE;
844  else app_deactivated = TRUE;
845  break;
846  }
847 
848  return DefWindowProcA(hwnd, msg, wparam, lparam);
849 }
850 
852 {
853  switch (msg)
854  {
855  case WM_GETTEXT:
857  if (g_wm_gettext_override.enabled)
858  {
859  WCHAR *text = (WCHAR*)lparam;
860  ok(g_wm_gettext_override.buffW == text, "expected buffer %p, got %p\n", g_wm_gettext_override.buffW, text);
861  ok(*text == 0, "expected empty string buffer %x\n", *text);
862  return 0;
863  }
864  break;
865  }
866 
867  return DefWindowProcA(hwnd, msg, wparam, lparam);
868 }
869 
871 {
872  switch (msg)
873  {
874  case WM_GETMINMAXINFO:
875  {
876  SetWindowLongPtrA(hwnd, GWLP_USERDATA, 0x20031021);
877  break;
878  }
879  case WM_NCCREATE:
880  {
881  BOOL got_getminmaxinfo = GetWindowLongPtrA(hwnd, GWLP_USERDATA) == 0x20031021;
883 
884  if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
885  ok(got_getminmaxinfo, "tool: WM_GETMINMAXINFO should have been received before WM_NCCREATE\n");
886  else
887  ok(!got_getminmaxinfo, "tool: WM_GETMINMAXINFO should NOT have been received before WM_NCCREATE\n");
888  break;
889  }
890  }
891 
892  return DefWindowProcA(hwnd, msg, wparam, lparam);
893 }
894 
895 static const WCHAR mainclassW[] = {'M','a','i','n','W','i','n','d','o','w','C','l','a','s','s','W',0};
896 
898 {
899  WNDCLASSW clsW;
900  WNDCLASSA cls;
901 
902  cls.style = CS_DBLCLKS;
904  cls.cbClsExtra = 0;
905  cls.cbWndExtra = 0;
906  cls.hInstance = GetModuleHandleA(0);
907  cls.hIcon = 0;
908  cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
910  cls.lpszMenuName = NULL;
911  cls.lpszClassName = "MainWindowClass";
912 
913  if(!RegisterClassA(&cls)) return FALSE;
914 
915  clsW.style = CS_DBLCLKS;
917  clsW.cbClsExtra = 0;
918  clsW.cbWndExtra = 0;
919  clsW.hInstance = GetModuleHandleA(0);
920  clsW.hIcon = 0;
921  clsW.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
923  clsW.lpszMenuName = NULL;
924  clsW.lpszClassName = mainclassW;
925 
926  if(!RegisterClassW(&clsW)) return FALSE;
927 
928  cls.style = 0;
930  cls.cbClsExtra = 0;
931  cls.cbWndExtra = 0;
932  cls.hInstance = GetModuleHandleA(0);
933  cls.hIcon = 0;
934  cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
936  cls.lpszMenuName = NULL;
937  cls.lpszClassName = "ToolWindowClass";
938 
939  if(!RegisterClassA(&cls)) return FALSE;
940 
941  return TRUE;
942 }
943 
944 static void verify_window_info(const char *hook, HWND hwnd, const WINDOWINFO *info)
945 {
946  RECT rcWindow, rcClient;
947  DWORD status;
948 
949  ok(IsWindow(hwnd), "bad window handle %p in hook %s\n", hwnd, hook);
950 
951  GetWindowRect(hwnd, &rcWindow);
952  ok(EqualRect(&rcWindow, &info->rcWindow), "wrong rcWindow for %p in hook %s\n", hwnd, hook);
953 
954  GetClientRect(hwnd, &rcClient);
955  /* translate to screen coordinates */
956  MapWindowPoints(hwnd, 0, (LPPOINT)&rcClient, 2);
957  ok(EqualRect(&rcClient, &info->rcClient), "wrong rcClient for %p in hook %s\n", hwnd, hook);
958 
959  ok(info->dwStyle == (DWORD)GetWindowLongA(hwnd, GWL_STYLE),
960  "wrong dwStyle: %08x != %08x for %p in hook %s\n",
961  info->dwStyle, GetWindowLongA(hwnd, GWL_STYLE), hwnd, hook);
962  /* Windows reports some undocumented exstyles in WINDOWINFO, but
963  * doesn't return them in GetWindowLong(hwnd, GWL_EXSTYLE).
964  */
965  ok((info->dwExStyle & ~0xe0000800) == (DWORD)GetWindowLongA(hwnd, GWL_EXSTYLE),
966  "wrong dwExStyle: %08x != %08x for %p in hook %s\n",
967  info->dwExStyle, GetWindowLongA(hwnd, GWL_EXSTYLE), hwnd, hook);
969  if (GetForegroundWindow())
970  ok(info->dwWindowStatus == status, "wrong dwWindowStatus: %04x != %04x active %p fg %p in hook %s\n",
971  info->dwWindowStatus, status, GetActiveWindow(), GetForegroundWindow(), hook);
972  else
973  ok(1, "Just counting");
974 
975  /* win2k and XP return broken border info in GetWindowInfo most of
976  * the time, so there is no point in testing it.
977  */
978 if (0)
979 {
980  UINT border;
981  ok(info->cxWindowBorders == (unsigned)(rcClient.left - rcWindow.left),
982  "wrong cxWindowBorders %d != %d\n", info->cxWindowBorders, rcClient.left - rcWindow.left);
983  border = min(rcWindow.bottom - rcClient.bottom, rcClient.top - rcWindow.top);
984  ok(info->cyWindowBorders == border,
985  "wrong cyWindowBorders %d != %d\n", info->cyWindowBorders, border);
986 }
987  ok(info->atomWindowType == GetClassLongA(hwnd, GCW_ATOM), "wrong atomWindowType for %p in hook %s\n",
988  hwnd, hook);
989  todo_ros
990  ok(info->wCreatorVersion == 0x0400 /* NT4, Win2000, XP, Win2003 */ ||
991  info->wCreatorVersion == 0x0500 /* Vista */,
992  "wrong wCreatorVersion %04x for %p in hook %s\n", info->wCreatorVersion, hwnd, hook);
993 }
994 
995 static void FixedAdjustWindowRectEx(RECT* rc, LONG style, BOOL menu, LONG exstyle)
996 {
997  AdjustWindowRectEx(rc, style, menu, exstyle);
998  /* AdjustWindowRectEx does not include scroll bars */
999  if (style & WS_VSCROLL)
1000  {
1001  if(exstyle & WS_EX_LEFTSCROLLBAR)
1003  else
1005  }
1006  if (style & WS_HSCROLL)
1008 }
1009 
1010 /* reimplement it to check that the Wine algorithm gives the correct result */
1011 static void wine_AdjustWindowRectEx( RECT *rect, LONG style, BOOL menu, LONG exStyle )
1012 {
1013  int adjust;
1014 
1015  if ((exStyle & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) ==
1017  {
1018  adjust = 1; /* for the outer frame always present */
1019  }
1020  else
1021  {
1022  adjust = 0;
1023  if ((exStyle & WS_EX_DLGMODALFRAME) ||
1024  (style & (WS_THICKFRAME|WS_DLGFRAME))) adjust = 2; /* outer */
1025  }
1026  if (style & WS_THICKFRAME)
1027  adjust += GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME); /* The resize border */
1028  if ((style & (WS_BORDER|WS_DLGFRAME)) ||
1029  (exStyle & WS_EX_DLGMODALFRAME))
1030  adjust++; /* The other border */
1031 
1032  InflateRect (rect, adjust, adjust);
1033 
1034  if ((style & WS_CAPTION) == WS_CAPTION)
1035  {
1036  if (exStyle & WS_EX_TOOLWINDOW)
1038  else
1040  }
1041  if (menu) rect->top -= GetSystemMetrics(SM_CYMENU);
1042 
1043  if (exStyle & WS_EX_CLIENTEDGE)
1045 
1046  if (style & WS_VSCROLL)
1047  {
1048  if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
1050  else
1051  rect->right += GetSystemMetrics(SM_CXVSCROLL);
1052  }
1053  if (style & WS_HSCROLL) rect->bottom += GetSystemMetrics(SM_CYHSCROLL);
1054 }
1055 
1057 {
1058  DWORD style, exstyle;
1059  RECT rc_window, rc_client, rc;
1060  BOOL menu;
1061  LRESULT ret;
1062 
1064  exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
1065  menu = !(style & WS_CHILD) && GetMenu(hwnd) != 0;
1066 
1067  GetWindowRect(hwnd, &rc_window);
1068  GetClientRect(hwnd, &rc_client);
1069 
1070  /* avoid some cases when things go wrong */
1071  if (IsRectEmpty(&rc_window) || IsRectEmpty(&rc_client) ||
1072  rc_window.right > 32768 || rc_window.bottom > 32768) return;
1073 
1074  rc = rc_client;
1075  MapWindowPoints(hwnd, 0, (LPPOINT)&rc, 2);
1076  FixedAdjustWindowRectEx(&rc, style, menu, exstyle);
1077 
1078  ok(EqualRect(&rc, &rc_window),
1079  "window rect does not match: style:exstyle=0x%08x:0x%08x, menu=%d, win=%s, calc=%s\n",
1080  style, exstyle, menu, wine_dbgstr_rect(&rc_window), wine_dbgstr_rect(&rc));
1081 
1082  rc = rc_client;
1083  MapWindowPoints(hwnd, 0, (LPPOINT)&rc, 2);
1084  wine_AdjustWindowRectEx(&rc, style, menu, exstyle);
1085  ok(EqualRect(&rc, &rc_window),
1086  "window rect does not match: style:exstyle=0x%08x:0x%08x, menu=%d, win=%s, calc=%s\n",
1087  style, exstyle, menu, wine_dbgstr_rect(&rc_window), wine_dbgstr_rect(&rc));
1088 
1089 
1090  rc = rc_window;
1092  MapWindowPoints(0, hwnd, (LPPOINT)&rc, 2);
1093  ok(EqualRect(&rc, &rc_client),
1094  "client rect does not match: style:exstyle=0x%08x:0x%08x, menu=%d client=%s, calc=%s\n",
1095  style, exstyle, menu, wine_dbgstr_rect(&rc_client), wine_dbgstr_rect(&rc));
1096 
1097  /* NULL rectangle shouldn't crash */
1099  ok(ret == 0, "NULL rectangle returned %ld instead of 0\n", ret);
1100 
1101  /* Win9x doesn't like WM_NCCALCSIZE with synthetic data and crashes */;
1102  if (is_win9x)
1103  return;
1104 
1105  /* and now test AdjustWindowRectEx and WM_NCCALCSIZE on synthetic data */
1106  SetRect(&rc_client, 0, 0, 250, 150);
1107  rc_window = rc_client;
1108  MapWindowPoints(hwnd, 0, (LPPOINT)&rc_window, 2);
1109  FixedAdjustWindowRectEx(&rc_window, style, menu, exstyle);
1110 
1111  rc = rc_window;
1113  MapWindowPoints(0, hwnd, (LPPOINT)&rc, 2);
1114  ok(EqualRect(&rc, &rc_client),
1115  "synthetic rect does not match: style:exstyle=0x%08x:0x%08x, menu=%d, client=%s, calc=%s\n",
1116  style, exstyle, menu, wine_dbgstr_rect(&rc_client), wine_dbgstr_rect(&rc));
1117 }
1118 
1120 {
1121  static const char *CBT_code_name[10] = {
1122  "HCBT_MOVESIZE",
1123  "HCBT_MINMAX",
1124  "HCBT_QS",
1125  "HCBT_CREATEWND",
1126  "HCBT_DESTROYWND",
1127  "HCBT_ACTIVATE",
1128  "HCBT_CLICKSKIPPED",
1129  "HCBT_KEYSKIPPED",
1130  "HCBT_SYSCOMMAND",
1131  "HCBT_SETFOCUS" };
1132  const char *code_name = (nCode >= 0 && nCode <= HCBT_SETFOCUS) ? CBT_code_name[nCode] : "Unknown";
1133  HWND hwnd = (HWND)wParam;
1134 
1135  switch (nCode)
1136  {
1137  case HCBT_CREATEWND:
1138  {
1139  static const RECT rc_null;
1140  RECT rc;
1141  LONG style;
1142  CBT_CREATEWNDA *createwnd = (CBT_CREATEWNDA *)lParam;
1143  ok(createwnd->hwndInsertAfter == HWND_TOP, "hwndInsertAfter should be always HWND_TOP\n");
1144 
1145  if (pGetWindowInfo)
1146  {
1147  WINDOWINFO info;
1148  info.cbSize = sizeof(WINDOWINFO);
1149  ok(pGetWindowInfo(hwnd, &info), "GetWindowInfo should not fail\n");
1150  verify_window_info(code_name, hwnd, &info);
1151  }
1152 
1153  /* WS_VISIBLE should be turned off yet */
1154  style = createwnd->lpcs->style & ~WS_VISIBLE;
1156  "style of hwnd and style in the CREATESTRUCT do not match: %08x != %08x\n",
1158 
1159  if (0)
1160  {
1161  /* Uncomment this once the test succeeds in all cases */
1162  if ((style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1163  {
1165  "wrong result from GetParent %p: message window %p\n",
1167  }
1168  else
1169  ok(!GetParent(hwnd), "GetParent should return 0 at this point\n");
1170 
1171  ok(!GetWindow(hwnd, GW_OWNER), "GW_OWNER should be set to 0 at this point\n");
1172  }
1173  if (0)
1174  {
1175  /* while NT assigns GW_HWNDFIRST/LAST some values at this point,
1176  * Win9x still has them set to 0.
1177  */
1178  ok(GetWindow(hwnd, GW_HWNDFIRST) != 0, "GW_HWNDFIRST should not be set to 0 at this point\n");
1179  ok(GetWindow(hwnd, GW_HWNDLAST) != 0, "GW_HWNDLAST should not be set to 0 at this point\n");
1180  }
1181  ok(!GetWindow(hwnd, GW_HWNDPREV), "GW_HWNDPREV should be set to 0 at this point\n");
1182  ok(!GetWindow(hwnd, GW_HWNDNEXT), "GW_HWNDNEXT should be set to 0 at this point\n");
1183 
1184  if (0)
1185  {
1186  /* Uncomment this once the test succeeds in all cases */
1187  if (pGetAncestor)
1188  {
1189  ok(pGetAncestor(hwnd, GA_PARENT) == hwndMessage, "GA_PARENT should be set to hwndMessage at this point\n");
1190  ok(pGetAncestor(hwnd, GA_ROOT) == hwnd,
1191  "GA_ROOT is set to %p, expected %p\n", pGetAncestor(hwnd, GA_ROOT), hwnd);
1192 
1193  if ((style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1194  ok(pGetAncestor(hwnd, GA_ROOTOWNER) == hwndMessage,
1195  "GA_ROOTOWNER should be set to hwndMessage at this point\n");
1196  else
1197  ok(pGetAncestor(hwnd, GA_ROOTOWNER) == hwnd,
1198  "GA_ROOTOWNER is set to %p, expected %p\n", pGetAncestor(hwnd, GA_ROOTOWNER), hwnd);
1199  }
1200 
1201  ok(GetWindowRect(hwnd, &rc), "GetWindowRect failed\n");
1202  ok(EqualRect(&rc, &rc_null), "window rect should be set to 0 HCBT_CREATEWND\n");
1203  ok(GetClientRect(hwnd, &rc), "GetClientRect failed\n");
1204  ok(EqualRect(&rc, &rc_null), "client rect should be set to 0 on HCBT_CREATEWND\n");
1205  }
1206  break;
1207  }
1208  case HCBT_MOVESIZE:
1209  case HCBT_MINMAX:
1210  case HCBT_ACTIVATE:
1211  if (pGetWindowInfo && IsWindow(hwnd))
1212  {
1213  WINDOWINFO info;
1214 
1215  /* Win98 actually does check the info.cbSize and doesn't allow
1216  * it to be anything except sizeof(WINDOWINFO), while Win95, Win2k,
1217  * WinXP do not check it at all.
1218  */
1219  info.cbSize = sizeof(WINDOWINFO);
1220  ok(pGetWindowInfo(hwnd, &info), "GetWindowInfo should not fail\n");
1221  verify_window_info(code_name, hwnd, &info);
1222  }
1223  break;
1224  /* window state is undefined */
1225  case HCBT_SETFOCUS:
1226  case HCBT_DESTROYWND:
1227  break;
1228  default:
1229  break;
1230  }
1231 
1232  return CallNextHookEx(hhook, nCode, wParam, lParam);
1233 }
1234 
1235 static void test_shell_window(void)
1236 {
1237  BOOL ret;
1238  DWORD error;
1239  HMODULE hinst, hUser32;
1241  HWND hwnd1, hwnd2, hwnd3, hwnd4, hwnd5;
1242  HWND shellWindow, nextWnd;
1243 
1244  if (is_win9x)
1245  {
1246  win_skip("Skipping shell window test on Win9x\n");
1247  return;
1248  }
1249 
1250  shellWindow = GetShellWindow();
1252  hUser32 = GetModuleHandleA("user32");
1253 
1254  SetShellWindow = (void *)GetProcAddress(hUser32, "SetShellWindow");
1255 
1256  trace("previous shell window: %p\n", shellWindow);
1257 
1258  if (shellWindow) {
1259  DWORD pid;
1260  HANDLE hProcess;
1261 
1262  GetWindowThreadProcessId(shellWindow, &pid);
1264  if (!hProcess)
1265  {
1266  skip( "cannot get access to shell process\n" );
1267  return;
1268  }
1269 
1270  SetLastError(0xdeadbeef);
1271  ret = DestroyWindow(shellWindow);
1272  error = GetLastError();
1273 
1274  ok(!ret, "DestroyWindow(shellWindow)\n");
1275  /* passes on Win XP, but not on Win98 */
1276  ok(error==ERROR_ACCESS_DENIED || error == 0xdeadbeef,
1277  "got %u after DestroyWindow(shellWindow)\n", error);
1278 
1279  /* close old shell instance */
1281  ok(ret, "termination of previous shell process failed: GetLastError()=%d\n", GetLastError());
1282  WaitForSingleObject(hProcess, INFINITE); /* wait for termination */
1284  }
1285 
1286  hwnd1 = CreateWindowExA(0, "#32770", "TEST1", WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 100, 100, 300, 200, 0, 0, hinst, 0);
1287  trace("created window 1: %p\n", hwnd1);
1288 
1289  ret = SetShellWindow(hwnd1);
1290  ok(ret, "first call to SetShellWindow(hwnd1)\n");
1291  shellWindow = GetShellWindow();
1292  ok(shellWindow==hwnd1, "wrong shell window: %p\n", shellWindow);
1293 
1294  ret = SetShellWindow(hwnd1);
1295  ok(!ret, "second call to SetShellWindow(hwnd1)\n");
1296 
1297  ret = SetShellWindow(0);
1298  error = GetLastError();
1299  /* passes on Win XP, but not on Win98
1300  ok(!ret, "reset shell window by SetShellWindow(0)\n");
1301  ok(error==ERROR_INVALID_WINDOW_HANDLE, "ERROR_INVALID_WINDOW_HANDLE after SetShellWindow(0)\n"); */
1302 
1303  ret = SetShellWindow(hwnd1);
1304  /* passes on Win XP, but not on Win98
1305  ok(!ret, "third call to SetShellWindow(hwnd1)\n"); */
1306 
1308  ret = (GetWindowLongA(hwnd1,GWL_EXSTYLE) & WS_EX_TOPMOST) != 0;
1309  ok(!ret, "SetWindowExStyle(hwnd1, WS_EX_TOPMOST)\n");
1310 
1311  ret = DestroyWindow(hwnd1);
1312  ok(ret, "DestroyWindow(hwnd1)\n");
1313 
1314  hwnd2 = CreateWindowExA(WS_EX_TOPMOST, "#32770", "TEST2", WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 150, 250, 300, 200, 0, 0, hinst, 0);
1315  trace("created window 2: %p\n", hwnd2);
1316  ret = SetShellWindow(hwnd2);
1317  ok(!ret, "SetShellWindow(hwnd2) with WS_EX_TOPMOST\n");
1318 
1319  hwnd3 = CreateWindowExA(0, "#32770", "TEST3", WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 200, 400, 300, 200, 0, 0, hinst, 0);
1320  trace("created window 3: %p\n", hwnd3);
1321 
1322  hwnd4 = CreateWindowExA(0, "#32770", "TEST4", WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 250, 500, 300, 200, 0, 0, hinst, 0);
1323  trace("created window 4: %p\n", hwnd4);
1324 
1325  nextWnd = GetWindow(hwnd4, GW_HWNDNEXT);
1326  ok(nextWnd==hwnd3, "wrong next window for hwnd4: %p - expected hwnd3\n", nextWnd);
1327 
1328  ret = SetShellWindow(hwnd4);
1329  ok(ret, "SetShellWindow(hwnd4)\n");
1330  shellWindow = GetShellWindow();
1331  ok(shellWindow==hwnd4, "wrong shell window: %p - expected hwnd4\n", shellWindow);
1332 
1333  nextWnd = GetWindow(hwnd4, GW_HWNDNEXT);
1334  ok(nextWnd==0, "wrong next window for hwnd4: %p - expected 0\n", nextWnd);
1335 
1336  ret = SetWindowPos(hwnd4, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
1337  ok(ret, "SetWindowPos(hwnd4, HWND_TOPMOST)\n");
1338 
1339  ret = SetWindowPos(hwnd4, hwnd3, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
1340  ok(ret, "SetWindowPos(hwnd4, hwnd3\n");
1341 
1342  ret = SetShellWindow(hwnd3);
1343  ok(!ret, "SetShellWindow(hwnd3)\n");
1344  shellWindow = GetShellWindow();
1345  ok(shellWindow==hwnd4, "wrong shell window: %p - expected hwnd4\n", shellWindow);
1346 
1347  hwnd5 = CreateWindowExA(0, "#32770", "TEST5", WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 300, 600, 300, 200, 0, 0, hinst, 0);
1348  trace("created window 5: %p\n", hwnd5);
1349  ret = SetWindowPos(hwnd4, hwnd5, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
1350  ok(ret, "SetWindowPos(hwnd4, hwnd5)\n");
1351 
1352  todo_wine
1353  {
1354  nextWnd = GetWindow(hwnd4, GW_HWNDNEXT);
1355  ok(nextWnd==0, "wrong next window for hwnd4 after SetWindowPos(): %p - expected 0\n", nextWnd);
1356  }
1357 
1358  /* destroy test windows */
1359  DestroyWindow(hwnd2);
1360  DestroyWindow(hwnd3);
1361  DestroyWindow(hwnd4);
1362  DestroyWindow(hwnd5);
1363 }
1364 
1365 /************** MDI test ****************/
1366 
1367 static char mdi_lParam_test_message[] = "just a test string";
1368 
1370 {
1371  MDICREATESTRUCTA mdi_cs;
1372  HWND mdi_child, hwnd, exp_hwnd;
1373  INT_PTR id;
1374  static const WCHAR classW[] = {'M','D','I','_','c','h','i','l','d','_','C','l','a','s','s','_','1',0};
1375  static const WCHAR titleW[] = {'M','D','I',' ','c','h','i','l','d',0};
1376  BOOL isWin9x = FALSE;
1377  HMENU frame_menu = GetMenu(parent);
1378 
1379  ok(frame_menu != NULL, "Frame window didn't have a menu\n");
1380 
1381  mdi_cs.szClass = "MDI_child_Class_1";
1382  mdi_cs.szTitle = "MDI child";
1383  mdi_cs.hOwner = GetModuleHandleA(NULL);
1384  mdi_cs.x = CW_USEDEFAULT;
1385  mdi_cs.y = CW_USEDEFAULT;
1386  mdi_cs.cx = CW_USEDEFAULT;
1387  mdi_cs.cy = CW_USEDEFAULT;
1388  mdi_cs.style = 0;
1390  mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
1391  ok(mdi_child != 0, "MDI child creation failed\n");
1392  id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1393  ok(id == first_id, "wrong child id %ld\n", id);
1395  exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0;
1396  ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd);
1397  SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1398  ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1399 
1400  mdi_cs.style = 0x7fffffff; /* without WS_POPUP */
1401  mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
1402  ok(mdi_child != 0, "MDI child creation failed\n");
1403  id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1404  ok(id == first_id, "wrong child id %ld\n", id);
1406  ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1407  SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1408  ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1409 
1410  mdi_cs.style = 0xffffffff; /* with WS_POPUP */
1411  mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
1413  {
1414  ok(!mdi_child, "MDI child with WS_POPUP and with MDIS_ALLCHILDSTYLES should fail\n");
1415  }
1416  else
1417  {
1418  ok(mdi_child != 0, "MDI child creation failed\n");
1419  id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1420  ok(id == first_id, "wrong child id %ld\n", id);
1422  ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1423  ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1424  SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1425  ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1426  }
1427 
1428  /* test MDICREATESTRUCT A<->W mapping */
1429  /* MDICREATESTRUCTA and MDICREATESTRUCTW have the same layout */
1430  mdi_cs.style = 0;
1431  mdi_cs.szClass = (LPCSTR)classW;
1432  mdi_cs.szTitle = (LPCSTR)titleW;
1433  SetLastError(0xdeadbeef);
1434  mdi_child = (HWND)SendMessageW(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
1435  if (!mdi_child)
1436  {
1438  isWin9x = TRUE;
1439  else
1440  ok(mdi_child != 0, "MDI child creation failed\n");
1441  }
1442  else
1443  {
1444  id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1445  ok(id == first_id, "wrong child id %ld\n", id);
1447  exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0;
1448  ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd);
1449  ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1450  SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1451  ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1452  }
1453 
1454  mdi_child = CreateMDIWindowA("MDI_child_Class_1", "MDI child",
1455  0,
1460  ok(mdi_child != 0, "MDI child creation failed\n");
1461  id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1462  ok(id == first_id, "wrong child id %ld\n", id);
1464  exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0;
1465  ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd);
1466  ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1467  SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1468  ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1469 
1470  mdi_child = CreateMDIWindowA("MDI_child_Class_1", "MDI child",
1471  0x7fffffff, /* without WS_POPUP */
1476  ok(mdi_child != 0, "MDI child creation failed\n");
1477  id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1478  ok(id == first_id, "wrong child id %ld\n", id);
1480  ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1481  ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1482  SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1483  ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1484 
1485  mdi_child = CreateMDIWindowA("MDI_child_Class_1", "MDI child",
1486  0xffffffff, /* with WS_POPUP */
1492  {
1493  ok(!mdi_child, "MDI child with WS_POPUP and with MDIS_ALLCHILDSTYLES should fail\n");
1494  }
1495  else
1496  {
1497  ok(mdi_child != 0, "MDI child creation failed\n");
1498  id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1499  ok(id == first_id, "wrong child id %ld\n", id);
1501  ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1502  ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1503  SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1504  ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1505  }
1506 
1507  /* test MDICREATESTRUCT A<->W mapping */
1508  SetLastError(0xdeadbeef);
1509  mdi_child = CreateMDIWindowW(classW, titleW,
1510  0,
1515  if (!mdi_child)
1516  {
1518  isWin9x = TRUE;
1519  else
1520  ok(mdi_child != 0, "MDI child creation failed\n");
1521  }
1522  else
1523  {
1524  id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1525  ok(id == first_id, "wrong child id %ld\n", id);
1527  exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0;
1528  ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd);
1529  ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1530  SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1531  ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1532  }
1533 
1534  mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
1535  0,
1540  ok(mdi_child != 0, "MDI child creation failed\n");
1541  id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1542  ok(id == first_id, "wrong child id %ld\n", id);
1544  exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0;
1545  ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd);
1546  ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1547  SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1548  ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1549 
1550  mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
1551  WS_MAXIMIZE,
1556  ok(mdi_child != 0, "MDI child creation failed\n");
1557  id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1558  ok(id == first_id, "wrong child id %ld\n", id);
1560  exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0;
1561  ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd);
1563  ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1564  else
1565  ok(GetMenuItemCount(frame_menu) == 4, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1566  SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1567  ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1568 
1569  mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
1570  0x7fffffff, /* without WS_POPUP */
1575  ok(mdi_child != 0, "MDI child creation failed\n");
1576  id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1577  ok(id == first_id, "wrong child id %ld\n", id);
1579  ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1580  ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1581  SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1582  ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1583 
1584  mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
1585  0xffffffff, /* with WS_POPUP */
1591  {
1592  ok(!mdi_child, "MDI child with WS_POPUP and with MDIS_ALLCHILDSTYLES should fail\n");
1593  }
1594  else
1595  {
1596  ok(mdi_child != 0, "MDI child creation failed\n");
1597  id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1598  ok(id == first_id, "wrong child id %ld\n", id);
1600  ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1601  ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1602  SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1603  ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1604  }
1605 
1606  /* test MDICREATESTRUCT A<->W mapping */
1607  SetLastError(0xdeadbeef);
1609  0,
1614  if (!mdi_child)
1615  {
1617  isWin9x = TRUE;
1618  else
1619  ok(mdi_child != 0, "MDI child creation failed\n");
1620  }
1621  else
1622  {
1623  id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1624  ok(id == first_id, "wrong child id %ld\n", id);
1626  exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0;
1627  ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd);
1628  ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1629  SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1630  ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1631  }
1632 
1633  /* This test fails on Win9x */
1634  if (!isWin9x)
1635  {
1636  mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_2", "MDI child",
1637  WS_CHILD,
1642  ok(!mdi_child, "WS_EX_MDICHILD with a not MDIClient parent should fail\n");
1643  }
1644 
1645  mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
1646  WS_CHILD, /* without WS_POPUP */
1651  ok(mdi_child != 0, "MDI child creation failed\n");
1652  id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1653  ok(id == 0, "wrong child id %ld\n", id);
1654  ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1656  ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1657  DestroyWindow(mdi_child);
1658 
1659  mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
1660  WS_CHILD | WS_POPUP, /* with WS_POPUP */
1665  ok(mdi_child != 0, "MDI child creation failed\n");
1666  id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1667  ok(id == 0, "wrong child id %ld\n", id);
1669  ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1670  ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1671  DestroyWindow(mdi_child);
1672 
1673  /* maximized child */
1674  mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
1680  ok(mdi_child != 0, "MDI child creation failed\n");
1681  id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1682  ok(id == 0, "wrong child id %ld\n", id);
1684  ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1685  ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1686  DestroyWindow(mdi_child);
1687 
1688  trace("Creating maximized child with a caption\n");
1689  mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
1695  ok(mdi_child != 0, "MDI child creation failed\n");
1696  id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1697  ok(id == 0, "wrong child id %ld\n", id);
1699  ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1700  ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1701  DestroyWindow(mdi_child);
1702 
1703  trace("Creating maximized child with a caption and a thick frame\n");
1704  mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
1710  ok(mdi_child != 0, "MDI child creation failed\n");
1711  id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1712  ok(id == 0, "wrong child id %ld\n", id);
1714  ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1715  ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1716  DestroyWindow(mdi_child);
1717 }
1718 
1720 {
1721  HWND child_1, child_2, child_3, child_4;
1722  HWND stack[4];
1724 
1725  cs.szClass = "MDI_child_Class_1";
1726  cs.szTitle = "MDI child";
1727  cs.hOwner = GetModuleHandleA(0);
1728  cs.x = CW_USEDEFAULT;
1729  cs.y = CW_USEDEFAULT;
1730  cs.cx = CW_USEDEFAULT;
1731  cs.cy = CW_USEDEFAULT;
1732  cs.style = 0;
1733  cs.lParam = (LPARAM)mdi_lParam_test_message;
1734 
1735  child_1 = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&cs);
1736  ok(child_1 != 0, "expected child_1 to be non NULL\n");
1737  child_2 = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&cs);
1738  ok(child_2 != 0, "expected child_2 to be non NULL\n");
1739  child_3 = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&cs);
1740  ok(child_3 != 0, "expected child_3 to be non NULL\n");
1741  child_4 = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&cs);
1742  ok(child_4 != 0, "expected child_4 to be non NULL\n");
1743 
1745  stack[1] = GetWindow(stack[0], GW_HWNDNEXT);
1746  stack[2] = GetWindow(stack[1], GW_HWNDNEXT);
1747  stack[3] = GetWindow(stack[2], GW_HWNDNEXT);
1748  trace("Initial MDI child stack: %p->%p->%p->%p\n", stack[0], stack[1], stack[2], stack[3]);
1749  ok(stack[0] == child_4 && stack[1] == child_3 &&
1750  stack[2] == child_2 && stack[3] == child_1,
1751  "Unexpected initial order, should be: %p->%p->%p->%p\n",
1752  child_4, child_3, child_2, child_1);
1753 
1754  trace("Activate child next to %p\n", child_3);
1755  SendMessageA(mdi_client, WM_MDINEXT, (WPARAM)child_3, 0);
1756 
1758  stack[1] = GetWindow(stack[0], GW_HWNDNEXT);
1759  stack[2] = GetWindow(stack[1], GW_HWNDNEXT);
1760  stack[3] = GetWindow(stack[2], GW_HWNDNEXT);
1761  ok(stack[0] == child_2 && stack[1] == child_4 &&
1762  stack[2] == child_1 && stack[3] == child_3,
1763  "Broken MDI child stack:\nexpected: %p->%p->%p->%p, but got: %p->%p->%p->%p\n",
1764  child_2, child_4, child_1, child_3, stack[0], stack[1], stack[2], stack[3]);
1765 
1766  trace("Activate child previous to %p\n", child_1);
1767  SendMessageA(mdi_client, WM_MDINEXT, (WPARAM)child_1, 1);
1768 
1770  stack[1] = GetWindow(stack[0], GW_HWNDNEXT);
1771  stack[2] = GetWindow(stack[1], GW_HWNDNEXT);
1772  stack[3] = GetWindow(stack[2], GW_HWNDNEXT);
1773  ok(stack[0] == child_4 && stack[1] == child_2 &&
1774  stack[2] == child_1 && stack[3] == child_3,
1775  "Broken MDI child stack:\nexpected: %p->%p->%p->%p, but got: %p->%p->%p->%p\n",
1776  child_4, child_2, child_1, child_3, stack[0], stack[1], stack[2], stack[3]);
1777 
1778  DestroyWindow(child_1);
1779  DestroyWindow(child_2);
1780  DestroyWindow(child_3);
1781  DestroyWindow(child_4);
1782 }
1783 
1784 /**********************************************************************
1785  * MDI_ChildGetMinMaxInfo (copied from windows/mdi.c)
1786  *
1787  * Note: The rule here is that client rect of the maximized MDI child
1788  * is equal to the client rect of the MDI client window.
1789  */
1791 {
1792  RECT rect;
1793 
1794  GetClientRect( client, &rect );
1797 
1798  rect.right -= rect.left;
1799  rect.bottom -= rect.top;
1800  lpMinMax->ptMaxSize.x = rect.right;
1801  lpMinMax->ptMaxSize.y = rect.bottom;
1802 
1803  lpMinMax->ptMaxPosition.x = rect.left;
1804  lpMinMax->ptMaxPosition.y = rect.top;
1805 
1806  trace("max rect %s\n", wine_dbgstr_rect(&rect));
1807 }
1808 
1810 {
1811  switch (msg)
1812  {
1813  case WM_NCCREATE:
1814  case WM_CREATE:
1815  {
1817  MDICREATESTRUCTA *mdi_cs = cs->lpCreateParams;
1818 
1819  ok(cs->dwExStyle & WS_EX_MDICHILD, "WS_EX_MDICHILD should be set\n");
1820  ok(mdi_cs->lParam == (LPARAM)mdi_lParam_test_message, "wrong mdi_cs->lParam\n");
1821 
1822  ok(!lstrcmpA(cs->lpszClass, "MDI_child_Class_1"), "wrong class name\n");
1823  ok(!lstrcmpA(cs->lpszClass, mdi_cs->szClass), "class name does not match\n");
1824  ok(!lstrcmpA(cs->lpszName, "MDI child"), "wrong title\n");
1825  ok(!lstrcmpA(cs->lpszName, mdi_cs->szTitle), "title does not match\n");
1826  ok(cs->hInstance == mdi_cs->hOwner, "%p != %p\n", cs->hInstance, mdi_cs->hOwner);
1827 
1828  /* MDICREATESTRUCT should have original values */
1829  ok(mdi_cs->style == 0 || mdi_cs->style == 0x7fffffff || mdi_cs->style == 0xffffffff || mdi_cs->style == WS_MAXIMIZE,
1830  "mdi_cs->style does not match (%08x)\n", mdi_cs->style);
1831  ok(mdi_cs->x == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->x);
1832  ok(mdi_cs->y == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->y);
1833  ok(mdi_cs->cx == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->cx);
1834  ok(mdi_cs->cy == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->cy);
1835 
1836  /* CREATESTRUCT should have fixed values */
1837  ok(cs->x != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->x);
1838  ok(cs->y != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->y);
1839 
1840  /* cx/cy == CW_USEDEFAULT are translated to NOT zero values */
1841  ok(cs->cx != CW_USEDEFAULT && cs->cx != 0, "%d == CW_USEDEFAULT\n", cs->cx);
1842  ok(cs->cy != CW_USEDEFAULT && cs->cy != 0, "%d == CW_USEDEFAULT\n", cs->cy);
1843 
1844  ok(!(cs->style & WS_POPUP), "WS_POPUP is not allowed\n");
1845 
1846  if (GetWindowLongA(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
1847  {
1848  LONG style = mdi_cs->style | WS_CHILD | WS_CLIPSIBLINGS;
1849  ok(cs->style == style,
1850  "cs->style does not match (%08x)\n", cs->style);
1851  }
1852  else
1853  {
1854  LONG style = mdi_cs->style;
1855  style &= ~WS_POPUP;
1858  ok(cs->style == style,
1859  "cs->style does not match (%08x)\n", cs->style);
1860  }
1861  break;
1862  }
1863 
1864  case WM_GETMINMAXINFO:
1865  {
1867  RECT rc;
1868  MINMAXINFO *minmax = (MINMAXINFO *)lparam;
1869  MINMAXINFO my_minmax;
1870  LONG style, exstyle;
1871 
1873  exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
1874 
1875  GetClientRect(client, &rc);
1876 
1877  GetClientRect(client, &rc);
1878  if ((style & WS_CAPTION) == WS_CAPTION)
1879  style &= ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
1880  AdjustWindowRectEx(&rc, style, 0, exstyle);
1881  trace("MDI child: calculated max window size = (%d x %d)\n", rc.right-rc.left, rc.bottom-rc.top);
1882  dump_minmax_info( minmax );
1883 
1884  ok(minmax->ptMaxSize.x == rc.right - rc.left, "default width of maximized child %d != %d\n",
1885  minmax->ptMaxSize.x, rc.right - rc.left);
1886  ok(minmax->ptMaxSize.y == rc.bottom - rc.top, "default height of maximized child %d != %d\n",
1887  minmax->ptMaxSize.y, rc.bottom - rc.top);
1888 
1890 
1891  trace("DefMDIChildProc returned:\n");
1892  dump_minmax_info( minmax );
1893 
1894  MDI_ChildGetMinMaxInfo(client, hwnd, &my_minmax);
1895  ok(minmax->ptMaxSize.x == my_minmax.ptMaxSize.x, "default width of maximized child %d != %d\n",
1896  minmax->ptMaxSize.x, my_minmax.ptMaxSize.x);
1897  ok(minmax->ptMaxSize.y == my_minmax.ptMaxSize.y, "default height of maximized child %d != %d\n",
1898  minmax->ptMaxSize.y, my_minmax.ptMaxSize.y);
1899 
1900  return 1;
1901  }
1902 
1903  case WM_MDIACTIVATE:
1904  {
1905  HWND active, client = GetParent(hwnd);
1906  /*trace("%p WM_MDIACTIVATE %08x %08lx\n", hwnd, wparam, lparam);*/
1907  active = (HWND)SendMessageA(client, WM_MDIGETACTIVE, 0, 0);
1908  if (hwnd == (HWND)lparam) /* if we are being activated */
1909  ok (active == (HWND)lparam, "new active %p != active %p\n", (HWND)lparam, active);
1910  else
1911  ok (active == (HWND)wparam, "old active %p != active %p\n", (HWND)wparam, active);
1912  break;
1913  }
1914  }
1915  return DefMDIChildProcA(hwnd, msg, wparam, lparam);
1916 }
1917 
1919 {
1920  switch (msg)
1921  {
1922  case WM_NCCREATE:
1923  case WM_CREATE:
1924  {
1926 
1927  trace("%s: x %d, y %d, cx %d, cy %d\n", (msg == WM_NCCREATE) ? "WM_NCCREATE" : "WM_CREATE",
1928  cs->x, cs->y, cs->cx, cs->cy);
1929 
1930  ok(!(cs->dwExStyle & WS_EX_MDICHILD), "WS_EX_MDICHILD should not be set\n");
1931  ok(cs->lpCreateParams == mdi_lParam_test_message, "wrong cs->lpCreateParams\n");
1932 
1933  ok(!lstrcmpA(cs->lpszClass, "MDI_child_Class_2"), "wrong class name\n");
1934  ok(!lstrcmpA(cs->lpszName, "MDI child"), "wrong title\n");
1935 
1936  /* CREATESTRUCT should have fixed values */
1937  /* For some reason Win9x doesn't translate cs->x from CW_USEDEFAULT,
1938  while NT does. */
1939  /*ok(cs->x != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->x);*/
1940  ok(cs->y != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->y);
1941 
1942  /* cx/cy == CW_USEDEFAULT are translated to 0 */
1943  /* For some reason Win98 doesn't translate cs->cx from CW_USEDEFAULT,
1944  while Win95, Win2k, WinXP do. */
1945  /*ok(cs->cx == 0, "%d != 0\n", cs->cx);*/
1946  ok(cs->cy == 0, "%d != 0\n", cs->cy);
1947  break;
1948  }
1949 
1950  case WM_GETMINMAXINFO:
1951  {
1953  RECT rc;
1954  MINMAXINFO *minmax = (MINMAXINFO *)lparam;
1955  LONG style, exstyle;
1956 
1958  exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
1959 
1960  GetClientRect(parent, &rc);
1961  trace("WM_GETMINMAXINFO: parent %p client size = (%d x %d)\n", parent, rc.right, rc.bottom);
1962 
1963  GetClientRect(parent, &rc);
1964  if ((style & WS_CAPTION) == WS_CAPTION)
1965  style &= ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
1966  AdjustWindowRectEx(&rc, style, 0, exstyle);
1967  dump_minmax_info( minmax );
1968 
1969  ok(minmax->ptMaxSize.x == rc.right - rc.left, "default width of maximized child %d != %d\n",
1970  minmax->ptMaxSize.x, rc.right - rc.left);
1971  ok(minmax->ptMaxSize.y == rc.bottom - rc.top, "default height of maximized child %d != %d\n",
1972  minmax->ptMaxSize.y, rc.bottom - rc.top);
1973  break;
1974  }
1975 
1976  case WM_WINDOWPOSCHANGED:
1977  {
1978  WINDOWPOS *winpos = (WINDOWPOS *)lparam;
1979  RECT rc1, rc2;
1980 
1981  GetWindowRect(hwnd, &rc1);
1982  SetRect(&rc2, winpos->x, winpos->y, winpos->x + winpos->cx, winpos->y + winpos->cy);
1983  /* note: winpos coordinates are relative to parent */
1985  ok(EqualRect(&rc1, &rc2), "rects do not match, window=%s pos=%s\n",
1987  GetWindowRect(hwnd, &rc1);
1988  GetClientRect(hwnd, &rc2);
1990  MapWindowPoints(0, hwnd, (LPPOINT)&rc1, 2);
1991  ok(EqualRect(&rc1, &rc2), "rects do not match, window=%s client=%s\n",
1993  }
1994  /* fall through */
1995  case WM_WINDOWPOSCHANGING:
1996  {
1997  WINDOWPOS *winpos = (WINDOWPOS *)lparam;
1998  WINDOWPOS my_winpos = *winpos;
1999 
2000  trace("%s: %p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
2001  (msg == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED",
2002  winpos->hwnd, winpos->hwndInsertAfter,
2003  winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
2004 
2006 
2007  ok(!memcmp(&my_winpos, winpos, sizeof(WINDOWPOS)),
2008  "DefWindowProc should not change WINDOWPOS: %p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
2009  winpos->hwnd, winpos->hwndInsertAfter,
2010  winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
2011 
2012  return 1;
2013  }
2014  }
2015  return DefWindowProcA(hwnd, msg, wparam, lparam);
2016 }
2017 
2019 {
2020  static HWND mdi_client;
2021 
2022  switch (msg)
2023  {
2024  case WM_CREATE:
2025  return 1;
2026 
2027  case WM_WINDOWPOSCHANGED:
2028  {
2029  WINDOWPOS *winpos = (WINDOWPOS *)lparam;
2030  RECT rc1, rc2;
2031 
2032  GetWindowRect(hwnd, &rc1);
2033  trace("window: %s\n", wine_dbgstr_rect(&rc1));
2034  SetRect(&rc2, winpos->x, winpos->y, winpos->x + winpos->cx, winpos->y + winpos->cy);
2035  /* note: winpos coordinates are relative to parent */
2037  trace("pos: %s\n", wine_dbgstr_rect(&rc2));
2038  ok(EqualRect(&rc1, &rc2), "rects do not match\n");
2039 
2040  GetWindowRect(hwnd, &rc1);
2041  GetClientRect(hwnd, &rc2);
2043  MapWindowPoints(0, hwnd, (LPPOINT)&rc1, 2);
2044  ok(EqualRect(&rc1, &rc2), "rects do not match\n");
2045  }
2046  /* fall through */
2047  case WM_WINDOWPOSCHANGING:
2048  {
2049  WINDOWPOS *winpos = (WINDOWPOS *)lparam;
2050  WINDOWPOS my_winpos = *winpos;
2051 
2052  trace("%s\n", (msg == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
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 
2058 
2059  trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
2060  winpos->hwnd, winpos->hwndInsertAfter,
2061  winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
2062 
2063  ok(!memcmp(&my_winpos, winpos, sizeof(WINDOWPOS)),
2064  "DefWindowProc should not change WINDOWPOS values\n");
2065 
2066  return 1;
2067  }
2068 
2069  case WM_CLOSE:
2070  PostQuitMessage(0);
2071  break;
2072  }
2074 }
2075 
2077 {
2078  WNDCLASSA cls;
2079 
2080  cls.style = 0;
2082  cls.cbClsExtra = 0;
2083  cls.cbWndExtra = 0;
2084  cls.hInstance = GetModuleHandleA(0);
2085  cls.hIcon = 0;
2086  cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
2088  cls.lpszMenuName = NULL;
2089  cls.lpszClassName = "MDI_parent_Class";
2090  if(!RegisterClassA(&cls)) return FALSE;
2091 
2093  cls.lpszClassName = "MDI_child_Class_1";
2094  if(!RegisterClassA(&cls)) return FALSE;
2095 
2097  cls.lpszClassName = "MDI_child_Class_2";
2098  if(!RegisterClassA(&cls)) return FALSE;
2099 
2100  return TRUE;
2101 }
2102 
2103 static void test_mdi(void)
2104 {
2105  static const DWORD style[] = { 0, WS_HSCROLL, WS_VSCROLL, WS_HSCROLL | WS_VSCROLL };
2106  HWND mdi_hwndMain, mdi_client, mdi_child;
2107  CLIENTCREATESTRUCT client_cs;
2108  RECT rc;
2109  DWORD i;
2110  MSG msg;
2111  HMENU frame_menu, child_menu;
2112 
2113  if (!mdi_RegisterWindowClasses()) assert(0);
2114 
2115  mdi_hwndMain = CreateWindowExA(0, "MDI_parent_Class", "MDI parent window",
2117  WS_MAXIMIZEBOX /*| WS_VISIBLE*/,
2118  100, 100, CW_USEDEFAULT, CW_USEDEFAULT,
2119  GetDesktopWindow(), 0,
2121  assert(mdi_hwndMain);
2122 
2123  frame_menu = CreateMenu();
2124 
2125  GetClientRect(mdi_hwndMain, &rc);
2126 
2127  client_cs.hWindowMenu = 0;
2128  client_cs.idFirstChild = 1;
2129 
2130  for (i = 0; i < sizeof(style)/sizeof(style[0]); i++)
2131  {
2132  SCROLLINFO si;
2133  BOOL ret, gotit;
2134 
2135  mdi_client = CreateWindowExA(0, "mdiclient", NULL,
2136  WS_CHILD | style[i],
2137  0, 0, rc.right, rc.bottom,
2138  mdi_hwndMain, 0, 0, &client_cs);
2139  ok(mdi_client != 0, "MDI client creation failed\n");
2140 
2141  mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
2142  0,
2145  mdi_client, 0, 0,
2147  ok(mdi_child != 0, "MDI child creation failed\n");
2148 
2149  SendMessageW(mdi_child, WM_SIZE, SIZE_MAXIMIZED, 0);
2150  SetMenu(mdi_hwndMain, frame_menu);
2151 
2152  ok(GetMenuItemCount(frame_menu) == 0, "Frame menu should be empty after child maximize, but has %u\n",
2153  GetMenuItemCount(frame_menu));
2154 
2155  child_menu = CreateMenu();
2156  SendMessageW(mdi_client, WM_MDISETMENU, 0, (LPARAM)child_menu);
2157 
2158  ok(GetMenuItemCount(frame_menu) == 0, "Frame menu should be empty after WM_MDISETMENU, but has %u\n",
2159  GetMenuItemCount(frame_menu));
2160 
2161  SendMessageW(mdi_child, WM_SIZE, SIZE_RESTORED, 0);
2162 
2163  ok(GetMenuItemCount(frame_menu) == 0, "Frame menu should be empty after child restored, but has %u items\n",
2164  GetMenuItemCount(frame_menu));
2165 
2166  SetMenu(mdi_hwndMain, NULL);
2167 
2168  si.cbSize = sizeof(si);
2169  si.fMask = SIF_ALL;
2171  if (style[i] & (WS_HSCROLL | WS_VSCROLL))
2172  {
2173  ok(ret, "style %#x: GetScrollInfo(SB_HORZ) failed\n", style[i]);
2174  ok(si.nPage == 0, "expected 0\n");
2175  ok(si.nPos == 0, "expected 0\n");
2176  ok(si.nTrackPos == 0, "expected 0\n");
2177  ok(si.nMin == 0, "expected 0\n");
2178  ok(si.nMax == 100, "expected 100\n");
2179  }
2180  else
2181  ok(!ret, "style %#x: GetScrollInfo(SB_HORZ) should fail\n", style[i]);
2182 
2184  if (style[i] & (WS_HSCROLL | WS_VSCROLL))
2185  {
2186  ok(ret, "style %#x: GetScrollInfo(SB_VERT) failed\n", style[i]);
2187  ok(si.nPage == 0, "expected 0\n");
2188  ok(si.nPos == 0, "expected 0\n");
2189  ok(si.nTrackPos == 0, "expected 0\n");
2190  ok(si.nMin == 0, "expected 0\n");
2191  ok(si.nMax == 100, "expected 100\n");
2192  }
2193  else
2194  ok(!ret, "style %#x: GetScrollInfo(SB_VERT) should fail\n", style[i]);
2195 
2196  SetWindowPos(mdi_child, 0, -100, -100, 0, 0, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE);
2197 
2198  si.cbSize = sizeof(si);
2199  si.fMask = SIF_ALL;
2201  if (style[i] & (WS_HSCROLL | WS_VSCROLL))
2202  {
2203  ok(ret, "style %#x: GetScrollInfo(SB_HORZ) failed\n", style[i]);
2204  ok(si.nPage == 0, "expected 0\n");
2205  ok(si.nPos == 0, "expected 0\n");
2206  ok(si.nTrackPos == 0, "expected 0\n");
2207  ok(si.nMin == 0, "expected 0\n");
2208  ok(si.nMax == 100, "expected 100\n");
2209  }
2210  else
2211  ok(!ret, "style %#x: GetScrollInfo(SB_HORZ) should fail\n", style[i]);
2212 
2214  if (style[i] & (WS_HSCROLL | WS_VSCROLL))
2215  {
2216  ok(ret, "style %#x: GetScrollInfo(SB_VERT) failed\n", style[i]);
2217  ok(si.nPage == 0, "expected 0\n");
2218  ok(si.nPos == 0, "expected 0\n");
2219  ok(si.nTrackPos == 0, "expected 0\n");
2220  ok(si.nMin == 0, "expected 0\n");
2221  ok(si.nMax == 100, "expected 100\n");
2222  }
2223  else
2224  ok(!ret, "style %#x: GetScrollInfo(SB_VERT) should fail\n", style[i]);
2225 
2226  gotit = FALSE;
2227  while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
2228  {
2229  if (msg.message == WM_MOUSEMOVE || msg.message == WM_PAINT)
2230  {
2232  continue;
2233  }
2234 
2235  if (msg.message == 0x003f) /* WM_MDICALCCHILDSCROLL ??? */
2236  {
2237  ok(msg.hwnd == mdi_client, "message 0x003f should be posted to mdiclient\n");
2238  gotit = TRUE;
2239  }
2240  else
2241  ok(msg.hwnd != mdi_client, "message %04x should not be posted to mdiclient\n", msg.message);
2243  }
2244  ok(gotit, "message 0x003f should appear after SetWindowPos\n");
2245 
2246  si.cbSize = sizeof(si);
2247  si.fMask = SIF_ALL;
2249  if (style[i] & (WS_HSCROLL | WS_VSCROLL))
2250  {
2251  ok(ret, "style %#x: GetScrollInfo(SB_HORZ) failed\n", style[i]);
2252 todo_wine
2253  ok(si.nPage != 0, "expected !0\n");
2254  ok(si.nPos == 0, "expected 0\n");
2255  ok(si.nTrackPos == 0, "expected 0\n");
2256  ok(si.nMin != 0, "expected !0\n");
2257  ok(si.nMax != 100, "expected !100\n");
2258  }
2259  else
2260  ok(!ret, "style %#x: GetScrollInfo(SB_HORZ) should fail\n", style[i]);
2261 
2263  if (style[i] & (WS_HSCROLL | WS_VSCROLL))
2264  {
2265  ok(ret, "style %#x: GetScrollInfo(SB_VERT) failed\n", style[i]);
2266 todo_wine
2267  ok(si.nPage != 0, "expected !0\n");
2268  ok(si.nPos == 0, "expected 0\n");
2269  ok(si.nTrackPos == 0, "expected 0\n");
2270  ok(si.nMin != 0, "expected !0\n");
2271  ok(si.nMax != 100, "expected !100\n");
2272  }
2273  else
2274  ok(!ret, "style %#x: GetScrollInfo(SB_VERT) should fail\n", style[i]);
2275 
2276  DestroyMenu(child_menu);
2277  DestroyWindow(mdi_child);
2279  }
2280 
2281  SetMenu(mdi_hwndMain, frame_menu);
2282 
2283  mdi_client = CreateWindowExA(0, "mdiclient", NULL,
2284  WS_CHILD,
2285  0, 0, rc.right, rc.bottom,
2286  mdi_hwndMain, 0, 0, &client_cs);
2287  ok(mdi_client != 0, "MDI client creation failed\n");
2288 
2289  mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
2290  0,
2293  mdi_client, 0, 0,
2295  ok(mdi_child != 0, "MDI child creation failed\n");
2296 
2297  SendMessageW(mdi_child, WM_SIZE, SIZE_MAXIMIZED, 0);
2298  ok(GetMenuItemCount(frame_menu) == 4, "Frame menu should have 4 items after child maximize, but has %u\n",
2299  GetMenuItemCount(frame_menu));
2300 
2301  child_menu = CreateMenu();
2302  SendMessageW(mdi_client, WM_MDISETMENU, 0, (LPARAM)child_menu);
2303 
2304  ok(GetMenuItemCount(frame_menu) == 4, "Frame menu should have 4 items after WM_MDISETMENU, but has %u\n",
2305  GetMenuItemCount(frame_menu));
2306 
2307  SendMessageW(mdi_child, WM_SIZE, SIZE_RESTORED, 0);
2308 
2309  ok(GetMenuItemCount(frame_menu) == 0, "Frame menu should be empty after child restored, but has %u items\n",
2310  GetMenuItemCount(frame_menu));
2311 
2312  DestroyMenu(child_menu);
2313  DestroyWindow(mdi_child);
2315 
2316  /* MDIClient without MDIS_ALLCHILDSTYLES */
2317  mdi_client = CreateWindowExA(0, "mdiclient",
2318  NULL,
2319  WS_CHILD /*| WS_VISIBLE*/,
2320  /* tests depend on a not zero MDIClient size */
2321  0, 0, rc.right, rc.bottom,
2322  mdi_hwndMain, 0, GetModuleHandleA(NULL),
2323  &client_cs);
2324  assert(mdi_client);
2325  test_MDI_create(mdi_hwndMain, mdi_client, client_cs.idFirstChild);
2327 
2328  /* MDIClient with MDIS_ALLCHILDSTYLES */
2329  mdi_client = CreateWindowExA(0, "mdiclient",
2330  NULL,
2331  WS_CHILD | MDIS_ALLCHILDSTYLES /*| WS_VISIBLE*/,
2332  /* tests depend on a not zero MDIClient size */
2333  0, 0, rc.right, rc.bottom,
2334  mdi_hwndMain, 0, GetModuleHandleA(NULL),
2335  &client_cs);
2336  assert(mdi_client);
2337  test_MDI_create(mdi_hwndMain, mdi_client, client_cs.idFirstChild);
2339 
2340  /* Test child window stack management */
2341  mdi_client = CreateWindowExA(0, "mdiclient",
2342  NULL,
2343  WS_CHILD,
2344  0, 0, rc.right, rc.bottom,
2345  mdi_hwndMain, 0, GetModuleHandleA(NULL),
2346  &client_cs);
2347  assert(mdi_client);
2350 /*
2351  while(GetMessage(&msg, 0, 0, 0))
2352  {
2353  TranslateMessage(&msg);
2354  DispatchMessage(&msg);
2355  }
2356 */
2357  DestroyWindow(mdi_hwndMain);
2358 }
2359 
2360 static void test_icons(void)
2361 {
2362  WNDCLASSEXA cls;
2363  HWND hwnd;
2364  HICON icon = LoadIconA(0, (LPCSTR)IDI_APPLICATION);
2365  HICON icon2 = LoadIconA(0, (LPCSTR)IDI_QUESTION);
2366  HICON small_icon = LoadImageA(0, (LPCSTR)IDI_APPLICATION, IMAGE_ICON,
2368  HICON res;
2369 
2370  cls.cbSize = sizeof(cls);
2371  cls.style = 0;
2373  cls.cbClsExtra = 0;
2374  cls.cbWndExtra = 0;
2375  cls.hInstance = 0;
2376  cls.hIcon = LoadIconA(0, (LPCSTR)IDI_HAND);
2377  cls.hIconSm = small_icon;
2378  cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
2380  cls.lpszMenuName = NULL;
2381  cls.lpszClassName = "IconWindowClass";
2382 
2383  RegisterClassExA(&cls);
2384 
2385  hwnd = CreateWindowExA(0, "IconWindowClass", "icon test", 0,
2386  100, 100, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, NULL, NULL);
2387  assert( hwnd );
2388 
2389  res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
2390  ok( res == 0, "wrong big icon %p/0\n", res );
2391  res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_BIG, (LPARAM)icon );
2392  ok( res == 0, "wrong previous big icon %p/0\n", res );
2393  res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
2394  ok( res == icon, "wrong big icon after set %p/%p\n", res, icon );
2395  res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_BIG, (LPARAM)icon2 );
2396  ok( res == icon, "wrong previous big icon %p/%p\n", res, icon );
2397  res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
2398  ok( res == icon2, "wrong big icon after set %p/%p\n", res, icon2 );
2399 
2400  res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 );
2401  ok( res == 0, "wrong small icon %p/0\n", res );
2402  res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
2403  ok( (res && res != small_icon && res != icon2) || broken(!res), "wrong small2 icon %p\n", res );
2404  res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_SMALL, (LPARAM)icon );
2405  ok( res == 0, "wrong previous small icon %p/0\n", res );
2406  res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 );
2407  ok( res == icon, "wrong small icon after set %p/%p\n", res, icon );
2408  res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
2409  ok( res == icon || broken(!res), "wrong small2 icon after set %p/%p\n", res, icon );
2410  res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_SMALL, (LPARAM)small_icon );
2411  ok( res == icon, "wrong previous small icon %p/%p\n", res, icon );
2412  res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 );
2413  ok( res == small_icon, "wrong small icon after set %p/%p\n", res, small_icon );
2414  res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
2415  ok( res == small_icon || broken(!res), "wrong small2 icon after set %p/%p\n", res, small_icon );
2416 
2417  /* make sure the big icon hasn't changed */
2418  res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
2419  ok( res == icon2, "wrong big icon after set %p/%p\n", res, icon2 );
2420 
2421  DestroyWindow( hwnd );
2422 }
2423 
2425 {
2426  if (msg == WM_NCCALCSIZE)
2427  {
2428  RECT *rect = (RECT *)lparam;
2429  /* first time around increase the rectangle, next time decrease it */
2430  if (rect->left == 100) InflateRect( rect, 10, 10 );
2431  else InflateRect( rect, -10, -10 );
2432  return 0;
2433  }
2434  return DefWindowProcA( hwnd, msg, wparam, lparam );
2435 }
2436 
2437 static void test_SetWindowPos(HWND hwnd, HWND hwnd2)
2438 {
2439  RECT orig_win_rc, rect;
2441  HWND hwnd_grandchild, hwnd_child, hwnd_child2;
2442  HWND hwnd_desktop;
2443  RECT rc1, rc2;
2444  BOOL ret;
2445 
2446  SetRect(&rect, 111, 222, 333, 444);
2447  ok(!GetWindowRect(0, &rect), "GetWindowRect succeeded\n");
2448  ok(rect.left == 111 && rect.top == 222 && rect.right == 333 && rect.bottom == 444,
2449  "wrong window rect %s\n", wine_dbgstr_rect(&rect));
2450 
2451  SetRect(&rect, 111, 222, 333, 444);
2452  ok(!GetClientRect(0, &rect), "GetClientRect succeeded\n");
2453  ok(rect.left == 111 && rect.top == 222 && rect.right == 333 && rect.bottom == 444,
2454  "wrong window rect %s\n", wine_dbgstr_rect(&rect));
2455 
2456  GetWindowRect(hwnd, &orig_win_rc);
2457 
2459  ret = SetWindowPos(hwnd, 0, 100, 100, 0, 0, SWP_NOZORDER|SWP_FRAMECHANGED);
2460  ok(ret, "Got %d\n", ret);
2461  GetWindowRect( hwnd, &rect );
2462  ok( rect.left == 100 && rect.top == 100 && rect.right == 100 && rect.bottom == 100,
2463  "invalid window rect %s\n", wine_dbgstr_rect(&rect));
2464  GetClientRect( hwnd, &rect );
2465  MapWindowPoints( hwnd, 0, (POINT *)&rect, 2 );
2466  ok( rect.left == 90 && rect.top == 90 && rect.right == 110 && rect.bottom == 110,
2467  "invalid client rect %s\n", wine_dbgstr_rect(&rect));
2468 
2469  ret = SetWindowPos(hwnd, 0, 200, 200, 0, 0, SWP_NOZORDER|SWP_FRAMECHANGED);
2470  ok(ret, "Got %d\n", ret);
2471  GetWindowRect( hwnd, &rect );
2472  ok( rect.left == 200 && rect.top == 200 && rect.right == 200 && rect.bottom == 200,
2473  "invalid window rect %s\n", wine_dbgstr_rect(&rect));
2474  GetClientRect( hwnd, &rect );
2475  MapWindowPoints( hwnd, 0, (POINT *)&rect, 2 );
2476  ok( rect.left == 210 && rect.top == 210 && rect.right == 190 && rect.bottom == 190,
2477  "invalid client rect %s\n", wine_dbgstr_rect(&rect));
2478 
2479  ret = SetWindowPos(hwnd, 0, orig_win_rc.left, orig_win_rc.top,
2480  orig_win_rc.right, orig_win_rc.bottom, 0);
2481  ok(ret, "Got %d\n", ret);
2483 
2484  /* Win9x truncates coordinates to 16-bit irrespectively */
2485  if (!is_win9x)
2486  {
2487  ret = SetWindowPos(hwnd, 0, -32769, -40000, -32769, -90000, SWP_NOMOVE);
2488  ok(ret, "Got %d\n", ret);
2489  ret = SetWindowPos(hwnd, 0, 32768, 40000, 32768, 40000, SWP_NOMOVE);
2490  ok(ret, "Got %d\n", ret);
2491 
2492  ret = SetWindowPos(hwnd, 0, -32769, -40000, -32769, -90000, SWP_NOSIZE);
2493  ok(ret, "Got %d\n", ret);
2494  ret = SetWindowPos(hwnd, 0, 32768, 40000, 32768, 40000, SWP_NOSIZE);
2495  ok(ret, "Got %d\n", ret);
2496  }
2497 
2498  ret = SetWindowPos(hwnd, 0, orig_win_rc.left, orig_win_rc.top,
2499  orig_win_rc.right, orig_win_rc.bottom, 0);
2500  ok(ret, "Got %d\n", ret);
2501 
2502  ok(!(GetWindowLongA(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST), "WS_EX_TOPMOST should not be set\n");
2504  ok(ret, "Got %d\n", ret);
2505  ok(GetWindowLongA(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST, "WS_EX_TOPMOST should be set\n");
2507  ok(ret, "Got %d\n", ret);
2508  ok(GetWindowLongA(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST, "WS_EX_TOPMOST should be set\n");
2510  ok(ret, "Got %d\n", ret);
2511  ok(!(GetWindowLongA(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST), "WS_EX_TOPMOST should not be set\n");
2512 
2513  hwnd_desktop = GetDesktopWindow();
2514  ok(!!hwnd_desktop, "Failed to get hwnd_desktop window (%d).\n", GetLastError());
2515  hwnd_child = create_tool_window(WS_VISIBLE|WS_CHILD, hwnd);
2516  ok(!!hwnd_child, "Failed to create child window (%d)\n", GetLastError());
2517  hwnd_grandchild = create_tool_window(WS_VISIBLE|WS_CHILD, hwnd_child);
2518  ok(!!hwnd_child, "Failed to create child window (%d)\n", GetLastError());
2519  hwnd_child2 = create_tool_window(WS_VISIBLE|WS_CHILD, hwnd);
2520  ok(!!hwnd_child2, "Failed to create second child window (%d)\n", GetLastError());
2521 
2522  ret = SetWindowPos(hwnd, hwnd2, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2523  ok(ret, "Got %d\n", ret);
2525 
2526  ret = SetWindowPos(hwnd2, hwnd, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2527  ok(ret, "Got %d\n", ret);
2528  check_active_state(hwnd2, hwnd2, hwnd2);
2529 
2530  /* Returns TRUE also for windows that are not siblings */
2531  ret = SetWindowPos(hwnd_child, hwnd2, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2532  ok(ret, "Got %d\n", ret);
2533  check_active_state(hwnd2, hwnd2, hwnd2);
2534 
2535  ret = SetWindowPos(hwnd2, hwnd_child, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2536  ok(ret, "Got %d\n", ret);
2537  check_active_state(hwnd2, hwnd2, hwnd2);
2538 
2539  /* Does not seem to do anything even without passing flags, still returns TRUE */
2540  GetWindowRect(hwnd_child, &rc1);
2541  ret = SetWindowPos(hwnd_child, hwnd2 , 1, 2, 3, 4, 0);
2542  ok(ret, "Got %d\n", ret);
2543  GetWindowRect(hwnd_child, &rc2);
2544  ok(EqualRect(&rc1, &rc2), "%s != %s\n", wine_dbgstr_rect(&rc1), wine_dbgstr_rect(&rc2));
2545  check_active_state(hwnd2, hwnd2, hwnd2);
2546 
2547  /* Same thing the other way around. */
2548  GetWindowRect(hwnd2, &rc1);
2549  ret = SetWindowPos(hwnd2, hwnd_child, 1, 2, 3, 4, 0);
2550  ok(ret, "Got %d\n", ret);
2551  GetWindowRect(hwnd2, &rc2);
2552  ok(EqualRect(&rc1, &rc2), "%s != %s\n", wine_dbgstr_rect(&rc1), wine_dbgstr_rect(&rc2));
2553  check_active_state(hwnd2, hwnd2, hwnd2);
2554 
2555  /* .. and with these windows. */
2556  GetWindowRect(hwnd_grandchild, &rc1);
2557  ret = SetWindowPos(hwnd_grandchild, hwnd_child2, 1, 2, 3, 4, 0);
2558  ok(ret, "Got %d\n", ret);
2559  GetWindowRect(hwnd_grandchild, &rc2);
2560  ok(EqualRect(&rc1, &rc2), "%s != %s\n", wine_dbgstr_rect(&rc1), wine_dbgstr_rect(&rc2));
2561  check_active_state(hwnd2, hwnd2, hwnd2);
2562 
2563  /* Add SWP_NOZORDER and it will be properly resized. */
2564  GetWindowRect(hwnd_grandchild, &rc1);
2565  ret = SetWindowPos(hwnd_grandchild, hwnd_child2, 1, 2, 3, 4, SWP_NOZORDER);
2566  ok(ret, "Got %d\n", ret);
2567  GetWindowRect(hwnd_grandchild, &rc2);
2568  ok((rc1.left+1) == rc2.left && (rc1.top+2) == rc2.top &&
2569  (rc1.left+4) == rc2.right && (rc1.top+6) == rc2.bottom,
2570  "(%d,%d)-(%d,%d) != %s\n", rc1.left+1, rc1.top+2, rc1.left+4, rc1.top+6,
2571  wine_dbgstr_rect(&rc2));
2572  check_active_state(hwnd2, hwnd2, hwnd2);
2573 
2574  /* Given a sibling window, the window is properly resized. */
2575  GetWindowRect(hwnd_child, &rc1);
2576  ret = SetWindowPos(hwnd_child, hwnd_child2, 1, 2, 3, 4, 0);
2577  ok(ret, "Got %d\n", ret);
2578  GetWindowRect(hwnd_child, &rc2);
2579  ok((rc1.left+1) == rc2.left && (rc1.top+2) == rc2.top &&
2580  (rc1.left+4) == rc2.right && (rc1.top+6) == rc2.bottom,
2581  "(%d,%d)-(%d,%d) != %s\n", rc1.left+1, rc1.top+2, rc1.left+4, rc1.top+6,
2582  wine_dbgstr_rect(&rc2));
2583  check_active_state(hwnd2, hwnd2, hwnd2);
2584 
2585  /* Involving the desktop window changes things. */
2586  ret = SetWindowPos(hwnd_child, hwnd_desktop, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2587  ok(!ret, "Got %d\n", ret);
2588  check_active_state(hwnd2, hwnd2, hwnd2);
2589 
2590  GetWindowRect(hwnd_child, &rc1);
2591  ret = SetWindowPos(hwnd_child, hwnd_desktop, 0, 0, 0, 0, 0);
2592  ok(!ret, "Got %d\n", ret);
2593  GetWindowRect(hwnd_child, &rc2);
2594  ok(EqualRect(&rc1, &rc2), "%s != %s\n", wine_dbgstr_rect(&rc1), wine_dbgstr_rect(&rc2));
2595  check_active_state(hwnd2, hwnd2, hwnd2);
2596 
2597  ret = SetWindowPos(hwnd_desktop, hwnd_child, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2598  ok(!ret, "Got %d\n", ret);
2599  check_active_state(hwnd2, hwnd2, hwnd2);
2600 
2601  ret = SetWindowPos(hwnd_desktop, hwnd, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2602  ok(!ret, "Got %d\n", ret);
2603  check_active_state(hwnd2, hwnd2, hwnd2);
2604 
2605  ret = SetWindowPos(hwnd, hwnd_desktop, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2606  ok(!ret, "Got %d\n", ret);
2607  check_active_state(hwnd2, hwnd2, hwnd2);
2608 
2609  DestroyWindow(hwnd_grandchild);
2610  DestroyWindow(hwnd_child);
2611  DestroyWindow(hwnd_child2);
2612 
2613  hwnd_child = create_tool_window(WS_CHILD|WS_POPUP|WS_SYSMENU, hwnd2);
2614  ok(!!hwnd_child, "Failed to create child window (%d)\n", GetLastError());
2616  ok(ret, "Got %d\n", ret);
2617  flush_events( TRUE );
2618  todo_wine check_active_state(hwnd2, hwnd2, hwnd2);
2619  DestroyWindow(hwnd_child);
2620 }
2621 
2623 {
2624  HWND child;
2625  HMENU hMenu, ret;
2626  BOOL retok;
2627  DWORD style;
2628 
2629  hMenu = CreateMenu();
2630  assert(hMenu);
2631 
2632  ok(SetMenu(parent, hMenu), "SetMenu on a top level window should not fail\n");
2633  if (0)
2634  {
2635  /* fails on (at least) Wine, NT4, XP SP2 */
2637  }
2638  ret = GetMenu(parent);
2639  ok(ret == hMenu, "unexpected menu id %p\n", ret);
2640  /* test whether we can destroy a menu assigned to a window */
2641  retok = DestroyMenu(hMenu);
2642  ok( retok, "DestroyMenu error %d\n", GetLastError());
2643  retok = IsMenu(hMenu);
2644  ok(!retok || broken(retok) /* nt4 */, "menu handle should be not valid after DestroyMenu\n");
2645  ret = GetMenu(parent);
2646  /* This test fails on Win9x */
2647  if (!is_win9x)
2648  ok(ret == hMenu, "unexpected menu id %p\n", ret);
2649  ok(SetMenu(parent, 0), "SetMenu(0) on a top level window should not fail\n");
2651 
2652  hMenu = CreateMenu();
2653  assert(hMenu);
2654 
2655  /* parent */
2656  ret = GetMenu(parent);
2657  ok(ret == 0, "unexpected menu id %p\n", ret);
2658 
2659  ok(!SetMenu(parent, (HMENU)20), "SetMenu with invalid menu handle should fail\n");
2661  ret = GetMenu(parent);
2662  ok(ret == 0, "unexpected menu id %p\n", ret);
2663 
2664  ok(SetMenu(parent, hMenu), "SetMenu on a top level window should not fail\n");
2665  if (0)
2666  {
2667  /* fails on (at least) Wine, NT4, XP SP2 */
2669  }
2670  ret = GetMenu(parent);
2671  ok(ret == hMenu, "unexpected menu id %p\n", ret);
2672 
2673  ok(SetMenu(parent, 0), "SetMenu(0) on a top level window should not fail\n");
2675  ret = GetMenu(parent);
2676  ok(ret == 0, "unexpected menu id %p\n", ret);
2677 
2678  /* child */
2679  child = CreateWindowExA(0, "static", NULL, WS_CHILD, 0, 0, 0, 0, parent, (HMENU)10, 0, NULL);
2680  assert(child);
2681 
2682  ret = GetMenu(child);
2683  ok(ret == (HMENU)10, "unexpected menu id %p\n", ret);
2684 
2685  ok(!SetMenu(child, (HMENU)20), "SetMenu with invalid menu handle should fail\n");
2687  ret = GetMenu(child);
2688  ok(ret == (HMENU)10, "unexpected menu id %p\n", ret);
2689 
2690  ok(!SetMenu(child, hMenu), "SetMenu on a child window should fail\n");
2692  ret = GetMenu(child);
2693  ok(ret == (HMENU)10, "unexpected menu id %p\n", ret);
2694 
2695  ok(!SetMenu(child, 0), "SetMenu(0) on a child window should fail\n");
2697  ret = GetMenu(child);
2698  ok(ret == (HMENU)10, "unexpected menu id %p\n", ret);
2699 
2702  ok(SetMenu(child, hMenu), "SetMenu on a popup child window should not fail\n");
2703  ok(SetMenu(child, 0), "SetMenu on a popup child window should not fail\n");
2705 
2707  ok(!SetMenu(child, hMenu), "SetMenu on an overlapped child window should fail\n");
2709 
2711  DestroyMenu(hMenu);
2712 }
2713 
2714 static void test_window_tree(HWND parent, const DWORD *style, const int *order, int total)
2715 {
2716  HWND child[5], hwnd;
2717  INT_PTR i;
2718 
2719  assert(total <= 5);
2720 
2722  ok(!hwnd, "have to start without children to perform the test\n");
2723 
2724  for (i = 0; i < total; i++)
2725  {
2726  if (style[i] & DS_CONTROL)
2727  {
2728  child[i] = CreateWindowExA(0, (LPCSTR)MAKEINTATOM(32770), "", style[i] & ~WS_VISIBLE,
2729  0,0,0,0, parent, (HMENU)i, 0, NULL);
2730  if (style[i] & WS_VISIBLE)
2732 
2734  }
2735  else
2736  child[i] = CreateWindowExA(0, "static", "", style[i], 0,0,10,10,
2737  parent, (HMENU)i, 0, NULL);
2738  trace("child[%ld] = %p\n", i, child[i]);
2739  ok(child[i] != 0, "CreateWindowEx failed to create child window\n");
2740  }
2741 
2743  ok(hwnd != 0, "GetWindow(GW_CHILD) failed\n");
2744  ok(hwnd == GetWindow(child[total - 1], GW_HWNDFIRST), "GW_HWNDFIRST is wrong\n");
2745  ok(child[order[total - 1]] == GetWindow(child[0], GW_HWNDLAST), "GW_HWNDLAST is wrong\n");
2746 
2747  for (i = 0; i < total; i++)
2748  {
2749  trace("hwnd[%ld] = %p\n", i, hwnd);
2750  ok(child[order[i]] == hwnd, "Z order of child #%ld is wrong\n", i);
2751 
2753  }
2754 
2755  for (i = 0; i < total; i++)
2756  ok(DestroyWindow(child[i]), "DestroyWindow failed\n");
2757 }
2758 
2760 {
2761  const DWORD simple_style[5] = { WS_CHILD, WS_CHILD, WS_CHILD, WS_CHILD,
2762  WS_CHILD };
2763  const int simple_order[5] = { 0, 1, 2, 3, 4 };
2764 
2765  const DWORD complex_style[5] = { WS_CHILD, WS_CHILD | WS_MAXIMIZE,
2768  const int complex_order_1[1] = { 0 };
2769  const int complex_order_2[2] = { 1, 0 };
2770  const int complex_order_3[3] = { 1, 0, 2 };
2771  const int complex_order_4[4] = { 1, 0, 2, 3 };
2772  const int complex_order_5[5] = { 4, 1, 0, 2, 3 };
2773  const DWORD complex_style_6[3] = { WS_CHILD | WS_VISIBLE,
2775  WS_CHILD | WS_VISIBLE };
2776  const int complex_order_6[3] = { 0, 1, 2 };
2777 
2778  /* simple WS_CHILD */
2779  test_window_tree(parent, simple_style, simple_order, 5);
2780 
2781  /* complex children styles */
2782  test_window_tree(parent, complex_style, complex_order_1, 1);
2783  test_window_tree(parent, complex_style, complex_order_2, 2);
2784  test_window_tree(parent, complex_style, complex_order_3, 3);
2785  test_window_tree(parent, complex_style, complex_order_4, 4);
2786  test_window_tree(parent, complex_style, complex_order_5, 5);
2787 
2788  /* another set of complex children styles */
2789  test_window_tree(parent, complex_style_6, complex_order_6, 3);
2790 }
2791 
2792 #define check_z_order(hwnd, next, prev, owner, topmost) \
2793  check_z_order_debug((hwnd), (next), (prev), (owner), (topmost), \
2794  __FILE__, __LINE__)
2795 
2796 static void check_z_order_debug(HWND hwnd, HWND next, HWND prev, HWND owner,
2797  BOOL topmost, const char *file, int line)
2798 {
2799  HWND test;
2800  DWORD ex_style;
2801 
2803  /* skip foreign windows */
2804  while (test && test != next &&
2807  GetWindow(test, GW_OWNER) == next))
2808  {
2809  /*trace("skipping next %p (%p)\n", test, UlongToHandle(GetWindowLongPtr(test, GWLP_HINSTANCE)));*/
2811  }
2812  ok_(file, line)(next == test, "%p: expected next %p, got %p\n", hwnd, next, test);
2813 
2815  /* skip foreign windows */
2816  while (test && test != prev &&
2819  GetWindow(test, GW_OWNER) == hwnd))
2820  {
2821  /*trace("skipping prev %p (%p)\n", test, UlongToHandle(GetWindowLongPtr(test, GWLP_HINSTANCE)));*/
2823  }
2824  ok_(file, line)(prev == test, "%p: expected prev %p, got %p\n", hwnd, prev, test);
2825 
2827  ok_(file, line)(owner == test, "%p: expected owner %p, got %p\n", hwnd, owner, test);
2828 
2829  ex_style = GetWindowLongA(hwnd, GWL_EXSTYLE);
2830  ok_(file, line)(!(ex_style & WS_EX_TOPMOST) == !topmost, "%p: expected %stopmost\n",
2831  hwnd, topmost ? "" : "NOT ");
2832 }
2833 
2834 static void test_popup_zorder(HWND hwnd_D, HWND hwnd_E, DWORD style)
2835 {
2836  HWND hwnd_A, hwnd_B, hwnd_C, hwnd_F;
2837 
2838  trace("hwnd_D %p, hwnd_E %p\n", hwnd_D, hwnd_E);
2839 
2840  SetWindowPos(hwnd_E, hwnd_D, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
2841 
2842  check_z_order(hwnd_D, hwnd_E, 0, 0, FALSE);
2843  check_z_order(hwnd_E, 0, hwnd_D, 0, FALSE);
2844 
2845  hwnd_F = CreateWindowExA(0, "MainWindowClass", "Owner window",
2847  100, 100, 100, 100,
2848  0, 0, GetModuleHandleA(NULL), NULL);
2849  trace("hwnd_F %p\n", hwnd_F);
2850  check_z_order(hwnd_F, hwnd_D, 0, 0, FALSE);
2851 
2852  SetWindowPos(hwnd_F, hwnd_E, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
2853  check_z_order(hwnd_F, 0, hwnd_E, 0, FALSE);
2854  check_z_order(hwnd_E, hwnd_F, hwnd_D, 0, FALSE);
2855  check_z_order(hwnd_D, hwnd_E, 0, 0, FALSE);
2856 
2857  hwnd_C = CreateWindowExA(0, "MainWindowClass", NULL,
2858  style,
2859  100, 100, 100, 100,
2860  hwnd_F, 0, GetModuleHandleA(NULL), NULL);
2861  trace("hwnd_C %p\n", hwnd_C);
2862  check_z_order(hwnd_F, 0, hwnd_E, 0, FALSE);
2863  check_z_order(hwnd_E, hwnd_F, hwnd_D, 0, FALSE);
2864  check_z_order(hwnd_D, hwnd_E, hwnd_C, 0, FALSE);
2865  check_z_order(hwnd_C, hwnd_D, 0, hwnd_F, FALSE);
2866 
2867  hwnd_B = CreateWindowExA(WS_EX_TOPMOST, "MainWindowClass", NULL,
2868  style,
2869  100, 100, 100, 100,
2870  hwnd_F, 0, GetModuleHandleA(NULL), NULL);
2871  trace("hwnd_B %p\n", hwnd_B);
2872  check_z_order(hwnd_F, 0, hwnd_E, 0, FALSE);
2873  check_z_order(hwnd_E, hwnd_F, hwnd_D, 0, FALSE);
2874  check_z_order(hwnd_D, hwnd_E, hwnd_C, 0, FALSE);
2875  check_z_order(hwnd_C, hwnd_D, hwnd_B, hwnd_F, FALSE);
2876  check_z_order(hwnd_B, hwnd_C, 0, hwnd_F, TRUE);
2877 
2878  hwnd_A = CreateWindowExA(WS_EX_TOPMOST, "MainWindowClass", NULL,
2879  style,
2880  100, 100, 100, 100,
2881  0, 0, GetModuleHandleA(NULL), NULL);
2882  trace("hwnd_A %p\n", hwnd_A);
2883  check_z_order(hwnd_F, 0, hwnd_E, 0, FALSE);
2884  check_z_order(hwnd_E, hwnd_F, hwnd_D, 0, FALSE);
2885  check_z_order(hwnd_D, hwnd_E, hwnd_C, 0, FALSE);
2886  check_z_order(hwnd_C, hwnd_D, hwnd_B, hwnd_F, FALSE);
2887  check_z_order(hwnd_B, hwnd_C, hwnd_A, hwnd_F, TRUE);
2888  check_z_order(hwnd_A, hwnd_B, 0, 0, TRUE);
2889 
2890  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);
2891 
2892  /* move hwnd_F and its popups up */
2894  check_z_order(hwnd_E, 0, hwnd_D, 0, FALSE);
2895  check_z_order(hwnd_D, hwnd_E, hwnd_F, 0, FALSE);
2896  check_z_order(hwnd_F, hwnd_D, hwnd_C, 0, FALSE);
2897  check_z_order(hwnd_C, hwnd_F, hwnd_B, hwnd_F, FALSE);
2898  check_z_order(hwnd_B, hwnd_C, hwnd_A, hwnd_F, TRUE);
2899  check_z_order(hwnd_A, hwnd_B, 0, 0, TRUE);
2900 
2901  /* move hwnd_F and its popups down */
2902 #if 0 /* enable once Wine is fixed to pass this test */
2904  check_z_order(hwnd_F, 0, hwnd_C, 0, FALSE);
2905  check_z_order(hwnd_C, hwnd_F, hwnd_B, hwnd_F, FALSE);
2906  check_z_order(hwnd_B, hwnd_C, hwnd_E, hwnd_F, FALSE);
2907  check_z_order(hwnd_E, hwnd_B, hwnd_D, 0, FALSE);
2908  check_z_order(hwnd_D, hwnd_E, hwnd_A, 0, FALSE);
2909  check_z_order(hwnd_A, hwnd_D, 0, 0, TRUE);
2910 #endif
2911 
2912  /* make hwnd_C owned by a topmost window */
2913  DestroyWindow( hwnd_C );
2914  hwnd_C = CreateWindowExA(0, "MainWindowClass", NULL,
2915  style,
2916  100, 100, 100, 100,
2917  hwnd_A, 0, GetModuleHandleA(NULL), NULL);
2918  trace("hwnd_C %p\n", hwnd_C);
2919  check_z_order(hwnd_E, 0, hwnd_D, 0, FALSE);
2920  check_z_order(hwnd_D, hwnd_E, hwnd_F, 0, FALSE);
2921  check_z_order(hwnd_F, hwnd_D, hwnd_B, 0, FALSE);
2922  check_z_order(hwnd_B, hwnd_F, hwnd_A, hwnd_F, TRUE);
2923  check_z_order(hwnd_A, hwnd_B, hwnd_C, 0, TRUE);
2924  check_z_order(hwnd_C, hwnd_A, 0, hwnd_A, TRUE);
2925 
2926  DestroyWindow(hwnd_A);
2927  DestroyWindow(hwnd_B);
2928  DestroyWindow(hwnd_C);
2929  DestroyWindow(hwnd_F);
2930 }
2931 
2932 static void test_vis_rgn( HWND hwnd )
2933 {
2934  RECT win_rect, rgn_rect;
2935  HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
2936  HDC hdc;
2937 
2939  hdc = GetDC( hwnd );
2940  ok( GetRandomRgn( hdc, hrgn, SYSRGN ) != 0, "GetRandomRgn failed\n" );
2941  GetWindowRect( hwnd, &win_rect );
2942  GetRgnBox( hrgn, &rgn_rect );
2943  if (is_win9x)
2944  {
2945  trace("win9x, mapping to screen coords\n");
2946  MapWindowPoints( hwnd, 0, (POINT *)&rgn_rect, 2 );
2947  }
2948  trace("win: %s\n", wine_dbgstr_rect(&win_rect));
2949  trace("rgn: %s\n", wine_dbgstr_rect(&rgn_rect));
2950  ok( win_rect.left <= rgn_rect.left, "rgn left %d not inside win rect %d\n",
2951  rgn_rect.left, win_rect.left );
2952  ok( win_rect.top <= rgn_rect.top, "rgn top %d not inside win rect %d\n",
2953  rgn_rect.top, win_rect.top );
2954  ok( win_rect.right >= rgn_rect.right, "rgn right %d not inside win rect %d\n",
2955  rgn_rect.right, win_rect.right );
2956  ok( win_rect.bottom >= rgn_rect.bottom, "rgn bottom %d not inside win rect %d\n",
2957  rgn_rect.bottom, win_rect.bottom );
2958  ReleaseDC( hwnd, hdc );
2959 }
2960 
2962 {
2963  if (msg == WM_ACTIVATE && LOWORD(wp) == WA_ACTIVE)
2964  {
2966  ok(child != 0, "couldn't find child window\n");
2967  SetFocus(child);
2968  ok(GetFocus() == child, "Focus should be on child %p\n", child);
2969  return 0;
2970  }
2971  return DefWindowProcA(hwnd, msg, wp, lp);
2972 }
2973 
2975 {
2976  HWND child, child2, ret;
2978 
2979  /* check if we can set focus to non-visible windows */
2980 
2982  SetFocus(0);
2983  SetFocus(hwnd);
2984  ok( GetFocus() == hwnd, "Failed to set focus to visible window %p\n", hwnd );
2985  ok( GetWindowLongA(hwnd,GWL_STYLE) & WS_VISIBLE, "Window %p not visible\n", hwnd );
2987  SetFocus(0);
2988  SetFocus(hwnd);
2989  ok( GetFocus() == hwnd, "Failed to set focus to invisible window %p\n", hwnd );
2990  ok( !(GetWindowLongA(hwnd,GWL_STYLE) & WS_VISIBLE), "Window %p still visible\n", hwnd );
2991  child = CreateWindowExA(0, "static", NULL, WS_CHILD, 0, 0, 0, 0, hwnd, 0, 0, NULL);
2992  assert(child);
2993  SetFocus(child);
2994  ok( GetFocus() == child, "Failed to set focus to invisible child %p\n", child );
2995  ok( !(GetWindowLongA(child,GWL_STYLE) & WS_VISIBLE), "Child %p is visible\n", child );
2997  ok( GetWindowLongA(child,GWL_STYLE) & WS_VISIBLE, "Child %p is not visible\n", child );
2998  ok( GetFocus() == child, "Focus no longer on child %p\n", child );
3000  ok( !(GetWindowLongA(child,GWL_STYLE) & WS_VISIBLE), "Child %p is visible\n", child );
3001  ok( GetFocus() == hwnd, "Focus should be on parent %p, not %p\n", hwnd, GetFocus() );
3003  child2 = CreateWindowExA(0, "static", NULL, WS_CHILD, 0, 0, 0, 0, child, 0, 0, NULL);
3004  assert(child2);
3005  ShowWindow(child2, SW_SHOW);
3006  SetFocus(child2);
3008  ok( !(GetWindowLongA(child,GWL_STYLE) & WS_VISIBLE), "Child %p is visible\n", child );
3009  ok( GetFocus() == child2, "Focus should be on %p, not %p\n", child2, GetFocus() );
3011  SetFocus(child);
3012  ok( GetFocus() == child, "Focus should be on child %p\n", child );
3014  ok( GetFocus() == child, "Focus should still be on child %p\n", child );
3015 
3017  SetFocus(hwnd);
3018  ok( GetFocus() == hwnd, "Focus should be on parent %p, not %p\n", hwnd, GetFocus() );
3020  ok( GetFocus() == hwnd, "Focus should still be on parent %p, not %p\n", hwnd, GetFocus() );
3022  ok( GetFocus() == hwnd, "Focus should still be on parent %p, not %p\n", hwnd, GetFocus() );
3023 
3026  SetFocus(child);
3027  ok( GetFocus() == child, "Focus should be on child %p\n", child );
3029  ok( GetFocus() == child, "Focus should still be on child %p\n", child );
3031 
3032  ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd);
3034  ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd);
3035 todo_wine
3036  ok( GetFocus() != child, "Focus should not be on child %p\n", child );
3037  ok( GetFocus() != hwnd, "Focus should not be on parent %p\n", hwnd );
3039  ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd);
3040  ok( GetFocus() == hwnd, "Focus should be on parent %p\n", hwnd );
3042  ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd);
3043  ok( GetFocus() != child, "Focus should not be on child %p\n", child );
3044 todo_wine
3045  ok( GetFocus() != hwnd, "Focus should not be on parent %p\n", hwnd );
3048  ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd);
3049 todo_wine
3050  ok( GetFocus() == child, "Focus should be on child %p, not %p\n", child, GetFocus() );
3052 
3053  SetFocus( hwnd );
3055  SetParent( child2, child );
3056  ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd);
3057  ok( GetFocus() == hwnd, "Focus should be on parent %p\n", hwnd );
3058  ret = SetFocus( child2 );
3059  ok( ret == 0, "SetFocus %p should fail\n", child2);
3060  ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd);
3061  ok( GetFocus() == hwnd, "Focus should be on parent %p\n", hwnd );
3062  ret = SetFocus( child );
3063  ok( ret == 0, "SetFocus %p should fail\n", child);
3064  ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd);
3065  ok( GetFocus() == hwnd, "Focus should be on parent %p\n", hwnd );
3067  SetFocus( child2 );
3068  ok( GetActiveWindow() == child, "child window %p should be active\n", child);
3069  ok( GetFocus() == child2, "Focus should be on child2 %p\n", child2 );
3070  SetFocus( hwnd );
3071  ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd);
3072  ok( GetFocus() == hwnd, "Focus should be on parent %p\n", hwnd );
3073  SetFocus( child );
3074  ok( GetActiveWindow() == child, "child window %p should be active\n", child);
3075  ok( GetFocus() == child, "Focus should be on child %p\n", child );
3076 
3077  DestroyWindow( child2 );
3078  DestroyWindow( child );
3079 }
3080 
3082 {
3083  HWND hwnd2;
3084 
3085  flush_events( TRUE );
3087  SetFocus(0);
3088  SetActiveWindow(0);
3089  check_wnd_state(0, 0, 0, 0);
3090 
3091  /*trace("testing SetActiveWindow %p\n", hwnd);*/
3092 
3094  check_wnd_state(hwnd, hwnd, hwnd, 0);
3095 
3096  hwnd2 = SetActiveWindow(0);
3097  ok(hwnd2 == hwnd, "SetActiveWindow returned %p instead of %p\n", hwnd2, hwnd);
3098  if (!GetActiveWindow()) /* doesn't always work on vista */
3099  {
3101  check_wnd_state(0, 0, 0, 0);
3102  hwnd2 = SetActiveWindow(hwnd);
3104  ok(hwnd2 == 0, "SetActiveWindow returned %p instead of 0\n", hwnd2);
3105  }
3106  check_wnd_state(hwnd, hwnd, hwnd, 0);
3107 
3109  check_wnd_state(hwnd, hwnd, hwnd, 0);
3110 
3112  check_wnd_state(hwnd, hwnd, hwnd, 0);
3113 
3115  check_wnd_state(0, 0, 0, 0);
3116 
3117  /*trace("testing SetActiveWindow on an invisible window %p\n", hwnd);*/
3119  check_wnd_state(hwnd, hwnd, hwnd, 0);
3120 
3122  check_wnd_state(hwnd, hwnd, hwnd, 0);
3123 
3124  hwnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 0, 0, hwnd, 0, 0, NULL);
3125  check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
3126 
3127  DestroyWindow(hwnd2);
3128  check_wnd_state(hwnd, hwnd, hwnd, 0);
3129 
3130  hwnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 0, 0, hwnd, 0, 0, NULL);
3131  check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
3132 
3134  check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
3135 
3136  DestroyWindow(hwnd2);
3137  check_wnd_state(hwnd, hwnd, hwnd, 0);
3138 }
3139 
3141 {
3145 };
3146 
3148 {
3150  DWORD res;
3151  BOOL ret;
3152 
3153  p->window = CreateWindowA("static", NULL, WS_POPUP | WS_VISIBLE, 0, 0, 0, 0, 0, 0, 0, 0);
3154 
3155  ret = SetEvent(p->window_created);
3156  ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
3157 
3158  res = WaitForSingleObject(p->test_finished, INFINITE);
3159  ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
3160 
3161  DestroyWindow(p->window);
3162  return 0;
3163 }
3164 
3166 {
3167  struct create_window_thread_params thread_params;
3168  HANDLE thread;
3169  DWORD res, tid;
3170  BOOL ret;
3171  HWND hwnd2;
3172  MSG msg;
3173  LONG style;
3174 
3175  flush_events( TRUE );
3177  SetFocus(0);
3178  SetActiveWindow(0);
3179  check_wnd_state(0, 0, 0, 0);
3180 
3181  /*trace("testing SetForegroundWindow %p\n", hwnd);*/
3182 
3184  check_wnd_state(hwnd, hwnd, hwnd, 0);
3185 
3186  hwnd2 = SetActiveWindow(0);
3187  ok(hwnd2 == hwnd, "SetActiveWindow(0) returned %p instead of %p\n", hwnd2, hwnd);
3188  if (GetActiveWindow() == hwnd) /* doesn't always work on vista */
3189  check_wnd_state(hwnd, hwnd, hwnd, 0);
3190  else
3191  check_wnd_state(0, 0, 0, 0);
3192 
3194  if (!ret)
3195  {
3196  skip( "SetForegroundWindow not working\n" );
3197  return;
3198  }
3199  check_wnd_state(hwnd, hwnd, hwnd, 0);
3200 
3201  SetLastError(0xdeadbeef);
3202  ret = SetForegroundWindow(0);
3203  ok(!ret, "SetForegroundWindow returned TRUE instead of FALSE\n");
3205  broken(GetLastError() == 0xdeadbeef), /* win9x */
3206  "got error %d expected ERROR_INVALID_WINDOW_HANDLE\n", GetLastError());
3207  check_wnd_state(hwnd, hwnd, hwnd, 0);
3208 
3210  check_wnd_state(hwnd, hwnd, hwnd, 0);
3211 
3213  check_wnd_state(hwnd, hwnd, hwnd, 0);
3214 
3215  hwnd2 = GetForegroundWindow();
3216  ok(hwnd2 == hwnd, "Wrong foreground window %p\n", hwnd2);
3218  ok(ret, "SetForegroundWindow(desktop) error: %d\n", GetLastError());
3219  hwnd2 = GetForegroundWindow();
3220  ok(hwnd2 != hwnd, "Wrong foreground window %p\n", hwnd2);
3221 
3223  check_wnd_state(0, 0, 0, 0);
3224 
3225  /*trace("testing SetForegroundWindow on an invisible window %p\n", hwnd);*/
3227  ok(ret || broken(!ret), /* win98 */ "SetForegroundWindow returned FALSE instead of TRUE\n");
3228  check_wnd_state(hwnd, hwnd, hwnd, 0);
3229 
3231  check_wnd_state(hwnd, hwnd, hwnd, 0);
3232 
3233  hwnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 0, 0, hwnd, 0, 0, NULL);
3234  check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
3235 
3236  DestroyWindow(hwnd2);
3237  check_wnd_state(hwnd, hwnd, hwnd, 0);
3238 
3239  hwnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 0, 0, hwnd, 0, 0, NULL);
3240  check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
3241 
3243  check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
3244 
3245  DestroyWindow(hwnd2);
3246  check_wnd_state(hwnd, hwnd, hwnd, 0);
3247 
3248  hwnd2 = CreateWindowA("static", NULL, WS_POPUP | WS_VISIBLE, 0, 0, 0, 0, 0, 0, 0, 0);
3249  check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
3250 
3251  thread_params.window_created = CreateEventW(NULL, FALSE, FALSE, NULL);
3252  ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
3253  thread_params.test_finished = CreateEventW(NULL, FALSE, FALSE, NULL);
3254  ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
3255  thread = CreateThread(NULL, 0, create_window_thread, &thread_params, 0, &tid);
3256  ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
3257  res = WaitForSingleObject(thread_params.window_created, INFINITE);
3258  ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
3259  check_wnd_state(hwnd2, thread_params.window, hwnd2, 0);
3260 
3261  SetForegroundWindow(hwnd2);
3262  check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
3263 
3264  while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
3265  if (0) check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
3266  todo_wine ok(GetActiveWindow() == hwnd2, "Expected active window %p, got %p.\n", hwnd2, GetActiveWindow());
3267  todo_wine ok(GetFocus() == hwnd2, "Expected focus window %p, got %p.\n", hwnd2, GetFocus());
3268 
3270  check_wnd_state(hwnd, hwnd, hwnd, 0);
3271  style = GetWindowLongA(hwnd2, GWL_STYLE) | WS_CHILD;
3272  ok(SetWindowLongA(hwnd2, GWL_STYLE, style), "SetWindowLong failed\n");
3273  ok(SetForegroundWindow(hwnd2), "SetForegroundWindow failed\n");
3274  check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
3275 
3277  check_wnd_state(hwnd, hwnd, hwnd, 0);
3278  ok(