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