ReactOS  0.4.15-dev-3745-g356babc
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  ok(info->wCreatorVersion == 0x0400 /* NT4, Win2000, XP, Win2003 */ ||
990  info->wCreatorVersion == 0x0500 /* Vista */,
991  "wrong wCreatorVersion %04x for %p in hook %s\n", info->wCreatorVersion, hwnd, hook);
992 }
993 
994 static void FixedAdjustWindowRectEx(RECT* rc, LONG style, BOOL menu, LONG exstyle)
995 {
996  AdjustWindowRectEx(rc, style, menu, exstyle);
997  /* AdjustWindowRectEx does not include scroll bars */
998  if (style & WS_VSCROLL)
999  {
1000  if(exstyle & WS_EX_LEFTSCROLLBAR)
1002  else
1004  }
1005  if (style & WS_HSCROLL)
1007 }
1008 
1009 /* reimplement it to check that the Wine algorithm gives the correct result */
1010 static void wine_AdjustWindowRectEx( RECT *rect, LONG style, BOOL menu, LONG exStyle )
1011 {
1012  int adjust;
1013 
1014  if ((exStyle & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) ==
1016  {
1017  adjust = 1; /* for the outer frame always present */
1018  }
1019  else
1020  {
1021  adjust = 0;
1022  if ((exStyle & WS_EX_DLGMODALFRAME) ||
1023  (style & (WS_THICKFRAME|WS_DLGFRAME))) adjust = 2; /* outer */
1024  }
1025  if (style & WS_THICKFRAME)
1026  adjust += GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME); /* The resize border */
1027  if ((style & (WS_BORDER|WS_DLGFRAME)) ||
1028  (exStyle & WS_EX_DLGMODALFRAME))
1029  adjust++; /* The other border */
1030 
1031  InflateRect (rect, adjust, adjust);
1032 
1033  if ((style & WS_CAPTION) == WS_CAPTION)
1034  {
1035  if (exStyle & WS_EX_TOOLWINDOW)
1037  else
1039  }
1040  if (menu) rect->top -= GetSystemMetrics(SM_CYMENU);
1041 
1042  if (exStyle & WS_EX_CLIENTEDGE)
1044 
1045  if (style & WS_VSCROLL)
1046  {
1047  if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
1049  else
1050  rect->right += GetSystemMetrics(SM_CXVSCROLL);
1051  }
1052  if (style & WS_HSCROLL) rect->bottom += GetSystemMetrics(SM_CYHSCROLL);
1053 }
1054 
1056 {
1057  DWORD style, exstyle;
1058  RECT rc_window, rc_client, rc;
1059  BOOL menu;
1060  LRESULT ret;
1061 
1063  exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
1064  menu = !(style & WS_CHILD) && GetMenu(hwnd) != 0;
1065 
1066  GetWindowRect(hwnd, &rc_window);
1067  GetClientRect(hwnd, &rc_client);
1068 
1069  /* avoid some cases when things go wrong */
1070  if (IsRectEmpty(&rc_window) || IsRectEmpty(&rc_client) ||
1071  rc_window.right > 32768 || rc_window.bottom > 32768) return;
1072 
1073  rc = rc_client;
1074  MapWindowPoints(hwnd, 0, (LPPOINT)&rc, 2);
1075  FixedAdjustWindowRectEx(&rc, style, menu, exstyle);
1076 
1077  ok(EqualRect(&rc, &rc_window),
1078  "window rect does not match: style:exstyle=0x%08x:0x%08x, menu=%d, win=%s, calc=%s\n",
1079  style, exstyle, menu, wine_dbgstr_rect(&rc_window), wine_dbgstr_rect(&rc));
1080 
1081  rc = rc_client;
1082  MapWindowPoints(hwnd, 0, (LPPOINT)&rc, 2);
1083  wine_AdjustWindowRectEx(&rc, style, menu, exstyle);
1084  ok(EqualRect(&rc, &rc_window),
1085  "window rect does not match: style:exstyle=0x%08x:0x%08x, menu=%d, win=%s, calc=%s\n",
1086  style, exstyle, menu, wine_dbgstr_rect(&rc_window), wine_dbgstr_rect(&rc));
1087 
1088 
1089  rc = rc_window;
1091  MapWindowPoints(0, hwnd, (LPPOINT)&rc, 2);
1092  ok(EqualRect(&rc, &rc_client),
1093  "client rect does not match: style:exstyle=0x%08x:0x%08x, menu=%d client=%s, calc=%s\n",
1094  style, exstyle, menu, wine_dbgstr_rect(&rc_client), wine_dbgstr_rect(&rc));
1095 
1096  /* NULL rectangle shouldn't crash */
1098  ok(ret == 0, "NULL rectangle returned %ld instead of 0\n", ret);
1099 
1100  /* Win9x doesn't like WM_NCCALCSIZE with synthetic data and crashes */;
1101  if (is_win9x)
1102  return;
1103 
1104  /* and now test AdjustWindowRectEx and WM_NCCALCSIZE on synthetic data */
1105  SetRect(&rc_client, 0, 0, 250, 150);
1106  rc_window = rc_client;
1107  MapWindowPoints(hwnd, 0, (LPPOINT)&rc_window, 2);
1108  FixedAdjustWindowRectEx(&rc_window, style, menu, exstyle);
1109 
1110  rc = rc_window;
1112  MapWindowPoints(0, hwnd, (LPPOINT)&rc, 2);
1113  ok(EqualRect(&rc, &rc_client),
1114  "synthetic rect does not match: style:exstyle=0x%08x:0x%08x, menu=%d, client=%s, calc=%s\n",
1115  style, exstyle, menu, wine_dbgstr_rect(&rc_client), wine_dbgstr_rect(&rc));
1116 }
1117 
1119 {
1120  static const char *CBT_code_name[10] = {
1121  "HCBT_MOVESIZE",
1122  "HCBT_MINMAX",
1123  "HCBT_QS",
1124  "HCBT_CREATEWND",
1125  "HCBT_DESTROYWND",
1126  "HCBT_ACTIVATE",
1127  "HCBT_CLICKSKIPPED",
1128  "HCBT_KEYSKIPPED",
1129  "HCBT_SYSCOMMAND",
1130  "HCBT_SETFOCUS" };
1131  const char *code_name = (nCode >= 0 && nCode <= HCBT_SETFOCUS) ? CBT_code_name[nCode] : "Unknown";
1132  HWND hwnd = (HWND)wParam;
1133 
1134  switch (nCode)
1135  {
1136  case HCBT_CREATEWND:
1137  {
1138  static const RECT rc_null;
1139  RECT rc;
1140  LONG style;
1141  CBT_CREATEWNDA *createwnd = (CBT_CREATEWNDA *)lParam;
1142  ok(createwnd->hwndInsertAfter == HWND_TOP, "hwndInsertAfter should be always HWND_TOP\n");
1143 
1144  if (pGetWindowInfo)
1145  {
1146  WINDOWINFO info;
1147  info.cbSize = sizeof(WINDOWINFO);
1148  ok(pGetWindowInfo(hwnd, &info), "GetWindowInfo should not fail\n");
1149  verify_window_info(code_name, hwnd, &info);
1150  }
1151 
1152  /* WS_VISIBLE should be turned off yet */
1153  style = createwnd->lpcs->style & ~WS_VISIBLE;
1155  "style of hwnd and style in the CREATESTRUCT do not match: %08x != %08x\n",
1157 
1158  if (0)
1159  {
1160  /* Uncomment this once the test succeeds in all cases */
1161  if ((style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1162  {
1164  "wrong result from GetParent %p: message window %p\n",
1166  }
1167  else
1168  ok(!GetParent(hwnd), "GetParent should return 0 at this point\n");
1169 
1170  ok(!GetWindow(hwnd, GW_OWNER), "GW_OWNER should be set to 0 at this point\n");
1171  }
1172  if (0)
1173  {
1174  /* while NT assigns GW_HWNDFIRST/LAST some values at this point,
1175  * Win9x still has them set to 0.
1176  */
1177  ok(GetWindow(hwnd, GW_HWNDFIRST) != 0, "GW_HWNDFIRST should not be set to 0 at this point\n");
1178  ok(GetWindow(hwnd, GW_HWNDLAST) != 0, "GW_HWNDLAST should not be set to 0 at this point\n");
1179  }
1180  ok(!GetWindow(hwnd, GW_HWNDPREV), "GW_HWNDPREV should be set to 0 at this point\n");
1181  ok(!GetWindow(hwnd, GW_HWNDNEXT), "GW_HWNDNEXT should be set to 0 at this point\n");
1182 
1183  if (0)
1184  {
1185  /* Uncomment this once the test succeeds in all cases */
1186  if (pGetAncestor)
1187  {
1188  ok(pGetAncestor(hwnd, GA_PARENT) == hwndMessage, "GA_PARENT should be set to hwndMessage at this point\n");
1189  ok(pGetAncestor(hwnd, GA_ROOT) == hwnd,
1190  "GA_ROOT is set to %p, expected %p\n", pGetAncestor(hwnd, GA_ROOT), hwnd);
1191 
1192  if ((style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1193  ok(pGetAncestor(hwnd, GA_ROOTOWNER) == hwndMessage,
1194  "GA_ROOTOWNER should be set to hwndMessage at this point\n");
1195  else
1196  ok(pGetAncestor(hwnd, GA_ROOTOWNER) == hwnd,
1197  "GA_ROOTOWNER is set to %p, expected %p\n", pGetAncestor(hwnd, GA_ROOTOWNER), hwnd);
1198  }
1199 
1200  ok(GetWindowRect(hwnd, &rc), "GetWindowRect failed\n");
1201  ok(EqualRect(&rc, &rc_null), "window rect should be set to 0 HCBT_CREATEWND\n");
1202  ok(GetClientRect(hwnd, &rc), "GetClientRect failed\n");
1203  ok(EqualRect(&rc, &rc_null), "client rect should be set to 0 on HCBT_CREATEWND\n");
1204  }
1205  break;
1206  }
1207  case HCBT_MOVESIZE:
1208  case HCBT_MINMAX:
1209  case HCBT_ACTIVATE:
1210  if (pGetWindowInfo && IsWindow(hwnd))
1211  {
1212  WINDOWINFO info;
1213 
1214  /* Win98 actually does check the info.cbSize and doesn't allow
1215  * it to be anything except sizeof(WINDOWINFO), while Win95, Win2k,
1216  * WinXP do not check it at all.
1217  */
1218  info.cbSize = sizeof(WINDOWINFO);
1219  ok(pGetWindowInfo(hwnd, &info), "GetWindowInfo should not fail\n");
1220  verify_window_info(code_name, hwnd, &info);
1221  }
1222  break;
1223  /* window state is undefined */
1224  case HCBT_SETFOCUS:
1225  case HCBT_DESTROYWND:
1226  break;
1227  default:
1228  break;
1229  }
1230 
1231  return CallNextHookEx(hhook, nCode, wParam, lParam);
1232 }
1233 
1234 static void test_shell_window(void)
1235 {
1236  BOOL ret;
1237  DWORD error;
1238  HMODULE hinst, hUser32;
1240  HWND hwnd1, hwnd2, hwnd3, hwnd4, hwnd5;
1241  HWND shellWindow, nextWnd;
1242 
1243  if (is_win9x)
1244  {
1245  win_skip("Skipping shell window test on Win9x\n");
1246  return;
1247  }
1248 
1249  shellWindow = GetShellWindow();
1251  hUser32 = GetModuleHandleA("user32");
1252 
1253  SetShellWindow = (void *)GetProcAddress(hUser32, "SetShellWindow");
1254 
1255  trace("previous shell window: %p\n", shellWindow);
1256 
1257  if (shellWindow) {
1258  DWORD pid;
1259  HANDLE hProcess;
1260 
1261  GetWindowThreadProcessId(shellWindow, &pid);
1263  if (!hProcess)
1264  {
1265  skip( "cannot get access to shell process\n" );
1266  return;
1267  }
1268 
1269  SetLastError(0xdeadbeef);
1270  ret = DestroyWindow(shellWindow);
1271  error = GetLastError();
1272 
1273  ok(!ret, "DestroyWindow(shellWindow)\n");
1274  /* passes on Win XP, but not on Win98 */
1275  ok(error==ERROR_ACCESS_DENIED || error == 0xdeadbeef,
1276  "got %u after DestroyWindow(shellWindow)\n", error);
1277 
1278  /* close old shell instance */
1280  ok(ret, "termination of previous shell process failed: GetLastError()=%d\n", GetLastError());
1281  WaitForSingleObject(hProcess, INFINITE); /* wait for termination */
1283  }
1284 
1285  hwnd1 = CreateWindowExA(0, "#32770", "TEST1", WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 100, 100, 300, 200, 0, 0, hinst, 0);
1286  trace("created window 1: %p\n", hwnd1);
1287 
1288  ret = SetShellWindow(hwnd1);
1289  ok(ret, "first call to SetShellWindow(hwnd1)\n");
1290  shellWindow = GetShellWindow();
1291  ok(shellWindow==hwnd1, "wrong shell window: %p\n", shellWindow);
1292 
1293  ret = SetShellWindow(hwnd1);
1294  ok(!ret, "second call to SetShellWindow(hwnd1)\n");
1295 
1296  ret = SetShellWindow(0);
1297  error = GetLastError();
1298  /* passes on Win XP, but not on Win98
1299  ok(!ret, "reset shell window by SetShellWindow(0)\n");
1300  ok(error==ERROR_INVALID_WINDOW_HANDLE, "ERROR_INVALID_WINDOW_HANDLE after SetShellWindow(0)\n"); */
1301 
1302  ret = SetShellWindow(hwnd1);
1303  /* passes on Win XP, but not on Win98
1304  ok(!ret, "third call to SetShellWindow(hwnd1)\n"); */
1305 
1307  ret = (GetWindowLongA(hwnd1,GWL_EXSTYLE) & WS_EX_TOPMOST) != 0;
1308  ok(!ret, "SetWindowExStyle(hwnd1, WS_EX_TOPMOST)\n");
1309 
1310  ret = DestroyWindow(hwnd1);
1311  ok(ret, "DestroyWindow(hwnd1)\n");
1312 
1313  hwnd2 = CreateWindowExA(WS_EX_TOPMOST, "#32770", "TEST2", WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 150, 250, 300, 200, 0, 0, hinst, 0);
1314  trace("created window 2: %p\n", hwnd2);
1315  ret = SetShellWindow(hwnd2);
1316  ok(!ret, "SetShellWindow(hwnd2) with WS_EX_TOPMOST\n");
1317 
1318  hwnd3 = CreateWindowExA(0, "#32770", "TEST3", WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 200, 400, 300, 200, 0, 0, hinst, 0);
1319  trace("created window 3: %p\n", hwnd3);
1320 
1321  hwnd4 = CreateWindowExA(0, "#32770", "TEST4", WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 250, 500, 300, 200, 0, 0, hinst, 0);
1322  trace("created window 4: %p\n", hwnd4);
1323 
1324  nextWnd = GetWindow(hwnd4, GW_HWNDNEXT);
1325  ok(nextWnd==hwnd3, "wrong next window for hwnd4: %p - expected hwnd3\n", nextWnd);
1326 
1327  ret = SetShellWindow(hwnd4);
1328  ok(ret, "SetShellWindow(hwnd4)\n");
1329  shellWindow = GetShellWindow();
1330  ok(shellWindow==hwnd4, "wrong shell window: %p - expected hwnd4\n", shellWindow);
1331 
1332  nextWnd = GetWindow(hwnd4, GW_HWNDNEXT);
1333  ok(nextWnd==0, "wrong next window for hwnd4: %p - expected 0\n", nextWnd);
1334 
1335  ret = SetWindowPos(hwnd4, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
1336  ok(ret, "SetWindowPos(hwnd4, HWND_TOPMOST)\n");
1337 
1338  ret = SetWindowPos(hwnd4, hwnd3, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
1339  ok(ret, "SetWindowPos(hwnd4, hwnd3\n");
1340 
1341  ret = SetShellWindow(hwnd3);
1342  ok(!ret, "SetShellWindow(hwnd3)\n");
1343  shellWindow = GetShellWindow();
1344  ok(shellWindow==hwnd4, "wrong shell window: %p - expected hwnd4\n", shellWindow);
1345 
1346  hwnd5 = CreateWindowExA(0, "#32770", "TEST5", WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 300, 600, 300, 200, 0, 0, hinst, 0);
1347  trace("created window 5: %p\n", hwnd5);
1348  ret = SetWindowPos(hwnd4, hwnd5, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
1349  ok(ret, "SetWindowPos(hwnd4, hwnd5)\n");
1350 
1351  todo_wine
1352  {
1353  nextWnd = GetWindow(hwnd4, GW_HWNDNEXT);
1354  ok(nextWnd==0, "wrong next window for hwnd4 after SetWindowPos(): %p - expected 0\n", nextWnd);
1355  }
1356 
1357  /* destroy test windows */
1358  DestroyWindow(hwnd2);
1359  DestroyWindow(hwnd3);
1360  DestroyWindow(hwnd4);
1361  DestroyWindow(hwnd5);
1362 }
1363 
1364 /************** MDI test ****************/
1365 
1366 static char mdi_lParam_test_message[] = "just a test string";
1367 
1369 {
1370  MDICREATESTRUCTA mdi_cs;
1371  HWND mdi_child, hwnd, exp_hwnd;
1372  INT_PTR id;
1373  static const WCHAR classW[] = {'M','D','I','_','c','h','i','l','d','_','C','l','a','s','s','_','1',0};
1374  static const WCHAR titleW[] = {'M','D','I',' ','c','h','i','l','d',0};
1375  BOOL isWin9x = FALSE;
1376  HMENU frame_menu = GetMenu(parent);
1377 
1378  ok(frame_menu != NULL, "Frame window didn't have a menu\n");
1379 
1380  mdi_cs.szClass = "MDI_child_Class_1";
1381  mdi_cs.szTitle = "MDI child";
1382  mdi_cs.hOwner = GetModuleHandleA(NULL);
1383  mdi_cs.x = CW_USEDEFAULT;
1384  mdi_cs.y = CW_USEDEFAULT;
1385  mdi_cs.cx = CW_USEDEFAULT;
1386  mdi_cs.cy = CW_USEDEFAULT;
1387  mdi_cs.style = 0;
1389  mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
1390  ok(mdi_child != 0, "MDI child creation failed\n");
1391  id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1392  ok(id == first_id, "wrong child id %ld\n", id);
1394  exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0;
1395  ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd);
1396  SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1397  ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1398 
1399  mdi_cs.style = 0x7fffffff; /* without WS_POPUP */
1400  mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
1401  ok(mdi_child != 0, "MDI child creation failed\n");
1402  id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1403  ok(id == first_id, "wrong child id %ld\n", id);
1405  ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1406  SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1407  ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1408 
1409  mdi_cs.style = 0xffffffff; /* with WS_POPUP */
1410  mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
1412  {
1413  ok(!mdi_child, "MDI child with WS_POPUP and with MDIS_ALLCHILDSTYLES should fail\n");
1414  }
1415  else
1416  {
1417  ok(mdi_child != 0, "MDI child creation failed\n");
1418  id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1419  ok(id == first_id, "wrong child id %ld\n", id);
1421  ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1422  ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1423  SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1424  ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1425  }
1426 
1427  /* test MDICREATESTRUCT A<->W mapping */
1428  /* MDICREATESTRUCTA and MDICREATESTRUCTW have the same layout */
1429  mdi_cs.style = 0;
1430  mdi_cs.szClass = (LPCSTR)classW;
1431  mdi_cs.szTitle = (LPCSTR)titleW;
1432  SetLastError(0xdeadbeef);
1433  mdi_child = (HWND)SendMessageW(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
1434  if (!mdi_child)
1435  {
1437  isWin9x = TRUE;
1438  else
1439  ok(mdi_child != 0, "MDI child creation failed\n");
1440  }
1441  else
1442  {
1443  id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1444  ok(id == first_id, "wrong child id %ld\n", id);
1446  exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0;
1447  ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd);
1448  ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1449  SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1450  ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1451  }
1452 
1453  mdi_child = CreateMDIWindowA("MDI_child_Class_1", "MDI child",
1454  0,
1459  ok(mdi_child != 0, "MDI child creation failed\n");
1460  id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1461  ok(id == first_id, "wrong child id %ld\n", id);
1463  exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0;
1464  ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd);
1465  ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1466  SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1467  ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1468 
1469  mdi_child = CreateMDIWindowA("MDI_child_Class_1", "MDI child",
1470  0x7fffffff, /* without WS_POPUP */
1475  ok(mdi_child != 0, "MDI child creation failed\n");
1476  id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1477  ok(id == first_id, "wrong child id %ld\n", id);
1479  ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1480  ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1481  SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1482  ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1483 
1484  mdi_child = CreateMDIWindowA("MDI_child_Class_1", "MDI child",
1485  0xffffffff, /* with WS_POPUP */
1491  {
1492  ok(!mdi_child, "MDI child with WS_POPUP and with MDIS_ALLCHILDSTYLES should fail\n");
1493  }
1494  else
1495  {
1496  ok(mdi_child != 0, "MDI child creation failed\n");
1497  id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1498  ok(id == first_id, "wrong child id %ld\n", id);
1500  ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1501  ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1502  SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1503  ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1504  }
1505 
1506  /* test MDICREATESTRUCT A<->W mapping */
1507  SetLastError(0xdeadbeef);
1508  mdi_child = CreateMDIWindowW(classW, titleW,
1509  0,
1514  if (!mdi_child)
1515  {
1517  isWin9x = TRUE;
1518  else
1519  ok(mdi_child != 0, "MDI child creation failed\n");
1520  }
1521  else
1522  {
1523  id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1524  ok(id == first_id, "wrong child id %ld\n", id);
1526  exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0;
1527  ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd);
1528  ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1529  SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1530  ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1531  }
1532 
1533  mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
1534  0,
1539  ok(mdi_child != 0, "MDI child creation failed\n");
1540  id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1541  ok(id == first_id, "wrong child id %ld\n", id);
1543  exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0;
1544  ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd);
1545  ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1546  SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1547  ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1548 
1549  mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
1550  WS_MAXIMIZE,
1555  ok(mdi_child != 0, "MDI child creation failed\n");
1556  id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1557  ok(id == first_id, "wrong child id %ld\n", id);
1559  exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0;
1560  ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd);
1562  ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1563  else
1564  ok(GetMenuItemCount(frame_menu) == 4, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1565  SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1566  ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1567 
1568  mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
1569  0x7fffffff, /* without WS_POPUP */
1574  ok(mdi_child != 0, "MDI child creation failed\n");
1575  id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1576  ok(id == first_id, "wrong child id %ld\n", id);
1578  ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1579  ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1580  SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1581  ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1582 
1583  mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
1584  0xffffffff, /* with WS_POPUP */
1590  {
1591  ok(!mdi_child, "MDI child with WS_POPUP and with MDIS_ALLCHILDSTYLES should fail\n");
1592  }
1593  else
1594  {
1595  ok(mdi_child != 0, "MDI child creation failed\n");
1596  id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1597  ok(id == first_id, "wrong child id %ld\n", id);
1599  ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1600  ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1601  SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1602  ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1603  }
1604 
1605  /* test MDICREATESTRUCT A<->W mapping */
1606  SetLastError(0xdeadbeef);
1608  0,
1613  if (!mdi_child)
1614  {
1616  isWin9x = TRUE;
1617  else
1618  ok(mdi_child != 0, "MDI child creation failed\n");
1619  }
1620  else
1621  {
1622  id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1623  ok(id == first_id, "wrong child id %ld\n", id);
1625  exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0;
1626  ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd);
1627  ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1628  SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1629  ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1630  }
1631 
1632  /* This test fails on Win9x */
1633  if (!isWin9x)
1634  {
1635  mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_2", "MDI child",
1636  WS_CHILD,
1641  ok(!mdi_child, "WS_EX_MDICHILD with a not MDIClient parent should fail\n");
1642  }
1643 
1644  mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
1645  WS_CHILD, /* without WS_POPUP */
1650  ok(mdi_child != 0, "MDI child creation failed\n");
1651  id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1652  ok(id == 0, "wrong child id %ld\n", id);
1653  ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1655  ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1656  DestroyWindow(mdi_child);
1657 
1658  mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
1659  WS_CHILD | WS_POPUP, /* with WS_POPUP */
1664  ok(mdi_child != 0, "MDI child creation failed\n");
1665  id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1666  ok(id == 0, "wrong child id %ld\n", id);
1668  ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1669  ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1670  DestroyWindow(mdi_child);
1671 
1672  /* maximized child */
1673  mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
1679  ok(mdi_child != 0, "MDI child creation failed\n");
1680  id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1681  ok(id == 0, "wrong child id %ld\n", id);
1683  ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1684  ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1685  DestroyWindow(mdi_child);
1686 
1687  trace("Creating maximized child with a caption\n");
1688  mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
1694  ok(mdi_child != 0, "MDI child creation failed\n");
1695  id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1696  ok(id == 0, "wrong child id %ld\n", id);
1698  ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1699  ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1700  DestroyWindow(mdi_child);
1701 
1702  trace("Creating maximized child with a caption and a thick frame\n");
1703  mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
1709  ok(mdi_child != 0, "MDI child creation failed\n");
1710  id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1711  ok(id == 0, "wrong child id %ld\n", id);
1713  ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1714  ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu));
1715  DestroyWindow(mdi_child);
1716 }
1717 
1719 {
1720  HWND child_1, child_2, child_3, child_4;
1721  HWND stack[4];
1723 
1724  cs.szClass = "MDI_child_Class_1";
1725  cs.szTitle = "MDI child";
1726  cs.hOwner = GetModuleHandleA(0);
1727  cs.x = CW_USEDEFAULT;
1728  cs.y = CW_USEDEFAULT;
1729  cs.cx = CW_USEDEFAULT;
1730  cs.cy = CW_USEDEFAULT;
1731  cs.style = 0;
1732  cs.lParam = (LPARAM)mdi_lParam_test_message;
1733 
1734  child_1 = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&cs);
1735  ok(child_1 != 0, "expected child_1 to be non NULL\n");
1736  child_2 = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&cs);
1737  ok(child_2 != 0, "expected child_2 to be non NULL\n");
1738  child_3 = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&cs);
1739  ok(child_3 != 0, "expected child_3 to be non NULL\n");
1740  child_4 = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&cs);
1741  ok(child_4 != 0, "expected child_4 to be non NULL\n");
1742 
1744  stack[1] = GetWindow(stack[0], GW_HWNDNEXT);
1745  stack[2] = GetWindow(stack[1], GW_HWNDNEXT);
1746  stack[3] = GetWindow(stack[2], GW_HWNDNEXT);
1747  trace("Initial MDI child stack: %p->%p->%p->%p\n", stack[0], stack[1], stack[2], stack[3]);
1748  ok(stack[0] == child_4 && stack[1] == child_3 &&
1749  stack[2] == child_2 && stack[3] == child_1,
1750  "Unexpected initial order, should be: %p->%p->%p->%p\n",
1751  child_4, child_3, child_2, child_1);
1752 
1753  trace("Activate child next to %p\n", child_3);
1754  SendMessageA(mdi_client, WM_MDINEXT, (WPARAM)child_3, 0);
1755 
1757  stack[1] = GetWindow(stack[0], GW_HWNDNEXT);
1758  stack[2] = GetWindow(stack[1], GW_HWNDNEXT);
1759  stack[3] = GetWindow(stack[2], GW_HWNDNEXT);
1760  ok(stack[0] == child_2 && stack[1] == child_4 &&
1761  stack[2] == child_1 && stack[3] == child_3,
1762  "Broken MDI child stack:\nexpected: %p->%p->%p->%p, but got: %p->%p->%p->%p\n",
1763  child_2, child_4, child_1, child_3, stack[0], stack[1], stack[2], stack[3]);
1764 
1765  trace("Activate child previous to %p\n", child_1);
1766  SendMessageA(mdi_client, WM_MDINEXT, (WPARAM)child_1, 1);
1767 
1769  stack[1] = GetWindow(stack[0], GW_HWNDNEXT);
1770  stack[2] = GetWindow(stack[1], GW_HWNDNEXT);
1771  stack[3] = GetWindow(stack[2], GW_HWNDNEXT);
1772  ok(stack[0] == child_4 && stack[1] == child_2 &&
1773  stack[2] == child_1 && stack[3] == child_3,
1774  "Broken MDI child stack:\nexpected: %p->%p->%p->%p, but got: %p->%p->%p->%p\n",
1775  child_4, child_2, child_1, child_3, stack[0], stack[1], stack[2], stack[3]);
1776 
1777  DestroyWindow(child_1);
1778  DestroyWindow(child_2);
1779  DestroyWindow(child_3);
1780  DestroyWindow(child_4);
1781 }
1782 
1783 /**********************************************************************
1784  * MDI_ChildGetMinMaxInfo (copied from windows/mdi.c)
1785  *
1786  * Note: The rule here is that client rect of the maximized MDI child
1787  * is equal to the client rect of the MDI client window.
1788  */
1790 {
1791  RECT rect;
1792 
1793  GetClientRect( client, &rect );
1796 
1797  rect.right -= rect.left;
1798  rect.bottom -= rect.top;
1799  lpMinMax->ptMaxSize.x = rect.right;
1800  lpMinMax->ptMaxSize.y = rect.bottom;
1801 
1802  lpMinMax->ptMaxPosition.x = rect.left;
1803  lpMinMax->ptMaxPosition.y = rect.top;
1804 
1805  trace("max rect %s\n", wine_dbgstr_rect(&rect));
1806 }
1807 
1809 {
1810  switch (msg)
1811  {
1812  case WM_NCCREATE:
1813  case WM_CREATE:
1814  {
1816  MDICREATESTRUCTA *mdi_cs = cs->lpCreateParams;
1817 
1818  ok(cs->dwExStyle & WS_EX_MDICHILD, "WS_EX_MDICHILD should be set\n");
1819  ok(mdi_cs->lParam == (LPARAM)mdi_lParam_test_message, "wrong mdi_cs->lParam\n");
1820 
1821  ok(!lstrcmpA(cs->lpszClass, "MDI_child_Class_1"), "wrong class name\n");
1822  ok(!lstrcmpA(cs->lpszClass, mdi_cs->szClass), "class name does not match\n");
1823  ok(!lstrcmpA(cs->lpszName, "MDI child"), "wrong title\n");
1824  ok(!lstrcmpA(cs->lpszName, mdi_cs->szTitle), "title does not match\n");
1825  ok(cs->hInstance == mdi_cs->hOwner, "%p != %p\n", cs->hInstance, mdi_cs->hOwner);
1826 
1827  /* MDICREATESTRUCT should have original values */
1828  ok(mdi_cs->style == 0 || mdi_cs->style == 0x7fffffff || mdi_cs->style == 0xffffffff || mdi_cs->style == WS_MAXIMIZE,
1829  "mdi_cs->style does not match (%08x)\n", mdi_cs->style);
1830  ok(mdi_cs->x == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->x);
1831  ok(mdi_cs->y == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->y);
1832  ok(mdi_cs->cx == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->cx);
1833  ok(mdi_cs->cy == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->cy);
1834 
1835  /* CREATESTRUCT should have fixed values */
1836  ok(cs->x != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->x);
1837  ok(cs->y != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->y);
1838 
1839  /* cx/cy == CW_USEDEFAULT are translated to NOT zero values */
1840  ok(cs->cx != CW_USEDEFAULT && cs->cx != 0, "%d == CW_USEDEFAULT\n", cs->cx);
1841  ok(cs->cy != CW_USEDEFAULT && cs->cy != 0, "%d == CW_USEDEFAULT\n", cs->cy);
1842 
1843  ok(!(cs->style & WS_POPUP), "WS_POPUP is not allowed\n");
1844 
1845  if (GetWindowLongA(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
1846  {
1847  LONG style = mdi_cs->style | WS_CHILD | WS_CLIPSIBLINGS;
1848  ok(cs->style == style,
1849  "cs->style does not match (%08x)\n", cs->style);
1850  }
1851  else
1852  {
1853  LONG style = mdi_cs->style;
1854  style &= ~WS_POPUP;
1857  ok(cs->style == style,
1858  "cs->style does not match (%08x)\n", cs->style);
1859  }
1860  break;
1861  }
1862 
1863  case WM_GETMINMAXINFO:
1864  {
1866  RECT rc;
1867  MINMAXINFO *minmax = (MINMAXINFO *)lparam;
1868  MINMAXINFO my_minmax;
1869  LONG style, exstyle;
1870 
1872  exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
1873 
1874  GetClientRect(client, &rc);
1875 
1876  GetClientRect(client, &rc);
1877  if ((style & WS_CAPTION) == WS_CAPTION)
1878  style &= ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
1879  AdjustWindowRectEx(&rc, style, 0, exstyle);
1880  trace("MDI child: calculated max window size = (%d x %d)\n", rc.right-rc.left, rc.bottom-rc.top);
1881  dump_minmax_info( minmax );
1882 
1883  ok(minmax->ptMaxSize.x == rc.right - rc.left, "default width of maximized child %d != %d\n",
1884  minmax->ptMaxSize.x, rc.right - rc.left);
1885  ok(minmax->ptMaxSize.y == rc.bottom - rc.top, "default height of maximized child %d != %d\n",
1886  minmax->ptMaxSize.y, rc.bottom - rc.top);
1887 
1889 
1890  trace("DefMDIChildProc returned:\n");
1891  dump_minmax_info( minmax );
1892 
1893  MDI_ChildGetMinMaxInfo(client, hwnd, &my_minmax);
1894  ok(minmax->ptMaxSize.x == my_minmax.ptMaxSize.x, "default width of maximized child %d != %d\n",
1895  minmax->ptMaxSize.x, my_minmax.ptMaxSize.x);
1896  ok(minmax->ptMaxSize.y == my_minmax.ptMaxSize.y, "default height of maximized child %d != %d\n",
1897  minmax->ptMaxSize.y, my_minmax.ptMaxSize.y);
1898 
1899  return 1;
1900  }
1901 
1902  case WM_MDIACTIVATE:
1903  {
1904  HWND active, client = GetParent(hwnd);
1905  /*trace("%p WM_MDIACTIVATE %08x %08lx\n", hwnd, wparam, lparam);*/
1906  active = (HWND)SendMessageA(client, WM_MDIGETACTIVE, 0, 0);
1907  if (hwnd == (HWND)lparam) /* if we are being activated */
1908  ok (active == (HWND)lparam, "new active %p != active %p\n", (HWND)lparam, active);
1909  else
1910  ok (active == (HWND)wparam, "old active %p != active %p\n", (HWND)wparam, active);
1911  break;
1912  }
1913  }
1914  return DefMDIChildProcA(hwnd, msg, wparam, lparam);
1915 }
1916 
1918 {
1919  switch (msg)
1920  {
1921  case WM_NCCREATE:
1922  case WM_CREATE:
1923  {
1925 
1926  trace("%s: x %d, y %d, cx %d, cy %d\n", (msg == WM_NCCREATE) ? "WM_NCCREATE" : "WM_CREATE",
1927  cs->x, cs->y, cs->cx, cs->cy);
1928 
1929  ok(!(cs->dwExStyle & WS_EX_MDICHILD), "WS_EX_MDICHILD should not be set\n");
1930  ok(cs->lpCreateParams == mdi_lParam_test_message, "wrong cs->lpCreateParams\n");
1931 
1932  ok(!lstrcmpA(cs->lpszClass, "MDI_child_Class_2"), "wrong class name\n");
1933  ok(!lstrcmpA(cs->lpszName, "MDI child"), "wrong title\n");
1934 
1935  /* CREATESTRUCT should have fixed values */
1936  /* For some reason Win9x doesn't translate cs->x from CW_USEDEFAULT,
1937  while NT does. */
1938  /*ok(cs->x != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->x);*/
1939  ok(cs->y != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->y);
1940 
1941  /* cx/cy == CW_USEDEFAULT are translated to 0 */
1942  /* For some reason Win98 doesn't translate cs->cx from CW_USEDEFAULT,
1943  while Win95, Win2k, WinXP do. */
1944  /*ok(cs->cx == 0, "%d != 0\n", cs->cx);*/
1945  ok(cs->cy == 0, "%d != 0\n", cs->cy);
1946  break;
1947  }
1948 
1949  case WM_GETMINMAXINFO:
1950  {
1952  RECT rc;
1953  MINMAXINFO *minmax = (MINMAXINFO *)lparam;
1954  LONG style, exstyle;
1955 
1957  exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
1958 
1959  GetClientRect(parent, &rc);
1960  trace("WM_GETMINMAXINFO: parent %p client size = (%d x %d)\n", parent, rc.right, rc.bottom);
1961 
1962  GetClientRect(parent, &rc);
1963  if ((style & WS_CAPTION) == WS_CAPTION)
1964  style &= ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
1965  AdjustWindowRectEx(&rc, style, 0, exstyle);
1966  dump_minmax_info( minmax );
1967 
1968  ok(minmax->ptMaxSize.x == rc.right - rc.left, "default width of maximized child %d != %d\n",
1969  minmax->ptMaxSize.x, rc.right - rc.left);
1970  ok(minmax->ptMaxSize.y == rc.bottom - rc.top, "default height of maximized child %d != %d\n",
1971  minmax->ptMaxSize.y, rc.bottom - rc.top);
1972  break;
1973  }
1974 
1975  case WM_WINDOWPOSCHANGED:
1976  {
1977  WINDOWPOS *winpos = (WINDOWPOS *)lparam;
1978  RECT rc1, rc2;
1979 
1980  GetWindowRect(hwnd, &rc1);
1981  SetRect(&rc2, winpos->x, winpos->y, winpos->x + winpos->cx, winpos->y + winpos->cy);
1982  /* note: winpos coordinates are relative to parent */
1984  ok(EqualRect(&rc1, &rc2), "rects do not match, window=%s pos=%s\n",
1986  GetWindowRect(hwnd, &rc1);
1987  GetClientRect(hwnd, &rc2);
1989  MapWindowPoints(0, hwnd, (LPPOINT)&rc1, 2);
1990  ok(EqualRect(&rc1, &rc2), "rects do not match, window=%s client=%s\n",
1992  }
1993  /* fall through */
1994  case WM_WINDOWPOSCHANGING:
1995  {
1996  WINDOWPOS *winpos = (WINDOWPOS *)lparam;
1997  WINDOWPOS my_winpos = *winpos;
1998 
1999  trace("%s: %p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
2000  (msg == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED",
2001  winpos->hwnd, winpos->hwndInsertAfter,
2002  winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
2003 
2005 
2006  ok(!memcmp(&my_winpos, winpos, sizeof(WINDOWPOS)),
2007  "DefWindowProc should not change WINDOWPOS: %p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
2008  winpos->hwnd, winpos->hwndInsertAfter,
2009  winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
2010 
2011  return 1;
2012  }
2013  }
2014  return DefWindowProcA(hwnd, msg, wparam, lparam);
2015 }
2016 
2018 {
2019  static HWND mdi_client;
2020 
2021  switch (msg)
2022  {
2023  case WM_CREATE:
2024  return 1;
2025 
2026  case WM_WINDOWPOSCHANGED:
2027  {
2028  WINDOWPOS *winpos = (WINDOWPOS *)lparam;
2029  RECT rc1, rc2;
2030 
2031  GetWindowRect(hwnd, &rc1);
2032  trace("window: %s\n", wine_dbgstr_rect(&rc1));
2033  SetRect(&rc2, winpos->x, winpos->y, winpos->x + winpos->cx, winpos->y + winpos->cy);
2034  /* note: winpos coordinates are relative to parent */
2036  trace("pos: %s\n", wine_dbgstr_rect(&rc2));
2037  ok(EqualRect(&rc1, &rc2), "rects do not match\n");
2038 
2039  GetWindowRect(hwnd, &rc1);
2040  GetClientRect(hwnd, &rc2);
2042  MapWindowPoints(0, hwnd, (LPPOINT)&rc1, 2);
2043  ok(EqualRect(&rc1, &rc2), "rects do not match\n");
2044  }
2045  /* fall through */
2046  case WM_WINDOWPOSCHANGING:
2047  {
2048  WINDOWPOS *winpos = (WINDOWPOS *)lparam;
2049  WINDOWPOS my_winpos = *winpos;
2050 
2051  trace("%s\n", (msg == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
2052  trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
2053  winpos->hwnd, winpos->hwndInsertAfter,
2054  winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
2055 
2057 
2058  trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
2059  winpos->hwnd, winpos->hwndInsertAfter,
2060  winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
2061 
2062  ok(!memcmp(&my_winpos, winpos, sizeof(WINDOWPOS)),
2063  "DefWindowProc should not change WINDOWPOS values\n");
2064 
2065  return 1;
2066  }
2067 
2068  case WM_CLOSE:
2069  PostQuitMessage(0);
2070  break;
2071  }
2073 }
2074 
2076 {
2077  WNDCLASSA cls;
2078 
2079  cls.style = 0;
2081  cls.cbClsExtra = 0;
2082  cls.cbWndExtra = 0;
2083  cls.hInstance = GetModuleHandleA(0);
2084  cls.hIcon = 0;
2085  cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
2087  cls.lpszMenuName = NULL;
2088  cls.lpszClassName = "MDI_parent_Class";
2089  if(!RegisterClassA(&cls)) return FALSE;
2090 
2092  cls.lpszClassName = "MDI_child_Class_1";
2093  if(!RegisterClassA(&cls)) return FALSE;
2094 
2096  cls.lpszClassName = "MDI_child_Class_2";
2097  if(!RegisterClassA(&cls)) return FALSE;
2098 
2099  return TRUE;
2100 }
2101 
2102 static void test_mdi(void)
2103 {
2104  static const DWORD style[] = { 0, WS_HSCROLL, WS_VSCROLL, WS_HSCROLL | WS_VSCROLL };
2105  HWND mdi_hwndMain, mdi_client, mdi_child;
2106  CLIENTCREATESTRUCT client_cs;
2107  RECT rc;
2108  DWORD i;
2109  MSG msg;
2110  HMENU frame_menu, child_menu;
2111 
2112  if (!mdi_RegisterWindowClasses()) assert(0);
2113 
2114  mdi_hwndMain = CreateWindowExA(0, "MDI_parent_Class", "MDI parent window",
2116  WS_MAXIMIZEBOX /*| WS_VISIBLE*/,
2117  100, 100, CW_USEDEFAULT, CW_USEDEFAULT,
2118  GetDesktopWindow(), 0,
2120  assert(mdi_hwndMain);
2121 
2122  frame_menu = CreateMenu();
2123 
2124  GetClientRect(mdi_hwndMain, &rc);
2125 
2126  client_cs.hWindowMenu = 0;
2127  client_cs.idFirstChild = 1;
2128 
2129  for (i = 0; i < sizeof(style)/sizeof(style[0]); i++)
2130  {
2131  SCROLLINFO si;
2132  BOOL ret, gotit;
2133 
2134  mdi_client = CreateWindowExA(0, "mdiclient", NULL,
2135  WS_CHILD | style[i],
2136  0, 0, rc.right, rc.bottom,
2137  mdi_hwndMain, 0, 0, &client_cs);
2138  ok(mdi_client != 0, "MDI client creation failed\n");
2139 
2140  mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
2141  0,
2144  mdi_client, 0, 0,
2146  ok(mdi_child != 0, "MDI child creation failed\n");
2147 
2148  SendMessageW(mdi_child, WM_SIZE, SIZE_MAXIMIZED, 0);
2149  SetMenu(mdi_hwndMain, frame_menu);
2150 
2151  ok(GetMenuItemCount(frame_menu) == 0, "Frame menu should be empty after child maximize, but has %u\n",
2152  GetMenuItemCount(frame_menu));
2153 
2154  child_menu = CreateMenu();
2155  SendMessageW(mdi_client, WM_MDISETMENU, 0, (LPARAM)child_menu);
2156 
2157  ok(GetMenuItemCount(frame_menu) == 0, "Frame menu should be empty after WM_MDISETMENU, but has %u\n",
2158  GetMenuItemCount(frame_menu));
2159 
2160  SendMessageW(mdi_child, WM_SIZE, SIZE_RESTORED, 0);
2161 
2162  ok(GetMenuItemCount(frame_menu) == 0, "Frame menu should be empty after child restored, but has %u items\n",
2163  GetMenuItemCount(frame_menu));
2164 
2165  SetMenu(mdi_hwndMain, NULL);
2166 
2167  si.cbSize = sizeof(si);
2168  si.fMask = SIF_ALL;
2170  if (style[i] & (WS_HSCROLL | WS_VSCROLL))
2171  {
2172  ok(ret, "style %#x: GetScrollInfo(SB_HORZ) failed\n", style[i]);
2173  ok(si.nPage == 0, "expected 0\n");
2174  ok(si.nPos == 0, "expected 0\n");
2175  ok(si.nTrackPos == 0, "expected 0\n");
2176  ok(si.nMin == 0, "expected 0\n");
2177  ok(si.nMax == 100, "expected 100\n");
2178  }
2179  else
2180  ok(!ret, "style %#x: GetScrollInfo(SB_HORZ) should fail\n", style[i]);
2181 
2183  if (style[i] & (WS_HSCROLL | WS_VSCROLL))
2184  {
2185  ok(ret, "style %#x: GetScrollInfo(SB_VERT) failed\n", style[i]);
2186  ok(si.nPage == 0, "expected 0\n");
2187  ok(si.nPos == 0, "expected 0\n");
2188  ok(si.nTrackPos == 0, "expected 0\n");
2189  ok(si.nMin == 0, "expected 0\n");
2190  ok(si.nMax == 100, "expected 100\n");
2191  }
2192  else
2193  ok(!ret, "style %#x: GetScrollInfo(SB_VERT) should fail\n", style[i]);
2194 
2195  SetWindowPos(mdi_child, 0, -100, -100, 0, 0, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE);
2196 
2197  si.cbSize = sizeof(si);
2198  si.fMask = SIF_ALL;
2200  if (style[i] & (WS_HSCROLL | WS_VSCROLL))
2201  {
2202  ok(ret, "style %#x: GetScrollInfo(SB_HORZ) failed\n", style[i]);
2203  ok(si.nPage == 0, "expected 0\n");
2204  ok(si.nPos == 0, "expected 0\n");
2205  ok(si.nTrackPos == 0, "expected 0\n");
2206  ok(si.nMin == 0, "expected 0\n");
2207  ok(si.nMax == 100, "expected 100\n");
2208  }
2209  else
2210  ok(!ret, "style %#x: GetScrollInfo(SB_HORZ) should fail\n", style[i]);
2211 
2213  if (style[i] & (WS_HSCROLL | WS_VSCROLL))
2214  {
2215  ok(ret, "style %#x: GetScrollInfo(SB_VERT) failed\n", style[i]);
2216  ok(si.nPage == 0, "expected 0\n");
2217  ok(si.nPos == 0, "expected 0\n");
2218  ok(si.nTrackPos == 0, "expected 0\n");
2219  ok(si.nMin == 0, "expected 0\n");
2220  ok(si.nMax == 100, "expected 100\n");
2221  }
2222  else
2223  ok(!ret, "style %#x: GetScrollInfo(SB_VERT) should fail\n", style[i]);
2224 
2225  gotit = FALSE;
2226  while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
2227  {
2228  if (msg.message == WM_MOUSEMOVE || msg.message == WM_PAINT)
2229  {
2231  continue;
2232  }
2233 
2234  if (msg.message == 0x003f) /* WM_MDICALCCHILDSCROLL ??? */
2235  {
2236  ok(msg.hwnd == mdi_client, "message 0x003f should be posted to mdiclient\n");
2237  gotit = TRUE;
2238  }
2239  else
2240  ok(msg.hwnd != mdi_client, "message %04x should not be posted to mdiclient\n", msg.message);
2242  }
2243  ok(gotit, "message 0x003f should appear after SetWindowPos\n");
2244 
2245  si.cbSize = sizeof(si);
2246  si.fMask = SIF_ALL;
2248  if (style[i] & (WS_HSCROLL | WS_VSCROLL))
2249  {
2250  ok(ret, "style %#x: GetScrollInfo(SB_HORZ) failed\n", style[i]);
2251 todo_wine
2252  ok(si.nPage != 0, "expected !0\n");
2253  ok(si.nPos == 0, "expected 0\n");
2254  ok(si.nTrackPos == 0, "expected 0\n");
2255  ok(si.nMin != 0, "expected !0\n");
2256  ok(si.nMax != 100, "expected !100\n");
2257  }
2258  else
2259  ok(!ret, "style %#x: GetScrollInfo(SB_HORZ) should fail\n", style[i]);
2260 
2262  if (style[i] & (WS_HSCROLL | WS_VSCROLL))
2263  {
2264  ok(ret, "style %#x: GetScrollInfo(SB_VERT) failed\n", style[i]);
2265 todo_wine
2266  ok(si.nPage != 0, "expected !0\n");
2267  ok(si.nPos == 0, "expected 0\n");
2268  ok(si.nTrackPos == 0, "expected 0\n");
2269  ok(si.nMin != 0, "expected !0\n");
2270  ok(si.nMax != 100, "expected !100\n");
2271  }
2272  else
2273  ok(!ret, "style %#x: GetScrollInfo(SB_VERT) should fail\n", style[i]);
2274 
2275  DestroyMenu(child_menu);
2276  DestroyWindow(mdi_child);
2278  }
2279 
2280  SetMenu(mdi_hwndMain, frame_menu);
2281 
2282  mdi_client = CreateWindowExA(0, "mdiclient", NULL,
2283  WS_CHILD,
2284  0, 0, rc.right, rc.bottom,
2285  mdi_hwndMain, 0, 0, &client_cs);
2286  ok(mdi_client != 0, "MDI client creation failed\n");
2287 
2288  mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
2289  0,
2292  mdi_client, 0, 0,
2294  ok(mdi_child != 0, "MDI child creation failed\n");
2295 
2296  SendMessageW(mdi_child, WM_SIZE, SIZE_MAXIMIZED, 0);
2297  ok(GetMenuItemCount(frame_menu) == 4, "Frame menu should have 4 items after child maximize, but has %u\n",
2298  GetMenuItemCount(frame_menu));
2299 
2300  child_menu = CreateMenu();
2301  SendMessageW(mdi_client, WM_MDISETMENU, 0, (LPARAM)child_menu);
2302 
2303  ok(GetMenuItemCount(frame_menu) == 4, "Frame menu should have 4 items after WM_MDISETMENU, but has %u\n",
2304  GetMenuItemCount(frame_menu));
2305 
2306  SendMessageW(mdi_child, WM_SIZE, SIZE_RESTORED, 0);
2307 
2308  ok(GetMenuItemCount(frame_menu) == 0, "Frame menu should be empty after child restored, but has %u items\n",
2309  GetMenuItemCount(frame_menu));
2310 
2311  DestroyMenu(child_menu);
2312  DestroyWindow(mdi_child);
2314 
2315  /* MDIClient without MDIS_ALLCHILDSTYLES */
2316  mdi_client = CreateWindowExA(0, "mdiclient",
2317  NULL,
2318  WS_CHILD /*| WS_VISIBLE*/,
2319  /* tests depend on a not zero MDIClient size */
2320  0, 0, rc.right, rc.bottom,
2321  mdi_hwndMain, 0, GetModuleHandleA(NULL),
2322  &client_cs);
2323  assert(mdi_client);
2324  test_MDI_create(mdi_hwndMain, mdi_client, client_cs.idFirstChild);
2326 
2327  /* MDIClient with MDIS_ALLCHILDSTYLES */
2328  mdi_client = CreateWindowExA(0, "mdiclient",
2329  NULL,
2330  WS_CHILD | MDIS_ALLCHILDSTYLES /*| WS_VISIBLE*/,
2331  /* tests depend on a not zero MDIClient size */
2332  0, 0, rc.right, rc.bottom,
2333  mdi_hwndMain, 0, GetModuleHandleA(NULL),
2334  &client_cs);
2335  assert(mdi_client);
2336  test_MDI_create(mdi_hwndMain, mdi_client, client_cs.idFirstChild);
2338 
2339  /* Test child window stack management */
2340  mdi_client = CreateWindowExA(0, "mdiclient",
2341  NULL,
2342  WS_CHILD,
2343  0, 0, rc.right, rc.bottom,
2344  mdi_hwndMain, 0, GetModuleHandleA(NULL),
2345  &client_cs);
2346  assert(mdi_client);
2349 /*
2350  while(GetMessage(&msg, 0, 0, 0))
2351  {
2352  TranslateMessage(&msg);
2353  DispatchMessage(&msg);
2354  }
2355 */
2356  DestroyWindow(mdi_hwndMain);
2357 }
2358 
2359 static void test_icons(void)
2360 {
2361  WNDCLASSEXA cls;
2362  HWND hwnd;
2363  HICON icon = LoadIconA(0, (LPCSTR)IDI_APPLICATION);
2364  HICON icon2 = LoadIconA(0, (LPCSTR)IDI_QUESTION);
2365  HICON small_icon = LoadImageA(0, (LPCSTR)IDI_APPLICATION, IMAGE_ICON,
2367  HICON res;
2368 
2369  cls.cbSize = sizeof(cls);
2370  cls.style = 0;
2372  cls.cbClsExtra = 0;
2373  cls.cbWndExtra = 0;
2374  cls.hInstance = 0;
2375  cls.hIcon = LoadIconA(0, (LPCSTR)IDI_HAND);
2376  cls.hIconSm = small_icon;
2377  cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
2379  cls.lpszMenuName = NULL;
2380  cls.lpszClassName = "IconWindowClass";
2381 
2382  RegisterClassExA(&cls);
2383 
2384  hwnd = CreateWindowExA(0, "IconWindowClass", "icon test", 0,
2385  100, 100, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, NULL, NULL);
2386  assert( hwnd );
2387 
2388  res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
2389  ok( res == 0, "wrong big icon %p/0\n", res );
2390  res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_BIG, (LPARAM)icon );
2391  ok( res == 0, "wrong previous big icon %p/0\n", res );
2392  res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
2393  ok( res == icon, "wrong big icon after set %p/%p\n", res, icon );
2394  res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_BIG, (LPARAM)icon2 );
2395  ok( res == icon, "wrong previous big icon %p/%p\n", res, icon );
2396  res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
2397  ok( res == icon2, "wrong big icon after set %p/%p\n", res, icon2 );
2398 
2399  res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 );
2400  ok( res == 0, "wrong small icon %p/0\n", res );
2401  res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
2402  ok( (res && res != small_icon && res != icon2) || broken(!res), "wrong small2 icon %p\n", res );
2403  res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_SMALL, (LPARAM)icon );
2404  ok( res == 0, "wrong previous small icon %p/0\n", res );
2405  res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 );
2406  ok( res == icon, "wrong small icon after set %p/%p\n", res, icon );
2407  res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
2408  ok( res == icon || broken(!res), "wrong small2 icon after set %p/%p\n", res, icon );
2409  res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_SMALL, (LPARAM)small_icon );
2410  ok( res == icon, "wrong previous small icon %p/%p\n", res, icon );
2411  res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 );
2412  ok( res == small_icon, "wrong small icon after set %p/%p\n", res, small_icon );
2413  res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
2414  ok( res == small_icon || broken(!res), "wrong small2 icon after set %p/%p\n", res, small_icon );
2415 
2416  /* make sure the big icon hasn't changed */
2417  res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
2418  ok( res == icon2, "wrong big icon after set %p/%p\n", res, icon2 );
2419 
2420  DestroyWindow( hwnd );
2421 }
2422 
2424 {
2425  if (msg == WM_NCCALCSIZE)
2426  {
2427  RECT *rect = (RECT *)lparam;
2428  /* first time around increase the rectangle, next time decrease it */
2429  if (rect->left == 100) InflateRect( rect, 10, 10 );
2430  else InflateRect( rect, -10, -10 );
2431  return 0;
2432  }
2433  return DefWindowProcA( hwnd, msg, wparam, lparam );
2434 }
2435 
2436 static void test_SetWindowPos(HWND hwnd, HWND hwnd2)
2437 {
2438  RECT orig_win_rc, rect;
2440  HWND hwnd_grandchild, hwnd_child, hwnd_child2;
2441  HWND hwnd_desktop;
2442  RECT rc1, rc2;
2443  BOOL ret;
2444 
2445  SetRect(&rect, 111, 222, 333, 444);
2446  ok(!GetWindowRect(0, &rect), "GetWindowRect succeeded\n");
2447  ok(rect.left == 111 && rect.top == 222 && rect.right == 333 && rect.bottom == 444,
2448  "wrong window rect %s\n", wine_dbgstr_rect(&rect));
2449 
2450  SetRect(&rect, 111, 222, 333, 444);
2451  ok(!GetClientRect(0, &rect), "GetClientRect succeeded\n");
2452  ok(rect.left == 111 && rect.top == 222 && rect.right == 333 && rect.bottom == 444,
2453  "wrong window rect %s\n", wine_dbgstr_rect(&rect));
2454 
2455  GetWindowRect(hwnd, &orig_win_rc);
2456 
2458  ret = SetWindowPos(hwnd, 0, 100, 100, 0, 0, SWP_NOZORDER|SWP_FRAMECHANGED);
2459  ok(ret, "Got %d\n", ret);
2460  GetWindowRect( hwnd, &rect );
2461  ok( rect.left == 100 && rect.top == 100 && rect.right == 100 && rect.bottom == 100,
2462  "invalid window rect %s\n", wine_dbgstr_rect(&rect));
2463  GetClientRect( hwnd, &rect );
2464  MapWindowPoints( hwnd, 0, (POINT *)&rect, 2 );
2465  ok( rect.left == 90 && rect.top == 90 && rect.right == 110 && rect.bottom == 110,
2466  "invalid client rect %s\n", wine_dbgstr_rect(&rect));
2467 
2468  ret = SetWindowPos(hwnd, 0, 200, 200, 0, 0, SWP_NOZORDER|SWP_FRAMECHANGED);
2469  ok(ret, "Got %d\n", ret);
2470  GetWindowRect( hwnd, &rect );
2471  ok( rect.left == 200 && rect.top == 200 && rect.right == 200 && rect.bottom == 200,
2472  "invalid window rect %s\n", wine_dbgstr_rect(&rect));
2473  GetClientRect( hwnd, &rect );
2474  MapWindowPoints( hwnd, 0, (POINT *)&rect, 2 );
2475  ok( rect.left == 210 && rect.top == 210 && rect.right == 190 && rect.bottom == 190,
2476  "invalid client rect %s\n", wine_dbgstr_rect(&rect));
2477 
2478  ret = SetWindowPos(hwnd, 0, orig_win_rc.left, orig_win_rc.top,
2479  orig_win_rc.right, orig_win_rc.bottom, 0);
2480  ok(ret, "Got %d\n", ret);
2482 
2483  /* Win9x truncates coordinates to 16-bit irrespectively */
2484  if (!is_win9x)
2485  {
2486  ret = SetWindowPos(hwnd, 0, -32769, -40000, -32769, -90000, SWP_NOMOVE);
2487  ok(ret, "Got %d\n", ret);
2488  ret = SetWindowPos(hwnd, 0, 32768, 40000, 32768, 40000, SWP_NOMOVE);
2489  ok(ret, "Got %d\n", ret);
2490 
2491  ret = SetWindowPos(hwnd, 0, -32769, -40000, -32769, -90000, SWP_NOSIZE);
2492  ok(ret, "Got %d\n", ret);
2493  ret = SetWindowPos(hwnd, 0, 32768, 40000, 32768, 40000, SWP_NOSIZE);
2494  ok(ret, "Got %d\n", ret);
2495  }
2496 
2497  ret = SetWindowPos(hwnd, 0, orig_win_rc.left, orig_win_rc.top,
2498  orig_win_rc.right, orig_win_rc.bottom, 0);
2499  ok(ret, "Got %d\n", ret);
2500 
2501  ok(!(GetWindowLongA(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST), "WS_EX_TOPMOST should not be set\n");
2503  ok(ret, "Got %d\n", ret);
2504  ok(GetWindowLongA(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST, "WS_EX_TOPMOST should be set\n");
2506  ok(ret, "Got %d\n", ret);
2507  ok(GetWindowLongA(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST, "WS_EX_TOPMOST should be set\n");
2509  ok(ret, "Got %d\n", ret);
2510  ok(!(GetWindowLongA(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST), "WS_EX_TOPMOST should not be set\n");
2511 
2512  hwnd_desktop = GetDesktopWindow();
2513  ok(!!hwnd_desktop, "Failed to get hwnd_desktop window (%d).\n", GetLastError());
2514  hwnd_child = create_tool_window(WS_VISIBLE|WS_CHILD, hwnd);
2515  ok(!!hwnd_child, "Failed to create child window (%d)\n", GetLastError());
2516  hwnd_grandchild = create_tool_window(WS_VISIBLE|WS_CHILD, hwnd_child);
2517  ok(!!hwnd_child, "Failed to create child window (%d)\n", GetLastError());
2518  hwnd_child2 = create_tool_window(WS_VISIBLE|WS_CHILD, hwnd);
2519  ok(!!hwnd_child2, "Failed to create second child window (%d)\n", GetLastError());
2520 
2521  ret = SetWindowPos(hwnd, hwnd2, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2522  ok(ret, "Got %d\n", ret);
2524 
2525  ret = SetWindowPos(hwnd2, hwnd, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2526  ok(ret, "Got %d\n", ret);
2527  check_active_state(hwnd2, hwnd2, hwnd2);
2528 
2529  /* Returns TRUE also for windows that are not siblings */
2530  ret = SetWindowPos(hwnd_child, hwnd2, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2531  ok(ret, "Got %d\n", ret);
2532  check_active_state(hwnd2, hwnd2, hwnd2);
2533 
2534  ret = SetWindowPos(hwnd2, hwnd_child, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2535  ok(ret, "Got %d\n", ret);
2536  check_active_state(hwnd2, hwnd2, hwnd2);
2537 
2538  /* Does not seem to do anything even without passing flags, still returns TRUE */
2539  GetWindowRect(hwnd_child, &rc1);
2540  ret = SetWindowPos(hwnd_child, hwnd2 , 1, 2, 3, 4, 0);
2541  ok(ret, "Got %d\n", ret);
2542  GetWindowRect(hwnd_child, &rc2);
2543  ok(EqualRect(&rc1, &rc2), "%s != %s\n", wine_dbgstr_rect(&rc1), wine_dbgstr_rect(&rc2));
2544  check_active_state(hwnd2, hwnd2, hwnd2);
2545 
2546  /* Same thing the other way around. */
2547  GetWindowRect(hwnd2, &rc1);
2548  ret = SetWindowPos(hwnd2, hwnd_child, 1, 2, 3, 4, 0);
2549  ok(ret, "Got %d\n", ret);
2550  GetWindowRect(hwnd2, &rc2);
2551  ok(EqualRect(&rc1, &rc2), "%s != %s\n", wine_dbgstr_rect(&rc1), wine_dbgstr_rect(&rc2));
2552  check_active_state(hwnd2, hwnd2, hwnd2);
2553 
2554  /* .. and with these windows. */
2555  GetWindowRect(hwnd_grandchild, &rc1);
2556  ret = SetWindowPos(hwnd_grandchild, hwnd_child2, 1, 2, 3, 4, 0);
2557  ok(ret, "Got %d\n", ret);
2558  GetWindowRect(hwnd_grandchild, &rc2);
2559  ok(EqualRect(&rc1, &rc2), "%s != %s\n", wine_dbgstr_rect(&rc1), wine_dbgstr_rect(&rc2));
2560  check_active_state(hwnd2, hwnd2, hwnd2);
2561 
2562  /* Add SWP_NOZORDER and it will be properly resized. */
2563  GetWindowRect(hwnd_grandchild, &rc1);
2564  ret = SetWindowPos(hwnd_grandchild, hwnd_child2, 1, 2, 3, 4, SWP_NOZORDER);
2565  ok(ret, "Got %d\n", ret);
2566  GetWindowRect(hwnd_grandchild, &rc2);
2567  ok((rc1.left+1) == rc2.left && (rc1.top+2) == rc2.top &&
2568  (rc1.left+4) == rc2.right && (rc1.top+6) == rc2.bottom,
2569  "(%d,%d)-(%d,%d) != %s\n", rc1.left+1, rc1.top+2, rc1.left+4, rc1.top+6,
2570  wine_dbgstr_rect(&rc2));
2571  check_active_state(hwnd2, hwnd2, hwnd2);
2572 
2573  /* Given a sibling window, the window is properly resized. */
2574  GetWindowRect(hwnd_child, &rc1);
2575  ret = SetWindowPos(hwnd_child, hwnd_child2, 1, 2, 3, 4, 0);
2576  ok(ret, "Got %d\n", ret);
2577  GetWindowRect(hwnd_child, &rc2);
2578  ok((rc1.left+1) == rc2.left && (rc1.top+2) == rc2.top &&
2579  (rc1.left+4) == rc2.right && (rc1.top+6) == rc2.bottom,
2580  "(%d,%d)-(%d,%d) != %s\n", rc1.left+1, rc1.top+2, rc1.left+4, rc1.top+6,
2581  wine_dbgstr_rect(&rc2));
2582  check_active_state(hwnd2, hwnd2, hwnd2);
2583 
2584  /* Involving the desktop window changes things. */
2585  ret = SetWindowPos(hwnd_child, hwnd_desktop, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2586  ok(!ret, "Got %d\n", ret);
2587  check_active_state(hwnd2, hwnd2, hwnd2);
2588 
2589  GetWindowRect(hwnd_child, &rc1);
2590  ret = SetWindowPos(hwnd_child, hwnd_desktop, 0, 0, 0, 0, 0);
2591  ok(!ret, "Got %d\n", ret);
2592  GetWindowRect(hwnd_child, &rc2);
2593  ok(EqualRect(&rc1, &rc2), "%s != %s\n", wine_dbgstr_rect(&rc1), wine_dbgstr_rect(&rc2));
2594  check_active_state(hwnd2, hwnd2, hwnd2);
2595 
2596  ret = SetWindowPos(hwnd_desktop, hwnd_child, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2597  ok(!ret, "Got %d\n", ret);
2598  check_active_state(hwnd2, hwnd2, hwnd2);
2599 
2600  ret = SetWindowPos(hwnd_desktop, hwnd, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2601  ok(!ret, "Got %d\n", ret);
2602  check_active_state(hwnd2, hwnd2, hwnd2);
2603 
2604  ret = SetWindowPos(hwnd, hwnd_desktop, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2605  ok(!ret, "Got %d\n", ret);
2606  check_active_state(hwnd2, hwnd2, hwnd2);
2607 
2608  DestroyWindow(hwnd_grandchild);
2609  DestroyWindow(hwnd_child);
2610  DestroyWindow(hwnd_child2);
2611 
2612  hwnd_child = create_tool_window(WS_CHILD|WS_POPUP|WS_SYSMENU, hwnd2);
2613  ok(!!hwnd_child, "Failed to create child window (%d)\n", GetLastError());
2615  ok(ret, "Got %d\n", ret);
2616  flush_events( TRUE );
2617  todo_wine check_active_state(hwnd2, hwnd2, hwnd2);
2618  DestroyWindow(hwnd_child);
2619 }
2620 
2622 {
2623  HWND child;
2624  HMENU hMenu, ret;
2625  BOOL retok;
2626  DWORD style;
2627 
2628  hMenu = CreateMenu();
2629  assert(hMenu);
2630 
2631  ok(SetMenu(parent, hMenu), "SetMenu on a top level window should not fail\n");
2632  if (0)
2633  {
2634  /* fails on (at least) Wine, NT4, XP SP2 */
2636  }
2637  ret = GetMenu(parent);
2638  ok(ret == hMenu, "unexpected menu id %p\n", ret);
2639  /* test whether we can destroy a menu assigned to a window */
2640  retok = DestroyMenu(hMenu);
2641  ok( retok, "DestroyMenu error %d\n", GetLastError());
2642  retok = IsMenu(hMenu);
2643  ok(!retok || broken(retok) /* nt4 */, "menu handle should be not valid after DestroyMenu\n");
2644  ret = GetMenu(parent);
2645  /* This test fails on Win9x */
2646  if (!is_win9x)
2647  ok(ret == hMenu, "unexpected menu id %p\n", ret);
2648  ok(SetMenu(parent, 0), "SetMenu(0) on a top level window should not fail\n");
2650 
2651  hMenu = CreateMenu();
2652  assert(hMenu);
2653 
2654  /* parent */
2655  ret = GetMenu(parent);
2656  ok(ret == 0, "unexpected menu id %p\n", ret);
2657 
2658  ok(!SetMenu(parent, (HMENU)20), "SetMenu with invalid menu handle should fail\n");
2660  ret = GetMenu(parent);
2661  ok(ret == 0, "unexpected menu id %p\n", ret);
2662 
2663  ok(SetMenu(parent, hMenu), "SetMenu on a top level window should not fail\n");
2664  if (0)
2665  {
2666  /* fails on (at least) Wine, NT4, XP SP2 */
2668  }
2669  ret = GetMenu(parent);
2670  ok(ret == hMenu, "unexpected menu id %p\n", ret);
2671 
2672  ok(SetMenu(parent, 0), "SetMenu(0) on a top level window should not fail\n");
2674  ret = GetMenu(parent);
2675  ok(ret == 0, "unexpected menu id %p\n", ret);
2676 
2677  /* child */
2678  child = CreateWindowExA(0, "static", NULL, WS_CHILD, 0, 0, 0, 0, parent, (HMENU)10, 0, NULL);
2679  assert(child);
2680 
2681  ret = GetMenu(child);
2682  ok(ret == (HMENU)10, "unexpected menu id %p\n", ret);
2683 
2684  ok(!SetMenu(child, (HMENU)20), "SetMenu with invalid menu handle should fail\n");
2686  ret = GetMenu(child);
2687  ok(ret == (HMENU)10, "unexpected menu id %p\n", ret);
2688 
2689  ok(!SetMenu(child, hMenu), "SetMenu on a child window should fail\n");
2691  ret = GetMenu(child);
2692  ok(ret == (HMENU)10, "unexpected menu id %p\n", ret);
2693 
2694  ok(!SetMenu(child, 0), "SetMenu(0) on a child window should fail\n");
2696  ret = GetMenu(child);
2697  ok(ret == (HMENU)10, "unexpected menu id %p\n", ret);
2698 
2701  ok(SetMenu(child, hMenu), "SetMenu on a popup child window should not fail\n");
2702  ok(SetMenu(child, 0), "SetMenu on a popup child window should not fail\n");
2704 
2706  ok(!SetMenu(child, hMenu), "SetMenu on an overlapped child window should fail\n");
2708 
2710  DestroyMenu(hMenu);
2711 }
2712 
2713 static void test_window_tree(HWND parent, const DWORD *style, const int *order, int total)
2714 {
2715  HWND child[5], hwnd;
2716  INT_PTR i;
2717 
2718  assert(total <= 5);
2719 
2721  ok(!hwnd, "have to start without children to perform the test\n");
2722 
2723  for (i = 0; i < total; i++)
2724  {
2725  if (style[i] & DS_CONTROL)
2726  {
2727  child[i] = CreateWindowExA(0, (LPCSTR)MAKEINTATOM(32770), "", style[i] & ~WS_VISIBLE,
2728  0,0,0,0, parent, (HMENU)i, 0, NULL);
2729  if (style[i] & WS_VISIBLE)
2731 
2733  }
2734  else
2735  child[i] = CreateWindowExA(0, "static", "", style[i], 0,0,10,10,
2736  parent, (HMENU)i, 0, NULL);
2737  trace("child[%ld] = %p\n", i, child[i]);
2738  ok(child[i] != 0, "CreateWindowEx failed to create child window\n");
2739  }
2740 
2742  ok(hwnd != 0, "GetWindow(GW_CHILD) failed\n");
2743  ok(hwnd == GetWindow(child[total - 1], GW_HWNDFIRST), "GW_HWNDFIRST is wrong\n");
2744  ok(child[order[total - 1]] == GetWindow(child[0], GW_HWNDLAST), "GW_HWNDLAST is wrong\n");
2745 
2746  for (i = 0; i < total; i++)
2747  {
2748  trace("hwnd[%ld] = %p\n", i, hwnd);
2749  ok(child[order[i]] == hwnd, "Z order of child #%ld is wrong\n", i);
2750 
2752  }
2753 
2754  for (i = 0; i < total; i++)
2755  ok(DestroyWindow(child[i]), "DestroyWindow failed\n");
2756 }
2757 
2759 {
2760  const DWORD simple_style[5] = { WS_CHILD, WS_CHILD, WS_CHILD, WS_CHILD,
2761  WS_CHILD };
2762  const int simple_order[5] = { 0, 1, 2, 3, 4 };
2763 
2764  const DWORD complex_style[5] = { WS_CHILD, WS_CHILD | WS_MAXIMIZE,
2767  const int complex_order_1[1] = { 0 };
2768  const int complex_order_2[2] = { 1, 0 };
2769  const int complex_order_3[3] = { 1, 0, 2 };
2770  const int complex_order_4[4] = { 1, 0, 2, 3 };
2771  const int complex_order_5[5] = { 4, 1, 0, 2, 3 };
2772  const DWORD complex_style_6[3] = { WS_CHILD | WS_VISIBLE,
2774  WS_CHILD | WS_VISIBLE };
2775  const int complex_order_6[3] = { 0, 1, 2 };
2776 
2777  /* simple WS_CHILD */
2778  test_window_tree(parent, simple_style, simple_order, 5);
2779 
2780  /* complex children styles */
2781  test_window_tree(parent, complex_style, complex_order_1, 1);
2782  test_window_tree(parent, complex_style, complex_order_2, 2);
2783  test_window_tree(parent, complex_style, complex_order_3, 3);
2784  test_window_tree(parent, complex_style, complex_order_4, 4);
2785  test_window_tree(parent, complex_style, complex_order_5, 5);
2786 
2787  /* another set of complex children styles */
2788  test_window_tree(parent, complex_style_6, complex_order_6, 3);
2789 }
2790 
2791 #define check_z_order(hwnd, next, prev, owner, topmost) \
2792  check_z_order_debug((hwnd), (next), (prev), (owner), (topmost), \
2793  __FILE__, __LINE__)
2794 
2795 static void check_z_order_debug(HWND hwnd, HWND next, HWND prev, HWND owner,
2796  BOOL topmost, const char *file, int line)
2797 {
2798  HWND test;
2799  DWORD ex_style;
2800 
2802  /* skip foreign windows */
2803  while (test && test != next &&
2806  GetWindow(test, GW_OWNER) == next))
2807  {
2808  /*trace("skipping next %p (%p)\n", test, UlongToHandle(GetWindowLongPtr(test, GWLP_HINSTANCE)));*/
2810  }
2811  ok_(file, line)(next == test, "%p: expected next %p, got %p\n", hwnd, next, test);
2812 
2814  /* skip foreign windows */
2815  while (test && test != prev &&
2818  GetWindow(test, GW_OWNER) == hwnd))
2819  {
2820  /*trace("skipping prev %p (%p)\n", test, UlongToHandle(GetWindowLongPtr(test, GWLP_HINSTANCE)));*/
2822  }
2823  ok_(file, line)(prev == test, "%p: expected prev %p, got %p\n", hwnd, prev, test);
2824 
2826  ok_(file, line)(owner == test, "%p: expected owner %p, got %p\n", hwnd, owner, test);
2827 
2828  ex_style = GetWindowLongA(hwnd, GWL_EXSTYLE);
2829  ok_(file, line)(!(ex_style & WS_EX_TOPMOST) == !topmost, "%p: expected %stopmost\n",
2830  hwnd, topmost ? "" : "NOT ");
2831 }
2832 
2833 static void test_popup_zorder(HWND hwnd_D, HWND hwnd_E, DWORD style)
2834 {
2835  HWND hwnd_A, hwnd_B, hwnd_C, hwnd_F;
2836 
2837  trace("hwnd_D %p, hwnd_E %p\n", hwnd_D, hwnd_E);
2838 
2839  SetWindowPos(hwnd_E, hwnd_D, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
2840 
2841  check_z_order(hwnd_D, hwnd_E, 0, 0, FALSE);
2842  check_z_order(hwnd_E, 0, hwnd_D, 0, FALSE);
2843 
2844  hwnd_F = CreateWindowExA(0, "MainWindowClass", "Owner window",
2846  100, 100, 100, 100,
2847  0, 0, GetModuleHandleA(NULL), NULL);
2848  trace("hwnd_F %p\n", hwnd_F);
2849  check_z_order(hwnd_F, hwnd_D, 0, 0, FALSE);
2850 
2851  SetWindowPos(hwnd_F, hwnd_E, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
2852  check_z_order(hwnd_F, 0, hwnd_E, 0, FALSE);
2853  check_z_order(hwnd_E, hwnd_F, hwnd_D, 0, FALSE);
2854  check_z_order(hwnd_D, hwnd_E, 0, 0, FALSE);
2855 
2856  hwnd_C = CreateWindowExA(0, "MainWindowClass", NULL,
2857  style,
2858  100, 100, 100, 100,
2859  hwnd_F, 0, GetModuleHandleA(NULL), NULL);
2860  trace("hwnd_C %p\n", hwnd_C);
2861  check_z_order(hwnd_F, 0, hwnd_E, 0, FALSE);
2862  check_z_order(hwnd_E, hwnd_F, hwnd_D, 0, FALSE);
2863  check_z_order(hwnd_D, hwnd_E, hwnd_C, 0, FALSE);
2864  check_z_order(hwnd_C, hwnd_D, 0, hwnd_F, FALSE);
2865 
2866  hwnd_B = CreateWindowExA(WS_EX_TOPMOST, "MainWindowClass", NULL,
2867  style,
2868  100, 100, 100, 100,
2869  hwnd_F, 0, GetModuleHandleA(NULL), NULL);
2870  trace("hwnd_B %p\n", hwnd_B);
2871  check_z_order(hwnd_F, 0, hwnd_E, 0, FALSE);
2872  check_z_order(hwnd_E, hwnd_F, hwnd_D, 0, FALSE);
2873  check_z_order(hwnd_D, hwnd_E, hwnd_C, 0, FALSE);
2874  check_z_order(hwnd_C, hwnd_D, hwnd_B, hwnd_F, FALSE);
2875  check_z_order(hwnd_B, hwnd_C, 0, hwnd_F, TRUE);
2876 
2877  hwnd_A = CreateWindowExA(WS_EX_TOPMOST, "MainWindowClass", NULL,
2878  style,
2879  100, 100, 100, 100,
2880  0, 0, GetModuleHandleA(NULL), NULL);
2881  trace("hwnd_A %p\n", hwnd_A);
2882  check_z_order(hwnd_F, 0, hwnd_E, 0, FALSE);
2883  check_z_order(hwnd_E, hwnd_F, hwnd_D, 0, FALSE);
2884  check_z_order(hwnd_D, hwnd_E, hwnd_C, 0, FALSE);
2885  check_z_order(hwnd_C, hwnd_D, hwnd_B, hwnd_F, FALSE);
2886  check_z_order(hwnd_B, hwnd_C, hwnd_A, hwnd_F, TRUE);
2887  check_z_order(hwnd_A, hwnd_B, 0, 0, TRUE);
2888 
2889  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);
2890 
2891  /* move hwnd_F and its popups up */
2893  check_z_order(hwnd_E, 0, hwnd_D, 0, FALSE);
2894  check_z_order(hwnd_D, hwnd_E, hwnd_F, 0, FALSE);
2895  check_z_order(hwnd_F, hwnd_D, hwnd_C, 0, FALSE);
2896  check_z_order(hwnd_C, hwnd_F, hwnd_B, hwnd_F, FALSE);
2897  check_z_order(hwnd_B, hwnd_C, hwnd_A, hwnd_F, TRUE);
2898  check_z_order(hwnd_A, hwnd_B, 0, 0, TRUE);
2899 
2900  /* move hwnd_F and its popups down */
2901 #if 0 /* enable once Wine is fixed to pass this test */
2903  check_z_order(hwnd_F, 0, hwnd_C, 0, FALSE);
2904  check_z_order(hwnd_C, hwnd_F, hwnd_B, hwnd_F, FALSE);
2905  check_z_order(hwnd_B, hwnd_C, hwnd_E, hwnd_F, FALSE);
2906  check_z_order(hwnd_E, hwnd_B, hwnd_D, 0, FALSE);
2907  check_z_order(hwnd_D, hwnd_E, hwnd_A, 0, FALSE);
2908  check_z_order(hwnd_A, hwnd_D, 0, 0, TRUE);
2909 #endif
2910 
2911  /* make hwnd_C owned by a topmost window */
2912  DestroyWindow( hwnd_C );
2913  hwnd_C = CreateWindowExA(0, "MainWindowClass", NULL,
2914  style,
2915  100, 100, 100, 100,
2916  hwnd_A, 0, GetModuleHandleA(NULL), NULL);
2917  trace("hwnd_C %p\n", hwnd_C);
2918  check_z_order(hwnd_E, 0, hwnd_D, 0, FALSE);
2919  check_z_order(hwnd_D, hwnd_E, hwnd_F, 0, FALSE);
2920  check_z_order(hwnd_F, hwnd_D, hwnd_B, 0, FALSE);
2921  check_z_order(hwnd_B, hwnd_F, hwnd_A, hwnd_F, TRUE);
2922  check_z_order(hwnd_A, hwnd_B, hwnd_C, 0, TRUE);
2923  check_z_order(hwnd_C, hwnd_A, 0, hwnd_A, TRUE);
2924 
2925  DestroyWindow(hwnd_A);
2926  DestroyWindow(hwnd_B);
2927  DestroyWindow(hwnd_C);
2928  DestroyWindow(hwnd_F);
2929 }
2930 
2931 static void test_vis_rgn( HWND hwnd )
2932 {
2933  RECT win_rect, rgn_rect;
2934  HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
2935  HDC hdc;
2936 
2938  hdc = GetDC( hwnd );
2939  ok( GetRandomRgn( hdc, hrgn, SYSRGN ) != 0, "GetRandomRgn failed\n" );
2940  GetWindowRect( hwnd, &win_rect );
2941  GetRgnBox( hrgn, &rgn_rect );
2942  if (is_win9x)
2943  {
2944  trace("win9x, mapping to screen coords\n");
2945  MapWindowPoints( hwnd, 0, (POINT *)&rgn_rect, 2 );
2946  }
2947  trace("win: %s\n", wine_dbgstr_rect(&win_rect));
2948  trace("rgn: %s\n", wine_dbgstr_rect(&rgn_rect));
2949  ok( win_rect.left <= rgn_rect.left, "rgn left %d not inside win rect %d\n",
2950  rgn_rect.left, win_rect.left );
2951  ok( win_rect.top <= rgn_rect.top, "rgn top %d not inside win rect %d\n",
2952  rgn_rect.top, win_rect.top );
2953  ok( win_rect.right >= rgn_rect.right, "rgn right %d not inside win rect %d\n",
2954  rgn_rect.right, win_rect.right );
2955  ok( win_rect.bottom >= rgn_rect.bottom, "rgn bottom %d not inside win rect %d\n",
2956  rgn_rect.bottom, win_rect.bottom );
2957  ReleaseDC( hwnd, hdc );
2958 }
2959 
2961 {
2962  if (msg == WM_ACTIVATE && LOWORD(wp) == WA_ACTIVE)
2963  {
2965  ok(child != 0, "couldn't find child window\n");
2966  SetFocus(child);
2967  ok(GetFocus() == child, "Focus should be on child %p\n", child);
2968  return 0;
2969  }
2970  return DefWindowProcA(hwnd, msg, wp, lp);
2971 }
2972 
2974 {
2975  HWND child, child2, ret;
2977 
2978  /* check if we can set focus to non-visible windows */
2979 
2981  SetFocus(0);
2982  SetFocus(hwnd);
2983  ok( GetFocus() == hwnd, "Failed to set focus to visible window %p\n", hwnd );
2984  ok( GetWindowLongA(hwnd,GWL_STYLE) & WS_VISIBLE, "Window %p not visible\n", hwnd );
2986  SetFocus(0);
2987  SetFocus(hwnd);
2988  ok( GetFocus() == hwnd, "Failed to set focus to invisible window %p\n", hwnd );
2989  ok( !(GetWindowLongA(hwnd,GWL_STYLE) & WS_VISIBLE), "Window %p still visible\n", hwnd );
2990  child = CreateWindowExA(0, "static", NULL, WS_CHILD, 0, 0, 0, 0, hwnd, 0, 0, NULL);
2991  assert(child);
2992  SetFocus(child);
2993  ok( GetFocus() == child, "Failed to set focus to invisible child %p\n", child );
2994  ok( !(GetWindowLongA(child,GWL_STYLE) & WS_VISIBLE), "Child %p is visible\n", child );
2996  ok( GetWindowLongA(child,GWL_STYLE) & WS_VISIBLE, "Child %p is not visible\n", child );
2997  ok( GetFocus() == child, "Focus no longer on child %p\n", child );
2999  ok( !(GetWindowLongA(child,GWL_STYLE) & WS_VISIBLE), "Child %p is visible\n", child );
3000  ok( GetFocus() == hwnd, "Focus should be on parent %p, not %p\n", hwnd, GetFocus() );
3002  child2 = CreateWindowExA(0, "static", NULL, WS_CHILD, 0, 0, 0, 0, child, 0, 0, NULL);
3003  assert(child2);
3004  ShowWindow(child2, SW_SHOW);
3005  SetFocus(child2);
3007  ok( !(GetWindowLongA(child,GWL_STYLE) & WS_VISIBLE), "Child %p is visible\n", child );
3008  ok( GetFocus() == child2, "Focus should be on %p, not %p\n", child2, GetFocus() );
3010  SetFocus(child);
3011  ok( GetFocus() == child, "Focus should be on child %p\n", child );
3013  ok( GetFocus() == child, "Focus should still be on child %p\n", child );
3014 
3016  SetFocus(hwnd);
3017  ok( GetFocus() == hwnd, "Focus should be on parent %p, not %p\n", hwnd, GetFocus() );
3019  ok( GetFocus() == hwnd, "Focus should still be on parent %p, not %p\n", hwnd, GetFocus() );
3021  ok( GetFocus() == hwnd, "Focus should still be on parent %p, not %p\n", hwnd, GetFocus() );
3022 
3025  SetFocus(child);
3026  ok( GetFocus() == child, "Focus should be on child %p\n", child );
3028  ok( GetFocus() == child, "Focus should still be on child %p\n", child );
3030 
3031  ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd);
3033  ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd);
3034 todo_wine
3035  ok( GetFocus() != child, "Focus should not be on child %p\n", child );
3036  ok( GetFocus() != hwnd, "Focus should not be on parent %p\n", hwnd );
3038  ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd);
3039  ok( GetFocus() == hwnd, "Focus should be on parent %p\n", hwnd );
3041  ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd);
3042  ok( GetFocus() != child, "Focus should not be on child %p\n", child );
3043 todo_wine
3044  ok( GetFocus() != hwnd, "Focus should not be on parent %p\n", hwnd );
3047  ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd);
3048 todo_wine
3049  ok( GetFocus() == child, "Focus should be on child %p, not %p\n", child, GetFocus() );
3051 
3052  SetFocus( hwnd );
3054  SetParent( child2, child );
3055  ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd);
3056  ok( GetFocus() == hwnd, "Focus should be on parent %p\n", hwnd );
3057  ret = SetFocus( child2 );
3058  ok( ret == 0, "SetFocus %p should fail\n", child2);
3059  ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd);
3060  ok( GetFocus() == hwnd, "Focus should be on parent %p\n", hwnd );
3061  ret = SetFocus( child );
3062  ok( ret == 0, "SetFocus %p should fail\n", child);
3063  ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd);
3064  ok( GetFocus() == hwnd, "Focus should be on parent %p\n", hwnd );
3066  SetFocus( child2 );
3067  ok( GetActiveWindow() == child, "child window %p should be active\n", child);
3068  ok( GetFocus() == child2, "Focus should be on child2 %p\n", child2 );
3069  SetFocus( hwnd );
3070  ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd);
3071  ok( GetFocus() == hwnd, "Focus should be on parent %p\n", hwnd );
3072  SetFocus( child );
3073  ok( GetActiveWindow() == child, "child window %p should be active\n", child);
3074  ok( GetFocus() == child, "Focus should be on child %p\n", child );
3075 
3076  DestroyWindow( child2 );
3077  DestroyWindow( child );
3078 }
3079 
3081 {
3082  HWND hwnd2;
3083 
3084  flush_events( TRUE );
3086  SetFocus(0);
3087  SetActiveWindow(0);
3088  check_wnd_state(0, 0, 0, 0);
3089 
3090  /*trace("testing SetActiveWindow %p\n", hwnd);*/
3091 
3093  check_wnd_state(hwnd, hwnd, hwnd, 0);
3094 
3095  hwnd2 = SetActiveWindow(0);
3096  ok(hwnd2 == hwnd, "SetActiveWindow returned %p instead of %p\n", hwnd2, hwnd);
3097  if (!GetActiveWindow()) /* doesn't always work on vista */
3098  {
3100  check_wnd_state(0, 0, 0, 0);
3101  hwnd2 = SetActiveWindow(hwnd);
3103  ok(hwnd2 == 0, "SetActiveWindow returned %p instead of 0\n", hwnd2);
3104  }
3105  check_wnd_state(hwnd, hwnd, hwnd, 0);
3106 
3108  check_wnd_state(hwnd, hwnd, hwnd, 0);
3109 
3111  check_wnd_state(hwnd, hwnd, hwnd, 0);
3112 
3114  check_wnd_state(0, 0, 0, 0);
3115 
3116  /*trace("testing SetActiveWindow on an invisible window %p\n", hwnd);*/
3118  check_wnd_state(hwnd, hwnd, hwnd, 0);
3119 
3121  check_wnd_state(hwnd, hwnd, hwnd, 0);
3122 
3123  hwnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 0, 0, hwnd, 0, 0, NULL);
3124  check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
3125 
3126  DestroyWindow(hwnd2);
3127  check_wnd_state(hwnd, hwnd, hwnd, 0);
3128 
3129  hwnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 0, 0, hwnd, 0, 0, NULL);
3130  check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
3131 
3133  check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
3134 
3135  DestroyWindow(hwnd2);
3136  check_wnd_state(hwnd, hwnd, hwnd, 0);
3137 }
3138 
3140 {
3144 };
3145 
3147 {
3149  DWORD res;
3150  BOOL ret;
3151 
3152  p->window = CreateWindowA("static", NULL, WS_POPUP | WS_VISIBLE, 0, 0, 0, 0, 0, 0, 0, 0);
3153 
3154  ret = SetEvent(p->window_created);
3155  ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
3156 
3157  res = WaitForSingleObject(p->test_finished, INFINITE);
3158  ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
3159 
3160  DestroyWindow(p->window);
3161  return 0;
3162 }
3163 
3165 {
3166  struct create_window_thread_params thread_params;
3167  HANDLE thread;
3168  DWORD res, tid;
3169  BOOL ret;
3170  HWND hwnd2;
3171  MSG msg;
3172  LONG style;
3173 
3174  flush_events( TRUE );
3176  SetFocus(0);
3177  SetActiveWindow(0);
3178  check_wnd_state(0, 0, 0, 0);
3179 
3180  /*trace("testing SetForegroundWindow %p\n", hwnd);*/
3181 
3183  check_wnd_state(hwnd, hwnd, hwnd, 0);
3184 
3185  hwnd2 = SetActiveWindow(0);
3186  ok(hwnd2 == hwnd, "SetActiveWindow(0) returned %p instead of %p\n", hwnd2, hwnd);
3187  if (GetActiveWindow() == hwnd) /* doesn't always work on vista */
3188  check_wnd_state(hwnd, hwnd, hwnd, 0);
3189  else
3190  check_wnd_state(0, 0, 0, 0);
3191 
3193  if (!ret)
3194  {
3195  skip( "SetForegroundWindow not working\n" );
3196  return;
3197  }
3198  check_wnd_state(hwnd, hwnd, hwnd, 0);
3199 
3200  SetLastError(0xdeadbeef);
3201  ret = SetForegroundWindow(0);
3202  ok(!ret, "SetForegroundWindow returned TRUE instead of FALSE\n");
3204  broken(GetLastError() == 0xdeadbeef), /* win9x */
3205  "got error %d expected ERROR_INVALID_WINDOW_HANDLE\n", GetLastError());
3206  check_wnd_state(hwnd, hwnd, hwnd, 0);
3207 
3209  check_wnd_state(hwnd, hwnd, hwnd, 0);
3210 
3212  check_wnd_state(hwnd, hwnd, hwnd, 0);
3213 
3214  hwnd2 = GetForegroundWindow();
3215  ok(hwnd2 == hwnd, "Wrong foreground window %p\n", hwnd2);
3217  ok(ret, "SetForegroundWindow(desktop) error: %d\n", GetLastError());
3218  hwnd2 = GetForegroundWindow();
3219  ok(hwnd2 != hwnd, "Wrong foreground window %p\n", hwnd2);
3220 
3222  check_wnd_state(0, 0, 0, 0);
3223 
3224  /*trace("testing SetForegroundWindow on an invisible window %p\n", hwnd);*/
3226  ok(ret || broken(!ret), /* win98 */ "SetForegroundWindow returned FALSE instead of TRUE\n");
3227  check_wnd_state(hwnd, hwnd, hwnd, 0);
3228 
3230  check_wnd_state(hwnd, hwnd, hwnd, 0);
3231 
3232  hwnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 0, 0, hwnd, 0, 0, NULL);
3233  check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
3234 
3235  DestroyWindow(hwnd2);
3236  check_wnd_state(hwnd, hwnd, hwnd, 0);
3237 
3238  hwnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 0, 0, hwnd, 0, 0, NULL);
3239  check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
3240 
3242  check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
3243 
3244  DestroyWindow(hwnd2);
3245  check_wnd_state(hwnd, hwnd, hwnd, 0);
3246 
3247  hwnd2 = CreateWindowA("static", NULL, WS_POPUP | WS_VISIBLE, 0, 0, 0, 0, 0, 0, 0, 0);
3248  check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
3249 
3250  thread_params.window_created = CreateEventW(NULL, FALSE, FALSE, NULL);
3251  ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
3252  thread_params.test_finished = CreateEventW(NULL, FALSE, FALSE, NULL);
3253  ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
3254  thread = CreateThread(NULL, 0, create_window_thread, &thread_params, 0, &tid);
3255  ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
3256  res = WaitForSingleObject(thread_params.window_created, INFINITE);
3257  ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
3258  check_wnd_state(hwnd2, thread_params.window, hwnd2, 0);
3259 
3260  SetForegroundWindow(hwnd2);
3261  check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
3262 
3263  while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
3264  if (0) check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
3265  todo_wine ok(GetActiveWindow() == hwnd2, "Expected active window %p, got %p.\n", hwnd2, GetActiveWindow());
3266  todo_wine ok(GetFocus() == hwnd2, "Expected focus window %p, got %p.\n", hwnd2, GetFocus());
3267