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