xref: /reactos/win32ss/user/ntuser/winpos.c (revision c2c66aff)
1 /*
2  * COPYRIGHT:        See COPYING in the top level directory
3  * PROJECT:          ReactOS kernel
4  * PURPOSE:          Windows
5  * FILE:             win32ss/user/ntuser/winpos.c
6  * PROGRAMER:        Casper S. Hornstrup (chorns@users.sourceforge.net)
7  */
8 
9 #include <win32k.h>
10 DBG_DEFAULT_CHANNEL(UserWinpos);
11 
12 /* GLOBALS *******************************************************************/
13 
14 #define MINMAX_NOSWP  (0x00010000)
15 
16 #define SWP_EX_NOCOPY 0x0001
17 #define SWP_EX_PAINTSELF 0x0002
18 
19 #define  SWP_AGG_NOGEOMETRYCHANGE \
20     (SWP_NOSIZE | SWP_NOCLIENTSIZE | SWP_NOZORDER)
21 #define  SWP_AGG_NOPOSCHANGE \
22     (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE | SWP_NOZORDER)
23 #define  SWP_AGG_STATUSFLAGS \
24     (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
25 #define SWP_AGG_NOCLIENTCHANGE \
26     (SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
27 
28 #define EMPTYPOINT(pt) ((pt).x == -1 && (pt).y == -1)
29 #define PLACE_MIN               0x0001
30 #define PLACE_MAX               0x0002
31 #define PLACE_RECT              0x0004
32 
33 VOID FASTCALL IntLinkWindow(PWND Wnd,PWND WndInsertAfter);
34 
35 /* FUNCTIONS *****************************************************************/
36 
37 #if DBG
38 /***********************************************************************
39  *           dump_winpos_flags
40  */
41 static void dump_winpos_flags(UINT flags)
42 {
43     static const DWORD dumped_flags = (SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW |
44                                        SWP_NOACTIVATE | SWP_FRAMECHANGED | SWP_SHOWWINDOW |
45                                        SWP_HIDEWINDOW | SWP_NOCOPYBITS | SWP_NOOWNERZORDER |
46                                        SWP_NOSENDCHANGING | SWP_DEFERERASE | SWP_ASYNCWINDOWPOS |
47                                        SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE | SWP_STATECHANGED);
48     TRACE("flags:");
49     if(flags & SWP_NOSIZE) TRACE(" SWP_NOSIZE");
50     if(flags & SWP_NOMOVE) TRACE(" SWP_NOMOVE");
51     if(flags & SWP_NOZORDER) TRACE(" SWP_NOZORDER");
52     if(flags & SWP_NOREDRAW) TRACE(" SWP_NOREDRAW");
53     if(flags & SWP_NOACTIVATE) TRACE(" SWP_NOACTIVATE");
54     if(flags & SWP_FRAMECHANGED) TRACE(" SWP_FRAMECHANGED");
55     if(flags & SWP_SHOWWINDOW) TRACE(" SWP_SHOWWINDOW");
56     if(flags & SWP_HIDEWINDOW) TRACE(" SWP_HIDEWINDOW");
57     if(flags & SWP_NOCOPYBITS) TRACE(" SWP_NOCOPYBITS");
58     if(flags & SWP_NOOWNERZORDER) TRACE(" SWP_NOOWNERZORDER");
59     if(flags & SWP_NOSENDCHANGING) TRACE(" SWP_NOSENDCHANGING");
60     if(flags & SWP_DEFERERASE) TRACE(" SWP_DEFERERASE");
61     if(flags & SWP_ASYNCWINDOWPOS) TRACE(" SWP_ASYNCWINDOWPOS");
62     if(flags & SWP_NOCLIENTSIZE) TRACE(" SWP_NOCLIENTSIZE");
63     if(flags & SWP_NOCLIENTMOVE) TRACE(" SWP_NOCLIENTMOVE");
64     if(flags & SWP_STATECHANGED) TRACE(" SWP_STATECHANGED");
65 
66     if(flags & ~dumped_flags) TRACE(" %08x", flags & ~dumped_flags);
67     TRACE("\n");
68 }
69 #endif
70 
71 BOOL FASTCALL
72 IntGetClientOrigin(PWND Window OPTIONAL, LPPOINT Point)
73 {
74    Window = Window ? Window : UserGetDesktopWindow();
75    if (Window == NULL)
76    {
77       Point->x = Point->y = 0;
78       return FALSE;
79    }
80    Point->x = Window->rcClient.left;
81    Point->y = Window->rcClient.top;
82 
83    return TRUE;
84 }
85 
86 /*!
87  * Internal function.
88  * Returns client window rectangle relative to the upper-left corner of client area.
89  *
90  * \note Does not check the validity of the parameters
91 */
92 VOID FASTCALL
93 IntGetClientRect(PWND Wnd, RECTL *Rect)
94 {
95    ASSERT( Wnd );
96    ASSERT( Rect );
97    if (Wnd->style & WS_MINIMIZED)
98    {
99       Rect->left = Rect->top = 0;
100       Rect->right = UserGetSystemMetrics(SM_CXMINIMIZED);
101       Rect->bottom = UserGetSystemMetrics(SM_CYMINIMIZED);
102       return;
103    }
104    if (!UserIsDesktopWindow(Wnd))
105    {
106       *Rect = Wnd->rcClient;
107       RECTL_vOffsetRect(Rect, -Wnd->rcClient.left, -Wnd->rcClient.top);
108    }
109    else
110    {
111       Rect->left = Rect->top = 0;
112       Rect->right  = Wnd->rcClient.right;
113       Rect->bottom = Wnd->rcClient.bottom;
114    /* Do this until Init bug is fixed. This sets 640x480, see InitMetrics.
115       Rect->right  = UserGetSystemMetrics(SM_CXSCREEN);
116       Rect->bottom = UserGetSystemMetrics(SM_CYSCREEN);
117    */
118    }
119 }
120 
121 BOOL FASTCALL
122 IntGetWindowRect(PWND Wnd, RECTL *Rect)
123 {
124    ASSERT( Wnd );
125    ASSERT( Rect );
126    if (!Wnd) return FALSE;
127    if (!UserIsDesktopWindow(Wnd))
128    {
129        *Rect = Wnd->rcWindow;
130    }
131    else
132    {
133        Rect->left = Rect->top = 0;
134        Rect->right = Wnd->rcWindow.right;
135        Rect->bottom = Wnd->rcWindow.bottom;
136 /* Do this until Init bug is fixed. This sets 640x480, see InitMetrics.
137        Rect->right = GetSystemMetrics(SM_CXSCREEN);
138        Rect->bottom = GetSystemMetrics(SM_CYSCREEN);
139 */   }
140    return TRUE;
141 }
142 
143 
144 INT FASTCALL
145 IntMapWindowPoints(PWND FromWnd, PWND ToWnd, LPPOINT lpPoints, UINT cPoints)
146 {
147     BOOL mirror_from, mirror_to;
148     POINT Delta;
149     UINT i;
150     int Change = 1;
151 
152     /* Note: Desktop Top and Left is always 0! */
153     Delta.x = Delta.y = 0;
154     mirror_from = mirror_to = FALSE;
155 
156     if (FromWnd && !UserIsDesktopWindow(FromWnd))
157     {
158        if (FromWnd->ExStyle & WS_EX_LAYOUTRTL)
159        {
160           mirror_from = TRUE;
161           Change = -Change;
162           Delta.x = -FromWnd->rcClient.right;
163        }
164        else
165           Delta.x = FromWnd->rcClient.left;
166        Delta.y = FromWnd->rcClient.top;
167     }
168 
169     if (ToWnd && !UserIsDesktopWindow(ToWnd))
170     {
171        if (ToWnd->ExStyle & WS_EX_LAYOUTRTL)
172        {
173           mirror_to = TRUE;
174           Change = -Change;
175           Delta.x += Change * ToWnd->rcClient.right;
176        }
177        else
178           Delta.x -= Change * ToWnd->rcClient.left;
179        Delta.y -= ToWnd->rcClient.top;
180     }
181 
182     for (i = 0; i != cPoints; i++)
183     {
184         lpPoints[i].x += Delta.x;
185         lpPoints[i].x *= Change;
186         lpPoints[i].y += Delta.y;
187     }
188 
189     if ((mirror_from || mirror_to) && cPoints == 2)  /* special case for rectangle */
190     {
191        int tmp = min(lpPoints[0].x, lpPoints[1].x);
192        lpPoints[1].x = max(lpPoints[0].x, lpPoints[1].x);
193        lpPoints[0].x = tmp;
194     }
195 
196     return MAKELONG(LOWORD(Delta.x), LOWORD(Delta.y));
197 }
198 
199 BOOL FASTCALL
200 IntClientToScreen(PWND Wnd, LPPOINT lpPoint)
201 {
202    if (Wnd && Wnd->fnid != FNID_DESKTOP )
203    {
204       if (Wnd->ExStyle & WS_EX_LAYOUTRTL)
205          lpPoint->x = Wnd->rcClient.right - lpPoint->x;
206       else
207          lpPoint->x += Wnd->rcClient.left;
208       lpPoint->y += Wnd->rcClient.top;
209    }
210    return TRUE;
211 }
212 
213 BOOL FASTCALL
214 IntScreenToClient(PWND Wnd, LPPOINT lpPoint)
215 {
216     if (Wnd && Wnd->fnid != FNID_DESKTOP )
217     {
218        if (Wnd->ExStyle & WS_EX_LAYOUTRTL)
219           lpPoint->x = Wnd->rcClient.right - lpPoint->x;
220        else
221           lpPoint->x -= Wnd->rcClient.left;
222        lpPoint->y -= Wnd->rcClient.top;
223     }
224     return TRUE;
225 }
226 
227 BOOL FASTCALL IsChildVisible(PWND pWnd)
228 {
229     do
230     {
231         if ( (pWnd->style & (WS_POPUP|WS_CHILD)) != WS_CHILD ||
232             !(pWnd = pWnd->spwndParent) )
233            return TRUE;
234     }
235     while (pWnd->style & WS_VISIBLE);
236     return FALSE;
237 }
238 
239 PWND FASTCALL IntGetLastTopMostWindow(VOID)
240 {
241     PWND pWnd;
242     PDESKTOP rpdesk = gptiCurrent->rpdesk;
243 
244     if ( rpdesk &&
245         (pWnd = rpdesk->pDeskInfo->spwnd->spwndChild) &&
246          pWnd->ExStyle & WS_EX_TOPMOST)
247     {
248         for (;;)
249         {
250            if (!pWnd->spwndNext) break;
251            if (!(pWnd->spwndNext->ExStyle & WS_EX_TOPMOST)) break;
252            pWnd = pWnd->spwndNext;
253         }
254         return pWnd;
255     }
256     return NULL;
257 }
258 
259 VOID
260 SelectWindowRgn(PWND Window, HRGN hRgnClip)
261 {
262     if (Window->hrgnClip)
263     {
264         /* Delete no longer needed region handle */
265         IntGdiSetRegionOwner(Window->hrgnClip, GDI_OBJ_HMGR_POWNED);
266         GreDeleteObject(Window->hrgnClip);
267         Window->hrgnClip = NULL;
268     }
269 
270     if (hRgnClip > HRGN_WINDOW)
271     {
272         /*if (!UserIsDesktopWindow(Window))
273         {
274             NtGdiOffsetRgn(hRgnClip, Window->rcWindow.left, Window->rcWindow.top);
275         }*/
276         /* Set public ownership */
277         IntGdiSetRegionOwner(hRgnClip, GDI_OBJ_HMGR_PUBLIC);
278 
279         Window->hrgnClip = hRgnClip;
280     }
281 }
282 
283 //
284 // This helps with CORE-6129 forcing modal dialog active when another app is minimized or closed.
285 //
286 BOOL FASTCALL ActivateOtherWindowMin(PWND Wnd)
287 {
288     BOOL ActivePrev, FindTopWnd;
289     PWND pWndTopMost, pWndChild, pWndSetActive, pWndTemp, pWndDesk;
290     USER_REFERENCE_ENTRY Ref;
291     PTHREADINFO pti = gptiCurrent;
292 
293     //ERR("AOWM 1 %p\n",Wnd->head.h);
294     ActivePrev = (pti->MessageQueue->spwndActivePrev != NULL);
295     FindTopWnd = TRUE;
296 
297     if ((pWndTopMost = IntGetLastTopMostWindow()))
298        pWndChild = pWndTopMost->spwndNext;
299     else
300        pWndChild = Wnd->spwndParent->spwndChild;
301 
302     for (;;)
303     {
304        if ( ActivePrev )
305           pWndSetActive = pti->MessageQueue->spwndActivePrev;
306        else
307           pWndSetActive = pWndChild;
308 
309        pWndTemp = NULL;
310 
311        while(pWndSetActive)
312        {
313           if ( VerifyWnd(pWndSetActive) &&
314               !(pWndSetActive->ExStyle & WS_EX_NOACTIVATE) &&
315                (pWndSetActive->style & (WS_VISIBLE|WS_DISABLED)) == WS_VISIBLE &&
316                (!(pWndSetActive->style & WS_ICONIC) /* FIXME MinMax pos? */ ) )
317           {
318              if (!(pWndSetActive->ExStyle & WS_EX_TOOLWINDOW) )
319              {
320                 UserRefObjectCo(pWndSetActive, &Ref);
321                 //ERR("ActivateOtherWindowMin Set FG 1\n");
322                 co_IntSetForegroundWindow(pWndSetActive);
323                 UserDerefObjectCo(pWndSetActive);
324                 //ERR("AOWM 2 Exit Good %p\n",pWndSetActive->head.h);
325                 return TRUE;
326              }
327              if (!pWndTemp ) pWndTemp = pWndSetActive;
328           }
329           if ( ActivePrev )
330           {
331              ActivePrev = FALSE;
332              pWndSetActive = pWndChild;
333           }
334           else
335              pWndSetActive = pWndSetActive->spwndNext;
336        }
337 
338        if ( !FindTopWnd ) break;
339        FindTopWnd = FALSE;
340 
341        if ( pWndChild )
342        {
343           pWndChild = pWndChild->spwndParent->spwndChild;
344           continue;
345        }
346 
347        if (!(pWndDesk = IntGetThreadDesktopWindow(pti)))
348        {
349           pWndChild = NULL;
350           continue;
351        }
352        pWndChild = pWndDesk->spwndChild;
353     }
354 
355     if ((pWndSetActive = pWndTemp))
356     {
357        UserRefObjectCo(pWndSetActive, &Ref);
358        //ERR("ActivateOtherWindowMin Set FG 2\n");
359        co_IntSetForegroundWindow(pWndSetActive);
360        UserDerefObjectCo(pWndSetActive);
361        //ERR("AOWM 3 Exit Good %p\n",pWndSetActive->head.h);
362        return TRUE;
363     }
364     //ERR("AOWM 4 Bad\n");
365     return FALSE;
366 }
367 
368 /*******************************************************************
369  *         can_activate_window
370  *
371  * Check if we can activate the specified window.
372  */
373 static
374 BOOL FASTCALL can_activate_window( PWND Wnd OPTIONAL)
375 {
376     LONG style;
377 
378     if (!Wnd) return FALSE;
379 
380     style = Wnd->style;
381     if (!(style & WS_VISIBLE)) return FALSE;
382     if (style & WS_MINIMIZE) return FALSE;
383     if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE;
384     return TRUE;
385     /* FIXME: This window could be disable because the child that closed
386               was a popup. */
387     //return !(style & WS_DISABLED);
388 }
389 
390 
391 /*******************************************************************
392  *         WinPosActivateOtherWindow
393  *
394  *  Activates window other than pWnd.
395  */
396 VOID FASTCALL
397 co_WinPosActivateOtherWindow(PWND Wnd)
398 {
399    PWND WndTo = NULL;
400    USER_REFERENCE_ENTRY Ref;
401 
402    ASSERT_REFS_CO(Wnd);
403 
404    if (IntIsDesktopWindow(Wnd))
405    {
406       //ERR("WinPosActivateOtherWindow Set Focus Msg Q No window!\n");
407       IntSetFocusMessageQueue(NULL);
408       return;
409    }
410 
411    /* If this is popup window, try to activate the owner first. */
412    if ((Wnd->style & WS_POPUP) && (WndTo = Wnd->spwndOwner))
413    {
414       TRACE("WPAOW Popup with Owner\n");
415       WndTo = UserGetAncestor( WndTo, GA_ROOT );
416       if (can_activate_window(WndTo)) goto done;
417    }
418 
419    /* Pick a next top-level window. */
420    /* FIXME: Search for non-tooltip windows first. */
421    WndTo = Wnd;
422    for (;;)
423    {
424       if (!(WndTo = WndTo->spwndNext))  break;
425       if (can_activate_window( WndTo )) goto done;
426    }
427 
428    /*
429       Fixes wine win.c:test_SetParent last ShowWindow test after popup dies.
430       Check for previous active window to bring to top.
431    */
432    if (Wnd)
433    {
434       WndTo = Wnd->head.pti->MessageQueue->spwndActivePrev;
435       if (can_activate_window( WndTo )) goto done;
436    }
437 
438    // Find any window to bring to top. Works Okay for wine since it does not see X11 windows.
439    WndTo = UserGetDesktopWindow();
440    WndTo = WndTo->spwndChild;
441    if ( WndTo == NULL )
442    {
443       //ERR("WinPosActivateOtherWindow No window!\n");
444       return;
445    }
446    for (;;)
447    {
448       if (WndTo == Wnd)
449       {
450          WndTo = NULL;
451          break;
452       }
453       if (can_activate_window( WndTo )) goto done;
454       if (!(WndTo = WndTo->spwndNext))  break;
455    }
456 
457 done:
458    if (WndTo) UserRefObjectCo(WndTo, &Ref);
459 
460    if (gpqForeground && (!gpqForeground->spwndActive || Wnd == gpqForeground->spwndActive))
461    {
462       /* ReactOS can pass WndTo = NULL to co_IntSetForegroundWindow and returns FALSE. */
463       //ERR("WinPosActivateOtherWindow Set FG 0x%p hWnd %p\n",WndTo, WndTo ? WndTo->head.h : 0);
464       if (co_IntSetForegroundWindow(WndTo))
465       {
466          if (WndTo) UserDerefObjectCo(WndTo);
467          return;
468       }
469    }
470    //ERR("WinPosActivateOtherWindow Set Active  0x%p\n",WndTo);
471    if (!UserSetActiveWindow(WndTo))  /* Ok for WndTo to be NULL here */
472    {
473       //ERR("WPAOW SA 1\n");
474       UserSetActiveWindow(NULL);
475    }
476    if (WndTo) UserDerefObjectCo(WndTo);
477 }
478 
479 VOID FASTCALL
480 WinPosInitInternalPos(PWND Wnd, RECTL *RestoreRect)
481 {
482    POINT Size;
483    RECTL Rect = *RestoreRect;
484 
485    if (Wnd->spwndParent && !UserIsDesktopWindow(Wnd->spwndParent))
486    {
487       RECTL_vOffsetRect(&Rect,
488                         -Wnd->spwndParent->rcClient.left,
489                         -Wnd->spwndParent->rcClient.top);
490    }
491 
492    Size.x = Rect.left;
493    Size.y = Rect.top;
494 
495    if (!Wnd->InternalPosInitialized)
496    {
497       // FIXME: Use check point Atom..
498       Wnd->InternalPos.flags = 0;
499       Wnd->InternalPos.MaxPos.x  = Wnd->InternalPos.MaxPos.y  = -1;
500       Wnd->InternalPos.IconPos.x = Wnd->InternalPos.IconPos.y = -1;
501       Wnd->InternalPos.NormalRect = Rect;
502       Wnd->InternalPosInitialized = TRUE;
503    }
504 
505    if (Wnd->style & WS_MINIMIZE)
506    {
507       Wnd->InternalPos.IconPos = Size;
508       Wnd->InternalPos.flags |= WPF_MININIT;
509    }
510    else if (Wnd->style & WS_MAXIMIZE)
511    {
512       Wnd->InternalPos.flags |= WPF_MAXINIT;
513 
514       if ( Wnd->spwndParent == Wnd->head.rpdesk->pDeskInfo->spwnd )
515       {
516          if (Wnd->state & WNDS_MAXIMIZESTOMONITOR)
517          {
518             Wnd->InternalPos.flags &= ~WPF_MAXINIT;
519             Wnd->InternalPos.MaxPos.x = Wnd->InternalPos.MaxPos.y = -1;
520          }
521          else
522          {
523             RECTL WorkArea;
524             PMONITOR pmonitor = UserMonitorFromRect(&Rect, MONITOR_DEFAULTTOPRIMARY );
525             // FIXME: support DPI aware, rcWorkDPI/Real etc..
526             WorkArea = pmonitor->rcMonitor;
527 
528             if (Wnd->style & WS_MAXIMIZEBOX)
529             {  // Support (Wnd->state & WNDS_HASCAPTION) || pmonitor->cFullScreen too.
530                if ((Wnd->style & WS_CAPTION) == WS_CAPTION || !(Wnd->style & (WS_CHILD | WS_POPUP)))
531                {
532                   WorkArea = pmonitor->rcWork;
533                   //ERR("rcWork\n");
534                }
535             }
536 
537             Wnd->InternalPos.MaxPos.x = Rect.left - WorkArea.left;
538             Wnd->InternalPos.MaxPos.y = Rect.top  - WorkArea.top;
539 
540             /*ERR("WinPosIP 2 X %d = R.l %d - W.l %d | Y %d = R.t %d - W.t %d\n",
541                                          Wnd->InternalPos.MaxPos.x,
542                                          Rect.left, WorkArea.left,
543                                          Wnd->InternalPos.MaxPos.y,
544                                          Rect.top, WorkArea.top);*/
545          }
546       }
547       else
548          Wnd->InternalPos.MaxPos = Size;
549    }
550    else
551    {
552       Wnd->InternalPos.NormalRect = Rect;
553    }
554 }
555 
556 BOOL
557 FASTCALL
558 IntGetWindowPlacement(PWND Wnd, WINDOWPLACEMENT *lpwndpl)
559 {
560    if (!Wnd) return FALSE;
561 
562    if(lpwndpl->length != sizeof(WINDOWPLACEMENT))
563    {
564       return FALSE;
565    }
566 
567    lpwndpl->flags = 0;
568 
569    WinPosInitInternalPos(Wnd, &Wnd->rcWindow);
570 
571    lpwndpl->showCmd = SW_HIDE;
572 
573    if ( Wnd->style & WS_MINIMIZE )
574       lpwndpl->showCmd = SW_SHOWMINIMIZED;
575    else
576       lpwndpl->showCmd = ( Wnd->style & WS_MAXIMIZE ) ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
577 
578    lpwndpl->rcNormalPosition = Wnd->InternalPos.NormalRect;
579 
580    if (Wnd->InternalPos.flags & WPF_MININIT) // Return if it was set!
581    {
582       lpwndpl->ptMinPosition.x = Wnd->InternalPos.IconPos.x;
583       lpwndpl->ptMinPosition.y = Wnd->InternalPos.IconPos.y;
584    }
585    else
586       lpwndpl->ptMinPosition.x = lpwndpl->ptMinPosition.y = -1;
587 
588    if ( Wnd->InternalPos.flags & WPF_MAXINIT && // Return if set and not maximized to monitor!
589         !(Wnd->state & WNDS_MAXIMIZESTOMONITOR))
590    {
591       lpwndpl->ptMaxPosition.x = Wnd->InternalPos.MaxPos.x;
592       lpwndpl->ptMaxPosition.y = Wnd->InternalPos.MaxPos.y;
593    }
594    else
595       lpwndpl->ptMaxPosition.x = lpwndpl->ptMaxPosition.y = -1;
596 
597    if ( Wnd->spwndParent == Wnd->head.rpdesk->pDeskInfo->spwnd &&
598        !(Wnd->ExStyle & WS_EX_TOOLWINDOW))
599    {
600       PMONITOR pmonitor = UserMonitorFromRect(&lpwndpl->rcNormalPosition, MONITOR_DEFAULTTOPRIMARY );
601 
602       // FIXME: support DPI aware, rcWorkDPI/Real etc..
603       if (Wnd->InternalPos.flags & WPF_MININIT)
604       {
605          lpwndpl->ptMinPosition.x -= (pmonitor->rcWork.left - pmonitor->rcMonitor.left);
606          lpwndpl->ptMinPosition.y -= (pmonitor->rcWork.top - pmonitor->rcMonitor.top);
607       }
608       RECTL_vOffsetRect(&lpwndpl->rcNormalPosition,
609                          pmonitor->rcMonitor.left - pmonitor->rcWork.left,
610                          pmonitor->rcMonitor.top  - pmonitor->rcWork.top);
611    }
612 
613    if ( Wnd->InternalPos.flags & WPF_RESTORETOMAXIMIZED || Wnd->style & WS_MAXIMIZE )
614       lpwndpl->flags |= WPF_RESTORETOMAXIMIZED;
615 
616    if ( ((Wnd->style & (WS_CHILD|WS_POPUP)) == WS_CHILD) && Wnd->InternalPos.flags & WPF_SETMINPOSITION)
617       lpwndpl->flags |= WPF_SETMINPOSITION;
618 
619    return TRUE;
620 }
621 
622 /* make sure the specified rect is visible on screen */
623 static void make_rect_onscreen( RECT *rect )
624 {
625     PMONITOR pmonitor = UserMonitorFromRect( rect, MONITOR_DEFAULTTONEAREST ); // Wine uses this.
626 
627     //  FIXME: support DPI aware, rcWorkDPI/Real etc..
628     if (!pmonitor) return;
629     /* FIXME: map coordinates from rcWork to rcMonitor */
630     if (rect->right <= pmonitor->rcWork.left)
631     {
632         rect->right += pmonitor->rcWork.left - rect->left;
633         rect->left = pmonitor->rcWork.left;
634     }
635     else if (rect->left >= pmonitor->rcWork.right)
636     {
637         rect->left += pmonitor->rcWork.right - rect->right;
638         rect->right = pmonitor->rcWork.right;
639     }
640     if (rect->bottom <= pmonitor->rcWork.top)
641     {
642         rect->bottom += pmonitor->rcWork.top - rect->top;
643         rect->top = pmonitor->rcWork.top;
644     }
645     else if (rect->top >= pmonitor->rcWork.bottom)
646     {
647         rect->top += pmonitor->rcWork.bottom - rect->bottom;
648         rect->bottom = pmonitor->rcWork.bottom;
649     }
650 }
651 
652 /* make sure the specified point is visible on screen */
653 static void make_point_onscreen( POINT *pt )
654 {
655     RECT rect;
656 
657     RECTL_vSetRect( &rect, pt->x, pt->y, pt->x + 1, pt->y + 1 );
658     make_rect_onscreen( &rect );
659     pt->x = rect.left;
660     pt->y = rect.top;
661 }
662 
663 BOOL FASTCALL
664 IntSetWindowPlacement(PWND Wnd, WINDOWPLACEMENT *wpl, UINT Flags)
665 {
666    BOOL sAsync;
667    UINT SWP_Flags;
668 
669    if ( Flags & PLACE_MIN) make_point_onscreen( &wpl->ptMinPosition );
670    if ( Flags & PLACE_MAX) make_point_onscreen( &wpl->ptMaxPosition );
671    if ( Flags & PLACE_RECT) make_rect_onscreen( &wpl->rcNormalPosition );
672 
673    if (!Wnd || Wnd == Wnd->head.rpdesk->pDeskInfo->spwnd) return FALSE;
674 
675    if ( Flags & PLACE_MIN ) Wnd->InternalPos.IconPos = wpl->ptMinPosition;
676    if ( Flags & PLACE_MAX ) Wnd->InternalPos.MaxPos = wpl->ptMaxPosition;
677    if ( Flags & PLACE_RECT) Wnd->InternalPos.NormalRect = wpl->rcNormalPosition;
678 
679    SWP_Flags = SWP_NOZORDER | SWP_NOACTIVATE | ((wpl->flags & WPF_ASYNCWINDOWPLACEMENT) ? SWP_ASYNCWINDOWPOS : 0);
680 
681    if (Wnd->style & WS_MINIMIZE )
682    {
683       if (Flags & PLACE_MIN || Wnd->InternalPos.flags & WPF_SETMINPOSITION)
684       {
685          co_WinPosSetWindowPos(Wnd, HWND_TOP,
686                                wpl->ptMinPosition.x, wpl->ptMinPosition.y, 0, 0,
687                                SWP_NOSIZE | SWP_Flags);
688          Wnd->InternalPos.flags |= WPF_MININIT;
689       }
690    }
691    else if (Wnd->style & WS_MAXIMIZE )
692    {
693       if (Flags & PLACE_MAX)
694       {
695          co_WinPosSetWindowPos(Wnd, HWND_TOP,
696                                wpl->ptMaxPosition.x, wpl->ptMaxPosition.y, 0, 0,
697                                SWP_NOSIZE | SWP_Flags);
698          Wnd->InternalPos.flags |= WPF_MAXINIT;
699       }
700    }
701    else if (Flags & PLACE_RECT)
702    {
703       co_WinPosSetWindowPos(Wnd, HWND_TOP,
704                             wpl->rcNormalPosition.left, wpl->rcNormalPosition.top,
705                             wpl->rcNormalPosition.right - wpl->rcNormalPosition.left,
706                             wpl->rcNormalPosition.bottom - wpl->rcNormalPosition.top,
707                             SWP_Flags);
708    }
709 
710    sAsync = (Wnd->head.pti->MessageQueue != gptiCurrent->MessageQueue && wpl->flags & WPF_ASYNCWINDOWPLACEMENT);
711 
712    if ( sAsync )
713       co_IntSendMessageNoWait( UserHMGetHandle(Wnd), WM_ASYNC_SHOWWINDOW, wpl->showCmd, 0 );
714    else
715       co_WinPosShowWindow(Wnd, wpl->showCmd);
716 
717    if ( Wnd->style & WS_MINIMIZE && !sAsync )
718    {
719       if ( wpl->flags & WPF_SETMINPOSITION )
720          Wnd->InternalPos.flags |= WPF_SETMINPOSITION;
721 
722       if ( wpl->flags & WPF_RESTORETOMAXIMIZED )
723          Wnd->InternalPos.flags |= WPF_RESTORETOMAXIMIZED;
724    }
725    return TRUE;
726 }
727 
728 UINT
729 FASTCALL
730 co_WinPosArrangeIconicWindows(PWND parent)
731 {
732    RECTL rectParent;
733    PWND Child;
734    INT x, y, xspacing, yspacing, sx, sy;
735 
736    ASSERT_REFS_CO(parent);
737 
738    IntGetClientRect( parent, &rectParent );
739    // FIXME: Support Minimize Metrics gspv.mm.iArrange.
740    // Default: ARW_BOTTOMLEFT
741    x = rectParent.left;
742    y = rectParent.bottom;
743 
744    xspacing = UserGetSystemMetrics(SM_CXMINIMIZED);
745    yspacing = UserGetSystemMetrics(SM_CYMINIMIZED);
746 
747    Child = parent->spwndChild;
748    while(Child)
749    {
750       if((Child->style & WS_MINIMIZE) != 0 )
751       {
752          USER_REFERENCE_ENTRY Ref;
753          UserRefObjectCo(Child, &Ref);
754 
755          sx = x + UserGetSystemMetrics(SM_CXBORDER);
756          sy = y - yspacing - UserGetSystemMetrics(SM_CYBORDER);
757 
758          Child->InternalPos.IconPos.x = sx;
759          Child->InternalPos.IconPos.y = sy;
760          Child->InternalPos.flags |= WPF_MININIT;
761 
762          co_WinPosSetWindowPos( Child, 0, sx, sy, xspacing, yspacing, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_ASYNCWINDOWPOS);
763 
764          UserDerefObjectCo(Child);
765 
766          if (x <= rectParent.right - xspacing)
767             x += xspacing;
768          else
769          {
770             x = rectParent.left;
771             y -= yspacing;
772          }
773       }
774       Child = Child->spwndNext;
775    }
776    return yspacing;
777 }
778 
779 static VOID FASTCALL
780 WinPosFindIconPos(PWND Window, POINT *Pos)
781 {
782    RECT rectParent;
783    PWND pwndChild, pwndParent;
784    int x, y, xspacing, yspacing;
785 
786    pwndParent = Window->spwndParent;
787    if (UserIsDesktopWindow(pwndParent))
788    {
789       ERR("FIXME: Parent is Desktop, Min off screen!\n");
790       /* FIXME: ReactOS doesn't support iconic minimize to desktop */
791       Pos->x = Pos->y = -32000;
792       Window->InternalPos.flags |= WPF_MININIT;
793       Window->InternalPos.IconPos.x = Pos->x;
794       Window->InternalPos.IconPos.y = Pos->y;
795       return;
796    }
797 
798    IntGetClientRect( pwndParent, &rectParent );
799    // FIXME: Support Minimize Metrics gspv.mm.iArrange.
800    // Default: ARW_BOTTOMLEFT
801    x = rectParent.left;
802    y = rectParent.bottom;
803 
804    xspacing = UserGetSystemMetrics(SM_CXMINIMIZED);
805    yspacing = UserGetSystemMetrics(SM_CYMINIMIZED);
806 
807    // Set to default position when minimized.
808    Pos->x = x + UserGetSystemMetrics(SM_CXBORDER);
809    Pos->y = y - yspacing - UserGetSystemMetrics(SM_CYBORDER);
810 
811    for (pwndChild = pwndParent->spwndChild; pwndChild; pwndChild = pwndChild->spwndNext)
812    {
813         if (pwndChild == Window) continue;
814 
815         if ((pwndChild->style & (WS_VISIBLE|WS_MINIMIZE)) != (WS_VISIBLE|WS_MINIMIZE) )
816         {
817             continue;
818         }
819 
820         if ( pwndChild->InternalPos.IconPos.x != Pos->x && pwndChild->InternalPos.IconPos.y != Pos->y )
821         {
822            break;
823         }
824         if (x <= rectParent.right - xspacing)
825             x += xspacing;
826         else
827         {
828             x = rectParent.left;
829             y -= yspacing;
830         }
831         Pos->x = x + UserGetSystemMetrics(SM_CXBORDER);
832         Pos->y = y - yspacing - UserGetSystemMetrics(SM_CYBORDER);
833    }
834 
835    Window->InternalPos.IconPos.x = Pos->x;
836    Window->InternalPos.IconPos.y = Pos->y;
837    Window->InternalPos.flags |= WPF_MININIT;
838    TRACE("Position is set! X:%d Y:%d\n",Pos->x,Pos->y);
839    return;
840 }
841 
842 BOOL
843 UserHasWindowEdge(DWORD Style, DWORD ExStyle)
844 {
845    if (Style & WS_MINIMIZE)
846       return TRUE;
847    if (ExStyle & WS_EX_DLGMODALFRAME)
848       return TRUE;
849    if (ExStyle & WS_EX_STATICEDGE)
850       return FALSE;
851    if (Style & WS_THICKFRAME)
852       return TRUE;
853    Style &= WS_CAPTION;
854    if (Style == WS_DLGFRAME || Style == WS_CAPTION)
855       return TRUE;
856    return FALSE;
857 }
858 
859 VOID FASTCALL
860 IntGetWindowBorderMeasures(PWND Wnd, UINT *cx, UINT *cy)
861 {
862    if(HAS_DLGFRAME(Wnd->style, Wnd->ExStyle) && !(Wnd->style & WS_MINIMIZE))
863    {
864       *cx = UserGetSystemMetrics(SM_CXDLGFRAME);
865       *cy = UserGetSystemMetrics(SM_CYDLGFRAME);
866    }
867    else
868    {
869       if(HAS_THICKFRAME(Wnd->style, Wnd->ExStyle)&& !(Wnd->style & WS_MINIMIZE))
870       {
871          *cx = UserGetSystemMetrics(SM_CXFRAME);
872          *cy = UserGetSystemMetrics(SM_CYFRAME);
873       }
874       else if(HAS_THINFRAME(Wnd->style, Wnd->ExStyle))
875       {
876          *cx = UserGetSystemMetrics(SM_CXBORDER);
877          *cy = UserGetSystemMetrics(SM_CYBORDER);
878       }
879       else
880       {
881          *cx = *cy = 0;
882       }
883    }
884 }
885 
886 VOID
887 UserGetWindowBorders(DWORD Style, DWORD ExStyle, SIZE *Size, BOOL WithClient)
888 {
889    DWORD Border = 0;
890 
891    if (UserHasWindowEdge(Style, ExStyle))
892       Border += 2;
893    else if (ExStyle & WS_EX_STATICEDGE)
894       Border += 1;
895    if ((ExStyle & WS_EX_CLIENTEDGE) && WithClient)
896       Border += 2;
897    if (Style & WS_CAPTION || ExStyle & WS_EX_DLGMODALFRAME)
898       Border ++;
899    Size->cx = Size->cy = Border;
900    if ((Style & WS_THICKFRAME) && !(Style & WS_MINIMIZE))
901    {
902       Size->cx += UserGetSystemMetrics(SM_CXFRAME) - UserGetSystemMetrics(SM_CXDLGFRAME);
903       Size->cy += UserGetSystemMetrics(SM_CYFRAME) - UserGetSystemMetrics(SM_CYDLGFRAME);
904    }
905    Size->cx *= UserGetSystemMetrics(SM_CXBORDER);
906    Size->cy *= UserGetSystemMetrics(SM_CYBORDER);
907 }
908 
909 BOOL WINAPI
910 UserAdjustWindowRectEx(LPRECT lpRect,
911                        DWORD dwStyle,
912                        BOOL bMenu,
913                        DWORD dwExStyle)
914 {
915    SIZE BorderSize;
916 
917    if (bMenu)
918    {
919       lpRect->top -= UserGetSystemMetrics(SM_CYMENU);
920    }
921    if ((dwStyle & WS_CAPTION) == WS_CAPTION)
922    {
923       if (dwExStyle & WS_EX_TOOLWINDOW)
924          lpRect->top -= UserGetSystemMetrics(SM_CYSMCAPTION);
925       else
926          lpRect->top -= UserGetSystemMetrics(SM_CYCAPTION);
927    }
928    UserGetWindowBorders(dwStyle, dwExStyle, &BorderSize, TRUE);
929    RECTL_vInflateRect(
930       lpRect,
931       BorderSize.cx,
932       BorderSize.cy);
933 
934    return TRUE;
935 }
936 
937 UINT FASTCALL
938 co_WinPosGetMinMaxInfo(PWND Window, POINT* MaxSize, POINT* MaxPos,
939                        POINT* MinTrack, POINT* MaxTrack)
940 {
941     MINMAXINFO MinMax;
942     PMONITOR monitor;
943     INT xinc, yinc;
944     LONG style = Window->style;
945     LONG adjustedStyle;
946     LONG exstyle = Window->ExStyle;
947     RECT rc;
948 
949     ASSERT_REFS_CO(Window);
950 
951     /* Compute default values */
952 
953     rc = Window->rcWindow;
954     MinMax.ptReserved.x = rc.left;
955     MinMax.ptReserved.y = rc.top;
956 
957     if ((style & WS_CAPTION) == WS_CAPTION)
958         adjustedStyle = style & ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
959     else
960         adjustedStyle = style;
961 
962     if(Window->spwndParent)
963         IntGetClientRect(Window->spwndParent, &rc);
964     UserAdjustWindowRectEx(&rc, adjustedStyle, ((style & WS_POPUP) && Window->IDMenu), exstyle);
965 
966     xinc = -rc.left;
967     yinc = -rc.top;
968 
969     MinMax.ptMaxSize.x = rc.right - rc.left;
970     MinMax.ptMaxSize.y = rc.bottom - rc.top;
971     if (style & (WS_DLGFRAME | WS_BORDER))
972     {
973         MinMax.ptMinTrackSize.x = UserGetSystemMetrics(SM_CXMINTRACK);
974         MinMax.ptMinTrackSize.y = UserGetSystemMetrics(SM_CYMINTRACK);
975     }
976     else
977     {
978         MinMax.ptMinTrackSize.x = 2 * xinc;
979         MinMax.ptMinTrackSize.y = 2 * yinc;
980     }
981     MinMax.ptMaxTrackSize.x = UserGetSystemMetrics(SM_CXMAXTRACK);
982     MinMax.ptMaxTrackSize.y = UserGetSystemMetrics(SM_CYMAXTRACK);
983     MinMax.ptMaxPosition.x = -xinc;
984     MinMax.ptMaxPosition.y = -yinc;
985 
986    if (!EMPTYPOINT(Window->InternalPos.MaxPos)) MinMax.ptMaxPosition = Window->InternalPos.MaxPos;
987 
988     co_IntSendMessage(Window->head.h, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax);
989 
990     /* if the app didn't change the values, adapt them for the current monitor */
991     if ((monitor = UserGetPrimaryMonitor()))
992     {
993         RECT rc_work;
994 
995         rc_work = monitor->rcMonitor;
996 
997         if (style & WS_MAXIMIZEBOX)
998         {
999             if ((style & WS_CAPTION) == WS_CAPTION || !(style & (WS_CHILD | WS_POPUP)))
1000                 rc_work = monitor->rcWork;
1001         }
1002 
1003         if (MinMax.ptMaxSize.x == UserGetSystemMetrics(SM_CXSCREEN) + 2 * xinc &&
1004             MinMax.ptMaxSize.y == UserGetSystemMetrics(SM_CYSCREEN) + 2 * yinc)
1005         {
1006             MinMax.ptMaxSize.x = (rc_work.right - rc_work.left) + 2 * xinc;
1007             MinMax.ptMaxSize.y = (rc_work.bottom - rc_work.top) + 2 * yinc;
1008         }
1009         if (MinMax.ptMaxPosition.x == -xinc && MinMax.ptMaxPosition.y == -yinc)
1010         {
1011             MinMax.ptMaxPosition.x = rc_work.left - xinc;
1012             MinMax.ptMaxPosition.y = rc_work.top - yinc;
1013         }
1014         if (MinMax.ptMaxSize.x >= (monitor->rcMonitor.right - monitor->rcMonitor.left) &&
1015             MinMax.ptMaxSize.y >= (monitor->rcMonitor.bottom - monitor->rcMonitor.top) )
1016             Window->state |= WNDS_MAXIMIZESTOMONITOR;
1017         else
1018             Window->state &= ~WNDS_MAXIMIZESTOMONITOR;
1019     }
1020 
1021 
1022    MinMax.ptMaxTrackSize.x = max(MinMax.ptMaxTrackSize.x,
1023                                  MinMax.ptMinTrackSize.x);
1024    MinMax.ptMaxTrackSize.y = max(MinMax.ptMaxTrackSize.y,
1025                                  MinMax.ptMinTrackSize.y);
1026 
1027    if (MaxSize)
1028       *MaxSize = MinMax.ptMaxSize;
1029    if (MaxPos)
1030       *MaxPos = MinMax.ptMaxPosition;
1031    if (MinTrack)
1032       *MinTrack = MinMax.ptMinTrackSize;
1033    if (MaxTrack)
1034       *MaxTrack = MinMax.ptMaxTrackSize;
1035 
1036    return 0; // FIXME: What does it return?
1037 }
1038 
1039 static
1040 BOOL
1041 IntValidateParent(PWND Child, PREGION ValidateRgn)
1042 {
1043    PWND ParentWnd = Child;
1044 
1045    if (ParentWnd->style & WS_CHILD)
1046    {
1047       do
1048          ParentWnd = ParentWnd->spwndParent;
1049       while (ParentWnd->style & WS_CHILD);
1050    }
1051 
1052    ParentWnd = Child->spwndParent;
1053    while (ParentWnd)
1054    {
1055       if (ParentWnd->style & WS_CLIPCHILDREN)
1056          break;
1057 
1058       if (ParentWnd->hrgnUpdate != 0)
1059       {
1060          IntInvalidateWindows( ParentWnd,
1061                                ValidateRgn,
1062                                RDW_VALIDATE | RDW_NOCHILDREN);
1063       }
1064 
1065       ParentWnd = ParentWnd->spwndParent;
1066    }
1067 
1068    return TRUE;
1069 }
1070 
1071 static
1072 VOID FASTCALL
1073 FixClientRect(PRECTL ClientRect, PRECTL WindowRect)
1074 {
1075    if (ClientRect->left < WindowRect->left)
1076    {
1077       ClientRect->left = WindowRect->left;
1078    }
1079    else if (WindowRect->right < ClientRect->left)
1080    {
1081       ClientRect->left = WindowRect->right;
1082    }
1083    if (ClientRect->right < WindowRect->left)
1084    {
1085       ClientRect->right = WindowRect->left;
1086    }
1087    else if (WindowRect->right < ClientRect->right)
1088    {
1089       ClientRect->right = WindowRect->right;
1090    }
1091    if (ClientRect->top < WindowRect->top)
1092    {
1093       ClientRect->top = WindowRect->top;
1094    }
1095    else if (WindowRect->bottom < ClientRect->top)
1096    {
1097       ClientRect->top = WindowRect->bottom;
1098    }
1099    if (ClientRect->bottom < WindowRect->top)
1100    {
1101       ClientRect->bottom = WindowRect->top;
1102    }
1103    else if (WindowRect->bottom < ClientRect->bottom)
1104    {
1105       ClientRect->bottom = WindowRect->bottom;
1106    }
1107 }
1108 /***********************************************************************
1109  *           get_valid_rects
1110  *
1111  * Compute the valid rects from the old and new client rect and WVR_* flags.
1112  * Helper for WM_NCCALCSIZE handling.
1113  */
1114 static
1115 VOID FASTCALL
1116 get_valid_rects( RECTL *old_client, RECTL *new_client, UINT flags, RECTL *valid )
1117 {
1118     int cx, cy;
1119 
1120     if (flags & WVR_REDRAW)
1121     {
1122         RECTL_vSetEmptyRect( &valid[0] );
1123         RECTL_vSetEmptyRect( &valid[1] );
1124         return;
1125     }
1126 
1127     if (flags & WVR_VALIDRECTS)
1128     {
1129         if (!RECTL_bIntersectRect( &valid[0], &valid[0], new_client ) ||
1130             !RECTL_bIntersectRect( &valid[1], &valid[1], old_client ))
1131         {
1132             RECTL_vSetEmptyRect( &valid[0] );
1133             RECTL_vSetEmptyRect( &valid[1] );
1134             return;
1135         }
1136         flags = WVR_ALIGNLEFT | WVR_ALIGNTOP;
1137     }
1138     else
1139     {
1140         valid[0] = *new_client;
1141         valid[1] = *old_client;
1142     }
1143 
1144     /* make sure the rectangles have the same size */
1145     cx = min( valid[0].right - valid[0].left, valid[1].right - valid[1].left );
1146     cy = min( valid[0].bottom - valid[0].top, valid[1].bottom - valid[1].top );
1147 
1148     if (flags & WVR_ALIGNBOTTOM)
1149     {
1150         valid[0].top = valid[0].bottom - cy;
1151         valid[1].top = valid[1].bottom - cy;
1152     }
1153     else
1154     {
1155         valid[0].bottom = valid[0].top + cy;
1156         valid[1].bottom = valid[1].top + cy;
1157     }
1158     if (flags & WVR_ALIGNRIGHT)
1159     {
1160         valid[0].left = valid[0].right - cx;
1161         valid[1].left = valid[1].right - cx;
1162     }
1163     else
1164     {
1165         valid[0].right = valid[0].left + cx;
1166         valid[1].right = valid[1].left + cx;
1167     }
1168 }
1169 
1170 static
1171 LONG FASTCALL
1172 co_WinPosDoNCCALCSize(PWND Window, PWINDOWPOS WinPos, RECTL* WindowRect, RECTL* ClientRect, RECTL* validRects)
1173 {
1174    PWND Parent;
1175    UINT wvrFlags = 0;
1176 
1177    ASSERT_REFS_CO(Window);
1178 
1179    /* Send WM_NCCALCSIZE message to get new client area */
1180    if ((WinPos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE)
1181    {
1182       NCCALCSIZE_PARAMS params;
1183       WINDOWPOS winposCopy;
1184 
1185       params.rgrc[0] = *WindowRect;      // new coordinates of a window that has been moved or resized
1186       params.rgrc[1] = Window->rcWindow; // window before it was moved or resized
1187       params.rgrc[2] = Window->rcClient; // client area before the window was moved or resized
1188 
1189       Parent = Window->spwndParent;
1190       if (0 != (Window->style & WS_CHILD) && Parent)
1191       {
1192          RECTL_vOffsetRect(&(params.rgrc[0]), - Parent->rcClient.left, - Parent->rcClient.top);
1193          RECTL_vOffsetRect(&(params.rgrc[1]), - Parent->rcClient.left, - Parent->rcClient.top);
1194          RECTL_vOffsetRect(&(params.rgrc[2]), - Parent->rcClient.left, - Parent->rcClient.top);
1195       }
1196 
1197       params.lppos = &winposCopy;
1198       winposCopy = *WinPos;
1199 
1200       wvrFlags = co_IntSendMessage(Window->head.h, WM_NCCALCSIZE, TRUE, (LPARAM) &params);
1201 
1202       /* If the application send back garbage, ignore it */
1203       if (params.rgrc[0].left <= params.rgrc[0].right &&
1204           params.rgrc[0].top <= params.rgrc[0].bottom)
1205       {
1206          *ClientRect = params.rgrc[0]; // First rectangle contains the coordinates of the new client rectangle resulting from the move or resize
1207          if ((Window->style & WS_CHILD) && Parent)
1208          {
1209             RECTL_vOffsetRect(ClientRect, Parent->rcClient.left, Parent->rcClient.top);
1210          }
1211          FixClientRect(ClientRect, WindowRect);
1212       }
1213 
1214       if (ClientRect->left != Window->rcClient.left ||
1215           ClientRect->top != Window->rcClient.top)
1216       {
1217          WinPos->flags &= ~SWP_NOCLIENTMOVE;
1218       }
1219 
1220       if (ClientRect->right - ClientRect->left != Window->rcClient.right - Window->rcClient.left)
1221       {
1222          WinPos->flags &= ~SWP_NOCLIENTSIZE;
1223       }
1224       else
1225          wvrFlags &= ~WVR_HREDRAW;
1226 
1227       if (ClientRect->bottom - ClientRect->top != Window->rcClient.bottom - Window->rcClient.top)
1228       {
1229          WinPos->flags &= ~SWP_NOCLIENTSIZE;
1230       }
1231       else
1232          wvrFlags &= ~WVR_VREDRAW;
1233 
1234       validRects[0] = params.rgrc[1]; // second rectangle contains the valid destination rectangle
1235       validRects[1] = params.rgrc[2]; // third rectangle contains the valid source rectangle
1236    }
1237    else
1238    {
1239       if (!(WinPos->flags & SWP_NOMOVE) &&
1240           (ClientRect->left != Window->rcClient.left ||
1241            ClientRect->top != Window->rcClient.top))
1242       {
1243          WinPos->flags &= ~SWP_NOCLIENTMOVE;
1244       }
1245    }
1246 
1247    if (WinPos->flags & (SWP_NOCOPYBITS | SWP_NOREDRAW | SWP_SHOWWINDOW | SWP_HIDEWINDOW))
1248    {
1249       RECTL_vSetEmptyRect( &validRects[0] );
1250       RECTL_vSetEmptyRect( &validRects[1] );
1251    }
1252    else get_valid_rects( &Window->rcClient, ClientRect, wvrFlags, validRects );
1253 
1254    return wvrFlags;
1255 }
1256 
1257 static
1258 BOOL FASTCALL
1259 co_WinPosDoWinPosChanging(PWND Window,
1260                           PWINDOWPOS WinPos,
1261                           PRECTL WindowRect,
1262                           PRECTL ClientRect)
1263 {
1264    ASSERT_REFS_CO(Window);
1265 
1266    /* Send WM_WINDOWPOSCHANGING message */
1267 
1268    if (!(WinPos->flags & SWP_NOSENDCHANGING)
1269           && !((WinPos->flags & SWP_AGG_NOCLIENTCHANGE) && (WinPos->flags & SWP_SHOWWINDOW)))
1270    {
1271       TRACE("Sending WM_WINDOWPOSCHANGING to hwnd %p flags %04x.\n", Window->head.h,WinPos->flags);
1272       co_IntSendMessage(Window->head.h, WM_WINDOWPOSCHANGING, 0, (LPARAM) WinPos);
1273    }
1274 
1275    /* Calculate new position and size */
1276 
1277    *WindowRect = Window->rcWindow;
1278    *ClientRect = (Window->style & WS_MINIMIZE) ? Window->rcWindow : Window->rcClient;
1279 
1280    if (!(WinPos->flags & SWP_NOSIZE))
1281    {
1282       if (Window->style & WS_MINIMIZE)
1283       {
1284          WindowRect->right  = WindowRect->left + UserGetSystemMetrics(SM_CXMINIMIZED);
1285          WindowRect->bottom = WindowRect->top  + UserGetSystemMetrics(SM_CYMINIMIZED);
1286       }
1287       else
1288       {
1289          WindowRect->right = WindowRect->left + WinPos->cx;
1290          WindowRect->bottom = WindowRect->top + WinPos->cy;
1291       }
1292    }
1293 
1294    if (!(WinPos->flags & SWP_NOMOVE))
1295    {
1296       INT X, Y;
1297       PWND Parent;
1298       X = WinPos->x;
1299       Y = WinPos->y;
1300 
1301       Parent = Window->spwndParent;
1302 
1303       // Parent child position issue is in here. SetParent_W7 test CORE-6651.
1304       if (//((Window->style & WS_CHILD) != 0) && <- Fixes wine msg test_SetParent: "rects do not match", the last test.
1305            Parent &&
1306            Parent != Window->head.rpdesk->pDeskInfo->spwnd)
1307       {
1308          TRACE("Not SWP_NOMOVE 1 Parent client offset X %d Y %d\n",X,Y);
1309          X += Parent->rcClient.left;
1310          Y += Parent->rcClient.top;
1311          TRACE("Not SWP_NOMOVE 2 Parent client offset X %d Y %d\n",X,Y);
1312       }
1313 
1314       WindowRect->left    = X;
1315       WindowRect->top     = Y;
1316       WindowRect->right  += X - Window->rcWindow.left;
1317       WindowRect->bottom += Y - Window->rcWindow.top;
1318 
1319       RECTL_vOffsetRect(ClientRect, X - Window->rcWindow.left,
1320                                     Y - Window->rcWindow.top);
1321    }
1322    WinPos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
1323 
1324    TRACE( "hwnd %p, after %p, swp %d,%d %dx%d flags %08x\n",
1325            WinPos->hwnd, WinPos->hwndInsertAfter, WinPos->x, WinPos->y,
1326            WinPos->cx, WinPos->cy, WinPos->flags );
1327    TRACE("WindowRect: %d %d %d %d\n", WindowRect->left,WindowRect->top,WindowRect->right,WindowRect->bottom);
1328    TRACE("ClientRect: %d %d %d %d\n", ClientRect->left,ClientRect->top,ClientRect->right,ClientRect->bottom);
1329 
1330    return TRUE;
1331 }
1332 
1333 /*
1334  * Fix Z order taking into account owned popups -
1335  * basically we need to maintain them above the window that owns them
1336  *
1337  * FIXME: hide/show owned popups when owner visibility changes.
1338  *
1339  * ReactOS: See bug CORE-6129 and CORE-6554.
1340  *
1341  */
1342  ////
1343  // Pass all the win:test_children/popup_zorder tests except "move hwnd_F and its popups down" which is if'ed out.
1344  // Side effect, breaks more of the DeferWindowPos api tests, but wine breaks more!!!!
1345 static
1346 HWND FASTCALL
1347 WinPosDoOwnedPopups(PWND Window, HWND hWndInsertAfter)
1348 {
1349    HWND *List = NULL;
1350    HWND Owner;
1351    LONG Style;
1352    PWND DesktopWindow, ChildObject;
1353    int i;
1354 
1355    TRACE("(%p) hInsertAfter = %p\n", Window, hWndInsertAfter );
1356 
1357    Style = Window->style;
1358 
1359    if (Style & WS_CHILD)
1360    {
1361       TRACE("Window is child\n");
1362       return hWndInsertAfter;
1363    }
1364 
1365    Owner = Window->spwndOwner ? Window->spwndOwner->head.h : NULL;
1366 
1367    if (Owner)
1368    {
1369       /* Make sure this popup stays above the owner */
1370 
1371       if (hWndInsertAfter != HWND_TOPMOST)
1372       {
1373          DesktopWindow = UserGetDesktopWindow();
1374          List = IntWinListChildren(DesktopWindow);
1375 
1376          if (List != NULL)
1377          {
1378             for (i = 0; List[i]; i++)
1379             {
1380                BOOL topmost = FALSE;
1381 
1382                ChildObject = ValidateHwndNoErr(List[i]);
1383                if (ChildObject)
1384                {
1385                   topmost = (ChildObject->ExStyle & WS_EX_TOPMOST) != 0;
1386                }
1387 
1388                if (List[i] == Owner)
1389                {
1390                   if (i > 0) hWndInsertAfter = List[i-1];
1391                   else hWndInsertAfter = topmost ? HWND_TOPMOST : HWND_TOP;
1392                   break;
1393                }
1394 
1395                if (hWndInsertAfter == HWND_TOP || hWndInsertAfter ==  HWND_NOTOPMOST)
1396                {
1397                   if (!topmost) break;
1398                }
1399                else if (List[i] == hWndInsertAfter) break;
1400             }
1401          }
1402          else
1403             return hWndInsertAfter;
1404       }
1405    }
1406 
1407    if (hWndInsertAfter == HWND_BOTTOM)
1408    {
1409       ERR("Window is HWND_BOTTOM hwnd %p\n",hWndInsertAfter);
1410       if (List) ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
1411       goto done;
1412    }
1413 
1414    if (!List)
1415    {
1416       DesktopWindow = UserGetDesktopWindow();
1417       List = IntWinListChildren(DesktopWindow);
1418    }
1419 
1420    if (List != NULL)
1421    {
1422       i = 0;
1423 
1424       if (hWndInsertAfter == HWND_TOP || hWndInsertAfter == HWND_NOTOPMOST)
1425       {
1426          if (hWndInsertAfter == HWND_NOTOPMOST || !(Window->ExStyle & WS_EX_TOPMOST))
1427          {
1428             TRACE("skip all the topmost windows\n");
1429             /* skip all the topmost windows */
1430             while (List[i] &&
1431                    (ChildObject = ValidateHwndNoErr(List[i])) &&
1432                    (ChildObject->ExStyle & WS_EX_TOPMOST)) i++;
1433          }
1434       }
1435       else if (hWndInsertAfter != HWND_TOPMOST)
1436       {
1437         /* skip windows that are already placed correctly */
1438         for (i = 0; List[i]; i++)
1439         {
1440             if (List[i] == hWndInsertAfter) break;
1441             if (List[i] == UserHMGetHandle(Window))
1442             {
1443                ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
1444                goto done;  /* nothing to do if window is moving backwards in z-order */
1445             }
1446         }
1447       }
1448 
1449       for (; List[i]; i++)
1450       {
1451          PWND Wnd;
1452          USER_REFERENCE_ENTRY Ref;
1453 
1454          if (List[i] == UserHMGetHandle(Window))
1455             break;
1456 
1457          if (!(Wnd = ValidateHwndNoErr(List[i])))
1458             continue;
1459 
1460          Owner = Wnd->spwndOwner ? Wnd->spwndOwner->head.h : NULL;
1461 
1462          if (Owner != UserHMGetHandle(Window)) continue;
1463 
1464          UserRefObjectCo(Wnd, &Ref);
1465          TRACE( "moving %p owned by %p after %p\n", List[i], UserHMGetHandle(Window), hWndInsertAfter );
1466          co_WinPosSetWindowPos(Wnd, hWndInsertAfter, 0, 0, 0, 0,
1467                                SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING| SWP_DEFERERASE);
1468 
1469          UserDerefObjectCo(Wnd);
1470          hWndInsertAfter = List[i];
1471       }
1472       ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
1473    }
1474 done:
1475    return hWndInsertAfter;
1476 }
1477 ////
1478 
1479 /***********************************************************************
1480  *      WinPosInternalMoveWindow
1481  *
1482  * Update WindowRect and ClientRect of Window and all of its children
1483  * We keep both WindowRect and ClientRect in screen coordinates internally
1484  */
1485 static
1486 VOID FASTCALL
1487 WinPosInternalMoveWindow(PWND Window, INT MoveX, INT MoveY)
1488 {
1489    PWND Child;
1490 
1491    ASSERT(Window != Window->spwndChild);
1492    TRACE("InternalMoveWin  X %d Y %d\n", MoveX, MoveY);
1493 
1494    Window->rcWindow.left += MoveX;
1495    Window->rcWindow.right += MoveX;
1496    Window->rcWindow.top += MoveY;
1497    Window->rcWindow.bottom += MoveY;
1498 
1499    Window->rcClient.left += MoveX;
1500    Window->rcClient.right += MoveX;
1501    Window->rcClient.top += MoveY;
1502    Window->rcClient.bottom += MoveY;
1503 
1504    for(Child = Window->spwndChild; Child; Child = Child->spwndNext)
1505    {
1506       WinPosInternalMoveWindow(Child, MoveX, MoveY);
1507    }
1508 }
1509 
1510 /*
1511  * WinPosFixupSWPFlags
1512  *
1513  * Fix redundant flags and values in the WINDOWPOS structure.
1514  */
1515 static
1516 BOOL FASTCALL
1517 WinPosFixupFlags(WINDOWPOS *WinPos, PWND Wnd)
1518 {
1519    PWND Parent;
1520    POINT pt;
1521 
1522    /* Finally make sure that all coordinates are valid */
1523    if (WinPos->x < -32768) WinPos->x = -32768;
1524    else if (WinPos->x > 32767) WinPos->x = 32767;
1525    if (WinPos->y < -32768) WinPos->y = -32768;
1526    else if (WinPos->y > 32767) WinPos->y = 32767;
1527 
1528    WinPos->cx = max(WinPos->cx, 0);
1529    WinPos->cy = max(WinPos->cy, 0);
1530 
1531    Parent = UserGetAncestor( Wnd, GA_PARENT );
1532    if (!IntIsWindowVisible( Parent ) &&
1533       /* Fix B : wine msg test_SetParent:WmSetParentSeq_2:25 wParam bits! */
1534        (WinPos->flags & SWP_AGG_STATUSFLAGS) == SWP_AGG_NOPOSCHANGE) WinPos->flags |= SWP_NOREDRAW;
1535 
1536    if (Wnd->style & WS_VISIBLE) WinPos->flags &= ~SWP_SHOWWINDOW;
1537    else
1538    {
1539       WinPos->flags &= ~SWP_HIDEWINDOW;
1540       if (!(WinPos->flags & SWP_SHOWWINDOW)) WinPos->flags |= SWP_NOREDRAW;
1541    }
1542 
1543    /* Check for right size */
1544    if (Wnd->rcWindow.right - Wnd->rcWindow.left == WinPos->cx &&
1545        Wnd->rcWindow.bottom - Wnd->rcWindow.top == WinPos->cy)
1546    {
1547       WinPos->flags |= SWP_NOSIZE;
1548    }
1549 
1550    pt.x = WinPos->x;
1551    pt.y = WinPos->y;
1552    IntClientToScreen( Parent, &pt );
1553    TRACE("WPFU C2S wpx %d wpy %d ptx %d pty %d\n",WinPos->x,WinPos->y,pt.x,pt.y);
1554    /* Check for right position */
1555    if (Wnd->rcWindow.left == pt.x && Wnd->rcWindow.top == pt.y)
1556    {
1557       //ERR("In right pos\n");
1558       WinPos->flags |= SWP_NOMOVE;
1559    }
1560 
1561    if ( WinPos->hwnd != UserGetForegroundWindow() && (Wnd->style & (WS_POPUP | WS_CHILD)) != WS_CHILD)
1562    {
1563       /* Bring to the top when activating */
1564       if (!(WinPos->flags & (SWP_NOACTIVATE|SWP_HIDEWINDOW)) &&
1565            (WinPos->flags & SWP_NOZORDER ||
1566            (WinPos->hwndInsertAfter != HWND_TOPMOST && WinPos->hwndInsertAfter != HWND_NOTOPMOST)))
1567       {
1568          WinPos->flags &= ~SWP_NOZORDER;
1569          WinPos->hwndInsertAfter = (0 != (Wnd->ExStyle & WS_EX_TOPMOST) ? HWND_TOPMOST : HWND_TOP);
1570       }
1571    }
1572 
1573    /* Check hwndInsertAfter */
1574    if (!(WinPos->flags & SWP_NOZORDER))
1575    {
1576       /* Fix sign extension */
1577       if (WinPos->hwndInsertAfter == (HWND)0xffff)
1578       {
1579          WinPos->hwndInsertAfter = HWND_TOPMOST;
1580       }
1581       else if (WinPos->hwndInsertAfter == (HWND)0xfffe)
1582       {
1583          WinPos->hwndInsertAfter = HWND_NOTOPMOST;
1584       }
1585 
1586       if (WinPos->hwndInsertAfter == HWND_TOP)
1587       {
1588          /* Keep it topmost when it's already topmost */
1589          if ((Wnd->ExStyle & WS_EX_TOPMOST) != 0)
1590             WinPos->hwndInsertAfter = HWND_TOPMOST;
1591 
1592          if (IntGetWindow(WinPos->hwnd, GW_HWNDFIRST) == WinPos->hwnd)
1593          {
1594             WinPos->flags |= SWP_NOZORDER;
1595          }
1596       }
1597       else if (WinPos->hwndInsertAfter == HWND_BOTTOM)
1598       {
1599          if (!(Wnd->ExStyle & WS_EX_TOPMOST) && IntGetWindow(WinPos->hwnd, GW_HWNDLAST) == WinPos->hwnd)
1600             WinPos->flags |= SWP_NOZORDER;
1601       }
1602       else if (WinPos->hwndInsertAfter == HWND_TOPMOST)
1603       {
1604           if ((Wnd->ExStyle & WS_EX_TOPMOST) && IntGetWindow(WinPos->hwnd, GW_HWNDFIRST) == WinPos->hwnd)
1605              WinPos->flags |= SWP_NOZORDER;
1606       }
1607       else if (WinPos->hwndInsertAfter == HWND_NOTOPMOST)
1608       {
1609          if (!(Wnd->ExStyle & WS_EX_TOPMOST))
1610             WinPos->flags |= SWP_NOZORDER;
1611       }
1612       else /* hwndInsertAfter must be a sibling of the window */
1613       {
1614          PWND InsAfterWnd;
1615 
1616          InsAfterWnd = ValidateHwndNoErr(WinPos->hwndInsertAfter);
1617          if(!InsAfterWnd)
1618          {
1619              return TRUE;
1620          }
1621 
1622          if (InsAfterWnd->spwndParent != Wnd->spwndParent)
1623          {
1624             /* Note from wine User32 Win test_SetWindowPos:
1625                "Returns TRUE also for windows that are not siblings"
1626                "Does not seem to do anything even without passing flags, still returns TRUE"
1627                "Same thing the other way around."
1628                ".. and with these windows."
1629              */
1630             return FALSE;
1631          }
1632          else
1633          {
1634             /*
1635              * We don't need to change the Z order of hwnd if it's already
1636              * inserted after hwndInsertAfter or when inserting hwnd after
1637              * itself.
1638              */
1639             if ((WinPos->hwnd == WinPos->hwndInsertAfter) ||
1640                 ((InsAfterWnd->spwndNext) && (WinPos->hwnd == InsAfterWnd->spwndNext->head.h)))
1641             {
1642                WinPos->flags |= SWP_NOZORDER;
1643             }
1644          }
1645       }
1646    }
1647 
1648    return TRUE;
1649 }
1650 
1651 /* x and y are always screen relative */
1652 BOOLEAN FASTCALL
1653 co_WinPosSetWindowPos(
1654    PWND Window,
1655    HWND WndInsertAfter,
1656    INT x,
1657    INT y,
1658    INT cx,
1659    INT cy,
1660    UINT flags
1661    )
1662 {
1663    WINDOWPOS WinPos;
1664    RECTL NewWindowRect;
1665    RECTL NewClientRect;
1666    RECTL valid_rects[2];
1667    PREGION VisBefore = NULL;
1668    PREGION VisBeforeJustClient = NULL;
1669    PREGION VisAfter = NULL;
1670    PREGION CopyRgn = NULL;
1671    ULONG WvrFlags = 0;
1672    RECTL OldWindowRect, OldClientRect;
1673    int RgnType;
1674    HDC Dc;
1675    RECTL CopyRect;
1676    PWND Ancestor;
1677    BOOL bPointerInWindow, PosChanged = FALSE;
1678    PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
1679 
1680    ASSERT_REFS_CO(Window);
1681 
1682    TRACE("pwnd %p, after %p, %d,%d (%dx%d), flags %s",
1683           Window, WndInsertAfter, x, y, cx, cy, flags);
1684 #if DBG
1685    dump_winpos_flags(flags);
1686 #endif
1687 
1688    /* FIXME: Get current active window from active queue. Why? since r2915. */
1689 
1690    bPointerInWindow = IntPtInWindow(Window, gpsi->ptCursor.x, gpsi->ptCursor.y);
1691 
1692    WinPos.hwnd = Window->head.h;
1693    WinPos.hwndInsertAfter = WndInsertAfter;
1694    WinPos.x = x;
1695    WinPos.y = y;
1696    WinPos.cx = cx;
1697    WinPos.cy = cy;
1698    WinPos.flags = flags;
1699 
1700    if ( flags & SWP_ASYNCWINDOWPOS )
1701    {
1702       LRESULT lRes;
1703       PWINDOWPOS ppos = ExAllocatePoolWithTag(PagedPool, sizeof(WINDOWPOS), USERTAG_SWP);
1704       if ( ppos )
1705       {
1706          WinPos.flags &= ~SWP_ASYNCWINDOWPOS; // Clear flag.
1707          *ppos = WinPos;
1708          /* Yes it's a pointer inside Win32k! */
1709          lRes = co_IntSendMessageNoWait( WinPos.hwnd, WM_ASYNC_SETWINDOWPOS, 0, (LPARAM)ppos);
1710          /* We handle this the same way as Event Hooks and Hooks. */
1711          if ( !lRes )
1712          {
1713             ExFreePoolWithTag(ppos, USERTAG_SWP);
1714             return FALSE;
1715          }
1716          return TRUE;
1717       }
1718       return FALSE;
1719    }
1720 
1721    co_WinPosDoWinPosChanging(Window, &WinPos, &NewWindowRect, &NewClientRect);
1722 
1723    /* Does the window still exist? */
1724    if (!IntIsWindow(WinPos.hwnd))
1725    {
1726       TRACE("WinPosSetWindowPos: Invalid handle 0x%p!\n",WinPos.hwnd);
1727       EngSetLastError(ERROR_INVALID_WINDOW_HANDLE);
1728       return FALSE;
1729    }
1730 
1731    /* Fix up the flags. */
1732    if (!WinPosFixupFlags(&WinPos, Window))
1733    {
1734       // See Note.
1735       return TRUE;
1736    }
1737 
1738    Ancestor = UserGetAncestor(Window, GA_PARENT);
1739    if ( (WinPos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER &&
1740          Ancestor && Ancestor->head.h == IntGetDesktopWindow() )
1741    {
1742       WinPos.hwndInsertAfter = WinPosDoOwnedPopups(Window, WinPos.hwndInsertAfter);
1743    }
1744 
1745    if (!(WinPos.flags & SWP_NOREDRAW))
1746    {
1747       /* Compute the visible region before the window position is changed */
1748       if (!(WinPos.flags & SWP_SHOWWINDOW) &&
1749            (WinPos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
1750                              SWP_HIDEWINDOW | SWP_FRAMECHANGED)) !=
1751             (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER))
1752       {
1753          VisBefore = VIS_ComputeVisibleRegion(Window, FALSE, FALSE,
1754                                               (Window->style & WS_CLIPSIBLINGS) ? TRUE : FALSE);
1755 
1756          if ( VisBefore != NULL &&
1757               REGION_Complexity(VisBefore) == NULLREGION )
1758          {
1759             REGION_Delete(VisBefore);
1760             VisBefore = NULL;
1761          }
1762          else if(VisBefore)
1763          {
1764             REGION_bOffsetRgn(VisBefore, -Window->rcWindow.left, -Window->rcWindow.top);
1765          }
1766 
1767          /* Calculate the non client area for resizes, as this is used in the copy region */
1768          if (!(WinPos.flags & SWP_NOSIZE))
1769          {
1770              VisBeforeJustClient = VIS_ComputeVisibleRegion(Window, TRUE, FALSE,
1771                  (Window->style & WS_CLIPSIBLINGS) ? TRUE : FALSE);
1772 
1773              if ( VisBeforeJustClient != NULL &&
1774                  REGION_Complexity(VisBeforeJustClient) == NULLREGION )
1775              {
1776                  REGION_Delete(VisBeforeJustClient);
1777                  VisBeforeJustClient = NULL;
1778              }
1779              else if(VisBeforeJustClient)
1780              {
1781                  REGION_bOffsetRgn(VisBeforeJustClient, -Window->rcWindow.left, -Window->rcWindow.top);
1782              }
1783          }
1784       }
1785    }
1786 
1787    //// HACK 3
1788    if (Window->hrgnNewFrame)
1789    {
1790        SelectWindowRgn( Window, Window->hrgnNewFrame ); // Should be PSMWP->acvr->hrgnClip
1791        Window->hrgnNewFrame = NULL;
1792    }
1793 
1794    WvrFlags = co_WinPosDoNCCALCSize(Window, &WinPos, &NewWindowRect, &NewClientRect, valid_rects);
1795 
1796 //   ERR("co_WinPosDoNCCALCSize returned 0x%x\n valid dest: %d %d %d %d\n valid src : %d %d %d %d\n", WvrFlags,
1797 //      valid_rects[0].left,valid_rects[0].top,valid_rects[0].right,valid_rects[0].bottom,
1798 //      valid_rects[1].left,valid_rects[1].top,valid_rects[1].right,valid_rects[1].bottom);
1799 
1800    /* Validate link windows. (also take into account shell window in hwndShellWindow) */
1801    if (!(WinPos.flags & SWP_NOZORDER) && WinPos.hwnd != UserGetShellWindow())
1802    {
1803       IntLinkHwnd(Window, WinPos.hwndInsertAfter);
1804    }
1805 
1806    OldWindowRect = Window->rcWindow;
1807    OldClientRect = Window->rcClient;
1808 
1809    if (NewClientRect.left != OldClientRect.left ||
1810        NewClientRect.top  != OldClientRect.top)
1811    {
1812       // Move child window if their parent is moved. Keep Child window relative to Parent...
1813       WinPosInternalMoveWindow(Window,
1814                                NewClientRect.left - OldClientRect.left,
1815                                NewClientRect.top - OldClientRect.top);
1816       PosChanged = TRUE;
1817    }
1818 
1819    Window->rcWindow = NewWindowRect;
1820    Window->rcClient = NewClientRect;
1821 
1822    /* erase parent when hiding or resizing child */
1823    if (WinPos.flags & SWP_HIDEWINDOW)
1824    {
1825       /* Clear the update region */
1826       co_UserRedrawWindow( Window,
1827                            NULL,
1828                            0,
1829                            RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_ALLCHILDREN);
1830 
1831       if (UserIsDesktopWindow(Window->spwndParent))
1832          co_IntShellHookNotify(HSHELL_WINDOWDESTROYED, (WPARAM)Window->head.h, 0);
1833 
1834       Window->style &= ~WS_VISIBLE; //IntSetStyle( Window, 0, WS_VISIBLE );
1835       Window->head.pti->cVisWindows--;
1836       IntNotifyWinEvent(EVENT_OBJECT_HIDE, Window, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI);
1837    }
1838    else if (WinPos.flags & SWP_SHOWWINDOW)
1839    {
1840        if (UserIsDesktopWindow(Window->spwndParent) &&
1841            Window->spwndOwner == NULL &&
1842            (!(Window->ExStyle & WS_EX_TOOLWINDOW) ||
1843             (Window->ExStyle & WS_EX_APPWINDOW)))
1844          co_IntShellHookNotify(HSHELL_WINDOWCREATED, (WPARAM)Window->head.h, 0);
1845 
1846       Window->style |= WS_VISIBLE; //IntSetStyle( Window, WS_VISIBLE, 0 );
1847       Window->head.pti->cVisWindows++;
1848       IntNotifyWinEvent(EVENT_OBJECT_SHOW, Window, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI);
1849    }
1850 
1851    if (Window->hrgnUpdate != NULL && Window->hrgnUpdate != HRGN_WINDOW)
1852    {
1853       NtGdiOffsetRgn(Window->hrgnUpdate,
1854                      NewWindowRect.left - OldWindowRect.left,
1855                      NewWindowRect.top - OldWindowRect.top);
1856    }
1857 
1858    DceResetActiveDCEs(Window); // For WS_VISIBLE changes.
1859 
1860    if (!(WinPos.flags & SWP_NOREDRAW))
1861    {
1862       /* Determine the new visible region */
1863       VisAfter = VIS_ComputeVisibleRegion(Window, FALSE, FALSE,
1864                                           (Window->style & WS_CLIPSIBLINGS) ? TRUE : FALSE);
1865 
1866       if ( VisAfter != NULL &&
1867            REGION_Complexity(VisAfter) == NULLREGION )
1868       {
1869          REGION_Delete(VisAfter);
1870          VisAfter = NULL;
1871       }
1872       else if(VisAfter)
1873       {
1874          REGION_bOffsetRgn(VisAfter, -Window->rcWindow.left, -Window->rcWindow.top);
1875       }
1876 
1877       /*
1878        * Determine which pixels can be copied from the old window position
1879        * to the new. Those pixels must be visible in both the old and new
1880        * position. Also, check the class style to see if the windows of this
1881        * class need to be completely repainted on (horizontal/vertical) size
1882        * change.
1883        */
1884       if ( ( VisBefore != NULL &&
1885              VisAfter != NULL &&
1886             !(WinPos.flags & SWP_NOCOPYBITS) &&
1887             ((WinPos.flags & SWP_NOSIZE) || !(WvrFlags & WVR_REDRAW)) &&
1888             !(Window->ExStyle & WS_EX_TRANSPARENT) ) ||
1889             ( !PosChanged && (WinPos.flags & SWP_FRAMECHANGED) && VisBefore) )
1890       {
1891 
1892          /*
1893           * If this is (also) a window resize, the whole nonclient area
1894           * needs to be repainted. So we limit the copy to the client area,
1895           * 'cause there is no use in copying it (would possibly cause
1896           * "flashing" too). However, if the copy region is already empty,
1897           * we don't have to crop (can't take anything away from an empty
1898           * region...)
1899           */
1900 
1901          CopyRgn = IntSysCreateRectpRgn(0, 0, 0, 0);
1902          if (WinPos.flags & SWP_NOSIZE)
1903             RgnType = IntGdiCombineRgn(CopyRgn, VisAfter, VisBefore, RGN_AND);
1904          else if (VisBeforeJustClient != NULL)
1905          {
1906             RgnType = IntGdiCombineRgn(CopyRgn, VisAfter, VisBeforeJustClient, RGN_AND);
1907             REGION_Delete(VisBeforeJustClient);
1908          }
1909 
1910          /* Now use in copying bits which are in the update region. */
1911          if (Window->hrgnUpdate != NULL)
1912          {
1913             PREGION RgnUpdate = REGION_LockRgn(Window->hrgnUpdate);
1914             if (RgnUpdate)
1915             {
1916                 REGION_bOffsetRgn(CopyRgn, NewWindowRect.left, NewWindowRect.top);
1917                 IntGdiCombineRgn(CopyRgn, CopyRgn, RgnUpdate, RGN_DIFF);
1918                 REGION_bOffsetRgn(CopyRgn, -NewWindowRect.left, -NewWindowRect.top);
1919                 REGION_UnlockRgn(RgnUpdate);
1920             }
1921          }
1922 
1923          /*
1924           * Now, get the bounding box of the copy region. If it's empty
1925           * there's nothing to copy. Also, it's no use copying bits onto
1926           * themselves.
1927           */
1928          if (REGION_GetRgnBox(CopyRgn, &CopyRect) == NULLREGION)
1929          {
1930             /* Nothing to copy, clean up */
1931             REGION_Delete(CopyRgn);
1932             CopyRgn = NULL;
1933          }
1934          else if ( OldWindowRect.left != NewWindowRect.left ||
1935                    OldWindowRect.top != NewWindowRect.top ||
1936                   (WinPos.flags & SWP_FRAMECHANGED) )
1937          {
1938              HRGN DcRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
1939              PREGION DcRgnObj = REGION_LockRgn(DcRgn);
1940 
1941           /*
1942            * Small trick here: there is no function to bitblt a region. So
1943            * we set the region as the clipping region, take the bounding box
1944            * of the region and bitblt that. Since nothing outside the clipping
1945            * region is copied, this has the effect of bitblt'ing the region.
1946            *
1947            * Since NtUserGetDCEx takes ownership of the clip region, we need
1948            * to create a copy of CopyRgn and pass that. We need CopyRgn later
1949            */
1950             IntGdiCombineRgn(DcRgnObj, CopyRgn, NULL, RGN_COPY);
1951             REGION_bOffsetRgn(DcRgnObj, NewWindowRect.left, NewWindowRect.top);
1952             REGION_UnlockRgn(DcRgnObj);
1953             Dc = UserGetDCEx( Window,
1954                               DcRgn,
1955                               DCX_WINDOW|DCX_CACHE|DCX_INTERSECTRGN|DCX_CLIPSIBLINGS|DCX_KEEPCLIPRGN);
1956             NtGdiBitBlt( Dc,
1957                          CopyRect.left, CopyRect.top,
1958                          CopyRect.right - CopyRect.left,
1959                          CopyRect.bottom - CopyRect.top,
1960                          Dc,
1961                          CopyRect.left + (OldWindowRect.left - NewWindowRect.left),
1962                          CopyRect.top + (OldWindowRect.top - NewWindowRect.top),
1963                          SRCCOPY,
1964                          0,
1965                          0);
1966 
1967             UserReleaseDC(Window, Dc, FALSE);
1968             IntValidateParent(Window, CopyRgn);
1969             GreDeleteObject(DcRgn);
1970          }
1971       }
1972       else
1973       {
1974          CopyRgn = NULL;
1975       }
1976 #if 0
1977       /////// Fixes NoPopup tests but breaks msg_paint tests.
1978       if ( !PosChanged && (WinPos.flags & SWP_FRAMECHANGED) && VisBefore)
1979       {
1980          PWND Parent = Window->spwndParent;
1981          ERR("SWP_FRAMECHANGED no chg\n");
1982          if ( !(Window->style & WS_CHILD) && (Parent) && (Parent->style & WS_CLIPCHILDREN))
1983          {
1984             ERR("SWP_FRAMECHANGED Parent WS_CLIPCHILDREN\n");
1985             //IntInvalidateWindows( Window, VisBefore, /*RDW_ERASE |*/ RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
1986          }
1987       }
1988 #endif
1989       /* We need to redraw what wasn't visible before */
1990       if (VisAfter != NULL)
1991       {
1992          PREGION DirtyRgn = IntSysCreateRectpRgn(0, 0, 0, 0);
1993          if (DirtyRgn)
1994          {
1995              if (CopyRgn != NULL)
1996              {
1997                 RgnType = IntGdiCombineRgn(DirtyRgn, VisAfter, CopyRgn, RGN_DIFF);
1998              }
1999              else
2000              {
2001                 RgnType = IntGdiCombineRgn(DirtyRgn, VisAfter, 0, RGN_COPY);
2002              }
2003 
2004              if (RgnType != ERROR && RgnType != NULLREGION)
2005              {
2006             /* old code
2007                 NtGdiOffsetRgn(DirtyRgn, Window->rcWindow.left, Window->rcWindow.top);
2008                 IntInvalidateWindows( Window,
2009                                       DirtyRgn,
2010                    RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
2011              }
2012              GreDeleteObject(DirtyRgn);
2013              */
2014 
2015                 PWND Parent = Window->spwndParent;
2016 
2017                 REGION_bOffsetRgn( DirtyRgn, Window->rcWindow.left, Window->rcWindow.top);
2018 
2019                 if ( (Window->style & WS_CHILD) && (Parent) && !(Parent->style & WS_CLIPCHILDREN))
2020                 {
2021                    IntInvalidateWindows( Parent, DirtyRgn, RDW_ERASE | RDW_INVALIDATE);
2022                    co_IntPaintWindows(Parent, RDW_NOCHILDREN, FALSE);
2023                 }
2024                 else
2025                 {
2026                    IntInvalidateWindows( Window, DirtyRgn, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
2027                 }
2028              }
2029              REGION_Delete(DirtyRgn);
2030          }
2031       }
2032 
2033       if (CopyRgn != NULL)
2034       {
2035          REGION_Delete(CopyRgn);
2036       }
2037 
2038       /* Expose what was covered before but not covered anymore */
2039       if (VisBefore != NULL)
2040       {
2041          PREGION ExposedRgn = IntSysCreateRectpRgn(0, 0, 0, 0);
2042          if (ExposedRgn)
2043          {
2044              RgnType = IntGdiCombineRgn(ExposedRgn, VisBefore, NULL, RGN_COPY);
2045              REGION_bOffsetRgn(ExposedRgn,
2046                                OldWindowRect.left - NewWindowRect.left,
2047                                OldWindowRect.top  - NewWindowRect.top);
2048 
2049              if (VisAfter != NULL)
2050                 RgnType = IntGdiCombineRgn(ExposedRgn, ExposedRgn, VisAfter, RGN_DIFF);
2051 
2052              if (RgnType != ERROR && RgnType != NULLREGION)
2053              {
2054                 co_VIS_WindowLayoutChanged(Window, ExposedRgn);
2055              }
2056              REGION_Delete(ExposedRgn);
2057          }
2058          REGION_Delete(VisBefore);
2059       }
2060 
2061       if (VisAfter != NULL)
2062       {
2063          REGION_Delete(VisAfter);
2064       }
2065    }
2066 
2067    if (!(WinPos.flags & (SWP_NOACTIVATE|SWP_HIDEWINDOW)))
2068    {
2069       if ((Window->style & (WS_CHILD | WS_POPUP)) == WS_CHILD)
2070       {
2071          co_IntSendMessageNoWait(WinPos.hwnd, WM_CHILDACTIVATE, 0, 0);
2072       }
2073       else
2074       {
2075          //ERR("SetWindowPos Set FG Window!\n");
2076          if ( pti->MessageQueue->spwndActive != Window ||
2077               pti->MessageQueue != gpqForeground )
2078          {
2079             //ERR("WPSWP : set active window\n");
2080             if (!(Window->state & WNDS_BEINGACTIVATED)) // Inside SAW?
2081             {
2082                co_IntSetForegroundWindow(Window); // Fixes SW_HIDE issues. Wine win test_SetActiveWindow & test_SetForegroundWindow.
2083             }
2084          }
2085       }
2086    }
2087 
2088    if ( !PosChanged &&
2089          (WinPos.flags & SWP_FRAMECHANGED) &&
2090         !(WinPos.flags & SWP_DEFERERASE) &&    // Prevent sending WM_SYNCPAINT message.
2091          VisAfter )
2092    {
2093        PWND Parent = Window->spwndParent;
2094        if ( !(Window->style & WS_CHILD) && (Parent) && (Parent->style & WS_CLIPCHILDREN))
2095        {
2096            TRACE("SWP_FRAMECHANGED Parent WS_CLIPCHILDREN\n");
2097            UserSyncAndPaintWindows( Parent, RDW_CLIPCHILDREN);
2098        }
2099    }
2100 
2101    // Fix wine msg test_SetFocus, prevents sending WM_WINDOWPOSCHANGED.
2102    if ( VisBefore == NULL &&
2103         VisBeforeJustClient == NULL &&
2104        !(Window->ExStyle & WS_EX_TOPMOST) &&
2105         (WinPos.flags & SWP_AGG_STATUSFLAGS) == (SWP_AGG_NOPOSCHANGE & ~SWP_NOZORDER))
2106    {
2107       TRACE("No drawing, set no Z order and no redraw!\n");
2108       WinPos.flags |= SWP_NOZORDER|SWP_NOREDRAW;
2109    }
2110 
2111    if(!(flags & SWP_DEFERERASE))
2112    {
2113        /* erase parent when hiding or resizing child */
2114        if ((flags & SWP_HIDEWINDOW) ||
2115          (!(flags & SWP_SHOWWINDOW) &&
2116           (WinPos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOGEOMETRYCHANGE))
2117        {
2118            PWND Parent = Window->spwndParent;
2119            if (!Parent || UserIsDesktopWindow(Parent)) Parent = Window;
2120            UserSyncAndPaintWindows( Parent, RDW_ERASENOW);
2121        }
2122 
2123        /* Give newly shown windows a chance to redraw */
2124        if(((WinPos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE)
2125                 && !(flags & SWP_AGG_NOCLIENTCHANGE) && (flags & SWP_SHOWWINDOW))
2126        {
2127            UserSyncAndPaintWindows( Window, RDW_ERASENOW);
2128        }
2129    }
2130 
2131    /* And last, send the WM_WINDOWPOSCHANGED message */
2132 
2133    TRACE("\tstatus hwnd %p flags = %04x\n",Window?Window->head.h:NULL,WinPos.flags & SWP_AGG_STATUSFLAGS);
2134 
2135    if (((WinPos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE)
2136             && !((flags & SWP_AGG_NOCLIENTCHANGE) && (flags & SWP_SHOWWINDOW)))
2137    {
2138       /* WM_WINDOWPOSCHANGED is sent even if SWP_NOSENDCHANGING is set
2139          and always contains final window position.
2140        */
2141       WinPos.x = NewWindowRect.left;
2142       WinPos.y = NewWindowRect.top;
2143       WinPos.cx = NewWindowRect.right - NewWindowRect.left;
2144       WinPos.cy = NewWindowRect.bottom - NewWindowRect.top;
2145       TRACE("WM_WINDOWPOSCHANGED hwnd %p Flags %04x\n",WinPos.hwnd,WinPos.flags);
2146       co_IntSendMessageNoWait(WinPos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM) &WinPos);
2147    }
2148 
2149    if ( WinPos.flags & SWP_FRAMECHANGED  || WinPos.flags & SWP_STATECHANGED ||
2150       !(WinPos.flags & SWP_NOCLIENTSIZE) || !(WinPos.flags & SWP_NOCLIENTMOVE) )
2151    {
2152       PWND pWnd = ValidateHwndNoErr(WinPos.hwnd);
2153       if (pWnd)
2154          IntNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE, pWnd, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI);
2155    }
2156 
2157    if(bPointerInWindow != IntPtInWindow(Window, gpsi->ptCursor.x, gpsi->ptCursor.y))
2158    {
2159       /* Generate mouse move message */
2160       MSG msg;
2161       msg.message = WM_MOUSEMOVE;
2162       msg.wParam = UserGetMouseButtonsState();
2163       msg.lParam = MAKELPARAM(gpsi->ptCursor.x, gpsi->ptCursor.y);
2164       msg.pt = gpsi->ptCursor;
2165       co_MsqInsertMouseMessage(&msg, 0, 0, TRUE);
2166    }
2167 
2168    return TRUE;
2169 }
2170 
2171 LRESULT FASTCALL
2172 co_WinPosGetNonClientSize(PWND Window, RECT* WindowRect, RECT* ClientRect)
2173 {
2174    LRESULT Result;
2175 
2176    ASSERT_REFS_CO(Window);
2177 
2178    *ClientRect = *WindowRect;
2179    Result = co_IntSendMessageNoWait(Window->head.h, WM_NCCALCSIZE, FALSE, (LPARAM) ClientRect);
2180 
2181    FixClientRect(ClientRect, WindowRect);
2182 
2183    return Result;
2184 }
2185 
2186 void FASTCALL
2187 co_WinPosSendSizeMove(PWND Wnd)
2188 {
2189     RECTL Rect;
2190     LPARAM lParam;
2191     WPARAM wParam = SIZE_RESTORED;
2192 
2193     IntGetClientRect(Wnd, &Rect);
2194     lParam = MAKELONG(Rect.right-Rect.left, Rect.bottom-Rect.top);
2195 
2196     Wnd->state &= ~WNDS_SENDSIZEMOVEMSGS;
2197 
2198     if (Wnd->style & WS_MAXIMIZE)
2199     {
2200         wParam = SIZE_MAXIMIZED;
2201     }
2202     else if (Wnd->style & WS_MINIMIZE)
2203     {
2204         wParam = SIZE_MINIMIZED;
2205         lParam = 0;
2206     }
2207 
2208     co_IntSendMessageNoWait(UserHMGetHandle(Wnd), WM_SIZE, wParam, lParam);
2209 
2210     if (UserIsDesktopWindow(Wnd->spwndParent))
2211        lParam = MAKELONG(Wnd->rcClient.left, Wnd->rcClient.top);
2212     else
2213        lParam = MAKELONG(Wnd->rcClient.left-Wnd->spwndParent->rcClient.left, Wnd->rcClient.top-Wnd->spwndParent->rcClient.top);
2214 
2215     co_IntSendMessageNoWait(UserHMGetHandle(Wnd), WM_MOVE, 0, lParam);
2216 
2217     IntEngWindowChanged(Wnd, WOC_RGN_CLIENT);
2218 }
2219 
2220 UINT FASTCALL
2221 co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos)
2222 {
2223    POINT Size;
2224    WINDOWPLACEMENT wpl;
2225    LONG old_style;
2226    UINT SwpFlags = 0;
2227 
2228    ASSERT_REFS_CO(Wnd);
2229 
2230    wpl.length = sizeof(wpl);
2231    IntGetWindowPlacement( Wnd, &wpl );
2232 
2233    if (co_HOOK_CallHooks( WH_CBT, HCBT_MINMAX, (WPARAM)Wnd->head.h, ShowFlag))
2234    {
2235       ERR("WinPosMinMaximize WH_CBT Call Hook return!\n");
2236       return SWP_NOSIZE | SWP_NOMOVE;
2237    }
2238       if (Wnd->style & WS_MINIMIZE)
2239       {
2240          switch (ShowFlag)
2241          {
2242          case SW_MINIMIZE:
2243          case SW_SHOWMINNOACTIVE:
2244          case SW_SHOWMINIMIZED:
2245          case SW_FORCEMINIMIZE:
2246              return SWP_NOSIZE | SWP_NOMOVE;
2247          }
2248          if (!co_IntSendMessageNoWait(Wnd->head.h, WM_QUERYOPEN, 0, 0))
2249          {
2250             return(SWP_NOSIZE | SWP_NOMOVE);
2251          }
2252          SwpFlags |= SWP_NOCOPYBITS;
2253       }
2254       switch (ShowFlag)
2255       {
2256          case SW_MINIMIZE:
2257          case SW_SHOWMINNOACTIVE:
2258          case SW_SHOWMINIMIZED:
2259          case SW_FORCEMINIMIZE:
2260             {
2261                //ERR("MinMaximize Minimize\n");
2262                if (Wnd->style & WS_MAXIMIZE)
2263                {
2264                   Wnd->InternalPos.flags |= WPF_RESTORETOMAXIMIZED;
2265                }
2266                else
2267                {
2268                   Wnd->InternalPos.flags &= ~WPF_RESTORETOMAXIMIZED;
2269                }
2270 
2271                old_style = IntSetStyle( Wnd, WS_MINIMIZE, WS_MAXIMIZE );
2272 
2273                co_UserRedrawWindow(Wnd, NULL, 0, RDW_VALIDATE | RDW_NOERASE | RDW_NOINTERNALPAINT);
2274 
2275                if (!(Wnd->InternalPos.flags & WPF_SETMINPOSITION))
2276                   Wnd->InternalPos.flags &= ~WPF_MININIT;
2277 
2278                WinPosFindIconPos(Wnd, &wpl.ptMinPosition);
2279 
2280                /*if (!(old_style & WS_MINIMIZE))
2281                {
2282                   SwpFlags |= SWP_STATECHANGED;
2283                   IntShowOwnedPopups(Wnd, FALSE);
2284                }*/
2285 
2286                RECTL_vSetRect(NewPos, wpl.ptMinPosition.x, wpl.ptMinPosition.y,
2287                              wpl.ptMinPosition.x + UserGetSystemMetrics(SM_CXMINIMIZED),
2288                              wpl.ptMinPosition.y + UserGetSystemMetrics(SM_CYMINIMIZED));
2289                SwpFlags |= SWP_NOCOPYBITS;
2290                break;
2291             }
2292 
2293          case SW_MAXIMIZE:
2294             {
2295                //ERR("MinMaximize Maximize\n");
2296                if ((Wnd->style & WS_MAXIMIZE) && (Wnd->style & WS_VISIBLE))
2297                {
2298                   SwpFlags = SWP_NOSIZE | SWP_NOMOVE;
2299                   break;
2300                }
2301                co_WinPosGetMinMaxInfo(Wnd, &Size, &wpl.ptMaxPosition, NULL, NULL);
2302 
2303                /*ERR("Maximize: %d,%d %dx%d\n",
2304                       wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, Size.x, Size.y);
2305                 */
2306                old_style = IntSetStyle( Wnd, WS_MAXIMIZE, WS_MINIMIZE );
2307                /*if (old_style & WS_MINIMIZE)
2308                {
2309                   IntShowOwnedPopups(Wnd, TRUE);
2310                }*/
2311 
2312                if (!(old_style & WS_MAXIMIZE)) SwpFlags |= SWP_STATECHANGED;
2313                RECTL_vSetRect(NewPos, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y,
2314                               //wpl.ptMaxPosition.x + Size.x, wpl.ptMaxPosition.y + Size.y);
2315                               Size.x, Size.y);
2316                break;
2317             }
2318 
2319          case SW_SHOWNOACTIVATE:
2320             Wnd->InternalPos.flags &= ~WPF_RESTORETOMAXIMIZED;
2321             /* fall through */
2322          case SW_SHOWNORMAL:
2323          case SW_RESTORE:
2324          case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
2325             {
2326                //ERR("MinMaximize Restore\n");
2327                old_style = IntSetStyle( Wnd, 0, WS_MINIMIZE | WS_MAXIMIZE );
2328                if (old_style & WS_MINIMIZE)
2329                {
2330                   //IntShowOwnedPopups(Wnd, TRUE);
2331 
2332                   if (Wnd->InternalPos.flags & WPF_RESTORETOMAXIMIZED)
2333                   {
2334                      co_WinPosGetMinMaxInfo(Wnd, &Size, &wpl.ptMaxPosition, NULL, NULL);
2335                      IntSetStyle( Wnd, WS_MAXIMIZE, 0 );
2336                      SwpFlags |= SWP_STATECHANGED;
2337                      RECTL_vSetRect(NewPos, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y,
2338                                     wpl.ptMaxPosition.x + Size.x, wpl.ptMaxPosition.y + Size.y);
2339                      break;
2340                   }
2341                   else
2342                   {
2343                      *NewPos = wpl.rcNormalPosition;
2344                      NewPos->right -= NewPos->left;
2345                      NewPos->bottom -= NewPos->top;
2346                      break;
2347                   }
2348                }
2349                else
2350                {
2351                   if (!(old_style & WS_MAXIMIZE))
2352                   {
2353                      break;
2354                   }
2355                   SwpFlags |= SWP_STATECHANGED;
2356                   Wnd->InternalPos.flags &= ~WPF_RESTORETOMAXIMIZED;
2357                   *NewPos = wpl.rcNormalPosition;
2358                   NewPos->right -= NewPos->left;
2359                   NewPos->bottom -= NewPos->top;
2360                   break;
2361                }
2362             }
2363       }
2364    return SwpFlags;
2365 }
2366 
2367 /*
2368    ShowWindow does not set SWP_FRAMECHANGED!!! Fix wine msg test_SetParent:WmSetParentSeq_2:23 wParam bits!
2369  */
2370 BOOLEAN FASTCALL
2371 co_WinPosShowWindow(PWND Wnd, INT Cmd)
2372 {
2373    BOOLEAN WasVisible;
2374    UINT Swp = 0, EventMsg = 0;
2375    RECTL NewPos = {0, 0, 0, 0};
2376    BOOLEAN ShowFlag;
2377    LONG style;
2378    PWND Parent;
2379    PTHREADINFO pti;
2380    //HRGN VisibleRgn;
2381    BOOL ShowOwned = FALSE;
2382    BOOL FirstTime = FALSE;
2383    ASSERT_REFS_CO(Wnd);
2384    //KeRosDumpStackFrames(NULL, 20);
2385    pti = PsGetCurrentThreadWin32Thread();
2386    WasVisible = (Wnd->style & WS_VISIBLE) != 0;
2387    style = Wnd->style;
2388 
2389    TRACE("co_WinPosShowWindow START hwnd %p Cmd %d usicmd %u\n",
2390          Wnd->head.h, Cmd, pti->ppi->usi.wShowWindow);
2391 
2392    if ( pti->ppi->usi.dwFlags & STARTF_USESHOWWINDOW )
2393    {
2394       if ((Wnd->style & (WS_POPUP|WS_CHILD)) != WS_CHILD)
2395       {
2396          if ((Wnd->style & WS_CAPTION) == WS_CAPTION)
2397          {
2398             if (Wnd->spwndOwner == NULL)
2399             {
2400                if ( Cmd == SW_SHOWNORMAL || Cmd == SW_SHOW)
2401                {
2402                     Cmd = SW_SHOWDEFAULT;
2403                }
2404                FirstTime = TRUE;
2405                TRACE("co_WPSW FT 1\n");
2406             }
2407          }
2408       }
2409    }
2410 
2411    if ( Cmd == SW_SHOWDEFAULT )
2412    {
2413       if ( pti->ppi->usi.dwFlags & STARTF_USESHOWWINDOW )
2414       {
2415          Cmd = pti->ppi->usi.wShowWindow;
2416          FirstTime = TRUE;
2417          TRACE("co_WPSW FT 2\n");
2418       }
2419    }
2420 
2421    if (FirstTime)
2422    {
2423       pti->ppi->usi.dwFlags &= ~(STARTF_USEPOSITION|STARTF_USESIZE|STARTF_USESHOWWINDOW);
2424    }
2425 
2426    switch (Cmd)
2427    {
2428       case SW_HIDE:
2429          {
2430             if (!WasVisible)
2431             {
2432                //ERR("co_WinPosShowWindow Exit Bad\n");
2433                return FALSE;
2434             }
2435             Swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE;
2436             if (Wnd != pti->MessageQueue->spwndActive)
2437                Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
2438             break;
2439          }
2440 
2441       case SW_FORCEMINIMIZE: /* FIXME: Does not work if thread is hung. */
2442       case SW_SHOWMINNOACTIVE:
2443          Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
2444          /* Fall through. */
2445       case SW_SHOWMINIMIZED:
2446          Swp |= SWP_SHOWWINDOW;
2447          /* Fall through. */
2448       case SW_MINIMIZE:
2449          {
2450             Swp |= SWP_NOACTIVATE;
2451             if (!(style & WS_MINIMIZE))
2452             {
2453                IntShowOwnedPopups(Wnd, FALSE );
2454                // Fix wine Win test_SetFocus todo #1 & #2,
2455                if (Cmd == SW_SHOWMINIMIZED)
2456                {
2457                   //ERR("co_WinPosShowWindow Set focus 1\n");
2458                   if ((style & (WS_CHILD | WS_POPUP)) == WS_CHILD)
2459                      co_UserSetFocus(Wnd->spwndParent);
2460                   else
2461                      co_UserSetFocus(0);
2462                }
2463 
2464                Swp |= co_WinPosMinMaximize(Wnd, Cmd, &NewPos);
2465 
2466                EventMsg = EVENT_SYSTEM_MINIMIZESTART;
2467             }
2468             else
2469             {
2470                if (WasVisible)
2471                {
2472                   //ERR("co_WinPosShowWindow Exit Good\n");
2473                   return TRUE;
2474                }
2475                Swp |= SWP_NOSIZE | SWP_NOMOVE;
2476             }
2477             break;
2478          }
2479 
2480       case SW_SHOWMAXIMIZED:
2481          {
2482             Swp |= SWP_SHOWWINDOW;
2483             if (!(style & WS_MAXIMIZE))
2484             {
2485                ShowOwned = TRUE;
2486 
2487                Swp |= co_WinPosMinMaximize(Wnd, SW_MAXIMIZE, &NewPos);
2488 
2489                EventMsg = EVENT_SYSTEM_MINIMIZEEND;
2490             }
2491             else
2492             {
2493                if (WasVisible)
2494                {
2495                   //ERR("co_WinPosShowWindow Exit Good 1\n");
2496                   return TRUE;
2497                }
2498                Swp |= SWP_NOSIZE | SWP_NOMOVE;
2499             }
2500             break;
2501          }
2502 
2503       case SW_SHOWNA:
2504          Swp |= SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
2505          if (style & WS_CHILD && !(Wnd->ExStyle & WS_EX_MDICHILD)) Swp |= SWP_NOZORDER;
2506          break;
2507       case SW_SHOW:
2508          if (WasVisible) return(TRUE); // Nothing to do!
2509          Swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
2510          /* Don't activate the topmost window. */
2511          if (style & WS_CHILD && !(Wnd->ExStyle & WS_EX_MDICHILD)) Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
2512          break;
2513 
2514       case SW_SHOWNOACTIVATE:
2515          Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
2516          /* Fall through. */
2517       case SW_SHOWNORMAL:
2518       case SW_SHOWDEFAULT:
2519       case SW_RESTORE:
2520          if (!WasVisible) Swp |= SWP_SHOWWINDOW;
2521          if (style & (WS_MINIMIZE | WS_MAXIMIZE))
2522          {
2523             Swp |= co_WinPosMinMaximize(Wnd, Cmd, &NewPos);
2524             if (style & WS_MINIMIZE) EventMsg = EVENT_SYSTEM_MINIMIZEEND;
2525          }
2526          else
2527          {
2528             if (WasVisible)
2529             {
2530                //ERR("co_WinPosShowWindow Exit Good 3\n");
2531                return TRUE;
2532             }
2533             Swp |= SWP_NOSIZE | SWP_NOMOVE;
2534          }
2535          if ( style & WS_CHILD &&
2536              !(Wnd->ExStyle & WS_EX_MDICHILD) &&
2537              !(Swp & SWP_STATECHANGED))
2538             Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
2539          break;
2540 
2541       default:
2542          //ERR("co_WinPosShowWindow Exit Good 4\n");
2543          return WasVisible;
2544    }
2545 
2546    ShowFlag = (Cmd != SW_HIDE);
2547 
2548    if ((ShowFlag != WasVisible || Cmd == SW_SHOWNA) && Cmd != SW_SHOWMAXIMIZED && !(Swp & SWP_STATECHANGED))
2549    {
2550       co_IntSendMessageNoWait(Wnd->head.h, WM_SHOWWINDOW, ShowFlag, 0);
2551 #if 0 // Fix wine msg test_SetParent:WmSetParentSeq_1:2
2552       if (!(Wnd->state2 & WNDS2_WIN31COMPAT)) // <------------- XP sets this bit!
2553          co_IntSendMessageNoWait(Wnd->head.h, WM_SETVISIBLE, ShowFlag, 0);
2554 #endif
2555       if (!VerifyWnd(Wnd)) return WasVisible;
2556    }
2557 
2558    /* We can't activate a child window */
2559    if ((Wnd->style & WS_CHILD) &&
2560        !(Wnd->ExStyle & WS_EX_MDICHILD) &&
2561        Cmd != SW_SHOWNA)
2562    {
2563       //ERR("SWP Child No active and ZOrder\n");
2564       Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
2565    }
2566 
2567 #if 0 // Explorer issues with common controls? Someone does not know how CS_SAVEBITS works.
2568       // Breaks startup and shutdown active window...
2569    if ((Wnd->style & (WS_POPUP|WS_CHILD)) != WS_CHILD &&
2570         Wnd->pcls->style & CS_SAVEBITS &&
2571         ((Cmd == SW_SHOW) || (Cmd == SW_NORMAL)))
2572    {
2573       ERR("WinPosShowWindow Set active\n");
2574       //UserSetActiveWindow(Wnd);
2575       co_IntSetForegroundWindow(Wnd); // HACK
2576       Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
2577    }
2578 #endif
2579 
2580    if (IsChildVisible(Wnd) || Swp & SWP_STATECHANGED)
2581    {
2582        TRACE("Child is Vis %s or State changed %s. ShowFlag %s Swp %04x\n",
2583              (IsChildVisible(Wnd) ? "TRUE" : "FALSE"), (Swp & SWP_STATECHANGED ? "TRUE" : "FALSE"),
2584              (ShowFlag ? "TRUE" : "FALSE"),LOWORD(Swp));
2585    co_WinPosSetWindowPos( Wnd,
2586                           0 != (Wnd->ExStyle & WS_EX_TOPMOST) ? HWND_TOPMOST : HWND_TOP,
2587                           NewPos.left,
2588                           NewPos.top,
2589                           NewPos.right, // NewPos.right - NewPos.left, when minimized and restore, the window becomes smaller.
2590                           NewPos.bottom,// NewPos.bottom - NewPos.top,
2591                           LOWORD(Swp));
2592    }
2593    else
2594    {
2595       TRACE("Parent Vis?\n");
2596       /* if parent is not visible simply toggle WS_VISIBLE and return */
2597       if (ShowFlag) IntSetStyle( Wnd, WS_VISIBLE, 0 );
2598       else IntSetStyle( Wnd, 0, WS_VISIBLE );
2599    }
2600 
2601    if ( EventMsg ) IntNotifyWinEvent(EventMsg, Wnd, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI);
2602 
2603    if ( ShowOwned ) IntShowOwnedPopups(Wnd, TRUE );
2604 
2605    if ((Cmd == SW_HIDE) || (Cmd == SW_MINIMIZE))
2606    {
2607       if ( Wnd == pti->MessageQueue->spwndActive && pti->MessageQueue == IntGetFocusMessageQueue()  )
2608       {
2609           if (UserIsDesktopWindow(Wnd->spwndParent))
2610           {
2611               if (!ActivateOtherWindowMin(Wnd))
2612               {
2613                 co_WinPosActivateOtherWindow(Wnd);
2614               }
2615           }
2616           else
2617           {
2618               co_WinPosActivateOtherWindow(Wnd);
2619           }
2620       }
2621 
2622       /* Revert focus to parent */
2623       if (Wnd == pti->MessageQueue->spwndFocus)
2624       {
2625          Parent = Wnd->spwndParent;
2626          if (UserIsDesktopWindow(Wnd->spwndParent))
2627              Parent = 0;
2628          co_UserSetFocus(Parent);
2629       }
2630       // Hide, just return.
2631       if (Cmd == SW_HIDE) return WasVisible;
2632    }
2633 
2634    /* FIXME: Check for window destruction. */
2635 
2636    if ((Wnd->state & WNDS_SENDSIZEMOVEMSGS) &&
2637        !(Wnd->state2 & WNDS2_INDESTROY))
2638    {
2639         co_WinPosSendSizeMove(Wnd);
2640    }
2641 
2642    /* if previous state was minimized Windows sets focus to the window */
2643    if (style & WS_MINIMIZE)
2644    {
2645       co_UserSetFocus(Wnd);
2646       // Fix wine Win test_SetFocus todo #3,
2647       if (!(style & WS_CHILD)) co_IntSendMessage(UserHMGetHandle(Wnd), WM_ACTIVATE, WA_ACTIVE, 0);
2648    }
2649    //ERR("co_WinPosShowWindow EXIT\n");
2650    return WasVisible;
2651 }
2652 
2653 static PWND
2654 co_WinPosSearchChildren(
2655    IN PWND ScopeWin,
2656    IN POINT *Point,
2657    IN OUT USHORT *HitTest,
2658    IN BOOL Ignore
2659    )
2660 {
2661     HWND *List, *phWnd;
2662     PWND pwndChild = NULL;
2663 
2664     /* not visible */
2665     if (!(ScopeWin->style & WS_VISIBLE))
2666     {
2667         return NULL;
2668     }
2669 
2670     /* not in window or in window region */
2671     if (!IntPtInWindow(ScopeWin, Point->x, Point->y))
2672     {
2673         return NULL;
2674     }
2675 
2676     /* transparent */
2677     if ((ScopeWin->ExStyle & (WS_EX_LAYERED|WS_EX_TRANSPARENT)) == (WS_EX_LAYERED|WS_EX_TRANSPARENT))
2678     {
2679         return NULL;
2680     }
2681 
2682     if (!Ignore && (ScopeWin->style & WS_DISABLED))
2683     {   /* disabled child */
2684         if ((ScopeWin->style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return NULL;
2685         /* process the hit error */
2686         *HitTest = HTERROR;
2687         return ScopeWin;
2688     }
2689 
2690     /* not minimized and check if point is inside the window */
2691     if (!(ScopeWin->style & WS_MINIMIZE) &&
2692          RECTL_bPointInRect(&ScopeWin->rcClient, Point->x, Point->y) )
2693     {
2694         UserReferenceObject(ScopeWin);
2695 
2696         List = IntWinListChildren(ScopeWin);
2697         if (List)
2698         {
2699             for (phWnd = List; *phWnd; ++phWnd)
2700             {
2701                 if (!(pwndChild = ValidateHwndNoErr(*phWnd)))
2702                 {
2703                     continue;
2704                 }
2705 
2706                 pwndChild = co_WinPosSearchChildren(pwndChild, Point, HitTest, Ignore);
2707 
2708                 if (pwndChild != NULL)
2709                 {
2710                     /* We found a window. Don't send any more WM_NCHITTEST messages */
2711                     ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
2712                     UserDereferenceObject(ScopeWin);
2713                     return pwndChild;
2714                 }
2715             }
2716             ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
2717         }
2718         UserDereferenceObject(ScopeWin);
2719     }
2720 
2721     if (ScopeWin->head.pti == PsGetCurrentThreadWin32Thread())
2722     {
2723        *HitTest = (USHORT)co_IntSendMessage(ScopeWin->head.h, WM_NCHITTEST, 0, MAKELONG(Point->x, Point->y));
2724 
2725        if ((*HitTest) == (USHORT)HTTRANSPARENT)
2726        {
2727            return NULL;
2728        }
2729     }
2730     else
2731     {
2732        if (*HitTest == HTNOWHERE && pwndChild == NULL) *HitTest = HTCLIENT;
2733     }
2734 
2735     return ScopeWin;
2736 }
2737 
2738 PWND APIENTRY
2739 co_WinPosWindowFromPoint(
2740    IN PWND ScopeWin,
2741    IN POINT *WinPoint,
2742    IN OUT USHORT* HitTest,
2743    IN BOOL Ignore)
2744 {
2745    PWND Window;
2746    POINT Point = *WinPoint;
2747    USER_REFERENCE_ENTRY Ref;
2748 
2749    if( ScopeWin == NULL )
2750    {
2751        ScopeWin = UserGetDesktopWindow();
2752        if(ScopeWin == NULL)
2753            return NULL;
2754    }
2755 
2756    *HitTest = HTNOWHERE;
2757 
2758    ASSERT_REFS_CO(ScopeWin);
2759    UserRefObjectCo(ScopeWin, &Ref);
2760 
2761    Window = co_WinPosSearchChildren(ScopeWin, &Point, HitTest, Ignore);
2762 
2763    UserDerefObjectCo(ScopeWin);
2764    if (Window)
2765        ASSERT_REFS_CO(Window);
2766    ASSERT_REFS_CO(ScopeWin);
2767 
2768    return Window;
2769 }
2770 
2771 PWND FASTCALL
2772 IntRealChildWindowFromPoint(PWND Parent, LONG x, LONG y)
2773 {
2774    POINTL Pt;
2775    HWND *List, *phWnd;
2776    PWND pwndHit = NULL;
2777 
2778    Pt.x = x;
2779    Pt.y = y;
2780 
2781    if (!UserIsDesktopWindow(Parent))
2782    {
2783       Pt.x += Parent->rcClient.left;
2784       Pt.y += Parent->rcClient.top;
2785    }
2786 
2787    if (!IntPtInWindow(Parent, Pt.x, Pt.y)) return NULL;
2788 
2789    if ((List = IntWinListChildren(Parent)))
2790    {
2791       for (phWnd = List; *phWnd; phWnd++)
2792       {
2793          PWND Child;
2794          if ((Child = ValidateHwndNoErr(*phWnd)))
2795          {
2796             if ( Child->style & WS_VISIBLE && IntPtInWindow(Child, Pt.x, Pt.y) )
2797             {
2798                if ( Child->pcls->atomClassName != gpsi->atomSysClass[ICLS_BUTTON] ||
2799                    (Child->style & BS_TYPEMASK) != BS_GROUPBOX )
2800                {
2801                   ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
2802                   return Child;
2803                }
2804                pwndHit = Child;
2805             }
2806          }
2807       }
2808       ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
2809    }
2810    return pwndHit ? pwndHit : Parent;
2811 }
2812 
2813 PWND APIENTRY
2814 IntChildWindowFromPointEx(PWND Parent, LONG x, LONG y, UINT uiFlags)
2815 {
2816    POINTL Pt;
2817    HWND *List, *phWnd;
2818    PWND pwndHit = NULL;
2819 
2820    Pt.x = x;
2821    Pt.y = y;
2822 
2823    if (!UserIsDesktopWindow(Parent))
2824    {
2825       if (Parent->ExStyle & WS_EX_LAYOUTRTL)
2826          Pt.x = Parent->rcClient.right - Pt.x;
2827       else
2828          Pt.x += Parent->rcClient.left;
2829       Pt.y += Parent->rcClient.top;
2830    }
2831 
2832    if (!IntPtInWindow(Parent, Pt.x, Pt.y)) return NULL;
2833 
2834    if ((List = IntWinListChildren(Parent)))
2835    {
2836       for (phWnd = List; *phWnd; phWnd++)
2837       {
2838          PWND Child;
2839          if ((Child = ValidateHwndNoErr(*phWnd)))
2840          {
2841             if (uiFlags & (CWP_SKIPINVISIBLE|CWP_SKIPDISABLED))
2842             {
2843                if (!(Child->style & WS_VISIBLE) && (uiFlags & CWP_SKIPINVISIBLE)) continue;
2844                if ((Child->style & WS_DISABLED) && (uiFlags & CWP_SKIPDISABLED)) continue;
2845             }
2846 
2847             if (uiFlags & CWP_SKIPTRANSPARENT)
2848             {
2849                if (Child->ExStyle & WS_EX_TRANSPARENT) continue;
2850             }
2851 
2852             if (IntPtInWindow(Child, Pt.x, Pt.y))
2853             {
2854                pwndHit = Child;
2855                break;
2856             }
2857          }
2858       }
2859       ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
2860    }
2861    return pwndHit ? pwndHit : Parent;
2862 }
2863 
2864 HDWP
2865 FASTCALL
2866 IntDeferWindowPos( HDWP hdwp,
2867                    HWND hwnd,
2868                    HWND hwndAfter,
2869                    INT x,
2870                    INT y,
2871                    INT cx,
2872                    INT cy,
2873                    UINT flags )
2874 {
2875     PSMWP pDWP;
2876     int i;
2877     HDWP retvalue = hdwp;
2878 
2879     TRACE("hdwp %p, hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
2880           hdwp, hwnd, hwndAfter, x, y, cx, cy, flags);
2881 
2882     if (flags & ~(SWP_NOSIZE | SWP_NOMOVE |
2883                   SWP_NOZORDER | SWP_NOREDRAW |
2884                   SWP_NOACTIVATE | SWP_NOCOPYBITS |
2885                   SWP_NOOWNERZORDER|SWP_SHOWWINDOW |
2886                   SWP_HIDEWINDOW | SWP_FRAMECHANGED))
2887     {
2888        EngSetLastError(ERROR_INVALID_PARAMETER);
2889        return NULL;
2890     }
2891 
2892     if (!(pDWP = (PSMWP)UserGetObject(gHandleTable, hdwp, TYPE_SETWINDOWPOS)))
2893     {
2894        EngSetLastError(ERROR_INVALID_DWP_HANDLE);
2895        return NULL;
2896     }
2897 
2898     for (i = 0; i < pDWP->ccvr; i++)
2899     {
2900         if (pDWP->acvr[i].pos.hwnd == hwnd)
2901         {
2902               /* Merge with the other changes */
2903             if (!(flags & SWP_NOZORDER))
2904             {
2905                 pDWP->acvr[i].pos.hwndInsertAfter = hwndAfter;
2906             }
2907             if (!(flags & SWP_NOMOVE))
2908             {
2909                 pDWP->acvr[i].pos.x = x;
2910                 pDWP->acvr[i].pos.y = y;
2911             }
2912             if (!(flags & SWP_NOSIZE))
2913             {
2914                 pDWP->acvr[i].pos.cx = cx;
2915                 pDWP->acvr[i].pos.cy = cy;
2916             }
2917             pDWP->acvr[i].pos.flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
2918                                                SWP_NOZORDER | SWP_NOREDRAW |
2919                                                SWP_NOACTIVATE | SWP_NOCOPYBITS|
2920                                                SWP_NOOWNERZORDER);
2921             pDWP->acvr[i].pos.flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
2922                                               SWP_FRAMECHANGED);
2923             goto END;
2924         }
2925     }
2926     if (pDWP->ccvr >= pDWP->ccvrAlloc)
2927     {
2928         PCVR newpos = ExAllocatePoolWithTag(PagedPool, pDWP->ccvrAlloc * 2 * sizeof(CVR), USERTAG_SWP);
2929         if (!newpos)
2930         {
2931             retvalue = NULL;
2932             goto END;
2933         }
2934         RtlZeroMemory(newpos, pDWP->ccvrAlloc * 2 * sizeof(CVR));
2935         RtlCopyMemory(newpos, pDWP->acvr, pDWP->ccvrAlloc * sizeof(CVR));
2936         ExFreePoolWithTag(pDWP->acvr, USERTAG_SWP);
2937         pDWP->ccvrAlloc *= 2;
2938         pDWP->acvr = newpos;
2939     }
2940     pDWP->acvr[pDWP->ccvr].pos.hwnd = hwnd;
2941     pDWP->acvr[pDWP->ccvr].pos.hwndInsertAfter = hwndAfter;
2942     pDWP->acvr[pDWP->ccvr].pos.x = x;
2943     pDWP->acvr[pDWP->ccvr].pos.y = y;
2944     pDWP->acvr[pDWP->ccvr].pos.cx = cx;
2945     pDWP->acvr[pDWP->ccvr].pos.cy = cy;
2946     pDWP->acvr[pDWP->ccvr].pos.flags = flags;
2947     pDWP->acvr[pDWP->ccvr].hrgnClip = NULL;
2948     pDWP->acvr[pDWP->ccvr].hrgnInterMonitor = NULL;
2949     pDWP->ccvr++;
2950 END:
2951     return retvalue;
2952 }
2953 
2954 BOOL FASTCALL IntEndDeferWindowPosEx( HDWP hdwp, BOOL sAsync )
2955 {
2956     PSMWP pDWP;
2957     PCVR winpos;
2958     BOOL res = TRUE;
2959     int i;
2960 
2961     TRACE("%p\n", hdwp);
2962 
2963     if (!(pDWP = (PSMWP)UserGetObject(gHandleTable, hdwp, TYPE_SETWINDOWPOS)))
2964     {
2965        EngSetLastError(ERROR_INVALID_DWP_HANDLE);
2966        return FALSE;
2967     }
2968 
2969     for (i = 0, winpos = pDWP->acvr; res && i < pDWP->ccvr; i++, winpos++)
2970     {
2971         PWND pwnd;
2972         USER_REFERENCE_ENTRY Ref;
2973 
2974         TRACE("hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
2975                winpos->pos.hwnd, winpos->pos.hwndInsertAfter, winpos->pos.x, winpos->pos.y,
2976                winpos->pos.cx, winpos->pos.cy, winpos->pos.flags);
2977 
2978         pwnd = ValidateHwndNoErr(winpos->pos.hwnd);
2979         if (!pwnd)
2980            continue;
2981 
2982         UserRefObjectCo(pwnd, &Ref);
2983 
2984         if ( sAsync )
2985         {
2986            LRESULT lRes;
2987            PWINDOWPOS ppos = ExAllocatePoolWithTag(PagedPool, sizeof(WINDOWPOS), USERTAG_SWP);
2988            if ( ppos )
2989            {
2990               *ppos = winpos->pos;
2991               /* Yes it's a pointer inside Win32k! */
2992               lRes = co_IntSendMessageNoWait( winpos->pos.hwnd, WM_ASYNC_SETWINDOWPOS, 0, (LPARAM)ppos);
2993               /* We handle this the same way as Event Hooks and Hooks. */
2994               if ( !lRes )
2995               {
2996                  ExFreePoolWithTag(ppos, USERTAG_SWP);
2997               }
2998            }
2999         }
3000         else
3001            res = co_WinPosSetWindowPos( pwnd,
3002                                         winpos->pos.hwndInsertAfter,
3003                                         winpos->pos.x,
3004                                         winpos->pos.y,
3005                                         winpos->pos.cx,
3006                                         winpos->pos.cy,
3007                                         winpos->pos.flags);
3008 
3009         // Hack to pass tests.... Must have some work to do so clear the error.
3010         if (res && (winpos->pos.flags & (SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER)) == SWP_NOZORDER )
3011            EngSetLastError(ERROR_SUCCESS);
3012 
3013         UserDerefObjectCo(pwnd);
3014     }
3015     ExFreePoolWithTag(pDWP->acvr, USERTAG_SWP);
3016     UserDereferenceObject(pDWP);
3017     UserDeleteObject(hdwp, TYPE_SETWINDOWPOS);
3018     return res;
3019 }
3020 
3021 /*
3022  * @implemented
3023  */
3024 HWND APIENTRY
3025 NtUserChildWindowFromPointEx(HWND hwndParent,
3026                              LONG x,
3027                              LONG y,
3028                              UINT uiFlags)
3029 {
3030    PWND pwndParent;
3031    TRACE("Enter NtUserChildWindowFromPointEx\n");
3032    UserEnterExclusive();
3033    if ((pwndParent = UserGetWindowObject(hwndParent)))
3034    {
3035       pwndParent = IntChildWindowFromPointEx(pwndParent, x, y, uiFlags);
3036    }
3037    UserLeave();
3038    TRACE("Leave NtUserChildWindowFromPointEx\n");
3039    return pwndParent ? UserHMGetHandle(pwndParent) : NULL;
3040 }
3041 
3042 /*
3043  * @implemented
3044  */
3045 BOOL APIENTRY
3046 NtUserEndDeferWindowPosEx(HDWP WinPosInfo,
3047                           DWORD Unknown1)
3048 {
3049    BOOL Ret;
3050    TRACE("Enter NtUserEndDeferWindowPosEx\n");
3051    UserEnterExclusive();
3052    Ret = IntEndDeferWindowPosEx(WinPosInfo, (BOOL)Unknown1);
3053    TRACE("Leave NtUserEndDeferWindowPosEx, ret=%i\n", Ret);
3054    UserLeave();
3055    return Ret;
3056 }
3057 
3058 /*
3059  * @implemented
3060  */
3061 HDWP APIENTRY
3062 NtUserDeferWindowPos(HDWP WinPosInfo,
3063                      HWND Wnd,
3064                      HWND WndInsertAfter,
3065                      int x,
3066                      int y,
3067                      int cx,
3068                      int cy,
3069                      UINT Flags)
3070 {
3071    PWND pWnd, pWndIA;
3072    HDWP Ret = NULL;
3073    UINT Tmp = ~(SWP_ASYNCWINDOWPOS|SWP_DEFERERASE|SWP_NOSENDCHANGING|SWP_NOREPOSITION|
3074                 SWP_NOCOPYBITS|SWP_HIDEWINDOW|SWP_SHOWWINDOW|SWP_FRAMECHANGED|
3075                 SWP_NOACTIVATE|SWP_NOREDRAW|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE);
3076 
3077    TRACE("Enter NtUserDeferWindowPos\n");
3078    UserEnterExclusive();
3079 
3080    if ( Flags & Tmp )
3081    {
3082       EngSetLastError(ERROR_INVALID_FLAGS);
3083       goto Exit;
3084    }
3085 
3086    pWnd = UserGetWindowObject(Wnd);
3087    if (!pWnd || UserIsDesktopWindow(pWnd) || UserIsMessageWindow(pWnd))
3088    {
3089       goto Exit;
3090    }
3091 
3092    if ( WndInsertAfter &&
3093         WndInsertAfter != HWND_BOTTOM &&
3094         WndInsertAfter != HWND_TOPMOST &&
3095         WndInsertAfter != HWND_NOTOPMOST )
3096    {
3097       pWndIA = UserGetWindowObject(WndInsertAfter);
3098       if (!pWndIA || UserIsDesktopWindow(pWndIA) || UserIsMessageWindow(pWndIA))
3099       {
3100          goto Exit;
3101       }
3102    }
3103 
3104    Ret = IntDeferWindowPos(WinPosInfo, Wnd, WndInsertAfter, x, y, cx, cy, Flags);
3105 
3106 Exit:
3107    TRACE("Leave NtUserDeferWindowPos, ret=%p\n", Ret);
3108    UserLeave();
3109    return Ret;
3110 }
3111 
3112 /*
3113  * @implemented
3114  */
3115 DWORD APIENTRY
3116 NtUserGetInternalWindowPos( HWND hWnd,
3117                             LPRECT rectWnd,
3118                             LPPOINT ptIcon)
3119 {
3120    PWND Window;
3121    DWORD Ret = 0;
3122    BOOL Hit = FALSE;
3123    WINDOWPLACEMENT wndpl;
3124 
3125    UserEnterShared();
3126 
3127    if (!(Window = UserGetWindowObject(hWnd)))
3128    {
3129       Hit = FALSE;
3130       goto Exit;
3131    }
3132 
3133    _SEH2_TRY
3134    {
3135        if(rectWnd)
3136        {
3137           ProbeForWrite(rectWnd,
3138                         sizeof(RECT),
3139                         1);
3140        }
3141        if(ptIcon)
3142        {
3143           ProbeForWrite(ptIcon,
3144                         sizeof(POINT),
3145                         1);
3146        }
3147 
3148    }
3149    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
3150    {
3151        SetLastNtError(_SEH2_GetExceptionCode());
3152        Hit = TRUE;
3153    }
3154    _SEH2_END;
3155 
3156    wndpl.length = sizeof(WINDOWPLACEMENT);
3157 
3158    if (IntGetWindowPlacement(Window, &wndpl) && !Hit)
3159    {
3160       _SEH2_TRY
3161       {
3162           if (rectWnd)
3163           {
3164              RtlCopyMemory(rectWnd, &wndpl.rcNormalPosition , sizeof(RECT));
3165           }
3166           if (ptIcon)
3167           {
3168              RtlCopyMemory(ptIcon, &wndpl.ptMinPosition, sizeof(POINT));
3169           }
3170 
3171       }
3172       _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
3173       {
3174           SetLastNtError(_SEH2_GetExceptionCode());
3175           Hit = TRUE;
3176       }
3177       _SEH2_END;
3178 
3179       if (!Hit) Ret = wndpl.showCmd;
3180    }
3181 Exit:
3182    UserLeave();
3183    return Ret;
3184 }
3185 
3186 /*
3187  * @implemented
3188  */
3189 BOOL APIENTRY
3190 NtUserGetWindowPlacement(HWND hWnd,
3191                          WINDOWPLACEMENT *lpwndpl)
3192 {
3193    PWND Wnd;
3194    WINDOWPLACEMENT Safepl;
3195    NTSTATUS Status;
3196    DECLARE_RETURN(BOOL);
3197 
3198    TRACE("Enter NtUserGetWindowPlacement\n");
3199    UserEnterShared();
3200 
3201    if (!(Wnd = UserGetWindowObject(hWnd)))
3202    {
3203       RETURN( FALSE);
3204    }
3205 
3206    Status = MmCopyFromCaller(&Safepl, lpwndpl, sizeof(WINDOWPLACEMENT));
3207    if (!NT_SUCCESS(Status))
3208    {
3209       SetLastNtError(Status);
3210       RETURN( FALSE);
3211    }
3212 
3213    Safepl.length = sizeof(WINDOWPLACEMENT);
3214 
3215    IntGetWindowPlacement(Wnd, &Safepl);
3216 
3217    Status = MmCopyToCaller(lpwndpl, &Safepl, sizeof(WINDOWPLACEMENT));
3218    if (!NT_SUCCESS(Status))
3219    {
3220       SetLastNtError(Status);
3221       RETURN( FALSE);
3222    }
3223 
3224    RETURN( TRUE);
3225 
3226 CLEANUP:
3227    TRACE("Leave NtUserGetWindowPlacement, ret=%i\n",_ret_);
3228    UserLeave();
3229    END_CLEANUP;
3230 }
3231 
3232 DWORD
3233 APIENTRY
3234 NtUserMinMaximize(
3235     HWND hWnd,
3236     UINT cmd, // Wine SW_ commands
3237     BOOL Hide)
3238 {
3239   PWND pWnd;
3240 
3241   TRACE("Enter NtUserMinMaximize\n");
3242   UserEnterExclusive();
3243 
3244   pWnd = UserGetWindowObject(hWnd);
3245   if (!pWnd || UserIsDesktopWindow(pWnd) || UserIsMessageWindow(pWnd))
3246   {
3247      goto Exit;
3248   }
3249 
3250   if ( cmd > SW_MAX || pWnd->state2 & WNDS2_INDESTROY)
3251   {
3252      EngSetLastError(ERROR_INVALID_PARAMETER);
3253      goto Exit;
3254   }
3255 
3256   cmd |= Hide ? SW_HIDE : 0;
3257 
3258   co_WinPosShowWindow(pWnd, cmd);
3259 
3260 Exit:
3261   TRACE("Leave NtUserMinMaximize\n");
3262   UserLeave();
3263   return 0; // Always NULL?
3264 }
3265 
3266 /*
3267  * @implemented
3268  */
3269 BOOL APIENTRY
3270 NtUserMoveWindow(
3271    HWND hWnd,
3272    int X,
3273    int Y,
3274    int nWidth,
3275    int nHeight,
3276    BOOL bRepaint)
3277 {
3278    return NtUserSetWindowPos(hWnd, 0, X, Y, nWidth, nHeight,
3279                              (bRepaint ? SWP_NOZORDER | SWP_NOACTIVATE :
3280                               SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW));
3281 }
3282 
3283 /*
3284  * @implemented
3285  */
3286 HWND APIENTRY
3287 NtUserRealChildWindowFromPoint(HWND Parent,
3288                                LONG x,
3289                                LONG y)
3290 {
3291    PWND pwndParent;
3292    TRACE("Enter NtUserRealChildWindowFromPoint\n");
3293    UserEnterShared();
3294    if ((pwndParent = UserGetWindowObject(Parent)))
3295    {
3296       pwndParent = IntRealChildWindowFromPoint(pwndParent, x, y);
3297    }
3298    UserLeave();
3299    TRACE("Leave NtUserRealChildWindowFromPoint\n");
3300    return pwndParent ? UserHMGetHandle(pwndParent) : NULL;
3301 }
3302 
3303 /*
3304  * @implemented
3305  */
3306 BOOL APIENTRY
3307 NtUserSetWindowPos(
3308    HWND hWnd,
3309    HWND hWndInsertAfter,
3310    int X,
3311    int Y,
3312    int cx,
3313    int cy,
3314    UINT uFlags)
3315 {
3316    DECLARE_RETURN(BOOL);
3317    PWND Window, pWndIA;
3318    BOOL ret;
3319    USER_REFERENCE_ENTRY Ref;
3320 
3321    TRACE("Enter NtUserSetWindowPos\n");
3322    UserEnterExclusive();
3323 
3324    if (!(Window = UserGetWindowObject(hWnd)) ||
3325         UserIsDesktopWindow(Window) || UserIsMessageWindow(Window))
3326    {
3327       ERR("NtUserSetWindowPos bad window handle!\n");
3328       RETURN(FALSE);
3329    }
3330 
3331    if ( hWndInsertAfter &&
3332         hWndInsertAfter != HWND_BOTTOM &&
3333         hWndInsertAfter != HWND_TOPMOST &&
3334         hWndInsertAfter != HWND_NOTOPMOST )
3335    {
3336       if (!(pWndIA = UserGetWindowObject(hWndInsertAfter)) ||
3337             UserIsDesktopWindow(pWndIA) || UserIsMessageWindow(pWndIA))
3338       {
3339          ERR("NtUserSetWindowPos bad insert window handle!\n");
3340          RETURN(FALSE);
3341       }
3342    }
3343 
3344    /* First make sure that coordinates are valid for WM_WINDOWPOSCHANGING */
3345    if (!(uFlags & SWP_NOMOVE))
3346    {
3347       if (X < -32768) X = -32768;
3348       else if (X > 32767) X = 32767;
3349       if (Y < -32768) Y = -32768;
3350       else if (Y > 32767) Y = 32767;
3351    }
3352    if (!(uFlags & SWP_NOSIZE))
3353    {
3354       if (cx < 0) cx = 0;
3355       else if (cx > 32767) cx = 32767;
3356       if (cy < 0) cy = 0;
3357       else if (cy > 32767) cy = 32767;
3358    }
3359 
3360    UserRefObjectCo(Window, &Ref);
3361    ret = co_WinPosSetWindowPos(Window, hWndInsertAfter, X, Y, cx, cy, uFlags);
3362    UserDerefObjectCo(Window);
3363 
3364    RETURN(ret);
3365 
3366 CLEANUP:
3367    TRACE("Leave NtUserSetWindowPos, ret=%i\n",_ret_);
3368    UserLeave();
3369    END_CLEANUP;
3370 }
3371 
3372 /*
3373  * @implemented
3374  */
3375 INT APIENTRY
3376 NtUserSetWindowRgn(
3377    HWND hWnd,
3378    HRGN hRgn,
3379    BOOL bRedraw)
3380 {
3381    HRGN hrgnCopy = NULL;
3382    PWND Window;
3383    INT flags = (SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE);
3384    BOOLEAN Ret = FALSE;
3385    DECLARE_RETURN(INT);
3386 
3387    TRACE("Enter NtUserSetWindowRgn\n");
3388    UserEnterExclusive();
3389 
3390    if (!(Window = UserGetWindowObject(hWnd)) ||
3391         UserIsDesktopWindow(Window) || UserIsMessageWindow(Window))
3392    {
3393       RETURN( 0);
3394    }
3395 
3396    if (hRgn) // The region will be deleted in user32.
3397    {
3398       if (GreIsHandleValid(hRgn))
3399       {
3400          hrgnCopy = NtGdiCreateRectRgn(0, 0, 0, 0);
3401       /* The coordinates of a window's window region are relative to the
3402          upper-left corner of the window, not the client area of the window. */
3403          NtGdiCombineRgn( hrgnCopy, hRgn, 0, RGN_COPY);
3404       }
3405       else
3406          RETURN( 0);
3407    }
3408 
3409    //// HACK 1 : Work around the lack of supporting DeferWindowPos.
3410    if (hrgnCopy)
3411    {
3412        Window->hrgnNewFrame = hrgnCopy; // Should be PSMWP->acvr->hrgnClip
3413    }
3414    else
3415    {
3416        Window->hrgnNewFrame = HRGN_WINDOW;
3417    }
3418    //// HACK 2
3419    Ret = co_WinPosSetWindowPos(Window, HWND_TOP, 0, 0, 0, 0, bRedraw ? flags : (flags|SWP_NOREDRAW) );
3420 
3421    RETURN( (INT)Ret);
3422 
3423 CLEANUP:
3424    TRACE("Leave NtUserSetWindowRgn, ret=%i\n",_ret_);
3425    UserLeave();
3426    END_CLEANUP;
3427 }
3428 
3429 /*
3430  * @implemented
3431  */
3432 DWORD APIENTRY
3433 NtUserSetInternalWindowPos(
3434    HWND    hwnd,
3435    UINT    showCmd,
3436    LPRECT  lprect,
3437    LPPOINT lppt)
3438 {
3439    WINDOWPLACEMENT wndpl;
3440    UINT flags;
3441    PWND Wnd;
3442    RECT rect;
3443    POINT pt = {0};
3444    DECLARE_RETURN(BOOL);
3445    USER_REFERENCE_ENTRY Ref;
3446 
3447    TRACE("Enter NtUserSetWindowPlacement\n");
3448    UserEnterExclusive();
3449 
3450    if (!(Wnd = UserGetWindowObject(hwnd)) || // FIXME:
3451         UserIsDesktopWindow(Wnd) || UserIsMessageWindow(Wnd))
3452    {
3453       RETURN( FALSE);
3454    }
3455 
3456    _SEH2_TRY
3457    {
3458       if (lppt)
3459       {
3460          ProbeForRead(lppt, sizeof(POINT), 1);
3461          RtlCopyMemory(&pt, lppt, sizeof(POINT));
3462       }
3463       if (lprect)
3464       {
3465          ProbeForRead(lprect, sizeof(RECT), 1);
3466          RtlCopyMemory(&rect, lprect, sizeof(RECT));
3467       }
3468    }
3469    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
3470    {
3471       SetLastNtError(_SEH2_GetExceptionCode());
3472       _SEH2_YIELD(RETURN( FALSE));
3473    }
3474    _SEH2_END
3475 
3476    wndpl.length  = sizeof(wndpl);
3477    wndpl.showCmd = showCmd;
3478    wndpl.flags = flags = 0;
3479 
3480    if ( lppt )
3481    {
3482       flags |= PLACE_MIN;
3483       wndpl.flags |= WPF_SETMINPOSITION;
3484       wndpl.ptMinPosition = pt;
3485    }
3486    if ( lprect )
3487    {
3488       flags |= PLACE_RECT;
3489       wndpl.rcNormalPosition = rect;
3490    }
3491 
3492    UserRefObjectCo(Wnd, &Ref);
3493    IntSetWindowPlacement(Wnd, &wndpl, flags);
3494    UserDerefObjectCo(Wnd);
3495    RETURN(TRUE);
3496 
3497 CLEANUP:
3498    TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_);
3499    UserLeave();
3500    END_CLEANUP;
3501 }
3502 
3503 /*
3504  * @implemented
3505  */
3506 BOOL APIENTRY
3507 NtUserSetWindowPlacement(HWND hWnd,
3508                          WINDOWPLACEMENT *lpwndpl)
3509 {
3510    PWND Wnd;
3511    WINDOWPLACEMENT Safepl;
3512    UINT Flags;
3513    DECLARE_RETURN(BOOL);
3514    USER_REFERENCE_ENTRY Ref;
3515 
3516    TRACE("Enter NtUserSetWindowPlacement\n");
3517    UserEnterExclusive();
3518 
3519    if (!(Wnd = UserGetWindowObject(hWnd)) ||
3520         UserIsDesktopWindow(Wnd) || UserIsMessageWindow(Wnd))
3521    {
3522       RETURN( FALSE);
3523    }
3524 
3525    _SEH2_TRY
3526    {
3527       ProbeForRead(lpwndpl, sizeof(WINDOWPLACEMENT), 1);
3528       RtlCopyMemory(&Safepl, lpwndpl, sizeof(WINDOWPLACEMENT));
3529    }
3530    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
3531    {
3532       SetLastNtError(_SEH2_GetExceptionCode());
3533       _SEH2_YIELD(RETURN( FALSE));
3534    }
3535    _SEH2_END
3536 
3537    if(Safepl.length != sizeof(WINDOWPLACEMENT))
3538    {
3539       RETURN( FALSE);
3540    }
3541 
3542    Flags = PLACE_MAX | PLACE_RECT;
3543    if (Safepl.flags & WPF_SETMINPOSITION) Flags |= PLACE_MIN;
3544    UserRefObjectCo(Wnd, &Ref);
3545    IntSetWindowPlacement(Wnd, &Safepl, Flags);
3546    UserDerefObjectCo(Wnd);
3547    RETURN(TRUE);
3548 
3549 CLEANUP:
3550    TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_);
3551    UserLeave();
3552    END_CLEANUP;
3553 }
3554 
3555 /*
3556  * @implemented
3557  */
3558 BOOL APIENTRY
3559 NtUserShowWindowAsync(HWND hWnd, LONG nCmdShow)
3560 {
3561    PWND Window;
3562    BOOL ret;
3563    DECLARE_RETURN(BOOL);
3564    USER_REFERENCE_ENTRY Ref;
3565 
3566    TRACE("Enter NtUserShowWindowAsync\n");
3567    UserEnterExclusive();
3568 
3569    if (!(Window = UserGetWindowObject(hWnd)) ||
3570         UserIsDesktopWindow(Window) || UserIsMessageWindow(Window))
3571    {
3572       RETURN(FALSE);
3573    }
3574 
3575    if ( nCmdShow > SW_MAX )
3576    {
3577       EngSetLastError(ERROR_INVALID_PARAMETER);
3578       RETURN(FALSE);
3579    }
3580 
3581    UserRefObjectCo(Window, &Ref);
3582    ret = co_IntSendMessageNoWait( hWnd, WM_ASYNC_SHOWWINDOW, nCmdShow, 0 );
3583    UserDerefObjectCo(Window);
3584    if (-1 == (int) ret || !ret) ret = FALSE;
3585 
3586    RETURN(ret);
3587 
3588 CLEANUP:
3589    TRACE("Leave NtUserShowWindowAsync, ret=%i\n",_ret_);
3590    UserLeave();
3591    END_CLEANUP;
3592 }
3593 
3594 /*
3595  * @implemented
3596  */
3597 BOOL APIENTRY
3598 NtUserShowWindow(HWND hWnd, LONG nCmdShow)
3599 {
3600    PWND Window;
3601    BOOL ret;
3602    DECLARE_RETURN(BOOL);
3603    USER_REFERENCE_ENTRY Ref;
3604 
3605    TRACE("Enter NtUserShowWindow hWnd %p SW_ %d\n",hWnd, nCmdShow);
3606    UserEnterExclusive();
3607 
3608    if (!(Window = UserGetWindowObject(hWnd)) ||
3609         UserIsDesktopWindow(Window) || UserIsMessageWindow(Window))
3610    {
3611       RETURN(FALSE);
3612    }
3613 
3614    if ( nCmdShow > SW_MAX || Window->state2 & WNDS2_INDESTROY)
3615    {
3616       EngSetLastError(ERROR_INVALID_PARAMETER);
3617       RETURN(FALSE);
3618    }
3619 
3620    UserRefObjectCo(Window, &Ref);
3621    ret = co_WinPosShowWindow(Window, nCmdShow);
3622    UserDerefObjectCo(Window);
3623 
3624    RETURN(ret);
3625 
3626 CLEANUP:
3627    TRACE("Leave NtUserShowWindow, ret=%i\n",_ret_);
3628    UserLeave();
3629    END_CLEANUP;
3630 }
3631 
3632 
3633 /*
3634  *    @implemented
3635  */
3636 HWND APIENTRY
3637 NtUserWindowFromPoint(LONG X, LONG Y)
3638 {
3639    POINT pt;
3640    HWND Ret;
3641    PWND DesktopWindow = NULL, Window = NULL;
3642    USHORT hittest;
3643    DECLARE_RETURN(HWND);
3644    USER_REFERENCE_ENTRY Ref;
3645 
3646    TRACE("Enter NtUserWindowFromPoint\n");
3647    UserEnterExclusive();
3648 
3649    if ((DesktopWindow = UserGetWindowObject(IntGetDesktopWindow())))
3650    {
3651       //PTHREADINFO pti;
3652 
3653       pt.x = X;
3654       pt.y = Y;
3655 
3656       // Hmm... Threads live on desktops thus we have a reference on the desktop and indirectly the desktop window.
3657       // It is possible this referencing is useless, though it should not hurt...
3658       UserRefObjectCo(DesktopWindow, &Ref);
3659 
3660       //pti = PsGetCurrentThreadWin32Thread();
3661       Window = co_WinPosWindowFromPoint(DesktopWindow, &pt, &hittest, FALSE);
3662 
3663       if (Window)
3664       {
3665          Ret = UserHMGetHandle(Window);
3666 
3667          RETURN( Ret);
3668       }
3669    }
3670 
3671    RETURN( NULL);
3672 
3673 CLEANUP:
3674    if (DesktopWindow) UserDerefObjectCo(DesktopWindow);
3675 
3676    TRACE("Leave NtUserWindowFromPoint, ret=%p\n", _ret_);
3677    UserLeave();
3678    END_CLEANUP;
3679 }
3680 
3681 /* EOF */
3682