Fix bug #129. Unfortunetly this causes another bug to appear (that is not caused...
[reactos.git] / reactos / subsys / win32k / ntuser / winpos.c
index 01a7382..5cb1e75 100644 (file)
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: winpos.c,v 1.29 2003/08/29 09:29:11 gvg Exp $
+/* $Id: winpos.c,v 1.83 2004/01/21 18:39:24 navaraf Exp $
  *
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
@@ -29,6 +29,7 @@
 /* INCLUDES ******************************************************************/
 
 #include <ddk/ntddk.h>
+#include <internal/safe.h>
 #include <win32k/win32k.h>
 #include <include/object.h>
 #include <include/guicheck.h>
 #include <include/class.h>
 #include <include/error.h>
 #include <include/winsta.h>
-#include <windows.h>
+#include <include/desktop.h>
 #include <include/winpos.h>
 #include <include/rect.h>
 #include <include/callback.h>
 #include <include/painting.h>
 #include <include/dce.h>
 #include <include/vis.h>
+#include <include/focus.h>
 
 #define NDEBUG
 #include <debug.h>
 #define  SWP_AGG_STATUSFLAGS \
     (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
 
-ATOM AtomInternalPos = (ATOM) NULL;
-
 /* FUNCTIONS *****************************************************************/
 
 #define HAS_DLGFRAME(Style, ExStyle) \
-       (((ExStyle) & WS_EX_DLGMODALFRAME) || \
-        (((Style) & WS_DLGFRAME) && !((Style) & WS_BORDER)))
+            (((ExStyle) & WS_EX_DLGMODALFRAME) || \
+            (((Style) & WS_DLGFRAME) && (!((Style) & WS_THICKFRAME))))
 
 #define HAS_THICKFRAME(Style, ExStyle) \
-       (((Style) & WS_THICKFRAME) && \
-        !((Style) & (WS_DLGFRAME | WS_BORDER)) == WS_DLGFRAME)
+            (((Style) & WS_THICKFRAME) && \
+            (!(((Style) & (WS_DLGFRAME | WS_BORDER)) == WS_DLGFRAME)))
 
-VOID FASTCALL
-WinPosSetupInternalPos(VOID)
-{
-  AtomInternalPos = NtAddAtom(L"SysIP", (ATOM*)(PULONG)&AtomInternalPos);
-}
+#define HAS_THINFRAME(Style, ExStyle) \
+            (((Style) & WS_BORDER) || (!((Style) & (WS_CHILD | WS_POPUP))))
 
-BOOL STDCALL
-NtUserGetClientOrigin(HWND hWnd, LPPOINT Point)
+BOOL FASTCALL
+IntGetClientOrigin(HWND hWnd, LPPOINT Point)
 {
   PWINDOW_OBJECT WindowObject;
-
+  
   WindowObject = IntGetWindowObject(hWnd);
   if (WindowObject == NULL)
     {
       Point->x = Point->y = 0;
-      return(TRUE);
+      return FALSE;
     }
   Point->x = WindowObject->ClientRect.left;
   Point->y = WindowObject->ClientRect.top;
-  return(TRUE);
+  
+  IntReleaseWindowObject(WindowObject);
+  return TRUE;
 }
 
-BOOL FASTCALL
-WinPosActivateOtherWindow(PWINDOW_OBJECT Window)
+BOOL STDCALL
+NtUserGetClientOrigin(HWND hWnd, LPPOINT Point)
 {
-       return FALSE;
+  BOOL Ret;
+  POINT pt;
+  NTSTATUS Status;
+  
+  Ret = IntGetClientOrigin(hWnd, &pt);
+  
+  Status = MmCopyToCaller(Point, &pt, sizeof(POINT));
+  if(!NT_SUCCESS(Status))
+  {
+    SetLastNtError(Status);
+    return FALSE;
+  }
+  
+  return Ret;
 }
 
-POINT STATIC FASTCALL
-WinPosFindIconPos(HWND hWnd, POINT Pos)
+/*******************************************************************
+ *         WinPosActivateOtherWindow
+ *
+ *  Activates window other than pWnd.
+ */
+VOID FASTCALL
+WinPosActivateOtherWindow(PWINDOW_OBJECT Window)
 {
-  POINT point;
-  //FIXME
-  return point;
+  PWINDOW_OBJECT Child;
+  PWINDOW_OBJECT TabooWindow = Window;
+
+  for (;;)
+    {
+      if (NULL == Window || IntIsDesktopWindow(Window))
+        {
+          IntSetFocusMessageQueue(NULL);
+          return;
+        }
+      Window = Window->Parent;
+      ExAcquireFastMutex(&(Window->ChildrenListLock));
+      Child = Window->FirstChild;
+      while (NULL != Child)
+        {
+          if (Child != TabooWindow)
+            {
+              ExReleaseFastMutex(&(Window->ChildrenListLock));
+              if (IntSetForegroundWindow(Child))
+                {
+                  return;
+                }
+              ExAcquireFastMutex(&(Window->ChildrenListLock));
+            }
+          Child = Child->NextSibling;
+        }
+      ExReleaseFastMutex(&(Window->ChildrenListLock));
+    }
 }
 
-HWND STATIC FASTCALL
-WinPosNtGdiIconTitle(PWINDOW_OBJECT WindowObject)
+VOID STATIC FASTCALL
+WinPosFindIconPos(HWND hWnd, POINT *Pos)
 {
-  return(NULL);
+  /* FIXME */
 }
 
-BOOL STATIC FASTCALL
-WinPosShowIconTitle(PWINDOW_OBJECT WindowObject, BOOL Show)
+PINTERNALPOS FASTCALL
+WinPosInitInternalPos(PWINDOW_OBJECT WindowObject, POINT pt, PRECT RestoreRect)
 {
-  PINTERNALPOS InternalPos = (PINTERNALPOS)IntGetProp(WindowObject, AtomInternalPos);
-  PWINDOW_OBJECT IconWindow;
-  NTSTATUS Status;
-
-  if (InternalPos)
+  INT XInc, YInc;
+  
+  if (WindowObject->InternalPos == NULL)
     {
-      HWND hWnd = InternalPos->IconTitle;
-
-      if (hWnd == NULL)
-       {
-         hWnd = WinPosNtGdiIconTitle(WindowObject);
-       }
-      if (Show)
-       {
-         Status = 
-           ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->
-                                      HandleTable,
-                                      hWnd,
-                                      otWindow,
-                                      (PVOID*)&IconWindow);
-         if (NT_SUCCESS(Status))
-           {
-             if (!(IconWindow->Style & WS_VISIBLE))
-               {
-                 NtUserSendMessage(hWnd, WM_SHOWWINDOW, TRUE, 0);
-                 WinPosSetWindowPos(hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE |
-                                    SWP_NOMOVE | SWP_NOACTIVATE | 
-                                    SWP_NOZORDER | SWP_SHOWWINDOW);
-               }
-             ObmDereferenceObject(IconWindow);
-           }
-       }
+      RECT WorkArea;
+      PDESKTOP_OBJECT Desktop = PsGetWin32Thread()->Desktop; /* Or rather get it from the window? */
+      
+      if(IntIsDesktopWindow(WindowObject->Parent))
+        WorkArea = *IntGetDesktopWorkArea(Desktop);
+      else
+        WorkArea = WindowObject->Parent->ClientRect;
+      
+      WindowObject->InternalPos = ExAllocatePool(NonPagedPool, sizeof(INTERNALPOS));
+      if(!WindowObject->InternalPos)
+      {
+        DPRINT1("Failed to allocate INTERNALPOS structure for window 0x%x\n", WindowObject->Self);
+        return NULL;
+      }
+      WindowObject->InternalPos->NormalRect = WindowObject->WindowRect;
+      if (HAS_DLGFRAME(WindowObject->Style, WindowObject->ExStyle) && !(WindowObject->Style & WS_MINIMIZE))
+      {
+        XInc = NtUserGetSystemMetrics(SM_CXDLGFRAME);
+        YInc = NtUserGetSystemMetrics(SM_CYDLGFRAME);
+      }
       else
+      {
+        XInc = YInc = 0;
+        if (HAS_THICKFRAME(WindowObject->Style, WindowObject->ExStyle)&& !(WindowObject->Style & WS_MINIMIZE))
+        {
+          XInc += NtUserGetSystemMetrics(SM_CXFRAME);
+          YInc += NtUserGetSystemMetrics(SM_CYFRAME);
+        }
+        else if (HAS_THINFRAME(WindowObject->Style, WindowObject->ExStyle))
        {
-         WinPosShowWindow(hWnd, SW_HIDE);
+         XInc += NtUserGetSystemMetrics(SM_CXBORDER);
+         YInc += NtUserGetSystemMetrics(SM_CYBORDER);
        }
-    }
-  return(FALSE);
-}
-
-PINTERNALPOS STATIC STDCALL
-WinPosInitInternalPos(PWINDOW_OBJECT WindowObject, POINT pt, PRECT RestoreRect)
-{
-  PINTERNALPOS InternalPos = (PINTERNALPOS)IntGetProp(WindowObject, AtomInternalPos);
-  if (InternalPos == NULL)
-    {
-      InternalPos = 
-       ExAllocatePool(NonPagedPool, sizeof(INTERNALPOS));
-      IntSetProp(WindowObject, AtomInternalPos, InternalPos);
-      InternalPos->IconTitle = 0;
-      InternalPos->NormalRect = WindowObject->WindowRect;
-      InternalPos->IconPos.x = InternalPos->MaxPos.x = 0xFFFFFFFF;
-      InternalPos->IconPos.y = InternalPos->MaxPos.y = 0xFFFFFFFF;
+      }
+      WindowObject->InternalPos->MaxPos.x = WorkArea.left - XInc;
+      WindowObject->InternalPos->MaxPos.y = WorkArea.top - YInc;
+      WindowObject->InternalPos->IconPos.x = WorkArea.left;
+      WindowObject->InternalPos->IconPos.y = WorkArea.bottom - NtUserGetSystemMetrics(SM_CYMINIMIZED);
     }
   if (WindowObject->Style & WS_MINIMIZE)
     {
-      InternalPos->IconPos = pt;
+      WindowObject->InternalPos->IconPos = pt;
     }
   else if (WindowObject->Style & WS_MAXIMIZE)
     {
-      InternalPos->MaxPos = pt;
+      WindowObject->InternalPos->MaxPos = pt;
     }
   else if (RestoreRect != NULL)
     {
-      InternalPos->NormalRect = *RestoreRect;
+      WindowObject->InternalPos->NormalRect = *RestoreRect;
     }
-  return(InternalPos);
+  return(WindowObject->InternalPos);
 }
 
-UINT STDCALL
+UINT FASTCALL
 WinPosMinMaximize(PWINDOW_OBJECT WindowObject, UINT ShowFlag, RECT* NewPos)
 {
   POINT Size;
@@ -203,7 +234,7 @@ WinPosMinMaximize(PWINDOW_OBJECT WindowObject, UINT ShowFlag, RECT* NewPos)
     {
       if (WindowObject->Style & WS_MINIMIZE)
        {
-         if (!NtUserSendMessage(WindowObject->Self, WM_QUERYOPEN, 0, 0))
+         if (!IntSendMessage(WindowObject->Self, WM_QUERYOPEN, 0, 0))
            {
              return(SWP_NOSIZE | SWP_NOMOVE);
            }
@@ -220,14 +251,15 @@ WinPosMinMaximize(PWINDOW_OBJECT WindowObject, UINT ShowFlag, RECT* NewPos)
              }
            else
              {
-               WindowObject->Style &= ~WINDOWOBJECT_RESTOREMAX;
+               WindowObject->Flags &= ~WINDOWOBJECT_RESTOREMAX;
              }
+           IntRedrawWindow(WindowObject, NULL, 0, RDW_VALIDATE | RDW_NOERASE |
+              RDW_NOINTERNALPAINT);
            WindowObject->Style |= WS_MINIMIZE;
-           InternalPos->IconPos = WinPosFindIconPos(WindowObject,
-                                                    InternalPos->IconPos);
+           WinPosFindIconPos(WindowObject, &InternalPos->IconPos);
            NtGdiSetRect(NewPos, InternalPos->IconPos.x, InternalPos->IconPos.y,
-                       NtUserGetSystemMetrics(SM_CXICON),
-                       NtUserGetSystemMetrics(SM_CYICON));
+                       NtUserGetSystemMetrics(SM_CXMINIMIZED),
+                       NtUserGetSystemMetrics(SM_CYMINIMIZED));
            SwpFlags |= SWP_NOCOPYBITS;
            break;
          }
@@ -236,12 +268,13 @@ WinPosMinMaximize(PWINDOW_OBJECT WindowObject, UINT ShowFlag, RECT* NewPos)
          {
            WinPosGetMinMaxInfo(WindowObject, &Size, &InternalPos->MaxPos, 
                                NULL, NULL);
+           DPRINT1("Maximize: %d,%d %dx%d\n",
+              InternalPos->MaxPos.x, InternalPos->MaxPos.y, Size.x, Size.y);
            if (WindowObject->Style & WS_MINIMIZE)
              {
-               WinPosShowIconTitle(WindowObject, FALSE);
                WindowObject->Style &= ~WS_MINIMIZE;
              }
-           WindowObject->Style |= WS_MINIMIZE;
+           WindowObject->Style |= WS_MAXIMIZE;
            NtGdiSetRect(NewPos, InternalPos->MaxPos.x, InternalPos->MaxPos.y,
                        Size.x, Size.y);
            break;
@@ -252,7 +285,6 @@ WinPosMinMaximize(PWINDOW_OBJECT WindowObject, UINT ShowFlag, RECT* NewPos)
            if (WindowObject->Style & WS_MINIMIZE)
              {
                WindowObject->Style &= ~WS_MINIMIZE;
-               WinPosShowIconTitle(WindowObject, FALSE);
                if (WindowObject->Flags & WINDOWOBJECT_RESTOREMAX)
                  {
                    WinPosGetMinMaxInfo(WindowObject, &Size,
@@ -262,17 +294,21 @@ WinPosMinMaximize(PWINDOW_OBJECT WindowObject, UINT ShowFlag, RECT* NewPos)
                                InternalPos->MaxPos.y, Size.x, Size.y);
                    break;
                  }
+               else
+                 {
+                   *NewPos = InternalPos->NormalRect;
+                   NewPos->right -= NewPos->left;
+                   NewPos->bottom -= NewPos->top;
+                   break;
+                 }
              }
            else
              {
                if (!(WindowObject->Style & WS_MAXIMIZE))
                  {
-                   return(-1);
+                   return 0;
                  }
-               else
-                 {
-                   WindowObject->Style &= ~WS_MAXIMIZE;
-                 }           
+               WindowObject->Style &= ~WS_MAXIMIZE;
                *NewPos = InternalPos->NormalRect;
                NewPos->right -= NewPos->left;
                NewPos->bottom -= NewPos->top;
@@ -288,21 +324,22 @@ WinPosMinMaximize(PWINDOW_OBJECT WindowObject, UINT ShowFlag, RECT* NewPos)
   return(SwpFlags);
 }
 
-UINT STDCALL
-WinPosGetMinMaxInfo(PWINDOW_OBJECT Window, POINT* MaxSize, POINT* MaxPos,
-                   POINT* MinTrack, POINT* MaxTrack)
+VOID FASTCALL
+WinPosFillMinMaxInfoStruct(PWINDOW_OBJECT Window, MINMAXINFO *Info)
 {
-  MINMAXINFO MinMax;
   INT XInc, YInc;
-  INTERNALPOS* Pos;
-
+  RECT WorkArea;
+  PDESKTOP_OBJECT Desktop = PsGetWin32Thread()->Desktop; /* Or rather get it from the window? */
+  
+  WorkArea = *IntGetDesktopWorkArea(Desktop);
+  
   /* Get default values. */
-  MinMax.ptMaxSize.x = NtUserGetSystemMetrics(SM_CXSCREEN);
-  MinMax.ptMaxSize.y = NtUserGetSystemMetrics(SM_CYSCREEN);
-  MinMax.ptMinTrackSize.x = NtUserGetSystemMetrics(SM_CXMINTRACK);
-  MinMax.ptMinTrackSize.y = NtUserGetSystemMetrics(SM_CYMINTRACK);
-  MinMax.ptMaxTrackSize.x = NtUserGetSystemMetrics(SM_CXSCREEN);
-  MinMax.ptMaxTrackSize.y = NtUserGetSystemMetrics(SM_CYSCREEN);
+  Info->ptMaxSize.x = WorkArea.right - WorkArea.left;
+  Info->ptMaxSize.y = WorkArea.bottom - WorkArea.top;
+  Info->ptMinTrackSize.x = NtUserGetSystemMetrics(SM_CXMINTRACK);
+  Info->ptMinTrackSize.y = NtUserGetSystemMetrics(SM_CYMINTRACK);
+  Info->ptMaxTrackSize.x = Info->ptMaxSize.x;
+  Info->ptMaxTrackSize.y = Info->ptMaxSize.y;
 
   if (HAS_DLGFRAME(Window->Style, Window->ExStyle))
     {
@@ -317,27 +354,35 @@ WinPosGetMinMaxInfo(PWINDOW_OBJECT Window, POINT* MaxSize, POINT* MaxPos,
          XInc += NtUserGetSystemMetrics(SM_CXFRAME);
          YInc += NtUserGetSystemMetrics(SM_CYFRAME);
        }
-      if (Window->Style & WS_BORDER)
+      else if (HAS_THINFRAME(Window->Style, Window->ExStyle))
        {
          XInc += NtUserGetSystemMetrics(SM_CXBORDER);
          YInc += NtUserGetSystemMetrics(SM_CYBORDER);
        }
     }
-  MinMax.ptMaxSize.x += 2 * XInc;
-  MinMax.ptMaxSize.y += 2 * YInc;
+  Info->ptMaxSize.x += 2 * XInc;
+  Info->ptMaxSize.y += 2 * YInc;
 
-  Pos = (PINTERNALPOS)IntGetProp(Window, AtomInternalPos);
-  if (Pos != NULL)
+  if (Window->InternalPos != NULL)
     {
-      MinMax.ptMaxPosition = Pos->MaxPos;
+      Info->ptMaxPosition = Window->InternalPos->MaxPos;
     }
   else
     {
-      MinMax.ptMaxPosition.x -= XInc;
-      MinMax.ptMaxPosition.y -= YInc;
+      Info->ptMaxPosition.x -= WorkArea.left + XInc;
+      Info->ptMaxPosition.y -= WorkArea.top + YInc;
     }
+}
 
-  IntSendMessage(Window->Self, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax, TRUE);
+UINT FASTCALL
+WinPosGetMinMaxInfo(PWINDOW_OBJECT Window, POINT* MaxSize, POINT* MaxPos,
+                   POINT* MinTrack, POINT* MaxTrack)
+{
+  MINMAXINFO MinMax;
+  
+  WinPosFillMinMaxInfoStruct(Window, &MinMax);
+  
+  IntSendMessage(Window->Self, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax);
 
   MinMax.ptMaxTrackSize.x = max(MinMax.ptMaxTrackSize.x,
                                MinMax.ptMinTrackSize.x);
@@ -352,50 +397,91 @@ WinPosGetMinMaxInfo(PWINDOW_OBJECT Window, POINT* MaxSize, POINT* MaxPos,
   return 0; //FIXME: what does it return?
 }
 
-BOOL STATIC FASTCALL
-WinPosChangeActiveWindow(HWND hWnd, BOOL MouseMsg)
+LONG STATIC FASTCALL
+WinPosDoNCCALCSize(PWINDOW_OBJECT Window, PWINDOWPOS WinPos,
+                  RECT* WindowRect, RECT* ClientRect)
 {
-  PWINDOW_OBJECT WindowObject;
+  UINT wvrFlags = 0;
 
-  WindowObject = IntGetWindowObject(hWnd);
-  if (WindowObject == NULL)
+  /* Send WM_NCCALCSIZE message to get new client area */
+  if ((WinPos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE)
     {
-      return FALSE;
-    }
+      NCCALCSIZE_PARAMS params;
+      WINDOWPOS winposCopy;
 
-  NtUserSendMessage(hWnd,
-    WM_ACTIVATE,
-         MAKELONG(MouseMsg ? WA_CLICKACTIVE : WA_CLICKACTIVE,
-      (WindowObject->Style & WS_MINIMIZE) ? 1 : 0),
-      (LPARAM)IntGetDesktopWindow());  /* FIXME: Previous active window */
+      params.rgrc[0] = *WindowRect;
+      params.rgrc[1] = Window->WindowRect;
+      params.rgrc[2] = Window->ClientRect;
+      if (0 != (Window->Style & WS_CHILD))
+       {
+         NtGdiOffsetRect(&(params.rgrc[0]), - Window->Parent->ClientRect.left,
+                             - Window->Parent->ClientRect.top);
+         NtGdiOffsetRect(&(params.rgrc[1]), - Window->Parent->ClientRect.left,
+                             - Window->Parent->ClientRect.top);
+         NtGdiOffsetRect(&(params.rgrc[2]), - Window->Parent->ClientRect.left,
+                             - Window->Parent->ClientRect.top);
+       }
+      params.lppos = &winposCopy;
+      winposCopy = *WinPos;
 
-  IntReleaseWindowObject(WindowObject);
+      wvrFlags = IntSendMessage(Window->Self, WM_NCCALCSIZE, TRUE, (LPARAM) &params);
 
-  return TRUE;
-}
+      /* If the application send back garbage, ignore it */
+      if (params.rgrc[0].left <= params.rgrc[0].right &&
+          params.rgrc[0].top <= params.rgrc[0].bottom)
+       {
+          *ClientRect = params.rgrc[0];
+         if (Window->Style & WS_CHILD)
+           {
+             NtGdiOffsetRect(ClientRect, Window->Parent->ClientRect.left,
+                             Window->Parent->ClientRect.top);
+           }
+       }
 
-LONG STATIC STDCALL
-WinPosDoNCCALCSize(PWINDOW_OBJECT Window, PWINDOWPOS WinPos,
-                  RECT* WindowRect, RECT* ClientRect)
-{
-  return 0; /* FIXME:  Calculate non client size */
+       /* FIXME: WVR_ALIGNxxx */
+
+      if (ClientRect->left != Window->ClientRect.left ||
+          ClientRect->top != Window->ClientRect.top)
+       {
+          WinPos->flags &= ~SWP_NOCLIENTMOVE;
+       }
+
+      if ((ClientRect->right - ClientRect->left !=
+           Window->ClientRect.right - Window->ClientRect.left) ||
+          (ClientRect->bottom - ClientRect->top !=
+           Window->ClientRect.bottom - Window->ClientRect.top))
+       {
+          WinPos->flags &= ~SWP_NOCLIENTSIZE;
+       }
+    }
+  else
+    {
+      if (! (WinPos->flags & SWP_NOMOVE)
+          && (ClientRect->left != Window->ClientRect.left ||
+              ClientRect->top != Window->ClientRect.top))
+       {
+          WinPos->flags &= ~SWP_NOCLIENTMOVE;
+       }
+    }
+
+  return wvrFlags;
 }
 
-BOOL STDCALL
+BOOL FASTCALL
 WinPosDoWinPosChanging(PWINDOW_OBJECT WindowObject,
                       PWINDOWPOS WinPos,
                       PRECT WindowRect,
                       PRECT ClientRect)
 {
+  INT X, Y;
+
   if (!(WinPos->flags & SWP_NOSENDCHANGING))
     {
-      IntSendWINDOWPOSCHANGINGMessage(WindowObject->Self, WinPos);
+      IntSendMessage(WindowObject->Self, WM_WINDOWPOSCHANGING, 0, (LPARAM) WinPos);
     }
   
   *WindowRect = WindowObject->WindowRect;
-  *ClientRect = 
-    (WindowObject->Style & WS_MINIMIZE) ? WindowObject->WindowRect :
-    WindowObject->ClientRect;
+  *ClientRect = WindowObject->ClientRect;
 
   if (!(WinPos->flags & SWP_NOSIZE))
     {
@@ -405,289 +491,91 @@ WinPosDoWinPosChanging(PWINDOW_OBJECT WindowObject,
 
   if (!(WinPos->flags & SWP_NOMOVE))
     {
-      WindowRect->left = WinPos->x;
-      WindowRect->top = WinPos->y;
-      WindowRect->right += WinPos->x - WindowObject->WindowRect.left;
-      WindowRect->bottom += WinPos->y - WindowObject->WindowRect.top;
-      NtGdiOffsetRect(ClientRect,
-        WinPos->x - WindowObject->WindowRect.left,
-        WinPos->y - WindowObject->WindowRect.top);
-    }
-
-  WinPos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
-
-  if (!(WinPos->flags & SWP_NOSIZE) || !(WinPos->flags & SWP_NOMOVE))
-    {
-      WinPosGetNonClientSize(WindowObject->Self, WindowRect, ClientRect);
-    }
-
-  return(TRUE);
-}
-
-/***********************************************************************
- *           SWP_DoSimpleFrameChanged
- *
- * NOTE: old and new client rect origins are identical, only
- *      extents may have changed. Window extents are the same.
- */
-VOID STATIC 
-WinPosDoSimpleFrameChanged( PWINDOW_OBJECT wndPtr, RECT* pOldClientRect, WORD swpFlags, UINT uFlags )
-{
-    INT         i = 0;
-    RECT rect;
-    HRGN hrgn = 0;
-
-    if( !(swpFlags & SWP_NOCLIENTSIZE) )
-    {
-       /* Client rect changed its position/size, most likely a scrollar
-        * was added/removed.
-        *
-        * FIXME: WVR alignment flags 
-        */
-
-       if( wndPtr->ClientRect.right >  pOldClientRect->right ) /* right edge */
+      X = WinPos->x;
+      Y = WinPos->y;
+      if (0 != (WindowObject->Style & WS_CHILD))
        {
-           i++;
-           rect.top = 0; 
-           rect.bottom = wndPtr->ClientRect.bottom - wndPtr->ClientRect.top;
-           rect.right = wndPtr->ClientRect.right - wndPtr->ClientRect.left;
-           if(!(uFlags & SWP_EX_NOCOPY))
-               rect.left = pOldClientRect->right - wndPtr->ClientRect.left;
-           else
-           {
-               rect.left = 0;
-               goto redraw;
-           }
-       }
-
-       if( wndPtr->ClientRect.bottom > pOldClientRect->bottom ) /* bottom edge */
-       {
-           if( i )
-               hrgn = NtGdiCreateRectRgnIndirect( &rect );
-           rect.left = 0;
-           rect.right = wndPtr->ClientRect.right - wndPtr->ClientRect.left;
-           rect.bottom = wndPtr->ClientRect.bottom - wndPtr->ClientRect.top;
-           if(!(uFlags & SWP_EX_NOCOPY))
-               rect.top = pOldClientRect->bottom - wndPtr->ClientRect.top;
-           else
-               rect.top = 0;
-           if( i++ ) 
-             {
-               HRGN hRectRgn = NtGdiCreateRectRgnIndirect(&rect);
-               NtGdiCombineRgn(hrgn, hrgn, hRectRgn, RGN_OR);
-               NtGdiDeleteObject(hRectRgn);
-             }
-       }
-
-       if( i == 0 && (uFlags & SWP_EX_NOCOPY) ) /* force redraw anyway */
-       {
-           rect = wndPtr->WindowRect;
-           NtGdiOffsetRect( &rect, wndPtr->WindowRect.left - wndPtr->ClientRect.left,
-                           wndPtr->WindowRect.top - wndPtr->ClientRect.top );
-           i++;
+         X += WindowObject->Parent->ClientRect.left;
+         Y += WindowObject->Parent->ClientRect.top;
        }
+      WindowRect->left = X;
+      WindowRect->top = Y;
+      WindowRect->right += X - WindowObject->WindowRect.left;
+      WindowRect->bottom += Y - WindowObject->WindowRect.top;
+      NtGdiOffsetRect(ClientRect,
+        X - WindowObject->WindowRect.left,
+        Y - WindowObject->WindowRect.top);
     }
 
-    if( i )
-    {
-redraw:
-       PaintRedrawWindow( wndPtr, &rect, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
-                           RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME | RDW_EX_USEHRGN );
-    }
-    else
-    {
-        PaintUpdateNCRegion(wndPtr, 0, UNC_UPDATE | UNC_ENTIRE);
-    }
+  WinPos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
 
-    if( hrgn > (HRGN)1 )
-       NtGdiDeleteObject( hrgn );
+  return TRUE;
 }
 
-/***********************************************************************
- *          SWP_CopyValidBits
- *
- * Make window look nice without excessive repainting
- *
- * visible and update regions are in window coordinates
- * client and window rectangles are in parent client coordinates
- *
- * Returns: uFlags and a dirty region in *pVisRgn.
+/*
+ * Fix Z order taking into account owned popups -
+ * basically we need to maintain them above the window that owns them
  */
-static UINT WinPosCopyValidBits( PWINDOW_OBJECT Wnd, HRGN* pVisRgn,
-                               LPRECT lpOldWndRect,
-                               LPRECT lpOldClientRect, UINT uFlags )
+HWND FASTCALL
+WinPosDoOwnedPopups(HWND hWnd, HWND hWndInsertAfter)
 {
- RECT r;
- HRGN newVisRgn, dirtyRgn;
- INT  my = COMPLEXREGION;
-
- if( Wnd->UpdateRegion == (HRGN)1 )
-     uFlags |= SWP_EX_NOCOPY; /* whole window is invalid, nothing to copy */
-
- newVisRgn = DceGetVisRgn( Wnd->Self, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
- NtGdiOffsetRgn(newVisRgn, -Wnd->WindowRect.left, -Wnd->WindowRect.top);
- dirtyRgn = NtGdiCreateRectRgn( 0, 0, 0, 0 );
-
- if( !(uFlags & SWP_EX_NOCOPY) ) /* make sure dst region covers only valid bits */
-     my = NtGdiCombineRgn( dirtyRgn, newVisRgn, *pVisRgn, RGN_AND );
-
- if( (my == NULLREGION) || (uFlags & SWP_EX_NOCOPY) )
- {
-nocopy:
-
-     /* set dirtyRgn to the sum of old and new visible regions 
-      * in parent client coordinates */
-
-     NtGdiOffsetRgn( newVisRgn, Wnd->WindowRect.left, Wnd->WindowRect.top );
-     NtGdiOffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
-
-     NtGdiCombineRgn(*pVisRgn, *pVisRgn, newVisRgn, RGN_OR );
- }
- else                  /* copy valid bits to a new location */
- {
-     INT  dx, dy, ow, oh, nw, nh, ocw, ncw, och, nch;
-     HRGN hrgnValid = dirtyRgn; /* non-empty intersection of old and new visible rgns */
-
-     /* subtract already invalid region inside Wnd from the dst region */
-
-     if( Wnd->UpdateRegion )
-         if( NtGdiCombineRgn( hrgnValid, hrgnValid, Wnd->UpdateRegion, RGN_DIFF) == NULLREGION )
-            goto nocopy;
-
-     /* check if entire window can be copied */
-
-     ow = lpOldWndRect->right - lpOldWndRect->left;
-     oh = lpOldWndRect->bottom - lpOldWndRect->top;
-     nw = Wnd->WindowRect.right - Wnd->WindowRect.left;
-     nh = Wnd->WindowRect.bottom - Wnd->WindowRect.top;
-
-     ocw = lpOldClientRect->right - lpOldClientRect->left;
-     och = lpOldClientRect->bottom - lpOldClientRect->top;
-     ncw = Wnd->ClientRect.right  - Wnd->ClientRect.left;
-     nch = Wnd->ClientRect.bottom  - Wnd->ClientRect.top;
-
-     if(  (ocw != ncw) || (och != nch) ||
-         ( ow !=  nw) || ( oh !=  nh) ||
-         ((lpOldClientRect->top - lpOldWndRect->top)   != 
-          (Wnd->ClientRect.top - Wnd->WindowRect.top)) ||
-          ((lpOldClientRect->left - lpOldWndRect->left) !=
-           (Wnd->ClientRect.left - Wnd->WindowRect.left)) )
-     {
-         if(uFlags & SWP_EX_PAINTSELF)
-         {
-             /* movement relative to the window itself */
-             dx = (Wnd->ClientRect.left - Wnd->WindowRect.left) -
-                 (lpOldClientRect->left - lpOldWndRect->left) ;
-             dy = (Wnd->ClientRect.top - Wnd->WindowRect.top) -
-                 (lpOldClientRect->top - lpOldWndRect->top) ;
-         }
-         else
+   HWND *List = NULL;
+   HWND Owner = NtUserGetWindow(hWnd, GW_OWNER);
+   LONG Style = NtUserGetWindowLong(hWnd, GWL_STYLE, FALSE);
+   PWINDOW_OBJECT DesktopWindow;
+   int i;
+
+   if ((Style & WS_POPUP) && Owner)
+   {
+      /* Make sure this popup stays above the owner */
+      HWND hWndLocalPrev = HWND_TOP;
+
+      if (hWndInsertAfter != HWND_TOP)
+      {
+         DesktopWindow = IntGetWindowObject(IntGetDesktopWindow());
+         List = IntWinListChildren(DesktopWindow);
+         IntReleaseWindowObject(DesktopWindow);
+         if (List != NULL)
          {
-             /* movement relative to the parent's client area */
-             dx = Wnd->ClientRect.left - lpOldClientRect->left;
-             dy = Wnd->ClientRect.top - lpOldClientRect->top;
-         }
-
-       /* restrict valid bits to the common client rect */
-
-       r.left = Wnd->ClientRect.left - Wnd->WindowRect.left;
-        r.top = Wnd->ClientRect.top  - Wnd->WindowRect.top;
-       r.right = r.left + min( ocw, ncw );
-       r.bottom = r.top + min( och, nch );
-
-       REGION_CropRgn( hrgnValid, hrgnValid, &r, 
-                       (uFlags & SWP_EX_PAINTSELF) ? NULL : (POINT*)&(Wnd->WindowRect));
-       NtGdiGetRgnBox( hrgnValid, &r );
-       if( NtGdiIsEmptyRect( &r ) )
-           goto nocopy;
-       r = *lpOldClientRect;
-     }
-     else
-     {
-         if(uFlags & SWP_EX_PAINTSELF) {
-             /* 
-              * with SWP_EX_PAINTSELF, the window repaints itself. Since a window can't move 
-              * relative to itself, only the client area can change.
-              * if the client rect didn't change, there's nothing to do.
-              */
-             dx = 0;
-             dy = 0;
+            for (i = 0; List[i]; i++)
+            {
+               if (List[i] == Owner) break;
+               if (List[i] != hWnd) hWndLocalPrev = List[i];
+               if (hWndLocalPrev == hWndInsertAfter) break;
+            }
+            hWndInsertAfter = hWndLocalPrev;
          }
-         else
+      }
+   }
+   else if (Style & WS_CHILD)
+   {
+      return hWndInsertAfter;
+   }
+
+   if (!List)
+   {
+      DesktopWindow = IntGetWindowObject(IntGetDesktopWindow());
+      List = IntWinListChildren(DesktopWindow);
+      IntReleaseWindowObject(DesktopWindow);
+   }
+   if (List != NULL)
+   {
+      for (i = 0; List[i]; i++)
+      {
+         if (List[i] == hWnd)
+            break;
+         if ((NtUserGetWindowLong(List[i], GWL_STYLE, FALSE) & WS_POPUP) &&
+             NtUserGetWindow(List[i], GW_OWNER) == hWnd)
          {
-             dx = Wnd->WindowRect.left - lpOldWndRect->left;
-             dy = Wnd->WindowRect.top -  lpOldWndRect->top;
-             NtGdiOffsetRgn( hrgnValid, Wnd->WindowRect.left, Wnd->WindowRect.top );
+            WinPosSetWindowPos(List[i], hWndInsertAfter, 0, 0, 0, 0,
+               SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING);
+            hWndInsertAfter = List[i];
          }
-       r = *lpOldWndRect;
-     }
-
-     if( !(uFlags & SWP_EX_PAINTSELF) )
-     {
-        /* Move remaining regions to parent coordinates */
-       NtGdiOffsetRgn( newVisRgn, Wnd->WindowRect.left, Wnd->WindowRect.top );
-       NtGdiOffsetRgn( *pVisRgn,  lpOldWndRect->left, lpOldWndRect->top );
-     }
-     else
-       NtGdiOffsetRect( &r, -lpOldWndRect->left, -lpOldWndRect->top );
-
-     /* Compute combined dirty region (old + new - valid) */
-     NtGdiCombineRgn( *pVisRgn, *pVisRgn, newVisRgn, RGN_OR);
-     NtGdiCombineRgn( *pVisRgn, *pVisRgn, hrgnValid, RGN_DIFF);
-
-     /* Blt valid bits, r is the rect to copy  */
-
-     if( dx || dy )
-     {
-        RECT rClip;
-        HDC hDC;
-
-        /* get DC and clip rect with drawable rect to avoid superfluous expose events
-           from copying clipped areas */
-
-        if( uFlags & SWP_EX_PAINTSELF )
-        {
-            hDC = NtUserGetDCEx( Wnd->Self, hrgnValid, DCX_WINDOW | DCX_CACHE |
-                           DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
-            rClip.right = nw; rClip.bottom = nh;
-        }
-        else
-        {
-            hDC = NtUserGetDCEx( Wnd->Parent->Self, hrgnValid, DCX_CACHE |
-                           DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
-            rClip.right = Wnd->Parent->ClientRect.right - Wnd->Parent->ClientRect.left;
-            rClip.bottom = Wnd->Parent->ClientRect.bottom - Wnd->Parent->ClientRect.top;
-        }
-        rClip.left = rClip.top = 0;    
-
-         if( oh > nh ) r.bottom = r.top  + nh;
-         if( ow < nw ) r.right = r.left  + nw;
-
-         if( NtGdiIntersectRect( &r, &r, &rClip ) )
-         {
-               NtGdiBitBlt(hDC, dx + r.left, dy + r.top, r.right - r.left, r.bottom - r.top, hDC, r.left, r.top, SRCCOPY);
-
-                 /* When you copy the bits without repainting, parent doesn't
-                    get validated appropriately. Therefore, we have to validate
-                    the parent with the windows' updated region when the
-                    parent's update region is not empty. */
-
-                if (Wnd->Parent->UpdateRegion != 0 && !(Wnd->Parent->Style & WS_CLIPCHILDREN))
-                {
-                  NtGdiOffsetRect(&r, dx, dy);
-                  NtUserValidateRect(Wnd->Parent->Self, &r);
-                }
-        }
-         NtUserReleaseDC( (uFlags & SWP_EX_PAINTSELF) ? 
-                       Wnd->Self :  Wnd->Parent->Self, hDC); 
-     }
- }
-
- /* *pVisRgn now points to the invalidated region */
+      }
+      ExFreePool(List);
+   }
 
- NtGdiDeleteObject(newVisRgn);
- NtGdiDeleteObject(dirtyRgn);
- return uFlags;
+   return hWndInsertAfter;
 }
 
 /***********************************************************************
@@ -696,7 +584,7 @@ nocopy:
  * Update WindowRect and ClientRect of Window and all of its children
  * We keep both WindowRect and ClientRect in screen coordinates internally
  */
-static VOID
+VOID STATIC FASTCALL
 WinPosInternalMoveWindow(PWINDOW_OBJECT Window, INT MoveX, INT MoveY)
 {
   PWINDOW_OBJECT Child;
@@ -721,257 +609,445 @@ WinPosInternalMoveWindow(PWINDOW_OBJECT Window, INT MoveX, INT MoveY)
   ExReleaseFastMutexUnsafe(&Window->ChildrenListLock);
 }
 
+/*
+ * WinPosFixupSWPFlags
+ *
+ * Fix redundant flags and values in the WINDOWPOS structure.
+ */
 
-BOOLEAN STDCALL
-WinPosSetWindowPos(HWND Wnd, HWND WndInsertAfter, INT x, INT y, INT cx,
-                  INT cy, UINT flags)
+BOOL FASTCALL
+WinPosFixupFlags(WINDOWPOS *WinPos, PWINDOW_OBJECT Window)
 {
-  PWINDOW_OBJECT Window;
-  NTSTATUS Status;
-  WINDOWPOS WinPos;
-  RECT NewWindowRect;
-  RECT NewClientRect;
-  HRGN VisRgn = NULL;
-  HRGN VisibleRgn = NULL;
-  ULONG WvrFlags = 0;
-  RECT OldWindowRect, OldClientRect;
-  UINT FlagsEx = 0;
-
-  /* FIXME: Get current active window from active queue. */
-
-  /* Check if the window is for a desktop. */
-  if (Wnd == PsGetWin32Thread()->Desktop->DesktopWindow)
-    {
-      return(FALSE);
-    }
+   if (Window->Style & WS_VISIBLE)
+   {
+      WinPos->flags &= ~SWP_SHOWWINDOW;
+   }
+   else
+   {
+      WinPos->flags &= ~SWP_HIDEWINDOW;
+      if (!(WinPos->flags & SWP_SHOWWINDOW))
+         WinPos->flags |= SWP_NOREDRAW;
+   }
+
+   WinPos->cx = max(WinPos->cx, 0);
+   WinPos->cy = max(WinPos->cy, 0);
+
+   /* Check for right size */
+   if (Window->WindowRect.right - Window->WindowRect.left == WinPos->cx &&
+       Window->WindowRect.bottom - Window->WindowRect.top == WinPos->cy)
+   {
+      WinPos->flags |= SWP_NOSIZE;    
+   }
+
+   /* Check for right position */
+   if (Window->WindowRect.left == WinPos->x &&
+       Window->WindowRect.top == WinPos->y)
+   {
+      WinPos->flags |= SWP_NOMOVE;    
+   }
+
+   if (WinPos->hwnd == NtUserGetForegroundWindow())
+   {
+      WinPos->flags |= SWP_NOACTIVATE;   /* Already active */
+   }
+   else
+   if ((Window->Style & (WS_POPUP | WS_CHILD)) != WS_CHILD)
+   {
+      /* Bring to the top when activating */
+      if (!(WinPos->flags & SWP_NOACTIVATE)) 
+      {
+         WinPos->flags &= ~SWP_NOZORDER;
+         WinPos->hwndInsertAfter = HWND_TOP;
+         return TRUE;
+      }
+   }
 
-  Status = 
-    ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->HandleTable,
-                              Wnd,
-                              otWindow,
-                              (PVOID*)&Window);
-  if (!NT_SUCCESS(Status))
-    {
-      return(FALSE);
-    }
-  
-  /* Fix up the flags. */
-  if (Window->Style & WS_VISIBLE)
-    {
-      flags &= ~SWP_SHOWWINDOW;
-    }
-  else 
-    {
-      if (!(flags & SWP_SHOWWINDOW))
-       {
-         flags |= SWP_NOREDRAW;
-       }
-      flags &= ~SWP_HIDEWINDOW;
-    }
+   /* Check hwndInsertAfter */
+   if (!(WinPos->flags & SWP_NOZORDER))
+   {
+      /* Fix sign extension */
+      if (WinPos->hwndInsertAfter == (HWND)0xffff)
+      {
+         WinPos->hwndInsertAfter = HWND_TOPMOST;
+      }
+      else if (WinPos->hwndInsertAfter == (HWND)0xfffe)
+      {
+         WinPos->hwndInsertAfter = HWND_NOTOPMOST;
+      }
 
-  cx = max(cx, 0);
-  cy = max(cy, 0);
+      /* FIXME: TOPMOST not supported yet */
+      if ((WinPos->hwndInsertAfter == HWND_TOPMOST) ||
+          (WinPos->hwndInsertAfter == HWND_NOTOPMOST))
+      {
+         WinPos->hwndInsertAfter = HWND_TOP;
+      }
 
-  if ((Window->WindowRect.right - Window->WindowRect.left) == cx &&
-      (Window->WindowRect.bottom - Window->WindowRect.top) == cy)
-    {
-      flags |= SWP_NOSIZE;
-    }
-  if (Window->WindowRect.left == x && Window->WindowRect.top == y)
-    {
-      flags |= SWP_NOMOVE;
-    }
-  if (Window->Style & WIN_NCACTIVATED)
-    {
-      flags |= SWP_NOACTIVATE;
-    }
-  else if ((Window->Style & (WS_POPUP | WS_CHILD)) != WS_CHILD)
-    {
-      if (!(flags & SWP_NOACTIVATE))
-       {
-         flags &= ~SWP_NOZORDER;
-         WndInsertAfter = HWND_TOP;
-       }
-    }
+      /* hwndInsertAfter must be a sibling of the window */
+      if ((WinPos->hwndInsertAfter != HWND_TOP) &&
+          (WinPos->hwndInsertAfter != HWND_BOTTOM))
+      {
+         if (NtUserGetAncestor(WinPos->hwndInsertAfter, GA_PARENT) !=
+             Window->Parent->Self)
+         {
+            return FALSE;
+         }
+         else
+         {
+            /*
+             * We don't need to change the Z order of hwnd if it's already
+             * inserted after hwndInsertAfter or when inserting hwnd after
+             * itself.
+             */
+            if ((WinPos->hwnd == WinPos->hwndInsertAfter) ||
+                (WinPos->hwnd == NtUserGetWindow(WinPos->hwndInsertAfter, GW_HWNDNEXT)))
+            {
+               WinPos->flags |= SWP_NOZORDER;
+            }
+         }
+      }
+   }
 
-  if (WndInsertAfter == HWND_TOPMOST || WndInsertAfter == HWND_NOTOPMOST)
-    {
-      WndInsertAfter = HWND_TOP;
-    }
+   return TRUE;
+}
 
-  if (WndInsertAfter != HWND_TOP && WndInsertAfter != HWND_BOTTOM)
-    {
-      /* FIXME: Find the window to insert after. */
-    }
+/* x and y are always screen relative */
+BOOLEAN FASTCALL
+WinPosSetWindowPos(HWND Wnd, HWND WndInsertAfter, INT x, INT y, INT cx,
+                  INT cy, UINT flags)
+{
+   PWINDOW_OBJECT Window;
+   WINDOWPOS WinPos;
+   RECT NewWindowRect;
+   RECT NewClientRect;
+   HRGN VisBefore = NULL;
+   HRGN VisAfter = NULL;
+   HRGN DirtyRgn = NULL;
+   HRGN ExposedRgn = NULL;
+   HRGN CopyRgn = NULL;
+   ULONG WvrFlags = 0;
+   RECT OldWindowRect, OldClientRect;
+   int RgnType;
+   HDC Dc;
+   RECT CopyRect;
+   RECT TempRect;
+
+   /* FIXME: Get current active window from active queue. */
+
+   Window = IntGetWindowObject(Wnd);
+   if (!Window)
+   {
+      SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
+      return FALSE;
+   }
+
+   /*
+    * Only allow CSRSS to mess with the desktop window
+    */
+   if (Wnd == IntGetDesktopWindow() &&
+       Window->OwnerThread->ThreadsProcess != PsGetCurrentProcess())
+   {
+      return FALSE;
+   }
+
+   WinPos.hwnd = Wnd;
+   WinPos.hwndInsertAfter = WndInsertAfter;
+   WinPos.x = x;
+   WinPos.y = y;
+   WinPos.cx = cx;
+   WinPos.cy = cy;
+   WinPos.flags = flags;
+
+   WinPosDoWinPosChanging(Window, &WinPos, &NewWindowRect, &NewClientRect);
+
+   /* Fix up the flags. */
+   if (!WinPosFixupFlags(&WinPos, Window))
+   {
+      SetLastWin32Error(ERROR_INVALID_PARAMETER);
+      IntReleaseWindowObject(Window);
+      return FALSE;
+   }
 
-  WinPos.hwnd = Wnd;
-  WinPos.hwndInsertAfter = WndInsertAfter;
-  WinPos.x = x;
-  WinPos.y = y;
-  WinPos.cx = cx;
-  WinPos.cy = cy;
-  WinPos.flags = flags;
+   /* Does the window still exist? */
+   if (!IntIsWindow(WinPos.hwnd))
+   {
+      SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
+      return FALSE;
+   }
+
+   if ((WinPos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) !=
+       SWP_NOZORDER &&
+       NtUserGetAncestor(WinPos.hwnd, GA_PARENT) == IntGetDesktopWindow())
+   {
+      WinPos.hwndInsertAfter = WinPosDoOwnedPopups(WinPos.hwnd, WinPos.hwndInsertAfter);
+   }
+  
+   /* Compute the visible region before the window position is changed */
+   if (!(WinPos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
+       (WinPos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | 
+                        SWP_HIDEWINDOW | SWP_FRAMECHANGED)) != 
+       (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER))
+   {
+      VisBefore = VIS_ComputeVisibleRegion(Window, FALSE, FALSE, TRUE);
+
+      if (VisBefore != NULL &&
+          UnsafeIntGetRgnBox(VisBefore, &TempRect) == NULLREGION)
+      {
+         NtGdiDeleteObject(VisBefore);
+         VisBefore = NULL;
+      }
+   }
 
-  WinPosDoWinPosChanging(Window, &WinPos, &NewWindowRect, &NewClientRect);
+   WvrFlags = WinPosDoNCCALCSize(Window, &WinPos, &NewWindowRect, &NewClientRect);
 
-  if ((WinPos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) !=
-      SWP_NOZORDER)
-    {
-      /* FIXME: SWP_DoOwnedPopups. */
-    }
-  
-  /* FIXME: Adjust flags based on WndInsertAfter */
+   /* Relink windows. (also take into account shell window in hwndShellWindow) */
+   if (!(WinPos.flags & SWP_NOZORDER) && WinPos.hwnd != NtUserGetShellWindow())
+   {
+      PWINDOW_OBJECT ParentWindow;
+      PWINDOW_OBJECT InsertAfterWindow;
 
-  if ((!(WinPos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
-       WinPos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | 
-                      SWP_HIDEWINDOW | SWP_FRAMECHANGED)) != 
-      (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER))
-    {
-      if (Window->Style & WS_CLIPCHILDREN)
-       {
-         VisRgn = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop,
-                                           Window, FALSE, FALSE, TRUE);
-       }
-      else
-       {
-         VisRgn = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop,
-                                           Window, FALSE, FALSE, FALSE);
-       }
-      NtGdiOffsetRgn(VisRgn, -Window->WindowRect.left, -Window->WindowRect.top);
-    }
+      ParentWindow = Window->Parent;
+      if (ParentWindow)
+      {
+         if (WinPos.hwndInsertAfter == HWND_TOP)
+            InsertAfterWindow = NULL;
+         else if (WinPos.hwndInsertAfter == HWND_BOTTOM)
+            InsertAfterWindow = IntGetWindowObject(ParentWindow->LastChild->Self);
+         else
+            InsertAfterWindow = IntGetWindowObject(WinPos.hwndInsertAfter);
+         /* Do nothing if hwndInsertAfter is HWND_BOTTOM and Window is already
+            the last window */
+         if (InsertAfterWindow != Window)
+         {
+             ExAcquireFastMutexUnsafe(&ParentWindow->ChildrenListLock);
+             IntUnlinkWindow(Window);
+             IntLinkWindow(Window, ParentWindow, InsertAfterWindow);
+             ExReleaseFastMutexUnsafe(&ParentWindow->ChildrenListLock);
+         }
+         if (InsertAfterWindow != NULL)
+            IntReleaseWindowObject(InsertAfterWindow);
+      }
+   }
 
-  WvrFlags = WinPosDoNCCALCSize(Window, &WinPos, &NewWindowRect,
-                               &NewClientRect);
+   /* FIXME: Reset active DCEs */
 
-  /* FIXME: Relink windows. */
+   OldWindowRect = Window->WindowRect;
+   OldClientRect = Window->ClientRect;
 
-  /* FIXME: Reset active DCEs */
+   if (OldClientRect.bottom - OldClientRect.top ==
+       NewClientRect.bottom - NewClientRect.top)
+   {
+      WvrFlags &= ~WVR_VREDRAW;
+   }
 
-  OldWindowRect = Window->WindowRect;
-  OldClientRect = Window->ClientRect;
+   if (OldClientRect.right - OldClientRect.left ==
+       NewClientRect.right - NewClientRect.left)
+   {
+      WvrFlags &= ~WVR_HREDRAW;
+   }
 
-  /* FIXME: Check for redrawing the whole client rect. */
+   /* FIXME: Actually do something with WVR_VALIDRECTS */
 
-  if (! (WinPos.flags & SWP_NOMOVE))
-    {
+   if (! (WinPos.flags & SWP_NOMOVE)
+       && (NewWindowRect.left != OldWindowRect.left
+           || NewWindowRect.top != OldWindowRect.top))
+   {
       WinPosInternalMoveWindow(Window,
                                NewWindowRect.left - OldWindowRect.left,
                                NewWindowRect.top - OldWindowRect.top);
-    }
-  Window->WindowRect = NewWindowRect;
-  Window->ClientRect = NewClientRect;
+   }
 
-  if (WinPos.flags & SWP_SHOWWINDOW)
-    {
-      Window->Style |= WS_VISIBLE;
-      FlagsEx |= SWP_EX_PAINTSELF;
-      /* Redraw entire window. */
-      VisRgn = (HRGN) 1;
-    }
-  else if (!(WinPos.flags & SWP_NOREDRAW))
-    {
-      if (WinPos.flags & SWP_HIDEWINDOW)
-       {
-         if (VisRgn > (HRGN)1)
-           {
-             NtGdiOffsetRgn(VisRgn, OldWindowRect.left, OldWindowRect.top);         
-           }
-         else
-           {
-             VisRgn = 0;
-           }
-       }
-      else
-       {
-         if ((WinPos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE)
-           {
-             if ((WinPos.flags & SWP_AGG_NOGEOMETRYCHANGE) == SWP_AGG_NOGEOMETRYCHANGE)
-               {
-                 FlagsEx |= SWP_EX_PAINTSELF;
-               }
-             FlagsEx = WinPosCopyValidBits(Window, &VisRgn, &OldWindowRect, &OldClientRect, FlagsEx);
-           }
-         else
-           {
-             if (WinPos.flags & SWP_FRAMECHANGED)
-               {
-                 WinPosDoSimpleFrameChanged(Window, &OldClientRect, WinPos.flags, FlagsEx);
-               }
-             if (VisRgn != 0)
-               {
-                 NtGdiDeleteObject(VisRgn);
-                 VisRgn = 0;
-               }
-           }
-       }
-    }  
+   Window->WindowRect = NewWindowRect;
+   Window->ClientRect = NewClientRect;
 
-  if (WinPos.flags & SWP_HIDEWINDOW)
-    {
-      VisibleRgn = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop, Window,
-                                            FALSE, FALSE, FALSE);
+   if (!(WinPos.flags & SWP_SHOWWINDOW) && (WinPos.flags & SWP_HIDEWINDOW))
+   {
+      /* Clear the update region */
+      IntRedrawWindow(Window, NULL, 0, RDW_VALIDATE | RDW_NOFRAME |
+                      RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_ALLCHILDREN);
       Window->Style &= ~WS_VISIBLE;
-      VIS_WindowLayoutChanged(PsGetWin32Thread()->Desktop, Window, VisibleRgn);
-      NtGdiDeleteObject(VisibleRgn);
-    }
-
-  if (! (WinPos.flags & SWP_NOMOVE))
-    {
-      VisibleRgn = UnsafeIntCreateRectRgnIndirect(&Window->WindowRect);
-      NtGdiCombineRgn(VisibleRgn, VisRgn, VisibleRgn, RGN_DIFF);
-      VIS_WindowLayoutChanged(PsGetWin32Thread()->Desktop, Window, VisibleRgn);
-      NtGdiDeleteObject(VisibleRgn);
-    }
+   }
+   else if (WinPos.flags & SWP_SHOWWINDOW)
+   {
+      Window->Style |= WS_VISIBLE;
+   }
+
+   /* Determine the new visible region */
+   VisAfter = VIS_ComputeVisibleRegion(Window, FALSE, FALSE, TRUE);
+
+   if (VisAfter != NULL &&
+       UnsafeIntGetRgnBox(VisAfter, &TempRect) == NULLREGION)
+   {
+      NtGdiDeleteObject(VisAfter);
+      VisAfter = NULL;
+   }
+
+   /*
+    * Determine which pixels can be copied from the old window position
+    * to the new. Those pixels must be visible in both the old and new
+    * position. Also, check the class style to see if the windows of this
+    * class need to be completely repainted on (horizontal/vertical) size
+    * change.
+    */
+   if (VisBefore != NULL && VisAfter != NULL && !(WinPos.flags & SWP_NOCOPYBITS) &&
+       ((WinPos.flags & SWP_NOSIZE) || !(WvrFlags & WVR_REDRAW)))
+   {
+      CopyRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
+      RgnType = NtGdiCombineRgn(CopyRgn, VisAfter, VisBefore, RGN_AND);
+
+      /*
+       * If this is (also) a window resize, the whole nonclient area
+       * needs to be repainted. So we limit the copy to the client area,
+       * 'cause there is no use in copying it (would possibly cause
+       * "flashing" too). However, if the copy region is already empty,
+       * we don't have to crop (can't take anything away from an empty
+       * region...)
+       */
+      if (!(WinPos.flags & SWP_NOSIZE) && RgnType != ERROR &&
+          RgnType != NULLREGION)
+      {
+         RECT ORect = OldClientRect;
+         RECT NRect = NewClientRect;
+         NtGdiOffsetRect(&ORect, - OldWindowRect.left, - OldWindowRect.top);
+         NtGdiOffsetRect(&NRect, - NewWindowRect.left, - NewWindowRect.top);
+         NtGdiIntersectRect(&CopyRect, &ORect, &NRect);
+         REGION_CropRgn(CopyRgn, CopyRgn, &CopyRect, NULL);
+      }
 
-  /* FIXME: Hide or show the claret */
+      /* No use in copying bits which are in the update region. */
+      if (Window->UpdateRegion != NULL)
+      {
+         NtGdiCombineRgn(CopyRgn, CopyRgn, Window->UpdateRegion, RGN_DIFF);
+      }
+      if (Window->NCUpdateRegion != NULL)
+      {
+         NtGdiCombineRgn(CopyRgn, CopyRgn, Window->NCUpdateRegion, RGN_DIFF);
+      }
+                 
+      /*
+       * Now, get the bounding box of the copy region. If it's empty
+       * there's nothing to copy. Also, it's no use copying bits onto
+       * themselves.
+       */
+      if (UnsafeIntGetRgnBox(CopyRgn, &CopyRect) == NULLREGION)
+      {
+         /* Nothing to copy, clean up */
+         NtGdiDeleteObject(CopyRgn);
+         CopyRgn = NULL;
+      }
+      else if (OldWindowRect.left != NewWindowRect.left ||
+               OldWindowRect.top != NewWindowRect.top)
+      {
+         /*
+          * Small trick here: there is no function to bitblt a region. So
+          * we set the region as the clipping region, take the bounding box
+          * of the region and bitblt that. Since nothing outside the clipping
+          * region is copied, this has the effect of bitblt'ing the region.
+          *
+          * Since NtUserGetDCEx takes ownership of the clip region, we need
+          * to create a copy of CopyRgn and pass that. We need CopyRgn later 
+          */
+         HRGN ClipRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
+
+         NtGdiCombineRgn(ClipRgn, CopyRgn, NULL, RGN_COPY);
+         Dc = NtUserGetDCEx(Wnd, ClipRgn, DCX_WINDOW | DCX_CACHE |
+            DCX_INTERSECTRGN | DCX_CLIPSIBLINGS);
+         NtGdiBitBlt(Dc,
+            CopyRect.left, CopyRect.top, CopyRect.right - CopyRect.left,
+            CopyRect.bottom - CopyRect.top, Dc,
+            CopyRect.left + (OldWindowRect.left - NewWindowRect.left),
+            CopyRect.top + (OldWindowRect.top - NewWindowRect.top), SRCCOPY);
+         NtUserReleaseDC(Wnd, Dc);
+         IntValidateParent(Window, CopyRgn);
+      }
+   }
+   else
+   {
+      CopyRgn = NULL;
+   }
+
+   /* We need to redraw what wasn't visible before */
+   if (VisAfter != NULL)
+   {
+      DirtyRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
+      if (CopyRgn != NULL)
+      {
+         RgnType = NtGdiCombineRgn(DirtyRgn, VisAfter, CopyRgn, RGN_DIFF);
+      }
+      else
+      {
+         RgnType = NtGdiCombineRgn(DirtyRgn, VisAfter, 0, RGN_COPY);
+      }
+      if (RgnType != ERROR && RgnType != NULLREGION)
+      {
+         NtGdiOffsetRgn(DirtyRgn,
+            Window->WindowRect.left - Window->ClientRect.left,
+            Window->WindowRect.top - Window->ClientRect.top);
+         IntRedrawWindow(Window, NULL, DirtyRgn,
+            RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
+      }
+      NtGdiDeleteObject(DirtyRgn);
+   }
+
+   if (CopyRgn != NULL)
+   {
+      NtGdiDeleteObject(CopyRgn);
+   }
+
+   /* Expose what was covered before but not covered anymore */
+   if (VisBefore != NULL)
+   {
+      ExposedRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
+      NtGdiCombineRgn(ExposedRgn, VisBefore, NULL, RGN_COPY);
+      NtGdiOffsetRgn(ExposedRgn, OldWindowRect.left - NewWindowRect.left,
+                     OldWindowRect.top - NewWindowRect.top);
+      if (VisAfter != NULL)
+         RgnType = NtGdiCombineRgn(ExposedRgn, ExposedRgn, VisAfter, RGN_DIFF);
+      else
+         RgnType = SIMPLEREGION;
 
-  if (VisRgn)
-    {
-      if (!(WinPos.flags & SWP_NOREDRAW))
-       {
-         if (FlagsEx & SWP_EX_PAINTSELF) 
-           {
-             PaintRedrawWindow(Window, NULL,
-                               (VisRgn == (HRGN) 1) ? 0 : VisRgn,
-                               RDW_ERASE | RDW_FRAME | RDW_INVALIDATE |
-                               RDW_ALLCHILDREN | RDW_ERASENOW, 
-                               RDW_EX_XYWINDOW | RDW_EX_USEHRGN);
-           }
-#if 0
-         else
-           {
-             PaintRedrawWindow(Window->Parent, NULL,
-                               (VisRgn == (HRGN) 1) ? 0 : VisRgn,
-                               RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN |
-                               RDW_ERASENOW,
-                               RDW_EX_USEHRGN);
-           }
-#endif
-         /* FIXME: Redraw the window parent. */
-       }
-      if ((HRGN) 1 != VisRgn)
-       {
-         NtGdiDeleteObject(VisRgn);
-       }
-    }
+      if (RgnType != ERROR && RgnType != NULLREGION)
+      {
+         VIS_WindowLayoutChanged(Window, ExposedRgn);
+      }
+      NtGdiDeleteObject(ExposedRgn);
+      NtGdiDeleteObject(VisBefore);
+   }
+
+   if (VisAfter != NULL)
+   {
+      NtGdiDeleteObject(VisAfter);
+   }
+
+   if (!(WinPos.flags & SWP_NOREDRAW))
+   {
+      IntRedrawWindow(Window, NULL, 0, RDW_ALLCHILDREN | RDW_ERASENOW);
+   }
+
+   if (!(WinPos.flags & SWP_NOACTIVATE))
+   {
+      if ((Window->Style & (WS_CHILD | WS_POPUP)) == WS_CHILD)
+      {
+         IntSendMessage(WinPos.hwnd, WM_CHILDACTIVATE, 0, 0);
+      }
+      else
+      {
+         IntSetForegroundWindow(Window);
+      }
+   }
 
-  if (!(flags & SWP_NOACTIVATE))
-    {
-      WinPosChangeActiveWindow(WinPos.hwnd, FALSE);
-    }
+   if ((WinPos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE)
+      IntSendMessage(WinPos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM) &WinPos);
 
-  /* FIXME: Check some conditions before doing this. */
-  IntSendWINDOWPOSCHANGEDMessage(WinPos.hwnd, &WinPos);
+   IntReleaseWindowObject(Window);
 
-  ObmDereferenceObject(Window);
-  return(TRUE);
+   return TRUE;
 }
 
-LRESULT STDCALL
+LRESULT FASTCALL
 WinPosGetNonClientSize(HWND Wnd, RECT* WindowRect, RECT* ClientRect)
 {
   *ClientRect = *WindowRect;
-  return(IntSendNCCALCSIZEMessage(Wnd, FALSE, ClientRect, NULL));
+  return(IntSendMessage(Wnd, WM_NCCALCSIZE, FALSE, (LPARAM) ClientRect));
 }
 
 BOOLEAN FASTCALL
@@ -983,7 +1059,7 @@ WinPosShowWindow(HWND Wnd, INT Cmd)
   UINT Swp = 0;
   RECT NewPos;
   BOOLEAN ShowFlag;
-  HRGN VisibleRgn;
+//  HRGN VisibleRgn;
 
   Status = 
     ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->HandleTable,
@@ -1019,7 +1095,7 @@ WinPosShowWindow(HWND Wnd, INT Cmd)
       /* Fall through. */
     case SW_MINIMIZE:
       {
-       Swp |= SWP_FRAMECHANGED;
+       Swp |= SWP_FRAMECHANGED | SWP_NOACTIVATE;
        if (!(Window->Style & WS_MINIMIZE))
          {
            Swp |= WinPosMinMaximize(Window, SW_MINIMIZE, &NewPos);
@@ -1074,64 +1150,45 @@ WinPosShowWindow(HWND Wnd, INT Cmd)
   ShowFlag = (Cmd != SW_HIDE);
   if (ShowFlag != WasVisible)
     {
-      NtUserSendMessage(Wnd, WM_SHOWWINDOW, ShowFlag, 0);
+      IntSendMessage(Wnd, WM_SHOWWINDOW, ShowFlag, 0);
       /* 
        * FIXME: Need to check the window wasn't destroyed during the 
        * window procedure. 
        */
     }
 
-  if (Window->Style & WS_CHILD &&
-      !IntIsWindowVisible(Window->Parent->Self) &&
-      (Swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE))
+  /* We can't activate a child window */
+  if ((Window->Style & WS_CHILD) &&
+      !(Window->ExStyle & WS_EX_MDICHILD))
     {
-      if (Cmd == SW_HIDE)
-       {
-         VisibleRgn = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop, Window,
-                                               FALSE, FALSE, FALSE);
-         Window->Style &= ~WS_VISIBLE;
-         VIS_WindowLayoutChanged(PsGetWin32Thread()->Desktop, Window, VisibleRgn);
-         NtGdiDeleteObject(VisibleRgn);
-       }
-      else
-       {
-         Window->Style |= WS_VISIBLE;
-       }
+      Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
     }
-  else
+
+  WinPosSetWindowPos(Window->Self, HWND_TOP, NewPos.left, NewPos.top,
+    NewPos.right, NewPos.bottom, LOWORD(Swp));
+
+  if (Cmd == SW_HIDE)
     {
-      if (Window->Style & WS_CHILD &&
-         !(Window->ExStyle & WS_EX_MDICHILD))
-       {
-         Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
-       }
-      if (!(Swp & MINMAX_NOSWP))
-       {
-         WinPosSetWindowPos(Wnd, HWND_TOP, NewPos.left, NewPos.top,
-                            NewPos.right, NewPos.bottom, LOWORD(Swp));
-         if (Cmd == SW_HIDE)
-           {
-             /* Hide the window. */
-             if (Wnd == IntGetActiveWindow())
-               {
-                 WinPosActivateOtherWindow(Window);
-               }
-             /* Revert focus to parent. */
-             if (Wnd == IntGetFocusWindow() ||
-                 IntIsChildWindow(Wnd, IntGetFocusWindow()))
-               {
-                 IntSetFocusWindow(Window->Parent->Self);
-               }
-           }
-       }
-      /* FIXME: Check for window destruction. */
-      /* Show title for minimized windows. */
-      if (Window->Style & WS_MINIMIZE)
-       {
-         WinPosShowIconTitle(Window, TRUE);
-       }
+      /* FIXME: This will cause the window to be activated irrespective
+       * of whether it is owned by the same thread. Has to be done
+       * asynchronously.
+       */
+
+      if (Window->Self == NtUserGetActiveWindow())
+        {
+          WinPosActivateOtherWindow(Window);
+        }
+
+      /* Revert focus to parent */
+      if (Wnd == IntGetThreadFocusWindow() ||
+          IntIsChildWindow(Wnd, IntGetThreadFocusWindow()))
+        {
+          NtUserSetFocus(Window->Parent->Self);
+        }
     }
 
+  /* FIXME: Check for window destruction. */
+
   if (Window->Flags & WINDOWOBJECT_NEED_SIZE)
     {
       WPARAM wParam = SIZE_RESTORED;
@@ -1146,21 +1203,23 @@ WinPosShowWindow(HWND Wnd, INT Cmd)
          wParam = SIZE_MINIMIZED;
        }
 
-      NtUserSendMessage(Wnd, WM_SIZE, wParam,
-                       MAKELONG(Window->ClientRect.right - 
-                                Window->ClientRect.left,
-                                Window->ClientRect.bottom -
-                                Window->ClientRect.top));
-      NtUserSendMessage(Wnd, WM_MOVE, 0,
-                       MAKELONG(Window->ClientRect.left,
-                                Window->ClientRect.top));
+      IntSendMessage(Wnd, WM_SIZE, wParam,
+                     MAKELONG(Window->ClientRect.right - 
+                              Window->ClientRect.left,
+                              Window->ClientRect.bottom -
+                              Window->ClientRect.top));
+      IntSendMessage(Wnd, WM_MOVE, 0,
+                     MAKELONG(Window->ClientRect.left,
+                              Window->ClientRect.top));
     }
 
   /* Activate the window if activation is not requested and the window is not minimized */
+/*
   if (!(Swp & (SWP_NOACTIVATE | SWP_HIDEWINDOW)) && !(Window->Style & WS_MINIMIZE))
     {
       WinPosChangeActiveWindow(Wnd, FALSE);
     }
+*/
 
   ObmDereferenceObject(Window);
   return(WasVisible);
@@ -1175,7 +1234,7 @@ WinPosPtInWindow(PWINDOW_OBJECT Window, POINT Point)
         Point.y < Window->WindowRect.bottom);
 }
 
-USHORT STATIC STDCALL
+USHORT STATIC FASTCALL
 WinPosSearchChildren(PWINDOW_OBJECT ScopeWin, POINT Point,
                     PWINDOW_OBJECT* Window)
 {
@@ -1190,17 +1249,17 @@ WinPosSearchChildren(PWINDOW_OBJECT ScopeWin, POINT Point,
           (Current->Style & (WS_CHILD | WS_POPUP)) != WS_CHILD) &&
          WinPosPtInWindow(Current, Point))
        {
+         if(*Window)
+           ObmDereferenceObject(*Window);
+         ObmReferenceObjectByPointer(Current, otWindow);
+         
          *Window = Current;
+         
          if (Current->Style & WS_DISABLED)
            {
                  ExReleaseFastMutexUnsafe(&ScopeWin->ChildrenListLock);
              return(HTERROR);
            }
-         if (Current->Style & WS_MINIMIZE)
-           {
-                 ExReleaseFastMutexUnsafe(&ScopeWin->ChildrenListLock);
-             return(HTCAPTION);
-           }
          if (Point.x >= Current->ClientRect.left &&
              Point.x < Current->ClientRect.right &&
              Point.y >= Current->ClientRect.top &&
@@ -1221,7 +1280,7 @@ WinPosSearchChildren(PWINDOW_OBJECT ScopeWin, POINT Point,
   return(0);
 }
 
-USHORT STDCALL
+USHORT FASTCALL
 WinPosWindowFromPoint(PWINDOW_OBJECT ScopeWin, POINT WinPoint, 
                      PWINDOW_OBJECT* Window)
 {
@@ -1231,6 +1290,12 @@ WinPosWindowFromPoint(PWINDOW_OBJECT ScopeWin, POINT WinPoint,
   USHORT HitTest;
 
   *Window = NULL;
+  
+  if(!ScopeWin)
+  {
+    DPRINT1("WinPosWindowFromPoint(): ScopeWin == NULL!\n");
+    return(HTERROR);
+  }
 
   if (ScopeWin->Style & WS_DISABLED)
     {
@@ -1257,7 +1322,7 @@ WinPosWindowFromPoint(PWINDOW_OBJECT ScopeWin, POINT WinPoint,
   if ((*Window)->MessageQueue == PsGetWin32Thread()->MessageQueue)
     {
       HitTest = IntSendMessage((*Window)->Self, WM_NCHITTEST, 0,
-                               MAKELONG(Point.x, Point.y), FALSE);
+                               MAKELONG(Point.x, Point.y));
       /* FIXME: Check for HTTRANSPARENT here. */
     }
   else
@@ -1269,110 +1334,53 @@ WinPosWindowFromPoint(PWINDOW_OBJECT ScopeWin, POINT WinPoint,
 }
 
 BOOL
-WinPosSetActiveWindow(PWINDOW_OBJECT Window, BOOL Mouse, BOOL ChangeFocus)
+STDCALL
+NtUserGetMinMaxInfo(
+  HWND hwnd,
+  MINMAXINFO *MinMaxInfo,
+  BOOL SendMessage)
 {
-  PUSER_MESSAGE_QUEUE ActiveQueue;
-  HWND PrevActive;
-
-  ActiveQueue = IntGetFocusMessageQueue();
-  if (ActiveQueue != NULL)
-    {
-      PrevActive = ActiveQueue->ActiveWindow;
-    }
-  else
-    {
-      PrevActive = NULL;
-    }
-
-  if (Window->Self == IntGetActiveDesktop() || Window->Self == PrevActive)
-    {
-      return(FALSE);
-    }
-  if (PrevActive != NULL)
-    {
-      PWINDOW_OBJECT PrevActiveWindow = IntGetWindowObject(PrevActive);
-      WORD Iconised = HIWORD(PrevActiveWindow->Style & WS_MINIMIZE);
-      if (!IntSendMessage(PrevActive, WM_NCACTIVATE, FALSE, 0, TRUE))
-       {
-         /* FIXME: Check if the new window is system modal. */
-         return(FALSE);
-       }
-      IntSendMessage(PrevActive, 
-                     WM_ACTIVATE, 
-                     MAKEWPARAM(WA_INACTIVE, Iconised), 
-                     (LPARAM)Window->Self,
-                     TRUE);
-      /* FIXME: Check if anything changed while processing the message. */
-      IntReleaseWindowObject(PrevActiveWindow);
-    }
-
-  if (Window != NULL)
-    {
-      Window->MessageQueue->ActiveWindow = Window->Self;
-    }
-  else if (ActiveQueue != NULL)
-    {
-      ActiveQueue->ActiveWindow = NULL;
-    }
-  /* FIXME:  Unset this flag for inactive windows */
-  //if ((Window->Style) & WS_CHILD) Window->Flags |= WIN_NCACTIVATED;
-
-  /* FIXME: Send palette messages. */
-
-  /* FIXME: Redraw icon title of previously active window. */
-
-  /* FIXME: Bring the window to the top. */  
-
-  /* FIXME: Send WM_ACTIVATEAPP */
+  POINT Size;
+  PINTERNALPOS InternalPos;
+  PWINDOW_OBJECT Window;
+  MINMAXINFO SafeMinMax;
+  NTSTATUS Status;
   
-  IntSetFocusMessageQueue(Window->MessageQueue);
-
-  /* FIXME: Send activate messages. */
-
-  /* FIXME: Change focus. */
-
-  /* FIXME: Redraw new window icon title. */
-
-  return(TRUE);
-}
-
-HWND STDCALL
-NtUserGetActiveWindow(VOID)
-{
-  PUSER_MESSAGE_QUEUE ActiveQueue;
-
-  ActiveQueue = IntGetFocusMessageQueue();
-  if (ActiveQueue == NULL)
+  Window = IntGetWindowObject(hwnd);
+  if(!Window)
+  {
+    SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
+    return FALSE;
+  }
+
+  Size.x = Window->WindowRect.left;
+  Size.y = Window->WindowRect.top;
+  InternalPos = WinPosInitInternalPos(Window, Size, 
+                                     &Window->WindowRect); 
+  if(InternalPos)
+  {
+    if(SendMessage)
     {
-      return(NULL);
+      WinPosGetMinMaxInfo(Window, &SafeMinMax.ptMaxSize, &SafeMinMax.ptMaxPosition, 
+                          &SafeMinMax.ptMinTrackSize, &SafeMinMax.ptMaxTrackSize);
     }
-  return(ActiveQueue->ActiveWindow);
-}
-
-HWND STDCALL
-NtUserSetActiveWindow(HWND hWnd)
-{
-  PWINDOW_OBJECT Window;
-  PUSER_MESSAGE_QUEUE ThreadQueue;
-  HWND Prev;
-
-  Window = IntGetWindowObject(hWnd);
-  if (Window == NULL || (Window->Style & (WS_DISABLED | WS_CHILD)))
+    else
     {
-      IntReleaseWindowObject(Window);
-      return(0);
+      WinPosFillMinMaxInfoStruct(Window, &SafeMinMax);
     }
-  ThreadQueue = (PUSER_MESSAGE_QUEUE)PsGetWin32Thread()->MessageQueue;
-  if (Window->MessageQueue != ThreadQueue)
+    Status = MmCopyToCaller(MinMaxInfo, &SafeMinMax, sizeof(MINMAXINFO));
+    if(!NT_SUCCESS(Status))
     {
       IntReleaseWindowObject(Window);
-      return(0);
+      SetLastNtError(Status);
+      return FALSE;
     }
-  Prev = Window->MessageQueue->ActiveWindow;
-  WinPosSetActiveWindow(Window, FALSE, FALSE);
+    IntReleaseWindowObject(Window);
+    return TRUE;
+  }
+  
   IntReleaseWindowObject(Window);
-  return(Prev);
+  return FALSE;
 }
 
-
 /* EOF */