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