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