xref: /reactos/win32ss/user/ntuser/winpos.c (revision 803b5e13)
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->spwndOwner == NULL ||
1908           !(Window->spwndOwner->style & WS_VISIBLE) ||
1909           (Window->spwndOwner->ExStyle & WS_EX_TOOLWINDOW))
1910       {
1911          if (UserIsDesktopWindow(Window->spwndParent) &&
1912              (!(Window->ExStyle & WS_EX_TOOLWINDOW) ||
1913               (Window->ExStyle & WS_EX_APPWINDOW)))
1914          {
1915             co_IntShellHookNotify(HSHELL_WINDOWCREATED, (WPARAM)Window->head.h, 0);
1916             if (!(WinPos.flags & SWP_NOACTIVATE))
1917                UpdateShellHook(Window);
1918          }
1919       }
1920 
1921       Window->style |= WS_VISIBLE; //IntSetStyle( Window, WS_VISIBLE, 0 );
1922       Window->head.pti->cVisWindows++;
1923       IntNotifyWinEvent(EVENT_OBJECT_SHOW, Window, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI);
1924    }
1925 
1926    if (Window->hrgnUpdate != NULL && Window->hrgnUpdate != HRGN_WINDOW)
1927    {
1928       NtGdiOffsetRgn(Window->hrgnUpdate,
1929                      NewWindowRect.left - OldWindowRect.left,
1930                      NewWindowRect.top - OldWindowRect.top);
1931    }
1932 
1933    DceResetActiveDCEs(Window); // For WS_VISIBLE changes.
1934 
1935    // Change or update, set send non-client paint flag.
1936    if ( Window->style & WS_VISIBLE &&
1937        (WinPos.flags & SWP_STATECHANGED || (!(Window->state2 & WNDS2_WIN31COMPAT) && WinPos.flags & SWP_NOREDRAW ) ) )
1938    {
1939       TRACE("Set WNDS_SENDNCPAINT %p\n",Window);
1940       Window->state |= WNDS_SENDNCPAINT;
1941    }
1942 
1943    if (!(WinPos.flags & SWP_NOREDRAW))
1944    {
1945       /* Determine the new visible region */
1946       VisAfter = VIS_ComputeVisibleRegion(Window, FALSE, FALSE,
1947                                           (Window->style & WS_CLIPSIBLINGS) ? TRUE : FALSE);
1948 
1949       if ( VisAfter != NULL &&
1950            REGION_Complexity(VisAfter) == NULLREGION )
1951       {
1952          REGION_Delete(VisAfter);
1953          VisAfter = NULL;
1954       }
1955       else if(VisAfter)
1956       {
1957          REGION_bOffsetRgn(VisAfter, -Window->rcWindow.left, -Window->rcWindow.top);
1958       }
1959 
1960       /*
1961        * Determine which pixels can be copied from the old window position
1962        * to the new. Those pixels must be visible in both the old and new
1963        * position. Also, check the class style to see if the windows of this
1964        * class need to be completely repainted on (horizontal/vertical) size
1965        * change.
1966        */
1967       if ( ( VisBefore != NULL &&
1968              VisAfter != NULL &&
1969             !(WinPos.flags & SWP_NOCOPYBITS) &&
1970             ((WinPos.flags & SWP_NOSIZE) || !(WvrFlags & WVR_REDRAW)) &&
1971             !(Window->ExStyle & WS_EX_TRANSPARENT) ) )
1972       {
1973 
1974          /*
1975           * If this is (also) a window resize, the whole nonclient area
1976           * needs to be repainted. So we limit the copy to the client area,
1977           * 'cause there is no use in copying it (would possibly cause
1978           * "flashing" too). However, if the copy region is already empty,
1979           * we don't have to crop (can't take anything away from an empty
1980           * region...)
1981           */
1982 
1983          CopyRgn = IntSysCreateRectpRgn(0, 0, 0, 0);
1984          if ((WinPos.flags & SWP_NOSIZE) && (WinPos.flags & SWP_NOCLIENTSIZE))
1985             RgnType = IntGdiCombineRgn(CopyRgn, VisAfter, VisBefore, RGN_AND);
1986          else if (VisBeforeJustClient != NULL)
1987          {
1988             RgnType = IntGdiCombineRgn(CopyRgn, VisAfter, VisBeforeJustClient, RGN_AND);
1989          }
1990 
1991          if (VisBeforeJustClient != NULL)
1992          {
1993              REGION_Delete(VisBeforeJustClient);
1994          }
1995 
1996          /* Now use in copying bits which are in the update region. */
1997          if (Window->hrgnUpdate != NULL)
1998          {
1999             PREGION RgnUpdate = REGION_LockRgn(Window->hrgnUpdate);
2000             if (RgnUpdate)
2001             {
2002                 REGION_bOffsetRgn(CopyRgn, NewWindowRect.left, NewWindowRect.top);
2003                 IntGdiCombineRgn(CopyRgn, CopyRgn, RgnUpdate, RGN_DIFF);
2004                 REGION_bOffsetRgn(CopyRgn, -NewWindowRect.left, -NewWindowRect.top);
2005                 REGION_UnlockRgn(RgnUpdate);
2006             }
2007          }
2008 
2009          /*
2010           * Now, get the bounding box of the copy region. If it's empty
2011           * there's nothing to copy. Also, it's no use copying bits onto
2012           * themselves.
2013           */
2014          if (REGION_GetRgnBox(CopyRgn, &CopyRect) == NULLREGION)
2015          {
2016             /* Nothing to copy, clean up */
2017             REGION_Delete(CopyRgn);
2018             CopyRgn = NULL;
2019          }
2020          else if ( OldWindowRect.left != NewWindowRect.left ||
2021                    OldWindowRect.top != NewWindowRect.top ||
2022                   (WinPos.flags & SWP_FRAMECHANGED) )
2023          {
2024              HRGN DcRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
2025              PREGION DcRgnObj = REGION_LockRgn(DcRgn);
2026 
2027           /*
2028            * Small trick here: there is no function to bitblt a region. So
2029            * we set the region as the clipping region, take the bounding box
2030            * of the region and bitblt that. Since nothing outside the clipping
2031            * region is copied, this has the effect of bitblt'ing the region.
2032            *
2033            * Since NtUserGetDCEx takes ownership of the clip region, we need
2034            * to create a copy of CopyRgn and pass that. We need CopyRgn later
2035            */
2036             IntGdiCombineRgn(DcRgnObj, CopyRgn, NULL, RGN_COPY);
2037             REGION_bOffsetRgn(DcRgnObj, NewWindowRect.left, NewWindowRect.top);
2038             REGION_UnlockRgn(DcRgnObj);
2039             Dc = UserGetDCEx( Window,
2040                               DcRgn,
2041                               DCX_WINDOW|DCX_CACHE|DCX_INTERSECTRGN|DCX_CLIPSIBLINGS|DCX_KEEPCLIPRGN); // DCX_WINDOW will set first, go read WinDC.c.
2042             NtGdiBitBlt( Dc,
2043                          CopyRect.left, CopyRect.top,
2044                          CopyRect.right - CopyRect.left,
2045                          CopyRect.bottom - CopyRect.top,
2046                          Dc,
2047                          CopyRect.left + (OldWindowRect.left - NewWindowRect.left),
2048                          CopyRect.top + (OldWindowRect.top - NewWindowRect.top),
2049                          SRCCOPY,
2050                          0,
2051                          0);
2052 
2053             UserReleaseDC(Window, Dc, FALSE);
2054             IntValidateParent(Window, CopyRgn);
2055             GreDeleteObject(DcRgn);
2056          }
2057       }
2058       else
2059       {
2060          CopyRgn = NULL;
2061       }
2062 
2063       /* We need to redraw what wasn't visible before or force a redraw */
2064       if (VisAfter != NULL)
2065       {
2066          PREGION DirtyRgn = IntSysCreateRectpRgn(0, 0, 0, 0);
2067          if (DirtyRgn)
2068          {
2069              if (CopyRgn != NULL)
2070              {
2071                 RgnType = IntGdiCombineRgn(DirtyRgn, VisAfter, CopyRgn, RGN_DIFF);
2072              }
2073              else
2074              {
2075                 RgnType = IntGdiCombineRgn(DirtyRgn, VisAfter, 0, RGN_COPY);
2076              }
2077 
2078              if (RgnType != ERROR && RgnType != NULLREGION) // Regions moved.
2079              {
2080             /* old code
2081                 NtGdiOffsetRgn(DirtyRgn, Window->rcWindow.left, Window->rcWindow.top);
2082                 IntInvalidateWindows( Window,
2083                                       DirtyRgn,
2084                    RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
2085              }
2086              GreDeleteObject(DirtyRgn);
2087              */
2088 
2089                 PWND Parent = Window->spwndParent;
2090 
2091                 REGION_bOffsetRgn( DirtyRgn, Window->rcWindow.left, Window->rcWindow.top);
2092 
2093                 if ( (Window->style & WS_CHILD) && (Parent) && !(Parent->style & WS_CLIPCHILDREN))
2094                 {
2095                    IntInvalidateWindows( Parent, DirtyRgn, RDW_ERASE | RDW_INVALIDATE);
2096                    co_IntPaintWindows(Parent, RDW_NOCHILDREN, FALSE);
2097                 }
2098                 else
2099                 {
2100                    IntInvalidateWindows( Window, DirtyRgn, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
2101                 }
2102              }
2103              else if ( RgnType != ERROR && RgnType == NULLREGION ) // Must be the same. See CORE-7166 & CORE-15934, NC HACK fix.
2104              {
2105                 if ( !PosChanged &&
2106                      !(WinPos.flags & SWP_DEFERERASE) &&
2107                       (WinPos.flags & SWP_FRAMECHANGED) )
2108                 {
2109                     PWND pwnd = Window;
2110                     PWND Parent = Window->spwndParent;
2111 
2112                     if ( pwnd->style & WS_CHILD ) // Fix ProgMan menu bar drawing.
2113                     {
2114                         TRACE("SWP_FRAMECHANGED win child %p Parent %p\n",pwnd,Parent);
2115                         pwnd = Parent ? Parent : pwnd;
2116                     }
2117 
2118                     if ( !(pwnd->style & WS_CHILD) )
2119                     {
2120                         HRGN DcRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
2121                         PREGION DcRgnObj = REGION_LockRgn(DcRgn);
2122                         TRACE("SWP_FRAMECHANGED win %p hRgn %p\n",pwnd, DcRgn);
2123                         IntGdiCombineRgn(DcRgnObj, VisBefore, NULL, RGN_COPY);
2124                         REGION_UnlockRgn(DcRgnObj);
2125                         ForceNCPaintErase(pwnd, DcRgn, DcRgnObj);
2126                         GreDeleteObject(DcRgn);
2127                     }
2128                 }
2129              }
2130              REGION_Delete(DirtyRgn);
2131          }
2132       }
2133 
2134       if (CopyRgn != NULL)
2135       {
2136          REGION_Delete(CopyRgn);
2137       }
2138 
2139       /* Expose what was covered before but not covered anymore */
2140       if ( VisBefore != NULL )
2141       {
2142          PREGION ExposedRgn = IntSysCreateRectpRgn(0, 0, 0, 0);
2143          if (ExposedRgn)
2144          {
2145              RgnType = IntGdiCombineRgn(ExposedRgn, VisBefore, NULL, RGN_COPY);
2146              REGION_bOffsetRgn(ExposedRgn,
2147                                OldWindowRect.left - NewWindowRect.left,
2148                                OldWindowRect.top  - NewWindowRect.top);
2149 
2150              if ( VisAfter != NULL )
2151                 RgnType = IntGdiCombineRgn(ExposedRgn, ExposedRgn, VisAfter, RGN_DIFF);
2152 
2153              if (RgnType != ERROR && RgnType != NULLREGION)
2154              {
2155                 co_VIS_WindowLayoutChanged(Window, ExposedRgn);
2156              }
2157              REGION_Delete(ExposedRgn);
2158          }
2159          REGION_Delete(VisBefore);
2160       }
2161 
2162       if (VisAfter != NULL)
2163       {
2164          REGION_Delete(VisAfter);
2165       }
2166    }
2167 
2168    if (!(WinPos.flags & (SWP_NOACTIVATE|SWP_HIDEWINDOW)))
2169    {
2170       if ((Window->style & (WS_CHILD | WS_POPUP)) == WS_CHILD)
2171       {
2172          co_IntSendMessageNoWait(WinPos.hwnd, WM_CHILDACTIVATE, 0, 0);
2173       }
2174       else
2175       {
2176          //ERR("SetWindowPos Set FG Window!\n");
2177          if ( pti->MessageQueue->spwndActive != Window ||
2178               pti->MessageQueue != gpqForeground )
2179          {
2180             //ERR("WPSWP : set active window\n");
2181             if (!(Window->state & WNDS_BEINGACTIVATED)) // Inside SAW?
2182             {
2183                co_IntSetForegroundWindow(Window); // Fixes SW_HIDE issues. Wine win test_SetActiveWindow & test_SetForegroundWindow.
2184             }
2185          }
2186       }
2187    }
2188 
2189    if ( !PosChanged &&
2190          (WinPos.flags & SWP_FRAMECHANGED) &&
2191         !(WinPos.flags & SWP_DEFERERASE) &&    // Prevent sending WM_SYNCPAINT message.
2192          VisAfter )
2193    {
2194        PWND Parent = Window->spwndParent;
2195        if ( !(Window->style & WS_CHILD) && (Parent) && (Parent->style & WS_CLIPCHILDREN))
2196        {
2197            TRACE("SWP_FRAMECHANGED Parent %p WS_CLIPCHILDREN %p\n",Parent,Window);
2198            UserSyncAndPaintWindows( Parent, RDW_CLIPCHILDREN); // NC should redraw here, see NC HACK fix.
2199        }
2200    }
2201 
2202    // Fix wine msg test_SetFocus, prevents sending WM_WINDOWPOSCHANGED.
2203    if ( VisBefore == NULL &&
2204         VisBeforeJustClient == NULL &&
2205        !(Window->ExStyle & WS_EX_TOPMOST) &&
2206         (WinPos.flags & SWP_AGG_STATUSFLAGS) == (SWP_AGG_NOPOSCHANGE & ~SWP_NOZORDER))
2207    {
2208       TRACE("No drawing, set no Z order and no redraw!\n");
2209       WinPos.flags |= SWP_NOZORDER|SWP_NOREDRAW;
2210    }
2211 
2212    if(!(flags & SWP_DEFERERASE))
2213    {
2214        /* erase parent when hiding or resizing child */
2215        if ((flags & SWP_HIDEWINDOW) ||
2216          (!(flags & SWP_SHOWWINDOW) &&
2217           (WinPos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOGEOMETRYCHANGE))
2218        {
2219            PWND Parent = Window->spwndParent;
2220            if (!Parent || UserIsDesktopWindow(Parent)) Parent = Window;
2221            UserSyncAndPaintWindows( Parent, RDW_ERASENOW);
2222        }
2223 
2224        /* Give newly shown windows a chance to redraw */
2225        if(((WinPos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE)
2226                 && !(flags & SWP_AGG_NOCLIENTCHANGE) && (flags & SWP_SHOWWINDOW))
2227        {
2228            UserSyncAndPaintWindows( Window, RDW_ERASENOW);
2229        }
2230    }
2231 
2232    /* And last, send the WM_WINDOWPOSCHANGED message */
2233 
2234    TRACE("\tstatus hwnd %p flags = %04x\n",Window?Window->head.h:NULL,WinPos.flags & SWP_AGG_STATUSFLAGS);
2235 
2236    if (((WinPos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE)
2237             && !((flags & SWP_AGG_NOCLIENTCHANGE) && (flags & SWP_SHOWWINDOW)))
2238    {
2239       /* WM_WINDOWPOSCHANGED is sent even if SWP_NOSENDCHANGING is set
2240          and always contains final window position.
2241        */
2242       WinPos.x = NewWindowRect.left;
2243       WinPos.y = NewWindowRect.top;
2244       WinPos.cx = NewWindowRect.right - NewWindowRect.left;
2245       WinPos.cy = NewWindowRect.bottom - NewWindowRect.top;
2246       TRACE("WM_WINDOWPOSCHANGED hwnd %p Flags %04x\n",WinPos.hwnd,WinPos.flags);
2247       co_IntSendMessageNoWait(WinPos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM) &WinPos);
2248    }
2249 
2250    if ( WinPos.flags & SWP_FRAMECHANGED  || WinPos.flags & SWP_STATECHANGED ||
2251       !(WinPos.flags & SWP_NOCLIENTSIZE) || !(WinPos.flags & SWP_NOCLIENTMOVE) )
2252    {
2253       PWND pWnd = ValidateHwndNoErr(WinPos.hwnd);
2254       if (pWnd)
2255          IntNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE, pWnd, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI);
2256    }
2257 
2258    if(bPointerInWindow != IntPtInWindow(Window, gpsi->ptCursor.x, gpsi->ptCursor.y))
2259    {
2260       /* Generate mouse move message */
2261       MSG msg;
2262       msg.message = WM_MOUSEMOVE;
2263       msg.wParam = UserGetMouseButtonsState();
2264       msg.lParam = MAKELPARAM(gpsi->ptCursor.x, gpsi->ptCursor.y);
2265       msg.pt = gpsi->ptCursor;
2266       co_MsqInsertMouseMessage(&msg, 0, 0, TRUE);
2267    }
2268 
2269    return TRUE;
2270 }
2271 
2272 LRESULT FASTCALL
2273 co_WinPosGetNonClientSize(PWND Window, RECT* WindowRect, RECT* ClientRect)
2274 {
2275    LRESULT Result;
2276 
2277    ASSERT_REFS_CO(Window);
2278 
2279    *ClientRect = *WindowRect;
2280    Result = co_IntSendMessageNoWait(Window->head.h, WM_NCCALCSIZE, FALSE, (LPARAM) ClientRect);
2281 
2282    FixClientRect(ClientRect, WindowRect);
2283 
2284    return Result;
2285 }
2286 
2287 void FASTCALL
2288 co_WinPosSendSizeMove(PWND Wnd)
2289 {
2290     RECTL Rect;
2291     LPARAM lParam;
2292     WPARAM wParam = SIZE_RESTORED;
2293 
2294     IntGetClientRect(Wnd, &Rect);
2295     lParam = MAKELONG(Rect.right-Rect.left, Rect.bottom-Rect.top);
2296 
2297     Wnd->state &= ~WNDS_SENDSIZEMOVEMSGS;
2298 
2299     if (Wnd->style & WS_MAXIMIZE)
2300     {
2301         wParam = SIZE_MAXIMIZED;
2302     }
2303     else if (Wnd->style & WS_MINIMIZE)
2304     {
2305         wParam = SIZE_MINIMIZED;
2306         lParam = 0;
2307     }
2308 
2309     co_IntSendMessageNoWait(UserHMGetHandle(Wnd), WM_SIZE, wParam, lParam);
2310 
2311     if (UserIsDesktopWindow(Wnd->spwndParent))
2312        lParam = MAKELONG(Wnd->rcClient.left, Wnd->rcClient.top);
2313     else
2314        lParam = MAKELONG(Wnd->rcClient.left-Wnd->spwndParent->rcClient.left, Wnd->rcClient.top-Wnd->spwndParent->rcClient.top);
2315 
2316     co_IntSendMessageNoWait(UserHMGetHandle(Wnd), WM_MOVE, 0, lParam);
2317 
2318     IntEngWindowChanged(Wnd, WOC_RGN_CLIENT);
2319 }
2320 
2321 UINT FASTCALL
2322 co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos)
2323 {
2324    POINT Size;
2325    WINDOWPLACEMENT wpl;
2326    LONG old_style;
2327    UINT SwpFlags = 0;
2328 
2329    ASSERT_REFS_CO(Wnd);
2330 
2331    wpl.length = sizeof(wpl);
2332    IntGetWindowPlacement( Wnd, &wpl );
2333 
2334    if (co_HOOK_CallHooks( WH_CBT, HCBT_MINMAX, (WPARAM)Wnd->head.h, ShowFlag))
2335    {
2336       ERR("WinPosMinMaximize WH_CBT Call Hook return!\n");
2337       return SWP_NOSIZE | SWP_NOMOVE;
2338    }
2339       if (Wnd->style & WS_MINIMIZE)
2340       {
2341          switch (ShowFlag)
2342          {
2343          case SW_MINIMIZE:
2344          case SW_SHOWMINNOACTIVE:
2345          case SW_SHOWMINIMIZED:
2346          case SW_FORCEMINIMIZE:
2347              return SWP_NOSIZE | SWP_NOMOVE;
2348          }
2349          if (!co_IntSendMessageNoWait(Wnd->head.h, WM_QUERYOPEN, 0, 0))
2350          {
2351             return(SWP_NOSIZE | SWP_NOMOVE);
2352          }
2353          SwpFlags |= SWP_NOCOPYBITS;
2354       }
2355       switch (ShowFlag)
2356       {
2357          case SW_MINIMIZE:
2358          case SW_SHOWMINNOACTIVE:
2359          case SW_SHOWMINIMIZED:
2360          case SW_FORCEMINIMIZE:
2361             {
2362                //ERR("MinMaximize Minimize\n");
2363                if (Wnd->style & WS_MAXIMIZE)
2364                {
2365                   Wnd->InternalPos.flags |= WPF_RESTORETOMAXIMIZED;
2366                }
2367                else
2368                {
2369                   Wnd->InternalPos.flags &= ~WPF_RESTORETOMAXIMIZED;
2370                }
2371 
2372                old_style = IntSetStyle( Wnd, WS_MINIMIZE, WS_MAXIMIZE );
2373 
2374                co_UserRedrawWindow(Wnd, NULL, 0, RDW_VALIDATE | RDW_NOERASE | RDW_NOINTERNALPAINT);
2375 
2376                if (!(Wnd->InternalPos.flags & WPF_SETMINPOSITION))
2377                   Wnd->InternalPos.flags &= ~WPF_MININIT;
2378 
2379                WinPosFindIconPos(Wnd, &wpl.ptMinPosition);
2380 
2381                if (!(old_style & WS_MINIMIZE))
2382                {
2383                   SwpFlags |= SWP_STATECHANGED;
2384                   IntShowOwnedPopups(Wnd, FALSE);
2385                }
2386 
2387                RECTL_vSetRect(NewPos, wpl.ptMinPosition.x, wpl.ptMinPosition.y,
2388                              wpl.ptMinPosition.x + UserGetSystemMetrics(SM_CXMINIMIZED),
2389                              wpl.ptMinPosition.y + UserGetSystemMetrics(SM_CYMINIMIZED));
2390                SwpFlags |= SWP_NOCOPYBITS;
2391                break;
2392             }
2393 
2394          case SW_MAXIMIZE:
2395             {
2396                //ERR("MinMaximize Maximize\n");
2397                if ((Wnd->style & WS_MAXIMIZE) && (Wnd->style & WS_VISIBLE))
2398                {
2399                   SwpFlags = SWP_NOSIZE | SWP_NOMOVE;
2400                   break;
2401                }
2402                co_WinPosGetMinMaxInfo(Wnd, &Size, &wpl.ptMaxPosition, NULL, NULL);
2403 
2404                /*ERR("Maximize: %d,%d %dx%d\n",
2405                       wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, Size.x, Size.y);
2406                 */
2407                old_style = IntSetStyle( Wnd, WS_MAXIMIZE, WS_MINIMIZE );
2408                /*if (old_style & WS_MINIMIZE)
2409                {
2410                   IntShowOwnedPopups(Wnd, TRUE);
2411                }*/
2412 
2413                if (!(old_style & WS_MAXIMIZE)) SwpFlags |= SWP_STATECHANGED;
2414                RECTL_vSetRect(NewPos, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y,
2415                               //wpl.ptMaxPosition.x + Size.x, wpl.ptMaxPosition.y + Size.y);
2416                               Size.x, Size.y);
2417                break;
2418             }
2419 
2420          case SW_SHOWNOACTIVATE:
2421             Wnd->InternalPos.flags &= ~WPF_RESTORETOMAXIMIZED;
2422             /* fall through */
2423          case SW_SHOWNORMAL:
2424          case SW_RESTORE:
2425          case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
2426             {
2427                //ERR("MinMaximize Restore\n");
2428                old_style = IntSetStyle( Wnd, 0, WS_MINIMIZE | WS_MAXIMIZE );
2429                if (old_style & WS_MINIMIZE)
2430                {
2431                   IntShowOwnedPopups(Wnd, TRUE);
2432 
2433                   if (Wnd->InternalPos.flags & WPF_RESTORETOMAXIMIZED)
2434                   {
2435                      co_WinPosGetMinMaxInfo(Wnd, &Size, &wpl.ptMaxPosition, NULL, NULL);
2436                      IntSetStyle( Wnd, WS_MAXIMIZE, 0 );
2437                      SwpFlags |= SWP_STATECHANGED;
2438                      RECTL_vSetRect(NewPos, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y,
2439                                     wpl.ptMaxPosition.x + Size.x, wpl.ptMaxPosition.y + Size.y);
2440                      break;
2441                   }
2442                   else
2443                   {
2444                      *NewPos = wpl.rcNormalPosition;
2445                      NewPos->right -= NewPos->left;
2446                      NewPos->bottom -= NewPos->top;
2447                      break;
2448                   }
2449                }
2450                else
2451                {
2452                   if (!(old_style & WS_MAXIMIZE))
2453                   {
2454                      break;
2455                   }
2456                   SwpFlags |= SWP_STATECHANGED;
2457                   Wnd->InternalPos.flags &= ~WPF_RESTORETOMAXIMIZED;
2458                   *NewPos = wpl.rcNormalPosition;
2459                   NewPos->right -= NewPos->left;
2460                   NewPos->bottom -= NewPos->top;
2461                   break;
2462                }
2463             }
2464       }
2465    return SwpFlags;
2466 }
2467 
2468 /*
2469    ShowWindow does not set SWP_FRAMECHANGED!!! Fix wine msg test_SetParent:WmSetParentSeq_2:23 wParam bits!
2470  */
2471 BOOLEAN FASTCALL
2472 co_WinPosShowWindow(PWND Wnd, INT Cmd)
2473 {
2474    BOOLEAN WasVisible;
2475    UINT Swp = 0, EventMsg = 0;
2476    RECTL NewPos = {0, 0, 0, 0};
2477    BOOLEAN ShowFlag;
2478    LONG style;
2479    PWND Parent;
2480    PTHREADINFO pti;
2481    //HRGN VisibleRgn;
2482    BOOL ShowOwned = FALSE;
2483    BOOL FirstTime = FALSE;
2484    ASSERT_REFS_CO(Wnd);
2485    //KeRosDumpStackFrames(NULL, 20);
2486    pti = PsGetCurrentThreadWin32Thread();
2487    WasVisible = (Wnd->style & WS_VISIBLE) != 0;
2488    style = Wnd->style;
2489 
2490    TRACE("co_WinPosShowWindow START hwnd %p Cmd %d usicmd %u\n",
2491          Wnd->head.h, Cmd, pti->ppi->usi.wShowWindow);
2492 
2493    if ( pti->ppi->usi.dwFlags & STARTF_USESHOWWINDOW )
2494    {
2495       if ((Wnd->style & (WS_POPUP|WS_CHILD)) != WS_CHILD)
2496       {
2497          if ((Wnd->style & WS_CAPTION) == WS_CAPTION)
2498          {
2499             if (Wnd->spwndOwner == NULL)
2500             {
2501                if ( Cmd == SW_SHOWNORMAL || Cmd == SW_SHOW)
2502                {
2503                     Cmd = SW_SHOWDEFAULT;
2504                }
2505                FirstTime = TRUE;
2506                TRACE("co_WPSW FT 1\n");
2507             }
2508          }
2509       }
2510    }
2511 
2512    if ( Cmd == SW_SHOWDEFAULT )
2513    {
2514       if ( pti->ppi->usi.dwFlags & STARTF_USESHOWWINDOW )
2515       {
2516          Cmd = pti->ppi->usi.wShowWindow;
2517          FirstTime = TRUE;
2518          TRACE("co_WPSW FT 2\n");
2519       }
2520    }
2521 
2522    if (FirstTime)
2523    {
2524       pti->ppi->usi.dwFlags &= ~(STARTF_USEPOSITION|STARTF_USESIZE|STARTF_USESHOWWINDOW);
2525    }
2526 
2527    switch (Cmd)
2528    {
2529       case SW_HIDE:
2530          {
2531             if (!WasVisible)
2532             {
2533                //ERR("co_WinPosShowWindow Exit Bad\n");
2534                return FALSE;
2535             }
2536             Swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE;
2537             if (Wnd != pti->MessageQueue->spwndActive)
2538                Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
2539             break;
2540          }
2541 
2542       case SW_FORCEMINIMIZE: /* FIXME: Does not work if thread is hung. */
2543       case SW_SHOWMINNOACTIVE:
2544          Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
2545          /* Fall through. */
2546       case SW_SHOWMINIMIZED:
2547          Swp |= SWP_SHOWWINDOW;
2548          /* Fall through. */
2549       case SW_MINIMIZE:
2550          {
2551             Swp |= SWP_NOACTIVATE;
2552             if (!(style & WS_MINIMIZE))
2553             {
2554                IntShowOwnedPopups(Wnd, FALSE );
2555                // Fix wine Win test_SetFocus todo #1 & #2,
2556                if (Cmd == SW_SHOWMINIMIZED)
2557                {
2558                   //ERR("co_WinPosShowWindow Set focus 1\n");
2559                   if ((style & (WS_CHILD | WS_POPUP)) == WS_CHILD)
2560                      co_UserSetFocus(Wnd->spwndParent);
2561                   else
2562                      co_UserSetFocus(0);
2563                }
2564 
2565                Swp |= co_WinPosMinMaximize(Wnd, Cmd, &NewPos);
2566 
2567                EventMsg = EVENT_SYSTEM_MINIMIZESTART;
2568             }
2569             else
2570             {
2571                if (WasVisible)
2572                {
2573                   //ERR("co_WinPosShowWindow Exit Good\n");
2574                   return TRUE;
2575                }
2576                Swp |= SWP_NOSIZE | SWP_NOMOVE;
2577             }
2578             break;
2579          }
2580 
2581       case SW_SHOWMAXIMIZED:
2582          {
2583             Swp |= SWP_SHOWWINDOW;
2584             if (!(style & WS_MAXIMIZE))
2585             {
2586                ShowOwned = TRUE;
2587 
2588                Swp |= co_WinPosMinMaximize(Wnd, SW_MAXIMIZE, &NewPos);
2589 
2590                EventMsg = EVENT_SYSTEM_MINIMIZEEND;
2591             }
2592             else
2593             {
2594                if (WasVisible)
2595                {
2596                   //ERR("co_WinPosShowWindow Exit Good 1\n");
2597                   return TRUE;
2598                }
2599                Swp |= SWP_NOSIZE | SWP_NOMOVE;
2600             }
2601             break;
2602          }
2603 
2604       case SW_SHOWNA:
2605          Swp |= SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
2606          if (style & WS_CHILD && !(Wnd->ExStyle & WS_EX_MDICHILD)) Swp |= SWP_NOZORDER;
2607          break;
2608       case SW_SHOW:
2609          if (WasVisible) return(TRUE); // Nothing to do!
2610          Swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
2611          /* Don't activate the topmost window. */
2612          if (style & WS_CHILD && !(Wnd->ExStyle & WS_EX_MDICHILD)) Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
2613          break;
2614 
2615       case SW_SHOWNOACTIVATE:
2616          Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
2617          /* Fall through. */
2618       case SW_SHOWNORMAL:
2619       case SW_SHOWDEFAULT:
2620       case SW_RESTORE:
2621          if (!WasVisible) Swp |= SWP_SHOWWINDOW;
2622          if (style & (WS_MINIMIZE | WS_MAXIMIZE))
2623          {
2624             Swp |= co_WinPosMinMaximize(Wnd, Cmd, &NewPos);
2625             if (style & WS_MINIMIZE) EventMsg = EVENT_SYSTEM_MINIMIZEEND;
2626          }
2627          else
2628          {
2629             if (WasVisible)
2630             {
2631                //ERR("co_WinPosShowWindow Exit Good 3\n");
2632                return TRUE;
2633             }
2634             Swp |= SWP_NOSIZE | SWP_NOMOVE;
2635          }
2636          if ( style & WS_CHILD &&
2637              !(Wnd->ExStyle & WS_EX_MDICHILD) &&
2638              !(Swp & SWP_STATECHANGED))
2639             Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
2640          break;
2641 
2642       default:
2643          //ERR("co_WinPosShowWindow Exit Good 4\n");
2644          return WasVisible;
2645    }
2646 
2647    ShowFlag = (Cmd != SW_HIDE);
2648 
2649    if ((ShowFlag != WasVisible || Cmd == SW_SHOWNA) && Cmd != SW_SHOWMAXIMIZED && !(Swp & SWP_STATECHANGED))
2650    {
2651       co_IntSendMessageNoWait(Wnd->head.h, WM_SHOWWINDOW, ShowFlag, 0);
2652 #if 0 // Fix wine msg test_SetParent:WmSetParentSeq_1:2
2653       if (!(Wnd->state2 & WNDS2_WIN31COMPAT)) // <------------- XP sets this bit!
2654          co_IntSendMessageNoWait(Wnd->head.h, WM_SETVISIBLE, ShowFlag, 0);
2655 #endif
2656       if (!VerifyWnd(Wnd)) return WasVisible;
2657    }
2658 
2659    /* We can't activate a child window */
2660    if ((Wnd->style & WS_CHILD) &&
2661        !(Wnd->ExStyle & WS_EX_MDICHILD) &&
2662        Cmd != SW_SHOWNA)
2663    {
2664       //ERR("SWP Child No active and ZOrder\n");
2665       Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
2666    }
2667 
2668 #if 0 // Explorer issues with common controls? Someone does not know how CS_SAVEBITS works.
2669       // Breaks startup and shutdown active window...
2670    if ((Wnd->style & (WS_POPUP|WS_CHILD)) != WS_CHILD &&
2671         Wnd->pcls->style & CS_SAVEBITS &&
2672         ((Cmd == SW_SHOW) || (Cmd == SW_NORMAL)))
2673    {
2674       ERR("WinPosShowWindow Set active\n");
2675       //UserSetActiveWindow(Wnd);
2676       co_IntSetForegroundWindow(Wnd); // HACK
2677       Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
2678    }
2679 #endif
2680 
2681    if (IsChildVisible(Wnd) || Swp & SWP_STATECHANGED)
2682    {
2683        TRACE("Child is Vis %s or State changed %s. ShowFlag %s Swp %04x\n",
2684              (IsChildVisible(Wnd) ? "TRUE" : "FALSE"), (Swp & SWP_STATECHANGED ? "TRUE" : "FALSE"),
2685              (ShowFlag ? "TRUE" : "FALSE"),LOWORD(Swp));
2686    co_WinPosSetWindowPos( Wnd,
2687                           0 != (Wnd->ExStyle & WS_EX_TOPMOST) ? HWND_TOPMOST : HWND_TOP,
2688                           NewPos.left,
2689                           NewPos.top,
2690                           NewPos.right, // NewPos.right - NewPos.left, when minimized and restore, the window becomes smaller.
2691                           NewPos.bottom,// NewPos.bottom - NewPos.top,
2692                           LOWORD(Swp));
2693    }
2694    else
2695    {
2696       TRACE("Parent Vis?\n");
2697       /* if parent is not visible simply toggle WS_VISIBLE and return */
2698       if (ShowFlag) IntSetStyle( Wnd, WS_VISIBLE, 0 );
2699       else IntSetStyle( Wnd, 0, WS_VISIBLE );
2700    }
2701 
2702    if ( EventMsg ) IntNotifyWinEvent(EventMsg, Wnd, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI);
2703 
2704    if ( ShowOwned ) IntShowOwnedPopups(Wnd, TRUE );
2705 
2706    if ((Cmd == SW_HIDE) || (Cmd == SW_MINIMIZE))
2707    {
2708       if ( Wnd == pti->MessageQueue->spwndActive && pti->MessageQueue == IntGetFocusMessageQueue()  )
2709       {
2710           if (UserIsDesktopWindow(Wnd->spwndParent))
2711           {
2712               if (!ActivateOtherWindowMin(Wnd))
2713               {
2714                 co_WinPosActivateOtherWindow(Wnd);
2715               }
2716           }
2717           else
2718           {
2719               co_WinPosActivateOtherWindow(Wnd);
2720           }
2721       }
2722 
2723       /* Revert focus to parent */
2724       if (Wnd == pti->MessageQueue->spwndFocus)
2725       {
2726          Parent = Wnd->spwndParent;
2727          if (UserIsDesktopWindow(Wnd->spwndParent))
2728              Parent = 0;
2729          co_UserSetFocus(Parent);
2730       }
2731       // Hide, just return.
2732       if (Cmd == SW_HIDE) return WasVisible;
2733    }
2734 
2735    /* FIXME: Check for window destruction. */
2736 
2737    if ((Wnd->state & WNDS_SENDSIZEMOVEMSGS) &&
2738        !(Wnd->state2 & WNDS2_INDESTROY))
2739    {
2740         co_WinPosSendSizeMove(Wnd);
2741    }
2742 
2743    /* if previous state was minimized Windows sets focus to the window */
2744    if (style & WS_MINIMIZE)
2745    {
2746       co_UserSetFocus(Wnd);
2747       // Fix wine Win test_SetFocus todo #3,
2748       if (!(style & WS_CHILD)) co_IntSendMessage(UserHMGetHandle(Wnd), WM_ACTIVATE, WA_ACTIVE, 0);
2749    }
2750    //ERR("co_WinPosShowWindow EXIT\n");
2751    return WasVisible;
2752 }
2753 
2754 static PWND
2755 co_WinPosSearchChildren(
2756    IN PWND ScopeWin,
2757    IN POINT *Point,
2758    IN OUT USHORT *HitTest,
2759    IN BOOL Ignore
2760    )
2761 {
2762     HWND *List, *phWnd;
2763     PWND pwndChild = NULL;
2764 
2765     /* not visible */
2766     if (!(ScopeWin->style & WS_VISIBLE))
2767     {
2768         return NULL;
2769     }
2770 
2771     /* not in window or in window region */
2772     if (!IntPtInWindow(ScopeWin, Point->x, Point->y))
2773     {
2774         return NULL;
2775     }
2776 
2777     /* transparent */
2778     if ((ScopeWin->ExStyle & (WS_EX_LAYERED|WS_EX_TRANSPARENT)) == (WS_EX_LAYERED|WS_EX_TRANSPARENT))
2779     {
2780         return NULL;
2781     }
2782 
2783     if (!Ignore && (ScopeWin->style & WS_DISABLED))
2784     {   /* disabled child */
2785         if ((ScopeWin->style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return NULL;
2786         /* process the hit error */
2787         *HitTest = HTERROR;
2788         return ScopeWin;
2789     }
2790 
2791     /* not minimized and check if point is inside the window */
2792     if (!(ScopeWin->style & WS_MINIMIZE) &&
2793          RECTL_bPointInRect(&ScopeWin->rcClient, Point->x, Point->y) )
2794     {
2795         UserReferenceObject(ScopeWin);
2796 
2797         List = IntWinListChildren(ScopeWin);
2798         if (List)
2799         {
2800             for (phWnd = List; *phWnd; ++phWnd)
2801             {
2802                 if (!(pwndChild = ValidateHwndNoErr(*phWnd)))
2803                 {
2804                     continue;
2805                 }
2806 
2807                 pwndChild = co_WinPosSearchChildren(pwndChild, Point, HitTest, Ignore);
2808 
2809                 if (pwndChild != NULL)
2810                 {
2811                     /* We found a window. Don't send any more WM_NCHITTEST messages */
2812                     ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
2813                     UserDereferenceObject(ScopeWin);
2814                     return pwndChild;
2815                 }
2816             }
2817             ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
2818         }
2819         UserDereferenceObject(ScopeWin);
2820     }
2821 
2822     if (ScopeWin->head.pti == PsGetCurrentThreadWin32Thread())
2823     {
2824        *HitTest = (USHORT)co_IntSendMessage(ScopeWin->head.h, WM_NCHITTEST, 0, MAKELONG(Point->x, Point->y));
2825 
2826        if ((*HitTest) == (USHORT)HTTRANSPARENT)
2827        {
2828            return NULL;
2829        }
2830     }
2831     else
2832     {
2833        if (*HitTest == HTNOWHERE && pwndChild == NULL) *HitTest = HTCLIENT;
2834     }
2835 
2836     return ScopeWin;
2837 }
2838 
2839 PWND APIENTRY
2840 co_WinPosWindowFromPoint(
2841    IN PWND ScopeWin,
2842    IN POINT *WinPoint,
2843    IN OUT USHORT* HitTest,
2844    IN BOOL Ignore)
2845 {
2846    PWND Window;
2847    POINT Point = *WinPoint;
2848    USER_REFERENCE_ENTRY Ref;
2849 
2850    if( ScopeWin == NULL )
2851    {
2852        ScopeWin = UserGetDesktopWindow();
2853        if(ScopeWin == NULL)
2854            return NULL;
2855    }
2856 
2857    *HitTest = HTNOWHERE;
2858 
2859    ASSERT_REFS_CO(ScopeWin);
2860    UserRefObjectCo(ScopeWin, &Ref);
2861 
2862    Window = co_WinPosSearchChildren(ScopeWin, &Point, HitTest, Ignore);
2863 
2864    UserDerefObjectCo(ScopeWin);
2865    if (Window)
2866        ASSERT_REFS_CO(Window);
2867    ASSERT_REFS_CO(ScopeWin);
2868 
2869    return Window;
2870 }
2871 
2872 PWND FASTCALL
2873 IntRealChildWindowFromPoint(PWND Parent, LONG x, LONG y)
2874 {
2875    POINTL Pt;
2876    HWND *List, *phWnd;
2877    PWND pwndHit = NULL;
2878 
2879    Pt.x = x;
2880    Pt.y = y;
2881 
2882    if (!UserIsDesktopWindow(Parent))
2883    {
2884       Pt.x += Parent->rcClient.left;
2885       Pt.y += Parent->rcClient.top;
2886    }
2887 
2888    if (!IntPtInWindow(Parent, Pt.x, Pt.y)) return NULL;
2889 
2890    if ((List = IntWinListChildren(Parent)))
2891    {
2892       for (phWnd = List; *phWnd; phWnd++)
2893       {
2894          PWND Child;
2895          if ((Child = ValidateHwndNoErr(*phWnd)))
2896          {
2897             if ( Child->style & WS_VISIBLE && IntPtInWindow(Child, Pt.x, Pt.y) )
2898             {
2899                if ( Child->pcls->atomClassName != gpsi->atomSysClass[ICLS_BUTTON] ||
2900                    (Child->style & BS_TYPEMASK) != BS_GROUPBOX )
2901                {
2902                   ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
2903                   return Child;
2904                }
2905                pwndHit = Child;
2906             }
2907          }
2908       }
2909       ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
2910    }
2911    return pwndHit ? pwndHit : Parent;
2912 }
2913 
2914 PWND APIENTRY
2915 IntChildWindowFromPointEx(PWND Parent, LONG x, LONG y, UINT uiFlags)
2916 {
2917    POINTL Pt;
2918    HWND *List, *phWnd;
2919    PWND pwndHit = NULL;
2920 
2921    Pt.x = x;
2922    Pt.y = y;
2923 
2924    if (!UserIsDesktopWindow(Parent))
2925    {
2926       if (Parent->ExStyle & WS_EX_LAYOUTRTL)
2927          Pt.x = Parent->rcClient.right - Pt.x;
2928       else
2929          Pt.x += Parent->rcClient.left;
2930       Pt.y += Parent->rcClient.top;
2931    }
2932 
2933    if (!IntPtInWindow(Parent, Pt.x, Pt.y)) return NULL;
2934 
2935    if ((List = IntWinListChildren(Parent)))
2936    {
2937       for (phWnd = List; *phWnd; phWnd++)
2938       {
2939          PWND Child;
2940          if ((Child = ValidateHwndNoErr(*phWnd)))
2941          {
2942             if (uiFlags & (CWP_SKIPINVISIBLE|CWP_SKIPDISABLED))
2943             {
2944                if (!(Child->style & WS_VISIBLE) && (uiFlags & CWP_SKIPINVISIBLE)) continue;
2945                if ((Child->style & WS_DISABLED) && (uiFlags & CWP_SKIPDISABLED)) continue;
2946             }
2947 
2948             if (uiFlags & CWP_SKIPTRANSPARENT)
2949             {
2950                if (Child->ExStyle & WS_EX_TRANSPARENT) continue;
2951             }
2952 
2953             if (IntPtInWindow(Child, Pt.x, Pt.y))
2954             {
2955                pwndHit = Child;
2956                break;
2957             }
2958          }
2959       }
2960       ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
2961    }
2962    return pwndHit ? pwndHit : Parent;
2963 }
2964 
2965 HDWP
2966 FASTCALL
2967 IntDeferWindowPos( HDWP hdwp,
2968                    HWND hwnd,
2969                    HWND hwndAfter,
2970                    INT x,
2971                    INT y,
2972                    INT cx,
2973                    INT cy,
2974                    UINT flags )
2975 {
2976     PSMWP pDWP;
2977     int i;
2978     HDWP retvalue = hdwp;
2979 
2980     TRACE("hdwp %p, hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
2981           hdwp, hwnd, hwndAfter, x, y, cx, cy, flags);
2982 
2983     if (flags & ~(SWP_NOSIZE | SWP_NOMOVE |
2984                   SWP_NOZORDER | SWP_NOREDRAW |
2985                   SWP_NOACTIVATE | SWP_NOCOPYBITS |
2986                   SWP_NOOWNERZORDER|SWP_SHOWWINDOW |
2987                   SWP_HIDEWINDOW | SWP_FRAMECHANGED))
2988     {
2989        EngSetLastError(ERROR_INVALID_PARAMETER);
2990        return NULL;
2991     }
2992 
2993     if (!(pDWP = (PSMWP)UserGetObject(gHandleTable, hdwp, TYPE_SETWINDOWPOS)))
2994     {
2995        EngSetLastError(ERROR_INVALID_DWP_HANDLE);
2996        return NULL;
2997     }
2998 
2999     for (i = 0; i < pDWP->ccvr; i++)
3000     {
3001         if (pDWP->acvr[i].pos.hwnd == hwnd)
3002         {
3003               /* Merge with the other changes */
3004             if (!(flags & SWP_NOZORDER))
3005             {
3006                 pDWP->acvr[i].pos.hwndInsertAfter = hwndAfter;
3007             }
3008             if (!(flags & SWP_NOMOVE))
3009             {
3010                 pDWP->acvr[i].pos.x = x;
3011                 pDWP->acvr[i].pos.y = y;
3012             }
3013             if (!(flags & SWP_NOSIZE))
3014             {
3015                 pDWP->acvr[i].pos.cx = cx;
3016                 pDWP->acvr[i].pos.cy = cy;
3017             }
3018             pDWP->acvr[i].pos.flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
3019                                                SWP_NOZORDER | SWP_NOREDRAW |
3020                                                SWP_NOACTIVATE | SWP_NOCOPYBITS|
3021                                                SWP_NOOWNERZORDER);
3022             pDWP->acvr[i].pos.flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
3023                                               SWP_FRAMECHANGED);
3024             goto END;
3025         }
3026     }
3027     if (pDWP->ccvr >= pDWP->ccvrAlloc)
3028     {
3029         PCVR newpos = ExAllocatePoolWithTag(PagedPool, pDWP->ccvrAlloc * 2 * sizeof(CVR), USERTAG_SWP);
3030         if (!newpos)
3031         {
3032             retvalue = NULL;
3033             goto END;
3034         }
3035         RtlZeroMemory(newpos, pDWP->ccvrAlloc * 2 * sizeof(CVR));
3036         RtlCopyMemory(newpos, pDWP->acvr, pDWP->ccvrAlloc * sizeof(CVR));
3037         ExFreePoolWithTag(pDWP->acvr, USERTAG_SWP);
3038         pDWP->ccvrAlloc *= 2;
3039         pDWP->acvr = newpos;
3040     }
3041     pDWP->acvr[pDWP->ccvr].pos.hwnd = hwnd;
3042     pDWP->acvr[pDWP->ccvr].pos.hwndInsertAfter = hwndAfter;
3043     pDWP->acvr[pDWP->ccvr].pos.x = x;
3044     pDWP->acvr[pDWP->ccvr].pos.y = y;
3045     pDWP->acvr[pDWP->ccvr].pos.cx = cx;
3046     pDWP->acvr[pDWP->ccvr].pos.cy = cy;
3047     pDWP->acvr[pDWP->ccvr].pos.flags = flags;
3048     pDWP->acvr[pDWP->ccvr].hrgnClip = NULL;
3049     pDWP->acvr[pDWP->ccvr].hrgnInterMonitor = NULL;
3050     pDWP->ccvr++;
3051 END:
3052     return retvalue;
3053 }
3054 
3055 BOOL FASTCALL IntEndDeferWindowPosEx( HDWP hdwp, BOOL sAsync )
3056 {
3057     PSMWP pDWP;
3058     PCVR winpos;
3059     BOOL res = TRUE;
3060     int i;
3061 
3062     TRACE("%p\n", hdwp);
3063 
3064     if (!(pDWP = (PSMWP)UserGetObject(gHandleTable, hdwp, TYPE_SETWINDOWPOS)))
3065     {
3066        EngSetLastError(ERROR_INVALID_DWP_HANDLE);
3067        return FALSE;
3068     }
3069 
3070     for (i = 0, winpos = pDWP->acvr; res && i < pDWP->ccvr; i++, winpos++)
3071     {
3072         PWND pwnd;
3073         USER_REFERENCE_ENTRY Ref;
3074 
3075         TRACE("hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
3076                winpos->pos.hwnd, winpos->pos.hwndInsertAfter, winpos->pos.x, winpos->pos.y,
3077                winpos->pos.cx, winpos->pos.cy, winpos->pos.flags);
3078 
3079         pwnd = ValidateHwndNoErr(winpos->pos.hwnd);
3080         if (!pwnd)
3081            continue;
3082 
3083         UserRefObjectCo(pwnd, &Ref);
3084 
3085         if ( sAsync )
3086         {
3087            LRESULT lRes;
3088            PWINDOWPOS ppos = ExAllocatePoolWithTag(PagedPool, sizeof(WINDOWPOS), USERTAG_SWP);
3089            if ( ppos )
3090            {
3091               *ppos = winpos->pos;
3092               /* Yes it's a pointer inside Win32k! */
3093               lRes = co_IntSendMessageNoWait( winpos->pos.hwnd, WM_ASYNC_SETWINDOWPOS, 0, (LPARAM)ppos);
3094               /* We handle this the same way as Event Hooks and Hooks. */
3095               if ( !lRes )
3096               {
3097                  ExFreePoolWithTag(ppos, USERTAG_SWP);
3098               }
3099            }
3100         }
3101         else
3102            res = co_WinPosSetWindowPos( pwnd,
3103                                         winpos->pos.hwndInsertAfter,
3104                                         winpos->pos.x,
3105                                         winpos->pos.y,
3106                                         winpos->pos.cx,
3107                                         winpos->pos.cy,
3108                                         winpos->pos.flags);
3109 
3110         // Hack to pass tests.... Must have some work to do so clear the error.
3111         if (res && (winpos->pos.flags & (SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER)) == SWP_NOZORDER )
3112            EngSetLastError(ERROR_SUCCESS);
3113 
3114         UserDerefObjectCo(pwnd);
3115     }
3116     ExFreePoolWithTag(pDWP->acvr, USERTAG_SWP);
3117     UserDereferenceObject(pDWP);
3118     UserDeleteObject(hdwp, TYPE_SETWINDOWPOS);
3119     return res;
3120 }
3121 
3122 /*
3123  * @implemented
3124  */
3125 HWND APIENTRY
3126 NtUserChildWindowFromPointEx(HWND hwndParent,
3127                              LONG x,
3128                              LONG y,
3129                              UINT uiFlags)
3130 {
3131    PWND pwndParent;
3132    TRACE("Enter NtUserChildWindowFromPointEx\n");
3133    UserEnterExclusive();
3134    if ((pwndParent = UserGetWindowObject(hwndParent)))
3135    {
3136       pwndParent = IntChildWindowFromPointEx(pwndParent, x, y, uiFlags);
3137    }
3138    UserLeave();
3139    TRACE("Leave NtUserChildWindowFromPointEx\n");
3140    return pwndParent ? UserHMGetHandle(pwndParent) : NULL;
3141 }
3142 
3143 /*
3144  * @implemented
3145  */
3146 BOOL APIENTRY
3147 NtUserEndDeferWindowPosEx(HDWP WinPosInfo,
3148                           DWORD Unknown1)
3149 {
3150    BOOL Ret;
3151    TRACE("Enter NtUserEndDeferWindowPosEx\n");
3152    UserEnterExclusive();
3153    Ret = IntEndDeferWindowPosEx(WinPosInfo, (BOOL)Unknown1);
3154    TRACE("Leave NtUserEndDeferWindowPosEx, ret=%i\n", Ret);
3155    UserLeave();
3156    return Ret;
3157 }
3158 
3159 /*
3160  * @implemented
3161  */
3162 HDWP APIENTRY
3163 NtUserDeferWindowPos(HDWP WinPosInfo,
3164                      HWND Wnd,
3165                      HWND WndInsertAfter,
3166                      int x,
3167                      int y,
3168                      int cx,
3169                      int cy,
3170                      UINT Flags)
3171 {
3172    PWND pWnd, pWndIA;
3173    HDWP Ret = NULL;
3174    UINT Tmp = ~(SWP_ASYNCWINDOWPOS|SWP_DEFERERASE|SWP_NOSENDCHANGING|SWP_NOREPOSITION|
3175                 SWP_NOCOPYBITS|SWP_HIDEWINDOW|SWP_SHOWWINDOW|SWP_FRAMECHANGED|
3176                 SWP_NOACTIVATE|SWP_NOREDRAW|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE);
3177 
3178    TRACE("Enter NtUserDeferWindowPos\n");
3179    UserEnterExclusive();
3180 
3181    if ( Flags & Tmp )
3182    {
3183       EngSetLastError(ERROR_INVALID_FLAGS);
3184       goto Exit;
3185    }
3186 
3187    pWnd = UserGetWindowObject(Wnd);
3188    if (!pWnd || UserIsDesktopWindow(pWnd) || UserIsMessageWindow(pWnd))
3189    {
3190       goto Exit;
3191    }
3192 
3193    if ( WndInsertAfter &&
3194         WndInsertAfter != HWND_BOTTOM &&
3195         WndInsertAfter != HWND_TOPMOST &&
3196         WndInsertAfter != HWND_NOTOPMOST )
3197    {
3198       pWndIA = UserGetWindowObject(WndInsertAfter);
3199       if (!pWndIA || UserIsDesktopWindow(pWndIA) || UserIsMessageWindow(pWndIA))
3200       {
3201          goto Exit;
3202       }
3203    }
3204 
3205    Ret = IntDeferWindowPos(WinPosInfo, Wnd, WndInsertAfter, x, y, cx, cy, Flags);
3206 
3207 Exit:
3208    TRACE("Leave NtUserDeferWindowPos, ret=%p\n", Ret);
3209    UserLeave();
3210    return Ret;
3211 }
3212 
3213 /*
3214  * @implemented
3215  */
3216 DWORD APIENTRY
3217 NtUserGetInternalWindowPos( HWND hWnd,
3218                             LPRECT rectWnd,
3219                             LPPOINT ptIcon)
3220 {
3221    PWND Window;
3222    DWORD Ret = 0;
3223    BOOL Hit = FALSE;
3224    WINDOWPLACEMENT wndpl;
3225 
3226    UserEnterShared();
3227 
3228    if (!(Window = UserGetWindowObject(hWnd)))
3229    {
3230       Hit = FALSE;
3231       goto Exit;
3232    }
3233 
3234    _SEH2_TRY
3235    {
3236        if(rectWnd)
3237        {
3238           ProbeForWrite(rectWnd,
3239                         sizeof(RECT),
3240                         1);
3241        }
3242        if(ptIcon)
3243        {
3244           ProbeForWrite(ptIcon,
3245                         sizeof(POINT),
3246                         1);
3247        }
3248 
3249    }
3250    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
3251    {
3252        SetLastNtError(_SEH2_GetExceptionCode());
3253        Hit = TRUE;
3254    }
3255    _SEH2_END;
3256 
3257    wndpl.length = sizeof(WINDOWPLACEMENT);
3258 
3259    if (IntGetWindowPlacement(Window, &wndpl) && !Hit)
3260    {
3261       _SEH2_TRY
3262       {
3263           if (rectWnd)
3264           {
3265              RtlCopyMemory(rectWnd, &wndpl.rcNormalPosition , sizeof(RECT));
3266           }
3267           if (ptIcon)
3268           {
3269              RtlCopyMemory(ptIcon, &wndpl.ptMinPosition, sizeof(POINT));
3270           }
3271 
3272       }
3273       _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
3274       {
3275           SetLastNtError(_SEH2_GetExceptionCode());
3276           Hit = TRUE;
3277       }
3278       _SEH2_END;
3279 
3280       if (!Hit) Ret = wndpl.showCmd;
3281    }
3282 Exit:
3283    UserLeave();
3284    return Ret;
3285 }
3286 
3287 /*
3288  * @implemented
3289  */
3290 BOOL APIENTRY
3291 NtUserGetWindowPlacement(HWND hWnd,
3292                          WINDOWPLACEMENT *lpwndpl)
3293 {
3294    PWND Wnd;
3295    WINDOWPLACEMENT Safepl;
3296    NTSTATUS Status;
3297    DECLARE_RETURN(BOOL);
3298 
3299    TRACE("Enter NtUserGetWindowPlacement\n");
3300    UserEnterShared();
3301 
3302    if (!(Wnd = UserGetWindowObject(hWnd)))
3303    {
3304       RETURN( FALSE);
3305    }
3306 
3307    Status = MmCopyFromCaller(&Safepl, lpwndpl, sizeof(WINDOWPLACEMENT));
3308    if (!NT_SUCCESS(Status))
3309    {
3310       SetLastNtError(Status);
3311       RETURN( FALSE);
3312    }
3313 
3314    Safepl.length = sizeof(WINDOWPLACEMENT);
3315 
3316    IntGetWindowPlacement(Wnd, &Safepl);
3317 
3318    Status = MmCopyToCaller(lpwndpl, &Safepl, sizeof(WINDOWPLACEMENT));
3319    if (!NT_SUCCESS(Status))
3320    {
3321       SetLastNtError(Status);
3322       RETURN( FALSE);
3323    }
3324 
3325    RETURN( TRUE);
3326 
3327 CLEANUP:
3328    TRACE("Leave NtUserGetWindowPlacement, ret=%i\n",_ret_);
3329    UserLeave();
3330    END_CLEANUP;
3331 }
3332 
3333 DWORD
3334 APIENTRY
3335 NtUserMinMaximize(
3336     HWND hWnd,
3337     UINT cmd, // Wine SW_ commands
3338     BOOL Hide)
3339 {
3340   PWND pWnd;
3341 
3342   TRACE("Enter NtUserMinMaximize\n");
3343   UserEnterExclusive();
3344 
3345   pWnd = UserGetWindowObject(hWnd);
3346   if (!pWnd || UserIsDesktopWindow(pWnd) || UserIsMessageWindow(pWnd))
3347   {
3348      goto Exit;
3349   }
3350 
3351   if ( cmd > SW_MAX || pWnd->state2 & WNDS2_INDESTROY)
3352   {
3353      EngSetLastError(ERROR_INVALID_PARAMETER);
3354      goto Exit;
3355   }
3356 
3357   cmd |= Hide ? SW_HIDE : 0;
3358 
3359   co_WinPosShowWindow(pWnd, cmd);
3360 
3361 Exit:
3362   TRACE("Leave NtUserMinMaximize\n");
3363   UserLeave();
3364   return 0; // Always NULL?
3365 }
3366 
3367 /*
3368  * @implemented
3369  */
3370 BOOL APIENTRY
3371 NtUserMoveWindow(
3372    HWND hWnd,
3373    int X,
3374    int Y,
3375    int nWidth,
3376    int nHeight,
3377    BOOL bRepaint)
3378 {
3379    return NtUserSetWindowPos(hWnd, 0, X, Y, nWidth, nHeight,
3380                              (bRepaint ? SWP_NOZORDER | SWP_NOACTIVATE :
3381                               SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW));
3382 }
3383 
3384 /*
3385  * @implemented
3386  */
3387 HWND APIENTRY
3388 NtUserRealChildWindowFromPoint(HWND Parent,
3389                                LONG x,
3390                                LONG y)
3391 {
3392    PWND pwndParent;
3393    TRACE("Enter NtUserRealChildWindowFromPoint\n");
3394    UserEnterShared();
3395    if ((pwndParent = UserGetWindowObject(Parent)))
3396    {
3397       pwndParent = IntRealChildWindowFromPoint(pwndParent, x, y);
3398    }
3399    UserLeave();
3400    TRACE("Leave NtUserRealChildWindowFromPoint\n");
3401    return pwndParent ? UserHMGetHandle(pwndParent) : NULL;
3402 }
3403 
3404 /*
3405  * @implemented
3406  */
3407 BOOL APIENTRY
3408 NtUserSetWindowPos(
3409    HWND hWnd,
3410    HWND hWndInsertAfter,
3411    int X,
3412    int Y,
3413    int cx,
3414    int cy,
3415    UINT uFlags)
3416 {
3417    DECLARE_RETURN(BOOL);
3418    PWND Window, pWndIA;
3419    BOOL ret;
3420    USER_REFERENCE_ENTRY Ref;
3421 
3422    TRACE("Enter NtUserSetWindowPos\n");
3423    UserEnterExclusive();
3424 
3425    if (!(Window = UserGetWindowObject(hWnd)) ||
3426         UserIsDesktopWindow(Window) || UserIsMessageWindow(Window))
3427    {
3428       ERR("NtUserSetWindowPos bad window handle!\n");
3429       RETURN(FALSE);
3430    }
3431 
3432    if ( hWndInsertAfter != HWND_TOP &&
3433         hWndInsertAfter != HWND_BOTTOM &&
3434         hWndInsertAfter != HWND_TOPMOST &&
3435         hWndInsertAfter != HWND_NOTOPMOST )
3436    {
3437       if (!(pWndIA = UserGetWindowObject(hWndInsertAfter)) ||
3438             UserIsDesktopWindow(pWndIA) || UserIsMessageWindow(pWndIA))
3439       {
3440          ERR("NtUserSetWindowPos bad insert window handle!\n");
3441          RETURN(FALSE);
3442       }
3443    }
3444 
3445    /* First make sure that coordinates are valid for WM_WINDOWPOSCHANGING */
3446    if (!(uFlags & SWP_NOMOVE))
3447    {
3448       if (X < -32768) X = -32768;
3449       else if (X > 32767) X = 32767;
3450       if (Y < -32768) Y = -32768;
3451       else if (Y > 32767) Y = 32767;
3452    }
3453    if (!(uFlags & SWP_NOSIZE))
3454    {
3455       if (cx < 0) cx = 0;
3456       else if (cx > 32767) cx = 32767;
3457       if (cy < 0) cy = 0;
3458       else if (cy > 32767) cy = 32767;
3459    }
3460 
3461    UserRefObjectCo(Window, &Ref);
3462    ret = co_WinPosSetWindowPos(Window, hWndInsertAfter, X, Y, cx, cy, uFlags);
3463    UserDerefObjectCo(Window);
3464 
3465    RETURN(ret);
3466 
3467 CLEANUP:
3468    TRACE("Leave NtUserSetWindowPos, ret=%i\n",_ret_);
3469    UserLeave();
3470    END_CLEANUP;
3471 }
3472 
3473 /*
3474  * @implemented
3475  */
3476 INT APIENTRY
3477 NtUserSetWindowRgn(
3478    HWND hWnd,
3479    HRGN hRgn,
3480    BOOL bRedraw)
3481 {
3482    HRGN hrgnCopy = NULL;
3483    PWND Window;
3484    INT flags = (SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE);
3485    BOOLEAN Ret = FALSE;
3486    DECLARE_RETURN(INT);
3487 
3488    TRACE("Enter NtUserSetWindowRgn\n");
3489    UserEnterExclusive();
3490 
3491    if (!(Window = UserGetWindowObject(hWnd)) ||
3492         UserIsDesktopWindow(Window) || UserIsMessageWindow(Window))
3493    {
3494       RETURN( 0);
3495    }
3496 
3497    if (hRgn) // The region will be deleted in user32.
3498    {
3499       if (GreIsHandleValid(hRgn))
3500       {
3501          hrgnCopy = NtGdiCreateRectRgn(0, 0, 0, 0);
3502       /* The coordinates of a window's window region are relative to the
3503          upper-left corner of the window, not the client area of the window. */
3504          NtGdiCombineRgn( hrgnCopy, hRgn, 0, RGN_COPY);
3505       }
3506       else
3507          RETURN( 0);
3508    }
3509 
3510    //// HACK 1 : Work around the lack of supporting DeferWindowPos.
3511    if (hrgnCopy)
3512    {
3513        Window->hrgnNewFrame = hrgnCopy; // Should be PSMWP->acvr->hrgnClip
3514    }
3515    else
3516    {
3517        Window->hrgnNewFrame = HRGN_WINDOW;
3518    }
3519    //// HACK 2
3520    Ret = co_WinPosSetWindowPos(Window, HWND_TOP, 0, 0, 0, 0, bRedraw ? flags : (flags|SWP_NOREDRAW) );
3521 
3522    RETURN( (INT)Ret);
3523 
3524 CLEANUP:
3525    TRACE("Leave NtUserSetWindowRgn, ret=%i\n",_ret_);
3526    UserLeave();
3527    END_CLEANUP;
3528 }
3529 
3530 /*
3531  * @implemented
3532  */
3533 DWORD APIENTRY
3534 NtUserSetInternalWindowPos(
3535    HWND    hwnd,
3536    UINT    showCmd,
3537    LPRECT  lprect,
3538    LPPOINT lppt)
3539 {
3540    WINDOWPLACEMENT wndpl;
3541    UINT flags;
3542    PWND Wnd;
3543    RECT rect;
3544    POINT pt = {0};
3545    DECLARE_RETURN(BOOL);
3546    USER_REFERENCE_ENTRY Ref;
3547 
3548    TRACE("Enter NtUserSetWindowPlacement\n");
3549    UserEnterExclusive();
3550 
3551    if (!(Wnd = UserGetWindowObject(hwnd)) || // FIXME:
3552         UserIsDesktopWindow(Wnd) || UserIsMessageWindow(Wnd))
3553    {
3554       RETURN( FALSE);
3555    }
3556 
3557    _SEH2_TRY
3558    {
3559       if (lppt)
3560       {
3561          ProbeForRead(lppt, sizeof(POINT), 1);
3562          RtlCopyMemory(&pt, lppt, sizeof(POINT));
3563       }
3564       if (lprect)
3565       {
3566          ProbeForRead(lprect, sizeof(RECT), 1);
3567          RtlCopyMemory(&rect, lprect, sizeof(RECT));
3568       }
3569    }
3570    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
3571    {
3572       SetLastNtError(_SEH2_GetExceptionCode());
3573       _SEH2_YIELD(RETURN( FALSE));
3574    }
3575    _SEH2_END
3576 
3577    wndpl.length  = sizeof(wndpl);
3578    wndpl.showCmd = showCmd;
3579    wndpl.flags = flags = 0;
3580 
3581    if ( lppt )
3582    {
3583       flags |= PLACE_MIN;
3584       wndpl.flags |= WPF_SETMINPOSITION;
3585       wndpl.ptMinPosition = pt;
3586    }
3587    if ( lprect )
3588    {
3589       flags |= PLACE_RECT;
3590       wndpl.rcNormalPosition = rect;
3591    }
3592 
3593    UserRefObjectCo(Wnd, &Ref);
3594    IntSetWindowPlacement(Wnd, &wndpl, flags);
3595    UserDerefObjectCo(Wnd);
3596    RETURN(TRUE);
3597 
3598 CLEANUP:
3599    TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_);
3600    UserLeave();
3601    END_CLEANUP;
3602 }
3603 
3604 /*
3605  * @implemented
3606  */
3607 BOOL APIENTRY
3608 NtUserSetWindowPlacement(HWND hWnd,
3609                          WINDOWPLACEMENT *lpwndpl)
3610 {
3611    PWND Wnd;
3612    WINDOWPLACEMENT Safepl;
3613    UINT Flags;
3614    DECLARE_RETURN(BOOL);
3615    USER_REFERENCE_ENTRY Ref;
3616 
3617    TRACE("Enter NtUserSetWindowPlacement\n");
3618    UserEnterExclusive();
3619 
3620    if (!(Wnd = UserGetWindowObject(hWnd)) ||
3621         UserIsDesktopWindow(Wnd) || UserIsMessageWindow(Wnd))
3622    {
3623       RETURN( FALSE);
3624    }
3625 
3626    _SEH2_TRY
3627    {
3628       ProbeForRead(lpwndpl, sizeof(WINDOWPLACEMENT), 1);
3629       RtlCopyMemory(&Safepl, lpwndpl, sizeof(WINDOWPLACEMENT));
3630    }
3631    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
3632    {
3633       SetLastNtError(_SEH2_GetExceptionCode());
3634       _SEH2_YIELD(RETURN( FALSE));
3635    }
3636    _SEH2_END
3637 
3638    if(Safepl.length != sizeof(WINDOWPLACEMENT))
3639    {
3640       RETURN( FALSE);
3641    }
3642 
3643    Flags = PLACE_MAX | PLACE_RECT;
3644    if (Safepl.flags & WPF_SETMINPOSITION) Flags |= PLACE_MIN;
3645    UserRefObjectCo(Wnd, &Ref);
3646    IntSetWindowPlacement(Wnd, &Safepl, Flags);
3647    UserDerefObjectCo(Wnd);
3648    RETURN(TRUE);
3649 
3650 CLEANUP:
3651    TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_);
3652    UserLeave();
3653    END_CLEANUP;
3654 }
3655 
3656 /*
3657  * @implemented
3658  */
3659 BOOL APIENTRY
3660 NtUserShowWindowAsync(HWND hWnd, LONG nCmdShow)
3661 {
3662    PWND Window;
3663    BOOL ret;
3664    DECLARE_RETURN(BOOL);
3665    USER_REFERENCE_ENTRY Ref;
3666 
3667    TRACE("Enter NtUserShowWindowAsync\n");
3668    UserEnterExclusive();
3669 
3670    if (!(Window = UserGetWindowObject(hWnd)) ||
3671         UserIsDesktopWindow(Window) || UserIsMessageWindow(Window))
3672    {
3673       RETURN(FALSE);
3674    }
3675 
3676    if ( nCmdShow > SW_MAX )
3677    {
3678       EngSetLastError(ERROR_INVALID_PARAMETER);
3679       RETURN(FALSE);
3680    }
3681 
3682    UserRefObjectCo(Window, &Ref);
3683    ret = co_IntSendMessageNoWait( hWnd, WM_ASYNC_SHOWWINDOW, nCmdShow, 0 );
3684    UserDerefObjectCo(Window);
3685    if (-1 == (int) ret || !ret) ret = FALSE;
3686 
3687    RETURN(ret);
3688 
3689 CLEANUP:
3690    TRACE("Leave NtUserShowWindowAsync, ret=%i\n",_ret_);
3691    UserLeave();
3692    END_CLEANUP;
3693 }
3694 
3695 /*
3696  * @implemented
3697  */
3698 BOOL APIENTRY
3699 NtUserShowWindow(HWND hWnd, LONG nCmdShow)
3700 {
3701    PWND Window;
3702    BOOL ret;
3703    DECLARE_RETURN(BOOL);
3704    USER_REFERENCE_ENTRY Ref;
3705 
3706    TRACE("Enter NtUserShowWindow hWnd %p SW_ %d\n",hWnd, nCmdShow);
3707    UserEnterExclusive();
3708 
3709    if (!(Window = UserGetWindowObject(hWnd)) ||
3710         UserIsDesktopWindow(Window) || UserIsMessageWindow(Window))
3711    {
3712       RETURN(FALSE);
3713    }
3714 
3715    if ( nCmdShow > SW_MAX || Window->state2 & WNDS2_INDESTROY)
3716    {
3717       EngSetLastError(ERROR_INVALID_PARAMETER);
3718       RETURN(FALSE);
3719    }
3720 
3721    UserRefObjectCo(Window, &Ref);
3722    ret = co_WinPosShowWindow(Window, nCmdShow);
3723    UserDerefObjectCo(Window);
3724 
3725    RETURN(ret);
3726 
3727 CLEANUP:
3728    TRACE("Leave NtUserShowWindow, ret=%i\n",_ret_);
3729    UserLeave();
3730    END_CLEANUP;
3731 }
3732 
3733 
3734 /*
3735  *    @implemented
3736  */
3737 HWND APIENTRY
3738 NtUserWindowFromPoint(LONG X, LONG Y)
3739 {
3740    POINT pt;
3741    HWND Ret;
3742    PWND DesktopWindow = NULL, Window = NULL;
3743    USHORT hittest;
3744    DECLARE_RETURN(HWND);
3745    USER_REFERENCE_ENTRY Ref;
3746 
3747    TRACE("Enter NtUserWindowFromPoint\n");
3748    UserEnterExclusive();
3749 
3750    if ((DesktopWindow = UserGetWindowObject(IntGetDesktopWindow())))
3751    {
3752       //PTHREADINFO pti;
3753 
3754       pt.x = X;
3755       pt.y = Y;
3756 
3757       // Hmm... Threads live on desktops thus we have a reference on the desktop and indirectly the desktop window.
3758       // It is possible this referencing is useless, though it should not hurt...
3759       UserRefObjectCo(DesktopWindow, &Ref);
3760 
3761       //pti = PsGetCurrentThreadWin32Thread();
3762       Window = co_WinPosWindowFromPoint(DesktopWindow, &pt, &hittest, FALSE);
3763 
3764       if (Window)
3765       {
3766          Ret = UserHMGetHandle(Window);
3767 
3768          RETURN( Ret);
3769       }
3770    }
3771 
3772    RETURN( NULL);
3773 
3774 CLEANUP:
3775    if (DesktopWindow) UserDerefObjectCo(DesktopWindow);
3776 
3777    TRACE("Leave NtUserWindowFromPoint, ret=%p\n", _ret_);
3778    UserLeave();
3779    END_CLEANUP;
3780 }
3781 
3782 /* EOF */
3783