[Win32SS]
[reactos.git] / reactos / win32ss / user / ntuser / painting.c
index 9fcc32e..43e8d88 100644 (file)
@@ -2,7 +2,7 @@
  *  COPYRIGHT:        See COPYING in the top level directory
  *  PROJECT:          ReactOS Win32k subsystem
  *  PURPOSE:          Window painting function
- *  FILE:             subsystems/win32/win32k/ntuser/painting.c
+ *  FILE:             win32ss/user/ntuser/painting.c
  *  PROGRAMER:        Filip Navara (xnavara@volny.cz)
  */
 
@@ -33,21 +33,21 @@ IntIntersectWithParents(PWND Child, RECTL *WindowRect)
 {
    PWND ParentWnd;
 
+   if (Child->ExStyle & WS_EX_REDIRECTED)
+      return TRUE;
+
    ParentWnd = Child->spwndParent;
    while (ParentWnd != NULL)
    {
-      if (!(ParentWnd->style & WS_VISIBLE) ||
-          (ParentWnd->style & WS_MINIMIZE))
-      {
-         return FALSE;
-      }
-
-      if (!RECTL_bIntersectRect(WindowRect, WindowRect, &ParentWnd->rcClient))
+      if (!(ParentWnd->style & WS_VISIBLE)  ||
+           (ParentWnd->style & WS_MINIMIZE) ||
+          !RECTL_bIntersectRect(WindowRect, WindowRect, &ParentWnd->rcClient) )
       {
          return FALSE;
       }
 
-      /* FIXME: Layered windows. */
+      if (ParentWnd->ExStyle & WS_EX_REDIRECTED)
+         return TRUE;
 
       ParentWnd = ParentWnd->spwndParent;
    }
@@ -56,9 +56,12 @@ IntIntersectWithParents(PWND Child, RECTL *WindowRect)
 }
 
 BOOL FASTCALL
-IntValidateParent(PWND Child, PREGION ValidateRgn, BOOL Recurse)
+IntValidateParents(PWND Child, BOOL Recurse)
 {
+   RECTL ParentRect, Rect;
+   BOOL Start, Ret = TRUE;
    PWND ParentWnd = Child;
+   PREGION Rgn = NULL;
 
    if (ParentWnd->style & WS_CHILD)
    {
@@ -66,9 +69,11 @@ IntValidateParent(PWND Child, PREGION ValidateRgn, BOOL Recurse)
          ParentWnd = ParentWnd->spwndParent;
       while (ParentWnd->style & WS_CHILD);
    }
-// Hax out for drawing issues.
-//   if (!(ParentWnd->state & WNDS_SYNCPAINTPENDING)) Recurse = FALSE;
 
+   // No pending nonclient paints.
+   if (!(ParentWnd->state & WNDS_SYNCPAINTPENDING)) Recurse = FALSE;
+
+   Start = TRUE;
    ParentWnd = Child->spwndParent;
    while (ParentWnd)
    {
@@ -78,17 +83,43 @@ IntValidateParent(PWND Child, PREGION ValidateRgn, BOOL Recurse)
       if (ParentWnd->hrgnUpdate != 0)
       {
          if (Recurse)
-            return FALSE;
+         {
+            Ret = FALSE;
+            break;
+         }
+         // Start with child clipping.
+         if (Start)
+         {
+            Start = FALSE;
+
+            Rect = Child->rcWindow;
+
+            if (!IntIntersectWithParents(Child, &Rect)) break;
+
+            Rgn = IntSysCreateRectpRgnIndirect(&Rect);
+
+            if (Child->hrgnClip)
+            {
+               PREGION RgnClip = REGION_LockRgn(Child->hrgnClip);
+               IntGdiCombineRgn(Rgn, Rgn, RgnClip, RGN_AND);
+               REGION_UnlockRgn(RgnClip);
+            }
+         }
+
+         ParentRect = ParentWnd->rcWindow;
+
+         if (!IntIntersectWithParents(ParentWnd, &ParentRect)) break;
 
          IntInvalidateWindows( ParentWnd,
-                               ValidateRgn,
-                               RDW_VALIDATE | RDW_NOCHILDREN);
+                               Rgn,
+                               RDW_VALIDATE | RDW_NOCHILDREN | RDW_NOUPDATEDIRTY);
       }
-
       ParentWnd = ParentWnd->spwndParent;
    }
 
-   return TRUE;
+   if (Rgn) REGION_Delete(Rgn);
+
+   return Ret;
 }
 
 /*
@@ -113,7 +144,7 @@ IntSendSyncPaint(PWND Wnd, ULONG Flags)
         Wnd->style & WS_VISIBLE)
    {
       // For testing, if you see this, break out the Champagne and have a party!
-      ERR("SendSyncPaint Wnd in State!\n");
+      TRACE("SendSyncPaint Wnd in State!\n");
       if (!IsListEmpty(&ptiWnd->SentMessagesListHead))
       {
          // Scan sent queue messages to see if we received sync paint messages.
@@ -136,7 +167,7 @@ IntSendSyncPaint(PWND Wnd, ULONG Flags)
       }
       if (bSend)
       {
-         ERR("Sending WM_SYNCPAINT\n");
+         TRACE("Sending WM_SYNCPAINT\n");
          // This message has no parameters. But it does! Pass Flags along.
          co_IntSendMessageNoWait(UserHMGetHandle(Wnd), WM_SYNCPAINT, Flags, 0);
          Wnd->state |= WNDS_SYNCPAINTPENDING;
@@ -165,7 +196,7 @@ IntSendSyncPaint(PWND Wnd, ULONG Flags)
    }
 }
 
-/**
+/*
  * @name IntCalcWindowRgn
  *
  * Get a window or client region.
@@ -207,7 +238,7 @@ IntCalcWindowRgn(PWND Wnd, BOOL Client)
    return hRgnWindow;
 }
 
-/**
+/*
  * @name IntGetNCUpdateRgn
  *
  * Get non-client update region of a window and optionally validate it.
@@ -227,7 +258,8 @@ IntGetNCUpdateRgn(PWND Window, BOOL Validate)
 {
    HRGN hRgnNonClient;
    HRGN hRgnWindow;
-   UINT RgnType;
+   UINT RgnType, NcType;
+   RECT update;
 
    if (Window->hrgnUpdate != NULL &&
        Window->hrgnUpdate != HRGN_WINDOW)
@@ -250,8 +282,10 @@ IntGetNCUpdateRgn(PWND Window, BOOL Validate)
          return HRGN_WINDOW;
       }
 
-      RgnType = NtGdiCombineRgn(hRgnNonClient, hRgnNonClient,
-                                hRgnWindow, RGN_DIFF);
+      NcType = IntGdiGetRgnBox(hRgnNonClient, &update);
+
+      RgnType = NtGdiCombineRgn(hRgnNonClient, hRgnNonClient, hRgnWindow, RGN_DIFF);
+
       if (RgnType == ERROR)
       {
          GreDeleteObject(hRgnWindow);
@@ -273,8 +307,7 @@ IntGetNCUpdateRgn(PWND Window, BOOL Validate)
 
       if (Validate)
       {
-         if (NtGdiCombineRgn(Window->hrgnUpdate, Window->hrgnUpdate,
-                             hRgnWindow, RGN_AND) == NULLREGION)
+         if (NtGdiCombineRgn(Window->hrgnUpdate, Window->hrgnUpdate, hRgnWindow, RGN_AND) == NULLREGION)
          {
             IntGdiSetRegionOwner(Window->hrgnUpdate, GDI_OBJ_HMGR_POWNED);
             GreDeleteObject(Window->hrgnUpdate);
@@ -285,6 +318,19 @@ IntGetNCUpdateRgn(PWND Window, BOOL Validate)
          }
       }
 
+      /* check if update rgn contains complete nonclient area */
+      if (NcType == SIMPLEREGION)
+      {
+         RECT window;
+         IntGetWindowRect( Window, &window );
+
+         if (IntEqualRect( &window, &update ))
+         {
+            GreDeleteObject(hRgnNonClient);
+            hRgnNonClient = HRGN_WINDOW;
+         }
+      }
+
       GreDeleteObject(hRgnWindow);
 
       return hRgnNonClient;
@@ -295,6 +341,45 @@ IntGetNCUpdateRgn(PWND Window, BOOL Validate)
    }
 }
 
+VOID FASTCALL
+IntSendNCPaint(PWND pWnd, HRGN hRgn)
+{
+   pWnd->state &= ~WNDS_SENDNCPAINT;
+
+   if ( pWnd == GetW32ThreadInfo()->MessageQueue->spwndActive &&
+       !(pWnd->state & WNDS_ACTIVEFRAME))
+   {
+      pWnd->state |= WNDS_ACTIVEFRAME;
+      pWnd->state &= ~WNDS_NONCPAINT;
+      hRgn = HRGN_WINDOW;
+   }
+
+   if (pWnd->state2 & WNDS2_FORCEFULLNCPAINTCLIPRGN)
+   {
+      pWnd->state2 &= ~WNDS2_FORCEFULLNCPAINTCLIPRGN;
+      hRgn = HRGN_WINDOW;
+   }
+
+   if (hRgn) co_IntSendMessage(UserHMGetHandle(pWnd), WM_NCPAINT, (WPARAM)hRgn, 0);
+}
+
+VOID FASTCALL
+IntSendChildNCPaint(PWND pWnd)
+{
+   pWnd = pWnd->spwndChild;
+   while(pWnd)
+   {
+      if (pWnd->hrgnUpdate == NULL && pWnd->state & WNDS_SENDNCPAINT)
+      {
+         USER_REFERENCE_ENTRY Ref;
+         UserRefObjectCo(pWnd, &Ref);
+         IntSendNCPaint(pWnd, HRGN_WINDOW);
+         UserDerefObjectCo(pWnd);
+      }
+      pWnd = pWnd->spwndNext;
+   }
+}
+
 /*
  * IntPaintWindows
  *
@@ -306,73 +391,67 @@ co_IntPaintWindows(PWND Wnd, ULONG Flags, BOOL Recurse)
 {
    HDC hDC;
    HWND hWnd = Wnd->head.h;
-   HRGN TempRegion;
+   HRGN TempRegion = NULL;
 
    Wnd->state &= ~WNDS_PAINTNOTPROCESSED;
 
-   if (Flags & (RDW_ERASENOW | RDW_UPDATENOW))
+   if (Wnd->state & WNDS_SENDNCPAINT ||
+       Wnd->state & WNDS_SENDERASEBACKGROUND)
    {
-      if (Wnd->hrgnUpdate)
+      if (!(Wnd->style & WS_VISIBLE))
       {
-          PREGION RgnUpdate = RGNOBJAPI_Lock(Wnd->hrgnUpdate, NULL);
-          if (RgnUpdate)
-          {
-              if (!IntValidateParent(Wnd, RgnUpdate, Recurse))
-              {
-                  RGNOBJAPI_Unlock(RgnUpdate);
-                  return;
-              }
-              RGNOBJAPI_Unlock(RgnUpdate);
-          }
+         Wnd->state &= ~(WNDS_SENDNCPAINT|WNDS_SENDERASEBACKGROUND|WNDS_ERASEBACKGROUND);
+         return;
       }
-
-      if (Flags & RDW_UPDATENOW)
+      else
       {
-         if ((Wnd->hrgnUpdate != NULL ||
-              Wnd->state & WNDS_INTERNALPAINT))
+         if (Wnd->hrgnUpdate == NULL)
          {
-            Wnd->state2 |= WNDS2_WMPAINTSENT;
-            co_IntSendMessage(hWnd, WM_PAINT, 0, 0);
+            Wnd->state &= ~(WNDS_SENDERASEBACKGROUND|WNDS_ERASEBACKGROUND);
          }
-      }
-      else if (Wnd->head.pti == PsGetCurrentThreadWin32Thread())
-      {
-         if (Wnd->state & WNDS_SENDNCPAINT)
+
+         if (Wnd->head.pti == PsGetCurrentThreadWin32Thread())
          {
-            TempRegion = IntGetNCUpdateRgn(Wnd, TRUE);
-            Wnd->state &= ~WNDS_SENDNCPAINT;
-            if ( Wnd == GetW32ThreadInfo()->MessageQueue->spwndActive &&
-                !(Wnd->state & WNDS_ACTIVEFRAME))
+            if (Wnd->state & WNDS_SENDNCPAINT)
             {
-               Wnd->state |= WNDS_ACTIVEFRAME;
-               Wnd->state &= ~WNDS_NONCPAINT;
+               TempRegion = IntGetNCUpdateRgn(Wnd, TRUE);
+
+               IntSendNCPaint(Wnd, TempRegion);
+
+               if (TempRegion > HRGN_WINDOW && GreIsHandleValid(TempRegion))
+               {
+                  /* NOTE: The region can already be deleted! */
+                  GreDeleteObject(TempRegion);
+               }
             }
-            if (TempRegion) co_IntSendMessage(hWnd, WM_NCPAINT, (WPARAM)TempRegion, 0);
-         }
 
-         if (Wnd->state & WNDS_SENDERASEBACKGROUND)
-         {
-            if (Wnd->hrgnUpdate)
+            if (Wnd->state & WNDS_SENDERASEBACKGROUND)
             {
-               hDC = UserGetDCEx( Wnd,
-                                  Wnd->hrgnUpdate,
-                                  DCX_CACHE|DCX_USESTYLE|DCX_INTERSECTRGN|DCX_KEEPCLIPRGN);
-
-               Wnd->state &= ~(WNDS_SENDERASEBACKGROUND|WNDS_ERASEBACKGROUND);
-               // Kill the loop, so Clear before we send.
-               if (!co_IntSendMessage(hWnd, WM_ERASEBKGND, (WPARAM)hDC, 0))
+               PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
+               if (Wnd->hrgnUpdate)
                {
-                  Wnd->state |= (WNDS_SENDERASEBACKGROUND|WNDS_ERASEBACKGROUND);
+                  hDC = UserGetDCEx( Wnd,
+                                     Wnd->hrgnUpdate,
+                                     DCX_CACHE|DCX_USESTYLE|DCX_INTERSECTRGN|DCX_KEEPCLIPRGN);
+
+                  if (Wnd->head.pti->ppi != pti->ppi)
+                  {
+                     ERR("Sending DC to another Process!!!\n");
+                  }
+
+                  Wnd->state &= ~(WNDS_SENDERASEBACKGROUND|WNDS_ERASEBACKGROUND);
+                  // Kill the loop, so Clear before we send.
+                  if (!co_IntSendMessage(hWnd, WM_ERASEBKGND, (WPARAM)hDC, 0))
+                  {
+                     Wnd->state |= (WNDS_SENDERASEBACKGROUND|WNDS_ERASEBACKGROUND);
+                  }
+                  UserReleaseDC(Wnd, hDC, FALSE);
                }
-               UserReleaseDC(Wnd, hDC, FALSE);
             }
          }
+
       }
    }
-   else
-   {
-      Wnd->state &= ~(WNDS_SENDNCPAINT|WNDS_SENDERASEBACKGROUND|WNDS_ERASEBACKGROUND);
-   }
 
    /*
     * Check that the window is still valid at this point
@@ -385,19 +464,26 @@ co_IntPaintWindows(PWND Wnd, ULONG Flags, BOOL Recurse)
    /*
     * Paint child windows.
     */
+
    if (!(Flags & RDW_NOCHILDREN) &&
        !(Wnd->style & WS_MINIMIZE) &&
-        ((Flags & RDW_ALLCHILDREN) || !(Wnd->style & WS_CLIPCHILDREN)) )
+        ( Flags & RDW_ALLCHILDREN ||
+         (Flags & RDW_CLIPCHILDREN && Wnd->style & WS_CLIPCHILDREN) ) )
    {
       HWND *List, *phWnd;
+      PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
 
       if ((List = IntWinListChildren(Wnd)))
       {
-         /* FIXME: Handle WS_EX_TRANSPARENT */
          for (phWnd = List; *phWnd; ++phWnd)
          {
-            Wnd = UserGetWindowObject(*phWnd);
-            if (Wnd && (Wnd->style & WS_VISIBLE))
+            if ((Wnd = UserGetWindowObject(*phWnd)) == NULL)
+               continue;
+
+            if (Wnd->head.pti != pti && Wnd->style & WS_CHILD)
+               continue;
+
+            if (Wnd->style & WS_VISIBLE)
             {
                USER_REFERENCE_ENTRY Ref;
                UserRefObjectCo(Wnd, &Ref);
@@ -411,64 +497,192 @@ co_IntPaintWindows(PWND Wnd, ULONG Flags, BOOL Recurse)
 }
 
 /*
- * IntInvalidateWindows
+ * IntUpdateWindows
  *
- * Internal function used by IntRedrawWindow, UserRedrawDesktop,
- * co_WinPosSetWindowPos, IntValidateParent, co_UserRedrawWindow.
+ * Internal function used by IntRedrawWindow, simplecall.
  */
+
 VOID FASTCALL
-IntInvalidateWindows(PWND Wnd, PREGION Rgn, ULONG Flags)
+co_IntUpdateWindows(PWND Wnd, ULONG Flags, BOOL Recurse)
 {
-   INT RgnType;
-   BOOL HadPaintMessage;
+   HWND hWnd = Wnd->head.h;
 
-   TRACE("IntInvalidateWindows start\n");
+   if ( Wnd->hrgnUpdate != NULL || Wnd->state & WNDS_INTERNALPAINT )
+   {
+      if (Wnd->hrgnUpdate)
+      {
+         if (!IntValidateParents(Wnd, Recurse))
+         {
+            return;
+         }
+      }
 
-   Wnd->state |= WNDS_PAINTNOTPROCESSED;
+      if (Wnd->state & WNDS_INTERNALPAINT)
+      {
+          Wnd->state &= ~WNDS_INTERNALPAINT;
 
-   /*
-    * If the nonclient is not to be redrawn, clip the region to the client
-    * rect
-    */
-   if (0 != (Flags & RDW_INVALIDATE) && 0 == (Flags & RDW_FRAME))
+          if (Wnd->hrgnUpdate == NULL)
+             MsqDecPaintCountQueue(Wnd->head.pti);
+      }
+
+      Wnd->state |= WNDS_PAINTNOTPROCESSED;
+      Wnd->state &= ~WNDS_UPDATEDIRTY;
+
+      Wnd->state2 |= WNDS2_WMPAINTSENT;
+      co_IntSendMessage(hWnd, WM_PAINT, 0, 0); 
+
+      if (Wnd->state & WNDS_PAINTNOTPROCESSED)
+      {
+         USER_REFERENCE_ENTRY Ref;
+         UserRefObjectCo(Wnd, &Ref);
+         co_IntPaintWindows(Wnd, RDW_NOCHILDREN, FALSE);
+         UserDerefObjectCo(Wnd);
+      }
+   }
+
+   // Force flags as a toggle. Fixes msg:test_paint_messages:WmChildPaintNc.
+   Flags = (Flags & RDW_NOCHILDREN) ? RDW_NOCHILDREN : RDW_ALLCHILDREN; // All children is the default.
+
+  /*
+   * Update child windows.
+   */
+
+   if (!(Flags & RDW_NOCHILDREN) && 
+         Flags & RDW_ALLCHILDREN &&
+         Wnd != UserGetDesktopWindow() )
    {
-      PREGION RgnClient;
+      PWND Child;
 
-      RgnClient = IntSysCreateRectpRgnIndirect(&Wnd->rcClient);
-      if (RgnClient)
+      for (Child = Wnd->spwndChild; Child; Child = Child->spwndNext)
       {
-          RgnType = IntGdiCombineRgn(Rgn, Rgn, RgnClient, RGN_AND);
-          REGION_Delete(RgnClient);
+         /* transparent window, check for non-transparent sibling to paint first, then skip it */
+         if ( Child->ExStyle & WS_EX_TRANSPARENT &&
+             ( Child->hrgnUpdate != NULL || Child->state & WNDS_INTERNALPAINT ) )
+         {
+            PWND Next = Child->spwndNext;
+            while (Next)
+            {
+               if ( Next->hrgnUpdate != NULL || Next->state & WNDS_INTERNALPAINT ) break;
+
+               Next = Next->spwndNext;
+            }
+
+            if (Next) continue;
+         }
+
+         if (Child->style & WS_VISIBLE)
+         {
+             USER_REFERENCE_ENTRY Ref;
+             UserRefObjectCo(Child, &Ref);
+             co_IntUpdateWindows(Child, Flags, TRUE);
+             UserDerefObjectCo(Child);
+         }
       }
    }
+}
 
-   /*
-    * Clip the given region with window rectangle (or region)
-    */
+VOID FASTCALL
+UserUpdateWindows(PWND pWnd, ULONG Flags)
+{
+   // If transparent and any sibling windows below needs to be painted, leave.
+   if (pWnd->ExStyle & WS_EX_TRANSPARENT)
+   {
+      PWND Next = pWnd->spwndNext;
+
+      while(Next)
+      {
+         if ( Next->head.pti == pWnd->head.pti &&
+            ( Next->hrgnUpdate != NULL || Next->state & WNDS_INTERNALPAINT) )
+         {
+            return;
+         }
+
+         Next = Next->spwndNext;
+      }
+   }
+   co_IntUpdateWindows(pWnd, Flags, FALSE);
+}
+
+VOID FASTCALL
+UserSyncAndPaintWindows(PWND pWnd, ULONG Flags)
+{
+   PWND Parent = pWnd;
+   // Find parent, if it needs to be painted, leave.
+   while(TRUE)
+   {
+      if ((Parent = Parent->spwndParent) == NULL) break;
+      if ( Parent->style & WS_CLIPCHILDREN ) break;
+      if ( Parent->hrgnUpdate != NULL || Parent->state & WNDS_INTERNALPAINT ) return;
+   }
+
+   IntSendSyncPaint(pWnd, Flags);
+   co_IntPaintWindows(pWnd, Flags, FALSE);
+}
+
+/*
+ * IntInvalidateWindows
+ *
+ * Internal function used by IntRedrawWindow, UserRedrawDesktop,
+ * co_WinPosSetWindowPos, co_UserRedrawWindow.
+ */
+VOID FASTCALL
+IntInvalidateWindows(PWND Wnd, PREGION Rgn, ULONG Flags)
+{
+   INT RgnType = NULLREGION;
+   BOOL HadPaintMessage;
+
+   TRACE("IntInvalidateWindows start Rgn %p\n",Rgn);
 
-   if (!Wnd->hrgnClip || (Wnd->style & WS_MINIMIZE))
+   if ( Rgn > PRGN_WINDOW )
    {
-      PREGION RgnWindow = IntSysCreateRectpRgnIndirect(&Wnd->rcWindow);
-      if (RgnWindow)
+      /*
+       * If the nonclient is not to be redrawn, clip the region to the client
+       * rect
+       */
+      if ((Flags & RDW_INVALIDATE) != 0 && (Flags & RDW_FRAME) == 0)
+      {
+         PREGION RgnClient;
+
+         RgnClient = IntSysCreateRectpRgnIndirect(&Wnd->rcClient);
+         if (RgnClient)
+         {
+             RgnType = IntGdiCombineRgn(Rgn, Rgn, RgnClient, RGN_AND);
+             REGION_Delete(RgnClient);
+         }
+      }
+
+      /*
+       * Clip the given region with window rectangle (or region)
+       */
+
+      if (!Wnd->hrgnClip || (Wnd->style & WS_MINIMIZE))
+      {
+         PREGION RgnWindow = IntSysCreateRectpRgnIndirect(&Wnd->rcWindow);
+         if (RgnWindow)
+         {
+             RgnType = IntGdiCombineRgn(Rgn, Rgn, RgnWindow, RGN_AND);
+             REGION_Delete(RgnWindow);
+         }
+      }
+      else
       {
-          RgnType = IntGdiCombineRgn(Rgn, Rgn, RgnWindow, RGN_AND);
-          REGION_Delete(RgnWindow);
+          PREGION RgnClip = REGION_LockRgn(Wnd->hrgnClip);
+          if (RgnClip)
+          {
+              REGION_bOffsetRgn(Rgn,
+                                -Wnd->rcWindow.left,
+                                -Wnd->rcWindow.top);
+              RgnType = IntGdiCombineRgn(Rgn, Rgn, RgnClip, RGN_AND);
+              REGION_bOffsetRgn(Rgn,
+                                Wnd->rcWindow.left,
+                                Wnd->rcWindow.top);
+              REGION_UnlockRgn(RgnClip);
+          }
       }
    }
    else
    {
-       PREGION RgnClip = RGNOBJAPI_Lock(Wnd->hrgnClip, NULL);
-       if (RgnClip)
-       {
-           REGION_iOffsetRgn(Rgn,
-                             -Wnd->rcWindow.left,
-                             -Wnd->rcWindow.top);
-           RgnType = IntGdiCombineRgn(Rgn, Rgn, RgnClip, RGN_AND);
-           REGION_iOffsetRgn(Rgn,
-                             Wnd->rcWindow.left,
-                             Wnd->rcWindow.top);
-           RGNOBJAPI_Unlock(RgnClip);
-       }
+      RgnType = NULLREGION;
    }
 
    /*
@@ -489,7 +703,7 @@ IntInvalidateWindows(PWND Wnd, PREGION Rgn, ULONG Flags)
          Wnd->state |= WNDS_INTERNALPAINT;
       }
 
-      if (Flags & RDW_INVALIDATE && RgnType != NULLREGION)
+      if (Flags & RDW_INVALIDATE )
       {
          PREGION RgnUpdate;
 
@@ -505,56 +719,73 @@ IntInvalidateWindows(PWND Wnd, PREGION Rgn, ULONG Flags)
 
          if (Flags & RDW_FRAME)
             Wnd->state |= WNDS_SENDNCPAINT;
+
          if (Flags & RDW_ERASE)
             Wnd->state |= WNDS_SENDERASEBACKGROUND;
 
-         if (Wnd->hrgnUpdate == NULL)
+         if (RgnType != NULLREGION && Rgn > PRGN_WINDOW)
          {
-            Wnd->hrgnUpdate = NtGdiCreateRectRgn(0, 0, 0, 0);
-            IntGdiSetRegionOwner(Wnd->hrgnUpdate, GDI_OBJ_HMGR_PUBLIC);
-         }
+            if (Wnd->hrgnUpdate == NULL)
+            {
+               Wnd->hrgnUpdate = NtGdiCreateRectRgn(0, 0, 0, 0);
+               IntGdiSetRegionOwner(Wnd->hrgnUpdate, GDI_OBJ_HMGR_PUBLIC);
+            }
 
-         RgnUpdate = RGNOBJAPI_Lock(Wnd->hrgnUpdate, NULL);
-         if (RgnUpdate)
-         {
-             RgnType = IntGdiCombineRgn(RgnUpdate, RgnUpdate, Rgn, RGN_OR);
-             RGNOBJAPI_Unlock(RgnUpdate);
-             if (RgnType == NULLREGION)
-             {
-                IntGdiSetRegionOwner(Wnd->hrgnUpdate, GDI_OBJ_HMGR_POWNED);
-                GreDeleteObject(Wnd->hrgnUpdate);
-                Wnd->hrgnUpdate = NULL;
-             }
+            if (Wnd->hrgnUpdate != HRGN_WINDOW)
+            {
+               RgnUpdate = REGION_LockRgn(Wnd->hrgnUpdate);
+               if (RgnUpdate)
+               {
+                  RgnType = IntGdiCombineRgn(RgnUpdate, RgnUpdate, Rgn, RGN_OR);
+                  REGION_UnlockRgn(RgnUpdate);
+                  if (RgnType == NULLREGION)
+                  {
+                     IntGdiSetRegionOwner(Wnd->hrgnUpdate, GDI_OBJ_HMGR_POWNED);
+                     GreDeleteObject(Wnd->hrgnUpdate);
+                     Wnd->hrgnUpdate = NULL;
+                  }
+               }
+            }
          }
-         Flags |= RDW_FRAME; // For children.
+
+         Flags |= RDW_ERASE|RDW_FRAME; // For children.
+
+      }
+
+      if (!HadPaintMessage && IntIsWindowDirty(Wnd))
+      {
+         MsqIncPaintCountQueue(Wnd->head.pti);
       }
+
    }    // The following flags are used to validate the window.
    else if (Flags & (RDW_VALIDATE|RDW_NOINTERNALPAINT|RDW_NOERASE|RDW_NOFRAME))
    {
-      /* FIXME: Handle WNDS_UPDATEDIRTY */
+      if (Wnd->state & WNDS_UPDATEDIRTY && !(Flags & RDW_NOUPDATEDIRTY))
+         return;
 
       if (Flags & RDW_NOINTERNALPAINT)
       {
          Wnd->state &= ~WNDS_INTERNALPAINT;
       }
 
-      if (Flags & RDW_VALIDATE && RgnType != NULLREGION)
+      if (Flags & RDW_VALIDATE)
       {
          if (Flags & RDW_NOFRAME)
             Wnd->state &= ~WNDS_SENDNCPAINT;
+
          if (Flags & RDW_NOERASE)
             Wnd->state &= ~(WNDS_SENDERASEBACKGROUND|WNDS_ERASEBACKGROUND);
 
-         if (Wnd->hrgnUpdate != NULL)
+         if (Wnd->hrgnUpdate > HRGN_WINDOW && RgnType != NULLREGION && Rgn > PRGN_WINDOW)
          {
-             PREGION RgnUpdate = RGNOBJAPI_Lock(Wnd->hrgnUpdate, NULL);
+             PREGION RgnUpdate = REGION_LockRgn(Wnd->hrgnUpdate);
 
              if (RgnUpdate)
              {
                  RgnType = IntGdiCombineRgn(RgnUpdate, RgnUpdate, Rgn, RGN_DIFF);
-                 RGNOBJAPI_Unlock(RgnUpdate);
+                 REGION_UnlockRgn(RgnUpdate);
 
-                 if(RgnType == NULLREGION)
+                 if (RgnType == NULLREGION)
                  {
                      IntGdiSetRegionOwner(Wnd->hrgnUpdate, GDI_OBJ_HMGR_POWNED);
                      GreDeleteObject(Wnd->hrgnUpdate);
@@ -562,9 +793,16 @@ IntInvalidateWindows(PWND Wnd, PREGION Rgn, ULONG Flags)
                  }
              }
          }
-
+         // If update is null, do not erase.
          if (Wnd->hrgnUpdate == NULL)
+         {
             Wnd->state &= ~(WNDS_SENDERASEBACKGROUND|WNDS_ERASEBACKGROUND);
+         }
+      }
+
+      if (HadPaintMessage && !IntIsWindowDirty(Wnd))
+      {
+         MsqDecPaintCountQueue(Wnd->head.pti);
       }
    }
 
@@ -572,9 +810,10 @@ IntInvalidateWindows(PWND Wnd, PREGION Rgn, ULONG Flags)
     * Process children if needed
     */
 
-   if (!(Flags & RDW_NOCHILDREN) && !(Wnd->style & WS_MINIMIZE) &&
+   if (!(Flags & RDW_NOCHILDREN) &&
+       !(Wnd->style & WS_MINIMIZE) &&
          ((Flags & RDW_ALLCHILDREN) || !(Wnd->style & WS_CLIPCHILDREN)))
-   {
+   { 
       PWND Child;
 
       for (Child = Wnd->spwndChild; Child; Child = Child->spwndNext)
@@ -587,25 +826,13 @@ IntInvalidateWindows(PWND Wnd, PREGION Rgn, ULONG Flags)
             PREGION RgnTemp = IntSysCreateRectpRgn(0, 0, 0, 0);
             if (RgnTemp)
             {
-                IntGdiCombineRgn(RgnTemp, Rgn, 0, RGN_COPY);
-                IntInvalidateWindows(Child, RgnTemp, Flags);
+                if (Rgn > PRGN_WINDOW) IntGdiCombineRgn(RgnTemp, Rgn, 0, RGN_COPY);
+                IntInvalidateWindows(Child, ((Rgn > PRGN_WINDOW)?RgnTemp:Rgn), Flags);
                 REGION_Delete(RgnTemp);
             }
          }
       }
    }
-
-   /*
-    * Fake post paint messages to window message queue if needed
-    */
-
-   if (HadPaintMessage != IntIsWindowDirty(Wnd))
-   {
-      if (HadPaintMessage)
-         MsqDecPaintCountQueue(Wnd->head.pti);
-      else
-         MsqIncPaintCountQueue(Wnd->head.pti);
-   }
    TRACE("IntInvalidateWindows exit\n");
 }
 
@@ -652,7 +879,7 @@ co_UserRedrawWindow(
    ULONG Flags)
 {
    PREGION TmpRgn = NULL;
-   TRACE("co_UserRedrawWindow start\n");
+   TRACE("co_UserRedrawWindow start Rgn %p\n",UpdateRgn);
 
    /*
     * Step 1.
@@ -664,6 +891,11 @@ co_UserRedrawWindow(
       return TRUE; // Just do nothing!!!
    }
 
+   if (Window == NULL)
+   {
+      Window = UserGetDesktopWindow();
+   }
+
    /*
     * Step 2.
     * Transform the parameters UpdateRgn and UpdateRect into
@@ -672,38 +904,59 @@ co_UserRedrawWindow(
 
    if (Flags & (RDW_INVALIDATE | RDW_VALIDATE)) // Both are OKAY!
    {
+      /* We can't hold lock on GDI objects while doing roundtrips to user mode,
+       * so use a copy instead */
       if (UpdateRgn)
       {
           TmpRgn = IntSysCreateRectpRgn(0, 0, 0, 0);
-          if (IntGdiCombineRgn(TmpRgn, UpdateRgn, NULL, RGN_COPY) == NULLREGION)
+
+          if (UpdateRgn > PRGN_WINDOW)
           {
-              REGION_Delete(TmpRgn);
-              TmpRgn = NULL;
+             IntGdiCombineRgn(TmpRgn, UpdateRgn, NULL, RGN_COPY);
           }
-          else
+
+          if (Window != UserGetDesktopWindow())
           {
-              REGION_iOffsetRgn(TmpRgn, Window->rcClient.left, Window->rcClient.top);
+             REGION_bOffsetRgn(TmpRgn, Window->rcClient.left, Window->rcClient.top);
           }
       }
-      else if (UpdateRect != NULL)
+      else
       {
-         if (!RECTL_bIsEmptyRect(UpdateRect))
+         if (UpdateRect != NULL)
+         {
+            if (Window == UserGetDesktopWindow())
+            {
+               TmpRgn = IntSysCreateRectpRgnIndirect(UpdateRect);
+            }          
+            else
+            {
+               TmpRgn = IntSysCreateRectpRgn(Window->rcClient.left + UpdateRect->left,
+                                             Window->rcClient.top  + UpdateRect->top,
+                                             Window->rcClient.left + UpdateRect->right,
+                                             Window->rcClient.top  + UpdateRect->bottom);
+            }
+         }
+         else
          {
-            TmpRgn = IntSysCreateRectpRgnIndirect(UpdateRect);
-            REGION_iOffsetRgn(TmpRgn, Window->rcClient.left, Window->rcClient.top);
+            if ((Flags & (RDW_INVALIDATE | RDW_FRAME)) == (RDW_INVALIDATE | RDW_FRAME) ||
+                (Flags & (RDW_VALIDATE | RDW_NOFRAME)) == (RDW_VALIDATE | RDW_NOFRAME))
+            {
+               if (!RECTL_bIsEmptyRect(&Window->rcWindow))
+                   TmpRgn = IntSysCreateRectpRgnIndirect(&Window->rcWindow);
+            }
+            else
+            {
+               if (!RECTL_bIsEmptyRect(&Window->rcClient))
+                   TmpRgn = IntSysCreateRectpRgnIndirect(&Window->rcClient);
+            }
          }
       }
-      else if ((Flags & (RDW_INVALIDATE | RDW_FRAME)) == (RDW_INVALIDATE | RDW_FRAME) ||
-               (Flags & (RDW_VALIDATE | RDW_NOFRAME)) == (RDW_VALIDATE | RDW_NOFRAME))
-      {
-         if (!RECTL_bIsEmptyRect(&Window->rcWindow))
-            TmpRgn = IntSysCreateRectpRgnIndirect(&Window->rcWindow);
-      }
-      else
-      {
-         if (!RECTL_bIsEmptyRect(&Window->rcClient))
-            TmpRgn = IntSysCreateRectpRgnIndirect(&Window->rcClient);
-      }
+   }
+
+   /* Fixes test RDW_INTERNALPAINT behavior */
+   if (TmpRgn == NULL)
+   {
+      TmpRgn = PRGN_WINDOW; // Need a region so the bits can be set!!!
    }
 
    /*
@@ -722,10 +975,16 @@ co_UserRedrawWindow(
     * Repaint and erase windows if needed.
     */
 
-   if (Flags & (RDW_ERASENOW | RDW_UPDATENOW))
+   if (Flags & RDW_UPDATENOW)
+   {
+      UserUpdateWindows(Window, Flags);
+   }
+   else if (Flags & RDW_ERASENOW)
    {
-      if (Flags & RDW_ERASENOW) IntSendSyncPaint(Window, Flags);
-      co_IntPaintWindows(Window, Flags, FALSE);
+      if ((Flags & (RDW_NOCHILDREN|RDW_ALLCHILDREN)) == 0)
+         Flags |= RDW_CLIPCHILDREN;
+
+      UserSyncAndPaintWindows(Window, Flags);
    }
 
    /*
@@ -733,7 +992,7 @@ co_UserRedrawWindow(
     * Cleanup ;-)
     */
 
-   if (TmpRgn != NULL)
+   if (TmpRgn > PRGN_WINDOW)
    {
       REGION_Delete(TmpRgn);
    }
@@ -742,43 +1001,152 @@ co_UserRedrawWindow(
    return TRUE;
 }
 
-BOOL FASTCALL
-IntIsWindowDirty(PWND Wnd)
-{
-   return ( Wnd->style & WS_VISIBLE &&
-           ( Wnd->hrgnUpdate != NULL ||
-             Wnd->state & WNDS_INTERNALPAINT ) );
-}
-
-PWND FASTCALL
-IntFindWindowToRepaint(PWND Window, PTHREADINFO Thread)
+VOID FASTCALL
+PaintSuspendedWindow(PWND pwnd, HRGN hrgnOrig)
 {
-   PWND hChild;
-   PWND TempWindow;
-
-   for (; Window != NULL; Window = Window->spwndNext)
+   if (pwnd->hrgnUpdate)
    {
-      if (IntWndBelongsToThread(Window, Thread) &&
-          IntIsWindowDirty(Window))
+      HDC hDC;
+      INT Flags = DC_NC|DC_NOSENDMSG;
+      HRGN hrgnTemp;
+      RECT Rect;
+      INT type;
+      PREGION prgn;
+
+      if (pwnd->hrgnUpdate > HRGN_WINDOW)
       {
-         /* Make sure all non-transparent siblings are already drawn. */
-         if (Window->ExStyle & WS_EX_TRANSPARENT)
+         hrgnTemp = NtGdiCreateRectRgn(0, 0, 0, 0);
+         type = NtGdiCombineRgn( hrgnTemp, pwnd->hrgnUpdate, 0, RGN_COPY);
+         if (type == ERROR)
          {
-            for (TempWindow = Window->spwndNext; TempWindow != NULL;
-                 TempWindow = TempWindow->spwndNext)
+            GreDeleteObject(hrgnTemp);
+            hrgnTemp = HRGN_WINDOW;
+         }
+      }
+      else
+      {
+         hrgnTemp = GreCreateRectRgnIndirect(&pwnd->rcWindow);
+      }
+
+      if ( hrgnOrig &&
+           hrgnTemp > HRGN_WINDOW &&
+           NtGdiCombineRgn(hrgnTemp, hrgnTemp, hrgnOrig, RGN_AND) == NULLREGION)
+      {
+         GreDeleteObject(hrgnTemp);
+         return;
+      }
+
+      hDC = UserGetDCEx(pwnd, hrgnTemp, DCX_WINDOW|DCX_INTERSECTRGN|DCX_USESTYLE|DCX_KEEPCLIPRGN);
+
+      Rect = pwnd->rcWindow;
+      RECTL_vOffsetRect(&Rect, -pwnd->rcWindow.left, -pwnd->rcWindow.top);
+
+      // Clear out client area!
+      FillRect(hDC, &Rect, IntGetSysColorBrush(COLOR_WINDOW));
+
+      NC_DoNCPaint(pwnd, hDC, Flags); // Redraw without MENUs.
+
+      UserReleaseDC(pwnd, hDC, FALSE);
+
+      prgn = REGION_LockRgn(hrgnTemp);
+      IntInvalidateWindows(pwnd, prgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ALLCHILDREN);
+      REGION_UnlockRgn(prgn);
+
+      // Set updates for this window.
+      pwnd->state |= WNDS_SENDNCPAINT|WNDS_SENDERASEBACKGROUND|WNDS_UPDATEDIRTY;
+
+      // DCX_KEEPCLIPRGN is set. Check it anyway.
+      if (hrgnTemp > HRGN_WINDOW && GreIsHandleValid(hrgnTemp)) GreDeleteObject(hrgnTemp);
+   }
+}
+
+VOID FASTCALL
+UpdateTheadChildren(PWND pWnd, HRGN hRgn)
+{
+   PaintSuspendedWindow( pWnd, hRgn );
+
+   if (!(pWnd->style & WS_CLIPCHILDREN))
+      return;
+
+   pWnd = pWnd->spwndChild; // invalidate children if any.
+   while (pWnd)
+   {
+      UpdateTheadChildren( pWnd, hRgn );
+      pWnd = pWnd->spwndNext;
+   }
+}
+
+VOID FASTCALL
+UpdateThreadWindows(PWND pWnd, PTHREADINFO pti, HRGN hRgn)
+{
+   PWND pwndTemp;
+
+   for ( pwndTemp = pWnd;
+         pwndTemp;
+         pwndTemp = pwndTemp->spwndNext )
+   {
+      if (pwndTemp->head.pti == pti)
+      {
+          UserUpdateWindows(pwndTemp, RDW_ALLCHILDREN);
+      }
+      else
+      {
+          if (IsThreadSuspended(pwndTemp->head.pti))
+          {
+             UpdateTheadChildren(pwndTemp, hRgn);
+          }
+          else
+             UserUpdateWindows(pwndTemp, RDW_ALLCHILDREN);
+      }
+   }
+}
+
+BOOL FASTCALL
+IntIsWindowDirty(PWND Wnd)
+{
+   return ( Wnd->style & WS_VISIBLE &&
+           ( Wnd->hrgnUpdate != NULL ||
+             Wnd->state & WNDS_INTERNALPAINT ) );
+}
+
+/*
+   Conditions to paint any window:
+
+   1. Update region is not null.
+   2. Internal paint flag is set.
+   3. Paint count is not zero.
+
+ */
+PWND FASTCALL
+IntFindWindowToRepaint(PWND Window, PTHREADINFO Thread)
+{
+   PWND hChild;
+   PWND TempWindow;
+
+   for (; Window != NULL; Window = Window->spwndNext)
+   {
+      if (IntWndBelongsToThread(Window, Thread))
+      {
+         if (IntIsWindowDirty(Window))
+         {
+            /* Make sure all non-transparent siblings are already drawn. */
+            if (Window->ExStyle & WS_EX_TRANSPARENT)
             {
-               if (!(TempWindow->ExStyle & WS_EX_TRANSPARENT) &&
-                   IntWndBelongsToThread(TempWindow, Thread) &&
-                   IntIsWindowDirty(TempWindow))
+               for (TempWindow = Window->spwndNext; TempWindow != NULL;
+                    TempWindow = TempWindow->spwndNext)
                {
-                  return TempWindow;
+                  if (!(TempWindow->ExStyle & WS_EX_TRANSPARENT) &&
+                       IntWndBelongsToThread(TempWindow, Thread) &&
+                       IntIsWindowDirty(TempWindow))
+                  {
+                     return TempWindow;
+                  }
                }
             }
+            return Window;
          }
-
-         return Window;
       }
-
+      /* find a child of the specified window that needs repainting */
       if (Window->spwndChild)
       {
          hChild = IntFindWindowToRepaint(Window->spwndChild, Thread);
@@ -789,6 +1157,16 @@ IntFindWindowToRepaint(PWND Window, PTHREADINFO Thread)
    return Window;
 }
 
+//
+// Internal painting of windows.
+//
+VOID FASTCALL
+IntPaintWindow( PWND Window )
+{
+   // Handle normal painting.
+   co_IntPaintWindows( Window, RDW_NOCHILDREN, FALSE );
+}
+
 BOOL FASTCALL
 IntGetPaintMessage(
    PWND Window,
@@ -798,7 +1176,7 @@ IntGetPaintMessage(
    MSG *Message,
    BOOL Remove)
 {
-   PWND PaintWnd;
+   PWND PaintWnd, StartWnd;
 
    if ((MsgFilterMin != 0 || MsgFilterMax != 0) &&
          (MsgFilterMin > WM_PAINT || MsgFilterMax < WM_PAINT))
@@ -809,19 +1187,26 @@ IntGetPaintMessage(
       ERR("WM_PAINT is in a System Thread!\n");
    }
 
-   PaintWnd = IntFindWindowToRepaint(UserGetDesktopWindow(), Thread);
+   StartWnd = UserGetDesktopWindow();
+   PaintWnd = IntFindWindowToRepaint(StartWnd, Thread);
 
    Message->hwnd = PaintWnd ? UserHMGetHandle(PaintWnd) : NULL;
 
-   if (Message->hwnd == NULL)
+   if (Message->hwnd == NULL && Thread->cPaintsReady)
    {
-      ERR("PAINTING BUG: Thread marked as containing dirty windows, but no dirty windows found! Counts %u\n",Thread->cPaintsReady);
-      /* Hack to stop spamming the debuglog ! */
+      // Find note in window.c:"PAINTING BUG".
+      ERR("WARNING SOMETHING HAS GONE WRONG: Thread marked as containing dirty windows, but no dirty windows found! Counts %u\n",Thread->cPaintsReady);
+      /* Hack to stop spamming the debug log ! */
       Thread->cPaintsReady = 0;
       return FALSE;
    }
 
-   if (Window != NULL && PaintWnd != Window)
+   if (Message->hwnd == NULL)
+      return FALSE;
+
+   if (!(Window == NULL ||
+         PaintWnd == Window ||
+         IntIsChildWindow(Window, PaintWnd))) /* check that it is a child of the specified parent */
       return FALSE;
 
    if (PaintWnd->state & WNDS_INTERNALPAINT)
@@ -830,60 +1215,23 @@ IntGetPaintMessage(
       if (!PaintWnd->hrgnUpdate)
          MsqDecPaintCountQueue(Thread);
    }
-   PaintWnd->state2 &= ~WNDS2_WMPAINTSENT;
+   PaintWnd->state2 &= ~WNDS2_STARTPAINT;
    PaintWnd->state &= ~WNDS_UPDATEDIRTY;
-   Message->wParam = Message->lParam = 0;
-   Message->message = WM_PAINT;
-   return TRUE;
-}
-
-static
-HWND FASTCALL
-co_IntFixCaret(PWND Window, RECTL *lprc, UINT flags)
-{
-   PDESKTOP Desktop;
-   PTHRDCARETINFO CaretInfo;
-   PTHREADINFO pti;
-   PUSER_MESSAGE_QUEUE ActiveMessageQueue;
-   HWND hWndCaret;
-   PWND WndCaret;
-
-   ASSERT_REFS_CO(Window);
 
-   pti = PsGetCurrentThreadWin32Thread();
-   Desktop = pti->rpdesk;
-   ActiveMessageQueue = Desktop->ActiveMessageQueue;
-   if (!ActiveMessageQueue) return 0;
-   CaretInfo = ActiveMessageQueue->CaretInfo;
-   hWndCaret = CaretInfo->hWnd;
-
-   WndCaret = ValidateHwndNoErr(hWndCaret);
-
-   // FIXME: Check for WndCaret can be NULL
-   if (WndCaret == Window ||
-         ((flags & SW_SCROLLCHILDREN) && IntIsChildWindow(Window, WndCaret)))
+   Window = PaintWnd;
+   while( Window && Window != UserGetDesktopWindow())
    {
-      POINT pt, FromOffset, ToOffset;
-      RECTL rcCaret;
-
-      pt.x = CaretInfo->Pos.x;
-      pt.y = CaretInfo->Pos.y;
-      IntGetClientOrigin(WndCaret, &FromOffset);
-      IntGetClientOrigin(Window, &ToOffset);
-      rcCaret.left = pt.x;
-      rcCaret.top = pt.y;
-      rcCaret.right = pt.x + CaretInfo->Size.cx;
-      rcCaret.bottom = pt.y + CaretInfo->Size.cy;
-      if (RECTL_bIntersectRect(lprc, lprc, &rcCaret))
+      // Role back and check for clip children, do not set if any.
+      if (Window->spwndParent && !(Window->spwndParent->style & WS_CLIPCHILDREN))
       {
-         co_UserHideCaret(0);
-         lprc->left = pt.x;
-         lprc->top = pt.y;
-         return hWndCaret;
+         PaintWnd->state2 |= WNDS2_WMPAINTSENT;
       }
+      Window = Window->spwndParent;
    }
 
-   return 0;
+   Message->wParam = Message->lParam = 0;
+   Message->message = WM_PAINT;
+   return TRUE;
 }
 
 BOOL
@@ -915,7 +1263,7 @@ IntPrintWindow(
     return FALSE;
 
     /* Update the window just incase. */
-    co_IntPaintWindows( pwnd, RDW_ERASENOW|RDW_UPDATENOW, FALSE);
+    co_IntUpdateWindows( pwnd, RDW_ALLCHILDREN, FALSE);
 
     hdcSrc = UserGetDCEx( pwnd, NULL, DCX_CACHE|DCX_WINDOW);
     /* Print window to printer context. */
@@ -942,23 +1290,129 @@ BOOL
 FASTCALL
 IntFlashWindowEx(PWND pWnd, PFLASHWINFO pfwi)
 {
-   PPROPERTY pprop;
    DWORD FlashState;
-   BOOL Ret = FALSE;
+   UINT uCount = pfwi->uCount;
+   BOOL Activate = FALSE, Ret = FALSE;
+
+   ASSERT(pfwi);
+
+   FlashState = (DWORD)UserGetProp(pWnd, AtomFlashWndState, TRUE);
 
-   pprop = IntGetProp(pWnd, AtomFlashWndState);
-   if (!pprop)
+   if (FlashState == FLASHW_FINISHED)
    {
-      FlashState = pfwi->dwFlags;
-      IntSetProp(pWnd, AtomFlashWndState, (HANDLE) FlashState);
-      return TRUE;
+      // Cycle has finished, kill timer and set this to Stop.
+      FlashState |= FLASHW_KILLSYSTIMER;
+      pfwi->dwFlags = FLASHW_STOP;
    }
+   else
+   {
+      if (FlashState)
+      {
+         if (pfwi->dwFlags == FLASHW_SYSTIMER)
+         {
+             // Called from system timer, restore flags, counts and state.
+             pfwi->dwFlags = LOWORD(FlashState);
+             uCount = HIWORD(FlashState);
+             FlashState = MAKELONG(LOWORD(FlashState),0);
+         }
+         else
+         {
+             // Clean out the trash! Fix SeaMonkey crash after restart.
+             FlashState = 0;
+         }
+      }
+
+      if (FlashState == 0)
+      {  // First time in cycle, setup flash state.
+         if ( pWnd->state & WNDS_ACTIVEFRAME ||
+             (pfwi->dwFlags & FLASHW_CAPTION && pWnd->style & (WS_BORDER|WS_DLGFRAME)))
+         {
+             FlashState = FLASHW_STARTED|FLASHW_ACTIVE;
+         }
+      }
 
-   FlashState = (DWORD)pprop->Data;
+      // Set previous window state.
+      Ret = !!(FlashState & FLASHW_ACTIVE);
+
+      if ( (pfwi->dwFlags & FLASHW_TIMERNOFG) == FLASHW_TIMERNOFG &&
+           gpqForeground == pWnd->head.pti->MessageQueue )
+      {
+          // Flashing until foreground, set this to Stop.
+          pfwi->dwFlags = FLASHW_STOP;
+      }
+   }
+
+   // Toggle activate flag.
    if ( pfwi->dwFlags == FLASHW_STOP )
    {
-      IntRemoveProp(pWnd, AtomFlashWndState);
-      Ret = TRUE;
+      if (gpqForeground && gpqForeground->spwndActive == pWnd)
+         Activate = TRUE;
+      else
+         Activate = FALSE;
+   }
+   else
+   {
+      Activate = (FlashState & FLASHW_ACTIVE) == 0;
+   }
+
+   if ( pfwi->dwFlags == FLASHW_STOP || pfwi->dwFlags & FLASHW_CAPTION )
+   {
+      co_IntSendMessage(UserHMGetHandle(pWnd), WM_NCACTIVATE, Activate, 0);
+   }
+
+   // FIXME: Check for a Stop Sign here.
+   if ( pfwi->dwFlags & FLASHW_TRAY )
+   {
+      // Need some shell work here too.
+      TRACE("FIXME: Flash window no Tray support!\n");
+   }
+
+   if ( pfwi->dwFlags == FLASHW_STOP )
+   {
+      if (FlashState & FLASHW_KILLSYSTIMER)
+      {
+         IntKillTimer(pWnd, ID_EVENT_SYSTIMER_FLASHWIN, TRUE);
+      }
+
+      UserRemoveProp(pWnd, AtomFlashWndState, TRUE);
+   }
+   else
+   {  // Have a count and started, set timer.
+      if ( uCount )
+      {
+         FlashState |= FLASHW_COUNT;
+
+         if (!(Activate ^ !!(FlashState & FLASHW_STARTED)))
+             uCount--;
+
+         if (!(FlashState & FLASHW_KILLSYSTIMER))
+             pfwi->dwFlags |= FLASHW_TIMER;
+      }
+
+      if (pfwi->dwFlags & FLASHW_TIMER)
+      {
+         FlashState |= FLASHW_KILLSYSTIMER;
+
+         IntSetTimer( pWnd,
+                      ID_EVENT_SYSTIMER_FLASHWIN,
+                      pfwi->dwTimeout ? pfwi->dwTimeout : gpsi->dtCaretBlink,
+                      SystemTimerProc,
+                      TMRF_SYSTEM );
+      }
+
+      if (FlashState & FLASHW_COUNT && uCount == 0)
+      {
+         // Keep spinning? Nothing else to do.
+         FlashState = FLASHW_FINISHED;
+      }
+      else
+      {
+         // Save state and flags so this can be restored next time through.
+         FlashState ^= (FlashState ^ -!!(Activate)) & FLASHW_ACTIVE;
+         FlashState ^= (FlashState ^ pfwi->dwFlags) & (FLASHW_MASK & ~FLASHW_TIMER);
+      }
+      FlashState = MAKELONG(LOWORD(FlashState),uCount);
+      UserSetProp(pWnd, AtomFlashWndState, (HANDLE)FlashState, TRUE);
    }
    return Ret;
 }
@@ -966,6 +1420,10 @@ IntFlashWindowEx(PWND pWnd, PFLASHWINFO pfwi)
 HDC FASTCALL
 IntBeginPaint(PWND Window, PPAINTSTRUCT Ps)
 {
+   RECT Rect;
+   INT type;
+   BOOL Erase = FALSE;
+
    co_UserHideCaret(Window);
 
    Window->state2 |= WNDS2_STARTPAINT;
@@ -974,16 +1432,19 @@ IntBeginPaint(PWND Window, PPAINTSTRUCT Ps)
    if (Window->state & WNDS_SENDNCPAINT)
    {
       HRGN hRgn;
-
-      Window->state &= ~WNDS_UPDATEDIRTY;
-      hRgn = IntGetNCUpdateRgn(Window, FALSE);
-      Window->state &= ~WNDS_SENDNCPAINT;
-      co_IntSendMessage(UserHMGetHandle(Window), WM_NCPAINT, (WPARAM)hRgn, 0);
-      if (hRgn != HRGN_WINDOW && hRgn != NULL && GreIsHandleValid(hRgn))
+      // Application can keep update dirty.
+      do
       {
-         /* NOTE: The region can already be deleted! */
-         GreDeleteObject(hRgn);
+         Window->state &= ~WNDS_UPDATEDIRTY;
+         hRgn = IntGetNCUpdateRgn(Window, FALSE);
+         IntSendNCPaint(Window, hRgn);
+         if (hRgn > HRGN_WINDOW && GreIsHandleValid(hRgn))
+         {
+            /* NOTE: The region can already be deleted! */
+            GreDeleteObject(hRgn);
+         }
       }
+      while(Window->state & WNDS_UPDATEDIRTY);
    }
    else
    {
@@ -992,18 +1453,29 @@ IntBeginPaint(PWND Window, PPAINTSTRUCT Ps)
 
    RtlZeroMemory(Ps, sizeof(PAINTSTRUCT));
 
+   if (Window->state2 & WNDS2_ENDPAINTINVALIDATE)
+   {
+      ERR("BP: Another thread invalidated this window\n");
+   }
+
    Ps->hdc = UserGetDCEx( Window,
-                         Window->hrgnUpdate,
-                         DCX_INTERSECTRGN | DCX_USESTYLE);
+                          Window->hrgnUpdate,
+                          DCX_INTERSECTRGN | DCX_USESTYLE);
    if (!Ps->hdc)
    {
       return NULL;
    }
 
+   // If set, always clear flags out due to the conditions later on for sending the message.
+   if (Window->state & WNDS_SENDERASEBACKGROUND)
+   {
+      Window->state &= ~(WNDS_SENDERASEBACKGROUND|WNDS_ERASEBACKGROUND);
+      Erase = TRUE;
+   }
+
    if (Window->hrgnUpdate != NULL)
    {
       MsqDecPaintCountQueue(Window->head.pti);
-      GdiGetClipBox(Ps->hdc, &Ps->rcPaint);
       IntGdiSetRegionOwner(Window->hrgnUpdate, GDI_OBJ_HMGR_POWNED);
       /* The region is part of the dc now and belongs to the process! */
       Window->hrgnUpdate = NULL;
@@ -1012,15 +1484,19 @@ IntBeginPaint(PWND Window, PPAINTSTRUCT Ps)
    {
       if (Window->state & WNDS_INTERNALPAINT)
          MsqDecPaintCountQueue(Window->head.pti);
-
-      IntGetClientRect(Window, &Ps->rcPaint);
    }
 
+   type = GdiGetClipBox(Ps->hdc, &Ps->rcPaint);
+
+   IntGetClientRect(Window, &Rect);
+
    Window->state &= ~WNDS_INTERNALPAINT;
 
-   if (Window->state & WNDS_SENDERASEBACKGROUND)
+   if ( Erase &&               // Set to erase,
+        type != NULLREGION &&  // don't erase if the clip box is empty,
+        (!(Window->pcls->style & CS_PARENTDC) || // not parent dc or
+         RECTL_bIntersectRect( &Rect, &Rect, &Ps->rcPaint) ) ) // intersecting.
    {
-      Window->state &= ~(WNDS_SENDERASEBACKGROUND|WNDS_ERASEBACKGROUND);
       Ps->fErase = !co_IntSendMessage(UserHMGetHandle(Window), WM_ERASEBKGND, (WPARAM)Ps->hdc, 0);
       if ( Ps->fErase )
       {
@@ -1031,18 +1507,9 @@ IntBeginPaint(PWND Window, PPAINTSTRUCT Ps)
    {
       Ps->fErase = FALSE;
    }
-   if (Window->hrgnUpdate)
-   {
-      if (!(Window->style & WS_CLIPCHILDREN))
-      {
-         PWND Child;
-         for (Child = Window->spwndChild; Child; Child = Child->spwndNext)
-         {
-            if (Child->hrgnUpdate == NULL && Child->state & WNDS_SENDNCPAINT) // Helped fixing test_redrawnow.
-            IntInvalidateWindows(Child, NULL, RDW_FRAME | RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN);
-         }
-      }
-   }
+
+   IntSendChildNCPaint(Window);
+
    return Ps->hdc;
 }
 
@@ -1055,6 +1522,12 @@ IntEndPaint(PWND Wnd, PPAINTSTRUCT Ps)
 
    UserReleaseDC(Wnd, hdc, TRUE);
 
+   if (Wnd->state2 & WNDS2_ENDPAINTINVALIDATE)
+   {
+      ERR("EP: Another thread invalidated this window\n");
+      Wnd->state2 &= ~WNDS2_ENDPAINTINVALIDATE;
+   }
+
    Wnd->state2 &= ~(WNDS2_WMPAINTSENT|WNDS2_STARTPAINT);
 
    co_UserShowCaret(Wnd);
@@ -1170,30 +1643,27 @@ NtUserFlashWindowEx(IN PFLASHWINFO pfwi)
 {
    PWND pWnd;
    FLASHWINFO finfo = {0};
-   BOOL Ret = TRUE;
+   BOOL Ret = FALSE;
 
    UserEnterExclusive();
 
    _SEH2_TRY
    {
-      ProbeForRead(pfwi, sizeof(FLASHWINFO), sizeof(ULONG));
+      ProbeForRead(pfwi, sizeof(FLASHWINFO), 1);
       RtlCopyMemory(&finfo, pfwi, sizeof(FLASHWINFO));
    }
    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
    {
       SetLastNtError(_SEH2_GetExceptionCode());
-      Ret = FALSE;
+      _SEH2_YIELD(goto Exit);
    }
    _SEH2_END
 
-   if (!Ret) goto Exit;
-
-   if (!( pWnd = (PWND)UserGetObject(gHandleTable, finfo.hwnd, TYPE_WINDOW)) ||
+   if (!( pWnd = ValidateHwndNoErr(finfo.hwnd)) ||
         finfo.cbSize != sizeof(FLASHWINFO) ||
         finfo.dwFlags & ~(FLASHW_ALL|FLASHW_TIMER|FLASHW_TIMERNOFG) )
    {
       EngSetLastError(ERROR_INVALID_PARAMETER);
-      Ret = FALSE;
       goto Exit;
    }
 
@@ -1204,765 +1674,318 @@ Exit:
    return Ret;
 }
 
-INT FASTCALL
-co_UserGetUpdateRgn(PWND Window, PREGION Rgn, BOOL bErase)
-{
-    int RegionType;
-    RECTL Rect;
-    PREGION UpdateRgn;
-
-    ASSERT_REFS_CO(Window);
-
-    Window->state &= ~WNDS_UPDATEDIRTY;
-
-    if (Window->hrgnUpdate == NULL)
-    {
-        REGION_SetRectRgn(Rgn, 0, 0, 0, 0);
-        return NULLREGION;
-    }
-
-    UpdateRgn = RGNOBJAPI_Lock(Window->hrgnUpdate, NULL);
-    if (!UpdateRgn)
-       return ERROR;
-
-    Rect = Window->rcClient;
-    IntIntersectWithParents(Window, &Rect);
-    REGION_SetRectRgn(Rgn, Rect.left, Rect.top, Rect.right, Rect.bottom);
-    RegionType = IntGdiCombineRgn(Rgn, Rgn, UpdateRgn, RGN_AND);
-    REGION_iOffsetRgn(Rgn, -Window->rcClient.left, -Window->rcClient.top);
-    RGNOBJAPI_Unlock(UpdateRgn);
-
-   if (bErase && RegionType != NULLREGION && RegionType != ERROR)
-   {
-      co_UserRedrawWindow(Window, NULL, NULL, RDW_ERASENOW | RDW_NOCHILDREN);
-   }
-
-   return RegionType;
-}
-
 /*
- * NtUserGetUpdateRgn
- *
- * Status
- *    @implemented
+    GetUpdateRgn, this fails the same as the old one.
  */
-
-INT APIENTRY
-NtUserGetUpdateRgn(HWND hWnd, HRGN hRgn, BOOL bErase)
-{
-   DECLARE_RETURN(INT);
-   PWND Window;
-   INT ret;
-   USER_REFERENCE_ENTRY Ref;
-   PREGION Rgn = NULL;
-
-   TRACE("Enter NtUserGetUpdateRgn\n");
-   UserEnterExclusive();
-
-   if (!(Window = UserGetWindowObject(hWnd)))
-   {
-      RETURN(ERROR);
-   }
-
-   /* Use a system region, we can't hold GDI locks when doing roundtrips to user mode */
-   Rgn = IntSysCreateRectpRgn(0, 0, 0, 0);
-   if (!Rgn)
-       RETURN(ERROR);
-
-   UserRefObjectCo(Window, &Ref);
-   ret = co_UserGetUpdateRgn(Window, Rgn, bErase);
-   UserDerefObjectCo(Window);
-
-   RETURN(ret);
-
-CLEANUP:
-   if (Rgn && (_ret_ != ERROR))
-   {
-       PREGION TheRgn = RGNOBJAPI_Lock(hRgn, NULL);
-       if (!TheRgn)
-       {
-           EngSetLastError(ERROR_INVALID_HANDLE);
-           _ret_ = ERROR;
-       }
-       IntGdiCombineRgn(TheRgn, Rgn, NULL, RGN_COPY);
-       RGNOBJAPI_Unlock(TheRgn);
-   }
-
-   if (Rgn)
-       REGION_Delete(Rgn);
-
-   TRACE("Leave NtUserGetUpdateRgn, ret=%i\n",_ret_);
-   UserLeave();
-   END_CLEANUP;
-}
-
-/*
- * NtUserGetUpdateRect
- *
- * Status
- *    @implemented
- */
-
-BOOL APIENTRY
-NtUserGetUpdateRect(HWND hWnd, LPRECT UnsafeRect, BOOL bErase)
+INT FASTCALL
+co_UserGetUpdateRgn(PWND Window, HRGN hRgn, BOOL bErase)
 {
-   PWND Window;
+   int RegionType;
+   BOOL Type;
    RECTL Rect;
-   INT RegionType;
-   PREGION RgnData;
-   NTSTATUS Status;
-   DECLARE_RETURN(BOOL);
 
-   TRACE("Enter NtUserGetUpdateRect\n");
-   UserEnterExclusive();
+   ASSERT_REFS_CO(Window);
 
-   if (!(Window = UserGetWindowObject(hWnd)))
+   if (bErase)
    {
-      RETURN(FALSE);
+      USER_REFERENCE_ENTRY Ref;
+      UserRefObjectCo(Window, &Ref);
+      co_IntPaintWindows(Window, RDW_NOCHILDREN, FALSE);
+      UserDerefObjectCo(Window);
    }
 
    Window->state &= ~WNDS_UPDATEDIRTY;
 
    if (Window->hrgnUpdate == NULL)
    {
-      Rect.left = Rect.top = Rect.right = Rect.bottom = 0;
+       NtGdiSetRectRgn(hRgn, 0, 0, 0, 0);
+       return NULLREGION;
    }
-   else
+
+   Rect = Window->rcClient;
+   Type = IntIntersectWithParents(Window, &Rect);
+
+   if (Window->hrgnUpdate == HRGN_WINDOW)
    {
-      /* Get the update region bounding box. */
-      if (Window->hrgnUpdate == HRGN_WINDOW)
+      // Trap it out.
+      ERR("GURn: Caller is passing Window Region 1\n");
+      if (!Type)
       {
-         Rect = Window->rcClient;
+         NtGdiSetRectRgn(hRgn, 0, 0, 0, 0);
+         return NULLREGION;
       }
-      else
-      {
-         RgnData = RGNOBJAPI_Lock(Window->hrgnUpdate, NULL);
-         ASSERT(RgnData != NULL);
-         RegionType = REGION_GetRgnBox(RgnData, &Rect);
-         RGNOBJAPI_Unlock(RgnData);
 
-         if (RegionType != ERROR && RegionType != NULLREGION)
-            RECTL_bIntersectRect(&Rect, &Rect, &Window->rcClient);
-      }
+      RegionType = SIMPLEREGION;
 
-      if (IntIntersectWithParents(Window, &Rect))
+      if (Window != UserGetDesktopWindow()) // Window->fnid == FNID_DESKTOP
       {
          RECTL_vOffsetRect(&Rect,
                           -Window->rcClient.left,
                           -Window->rcClient.top);
-      } else
-      {
-         Rect.left = Rect.top = Rect.right = Rect.bottom = 0;
       }
+      GreSetRectRgnIndirect(hRgn, &Rect);
    }
-
-   if (bErase && !RECTL_bIsEmptyRect(&Rect))
-   {
-      USER_REFERENCE_ENTRY Ref;
-      UserRefObjectCo(Window, &Ref);
-      co_UserRedrawWindow(Window, NULL, NULL, RDW_ERASENOW | RDW_NOCHILDREN);
-      UserDerefObjectCo(Window);
-   }
-
-   if (UnsafeRect != NULL)
+   else
    {
-      Status = MmCopyToCaller(UnsafeRect, &Rect, sizeof(RECTL));
-      if (!NT_SUCCESS(Status))
-      {
-         EngSetLastError(ERROR_INVALID_PARAMETER);
-         RETURN(FALSE);
-      }
-   }
-
-   RETURN(!RECTL_bIsEmptyRect(&Rect));
-
-CLEANUP:
-   TRACE("Leave NtUserGetUpdateRect, ret=%i\n",_ret_);
-   UserLeave();
-   END_CLEANUP;
-}
-
-/*
- * NtUserRedrawWindow
- *
- * Status
- *    @implemented
- */
+      HRGN hrgnTemp = GreCreateRectRgnIndirect(&Rect);
 
-BOOL APIENTRY
-NtUserRedrawWindow(
-   HWND hWnd,
-   CONST RECT *lprcUpdate,
-   HRGN hrgnUpdate,
-   UINT flags)
-{
-   RECTL SafeUpdateRect;
-   PWND Wnd;
-   BOOL Ret;
-   USER_REFERENCE_ENTRY Ref;
-   NTSTATUS Status = STATUS_SUCCESS;
-   PREGION RgnUpdate = NULL;
-   DECLARE_RETURN(BOOL);
-
-   TRACE("Enter NtUserRedrawWindow\n");
-   UserEnterExclusive();
+      RegionType = NtGdiCombineRgn(hRgn, hrgnTemp, Window->hrgnUpdate, RGN_AND);
 
-   if (!(Wnd = UserGetWindowObject(hWnd ? hWnd : IntGetDesktopWindow())))
-   {
-      RETURN( FALSE);
-   }
-
-   if (lprcUpdate)
-   {
-      _SEH2_TRY
-      {
-          ProbeForRead(lprcUpdate, sizeof(RECTL), 1);
-          RtlCopyMemory(&SafeUpdateRect, lprcUpdate, sizeof(RECTL));
-      }
-      _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+      if (RegionType == ERROR || RegionType == NULLREGION)
       {
-         Status = _SEH2_GetExceptionCode();
+         if (hrgnTemp) GreDeleteObject(hrgnTemp);
+         NtGdiSetRectRgn(hRgn, 0, 0, 0, 0);
+         return RegionType;
       }
-      _SEH2_END
-      if (!NT_SUCCESS(Status))
+
+      if (Window != UserGetDesktopWindow()) // Window->fnid == FNID_DESKTOP
       {
-         EngSetLastError(RtlNtStatusToDosError(Status));
-         RETURN( FALSE);
+         NtGdiOffsetRgn(hRgn,
+                       -Window->rcClient.left,
+                       -Window->rcClient.top);
       }
+      if (hrgnTemp) GreDeleteObject(hrgnTemp);
    }
-
-   if ( flags & ~(RDW_ERASE|RDW_FRAME|RDW_INTERNALPAINT|RDW_INVALIDATE|
-                  RDW_NOERASE|RDW_NOFRAME|RDW_NOINTERNALPAINT|RDW_VALIDATE|
-                  RDW_ERASENOW|RDW_UPDATENOW|RDW_ALLCHILDREN|RDW_NOCHILDREN) )
-   {
-      /* RedrawWindow fails only in case that flags are invalid */
-      EngSetLastError(ERROR_INVALID_FLAGS);
-      RETURN( FALSE);
-   }
-
-   /* We can't hold lock on GDI obects while doing roundtrips to user mode,
-    * so use a copy instead */
-   if (hrgnUpdate)
-   {
-       PREGION RgnTemp;
-
-       RgnUpdate = IntSysCreateRectpRgn(0, 0, 0, 0);
-       if (!RgnUpdate)
-       {
-           EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
-           RETURN(FALSE);
-       }
-
-       RgnTemp = RGNOBJAPI_Lock(hrgnUpdate, NULL);
-       if (!RgnTemp)
-       {
-           EngSetLastError(ERROR_INVALID_HANDLE);
-           RETURN(FALSE);
-       }
-       IntGdiCombineRgn(RgnUpdate, RgnTemp, NULL, RGN_COPY);
-       RGNOBJAPI_Unlock(RgnTemp);
-   }
-
-   UserRefObjectCo(Wnd, &Ref);
-
-   Ret = co_UserRedrawWindow( Wnd,
-                              lprcUpdate ? &SafeUpdateRect : NULL,
-                              RgnUpdate,
-                              flags);
-
-   UserDerefObjectCo(Wnd);
-
-   RETURN( Ret);
-
-CLEANUP:
-    if (RgnUpdate)
-        REGION_Delete(RgnUpdate);
-   TRACE("Leave NtUserRedrawWindow, ret=%i\n",_ret_);
-   UserLeave();
-   END_CLEANUP;
+   return RegionType;
 }
 
-static
-INT FASTCALL
-UserScrollDC(
-   HDC hDC,
-   INT dx,
-   INT dy,
-   const RECTL *prcScroll,
-   const RECTL *prcClip,
-   PREGION RgnUpdate,
-   RECTL *prcUpdate)
+BOOL FASTCALL
+co_UserGetUpdateRect(PWND Window, PRECT pRect, BOOL bErase)
 {
-   PDC pDC;
-   RECTL rcScroll, rcClip, rcSrc, rcDst;
-   INT Result;
-
-   GdiGetClipBox(hDC, &rcClip);
-   rcScroll = rcClip;
-   if (prcClip)
-   {
-      RECTL_bIntersectRect(&rcClip, &rcClip, prcClip);
-   }
+   INT RegionType;
+   BOOL Ret = TRUE;
 
-   if (prcScroll)
-   {
-      rcScroll = *prcScroll;
-      RECTL_bIntersectRect(&rcSrc, &rcClip, prcScroll);
-   }
-   else
+   if (bErase)
    {
-      rcSrc = rcClip;
+      USER_REFERENCE_ENTRY Ref;
+      UserRefObjectCo(Window, &Ref);
+      co_IntPaintWindows(Window, RDW_NOCHILDREN, FALSE);
+      UserDerefObjectCo(Window);
    }
 
-   rcDst = rcSrc;
-   RECTL_vOffsetRect(&rcDst, dx, dy);
-   RECTL_bIntersectRect(&rcDst, &rcDst, &rcClip);
+   Window->state &= ~WNDS_UPDATEDIRTY;
 
-   if (!NtGdiBitBlt( hDC,
-                     rcDst.left,
-                     rcDst.top,
-                     rcDst.right - rcDst.left,
-                     rcDst.bottom - rcDst.top,
-                     hDC,
-                     rcDst.left - dx,
-                     rcDst.top - dy,
-                     SRCCOPY,
-                     0,
-                     0))
+   if (Window->hrgnUpdate == NULL)
    {
-      return ERROR;
+      pRect->left = pRect->top = pRect->right = pRect->bottom = 0;
+      Ret = FALSE;
    }
-
-   /* Calculate the region that was invalidated by moving or
-      could not be copied, because it was not visible */
-   if (RgnUpdate || prcUpdate)
+   else
    {
-      PREGION RgnOwn, RgnTmp;
-
-      pDC = DC_LockDc(hDC);
-      if (!pDC)
+      /* Get the update region bounding box. */
+      if (Window->hrgnUpdate == HRGN_WINDOW)
       {
-         return FALSE;
+         *pRect = Window->rcClient;
+         ERR("GURt: Caller is retrieving Window Region 1\n");
+      }
+      else
+      {
+         RegionType = IntGdiGetRgnBox(Window->hrgnUpdate, pRect);
+
+         if (RegionType != ERROR && RegionType != NULLREGION)
+            RECTL_bIntersectRect(pRect, pRect, &Window->rcClient);
       }
 
-      /* Begin with the shifted and then clipped scroll rect */
-      rcDst = rcScroll;
-      RECTL_vOffsetRect(&rcDst, dx, dy);
-      RECTL_bIntersectRect(&rcDst, &rcDst, &rcClip);
-      if (RgnUpdate)
+      if (IntIntersectWithParents(Window, pRect))
       {
-         RgnOwn = RgnUpdate;
-         REGION_SetRectRgn(RgnOwn, rcDst.left, rcDst.top, rcDst.right, rcDst.bottom);
+         if (Window != UserGetDesktopWindow()) // Window->fnid == FNID_DESKTOP
+         {
+            RECTL_vOffsetRect(pRect,
+                              -Window->rcClient.left,
+                              -Window->rcClient.top);
+         }
+         if (Window->pcls->style & CS_OWNDC)
+         {
+            HDC hdc;
+            //DWORD layout;
+            hdc = UserGetDCEx(Window, NULL, DCX_USESTYLE);
+            //layout = NtGdiSetLayout(hdc, -1, 0);
+            //IntMapWindowPoints( 0, Window, (LPPOINT)pRect, 2 );
+            GreDPtoLP( hdc, (LPPOINT)pRect, 2 );
+            //NtGdiSetLayout(hdc, -1, layout);
+            UserReleaseDC(Window, hdc, FALSE);
+         }
       }
       else
       {
-         RgnOwn = IntSysCreateRectpRgnIndirect(&rcDst);
+         pRect->left = pRect->top = pRect->right = pRect->bottom = 0;
       }
+   }
+   return Ret;
+}
 
-      /* Add the source rect */
-      RgnTmp = IntSysCreateRectpRgnIndirect(&rcSrc);
-      IntGdiCombineRgn(RgnOwn, RgnOwn, RgnTmp, RGN_OR);
+/*
+ * NtUserGetUpdateRgn
+ *
+ * Status
+ *    @implemented
+ */
 
-      /* Substract the part of the dest that was visible in source */
-      IntGdiCombineRgn(RgnTmp, RgnTmp, pDC->prgnVis, RGN_AND);
-      REGION_iOffsetRgn(RgnTmp, dx, dy);
-      Result = IntGdiCombineRgn(RgnOwn, RgnOwn, RgnTmp, RGN_DIFF);
+INT APIENTRY
+NtUserGetUpdateRgn(HWND hWnd, HRGN hRgn, BOOL bErase)
+{
+   DECLARE_RETURN(INT);
+   PWND Window;
+   INT ret;
 
-      /* DO NOT Unlock DC while messing with prgnVis! */
-      DC_UnlockDc(pDC);
+   TRACE("Enter NtUserGetUpdateRgn\n");
+   UserEnterExclusive();
 
-      REGION_Delete(RgnTmp);
+   if (!(Window = UserGetWindowObject(hWnd)))
+   {
+      RETURN(ERROR);
+   }
 
-      if (prcUpdate)
-      {
-         REGION_GetRgnBox(RgnOwn, prcUpdate);
-      }
+   ret = co_UserGetUpdateRgn(Window, hRgn, bErase);
 
-      if (!RgnUpdate)
-      {
-         REGION_Delete(RgnOwn);
-      }
-   }
-   else
-      Result = NULLREGION;
+   RETURN(ret);
 
-   return Result;
+CLEANUP:
+   TRACE("Leave NtUserGetUpdateRgn, ret=%i\n",_ret_);
+   UserLeave();
+   END_CLEANUP;
 }
 
 /*
- * NtUserScrollDC
+ * NtUserGetUpdateRect
  *
  * Status
  *    @implemented
  */
+
 BOOL APIENTRY
-NtUserScrollDC(
-   HDC hDC,
-   INT dx,
-   INT dy,
-   const RECT *prcUnsafeScroll,
-   const RECT *prcUnsafeClip,
-   HRGN hrgnUpdate,
-   LPRECT prcUnsafeUpdate)
+NtUserGetUpdateRect(HWND hWnd, LPRECT UnsafeRect, BOOL bErase)
 {
-   DECLARE_RETURN(DWORD);
-   RECTL rcScroll, rcClip, rcUpdate;
-   NTSTATUS Status = STATUS_SUCCESS;
-   DWORD Result;
-   PREGION RgnUpdate = NULL;
+   PWND Window;
+   RECTL Rect;
+   NTSTATUS Status;
+   BOOL Ret;
+   DECLARE_RETURN(BOOL);
 
-   TRACE("Enter NtUserScrollDC\n");
+   TRACE("Enter NtUserGetUpdateRect\n");
    UserEnterExclusive();
 
-   _SEH2_TRY
-   {
-      if (prcUnsafeScroll)
-      {
-         ProbeForRead(prcUnsafeScroll, sizeof(*prcUnsafeScroll), 1);
-         rcScroll = *prcUnsafeScroll;
-      }
-      if (prcUnsafeClip)
-      {
-         ProbeForRead(prcUnsafeClip, sizeof(*prcUnsafeClip), 1);
-         rcClip = *prcUnsafeClip;
-      }
-      if (prcUnsafeUpdate)
-      {
-         ProbeForWrite(prcUnsafeUpdate, sizeof(*prcUnsafeUpdate), 1);
-      }
-   }
-   _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-   {
-      Status = _SEH2_GetExceptionCode();
-   }
-   _SEH2_END
-   if (!NT_SUCCESS(Status))
+   if (!(Window = UserGetWindowObject(hWnd)))
    {
-      SetLastNtError(Status);
       RETURN(FALSE);
    }
 
-   if (hrgnUpdate)
-   {
-       RgnUpdate = RGNOBJAPI_Lock(hrgnUpdate, NULL);
-       if (!RgnUpdate)
-           RETURN(FALSE);
-   }
-
-   Result = UserScrollDC( hDC,
-                          dx,
-                          dy,
-                          prcUnsafeScroll? &rcScroll : 0,
-                          prcUnsafeClip? &rcClip : 0,
-                          RgnUpdate,
-                          prcUnsafeUpdate? &rcUpdate : NULL);
-   if(Result == ERROR)
-   {
-         /* FIXME: Only if hRgnUpdate is invalid we should SetLastError(ERROR_INVALID_HANDLE) */
-      RETURN(FALSE);
-   }
+   Ret = co_UserGetUpdateRect(Window, &Rect, bErase);
 
-   if (prcUnsafeUpdate)
+   if (UnsafeRect != NULL)
    {
-      _SEH2_TRY
-      {
-         *prcUnsafeUpdate = rcUpdate;
-      }
-      _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-      {
-         Status = _SEH2_GetExceptionCode();
-      }
-      _SEH2_END
+      Status = MmCopyToCaller(UnsafeRect, &Rect, sizeof(RECTL));
       if (!NT_SUCCESS(Status))
       {
-         /* FIXME: SetLastError? */
-         /* FIXME: correct? We have already scrolled! */
+         EngSetLastError(ERROR_INVALID_PARAMETER);
          RETURN(FALSE);
       }
    }
 
-   RETURN(TRUE);
+   RETURN(Ret);
 
 CLEANUP:
-   if (RgnUpdate)
-       RGNOBJAPI_Unlock(RgnUpdate);
-   TRACE("Leave NtUserScrollDC, ret=%lu\n",_ret_);
+   TRACE("Leave NtUserGetUpdateRect, ret=%i\n",_ret_);
    UserLeave();
    END_CLEANUP;
 }
 
 /*
- * NtUserScrollWindowEx
+ * NtUserRedrawWindow
  *
  * Status
  *    @implemented
  */
 
-DWORD APIENTRY
-NtUserScrollWindowEx(
+BOOL APIENTRY
+NtUserRedrawWindow(
    HWND hWnd,
-   INT dx,
-   INT dy,
-   const RECT *prcUnsafeScroll,
-   const RECT *prcUnsafeClip,
+   CONST RECT *lprcUpdate,
    HRGN hrgnUpdate,
-   LPRECT prcUnsafeUpdate,
    UINT flags)
 {
-   RECTL rcScroll, rcClip, rcCaret, rcUpdate;
-   INT Result;
-   PWND Window = NULL, CaretWnd;
-   HDC hDC;
-   PREGION RgnUpdate = NULL, RgnTemp, RgnWinupd = NULL;
-   HWND hwndCaret;
-   DWORD dcxflags = 0;
-   int rdw_flags;
+   RECTL SafeUpdateRect;
+   PWND Wnd;
+   BOOL Ret;
+   USER_REFERENCE_ENTRY Ref;
    NTSTATUS Status = STATUS_SUCCESS;
-   DECLARE_RETURN(DWORD);
-   USER_REFERENCE_ENTRY Ref, CaretRef;
+   PREGION RgnUpdate = NULL;
+   DECLARE_RETURN(BOOL);
 
-   TRACE("Enter NtUserScrollWindowEx\n");
+   TRACE("Enter NtUserRedrawWindow\n");
    UserEnterExclusive();
 
-   Window = UserGetWindowObject(hWnd);
-   if (!Window || !IntIsWindowDrawable(Window))
-   {
-      Window = NULL; /* prevent deref at cleanup */
-      RETURN( ERROR);
-   }
-   UserRefObjectCo(Window, &Ref);
-
-   IntGetClientRect(Window, &rcClip);
-
-   _SEH2_TRY
-   {
-      if (prcUnsafeScroll)
-      {
-         ProbeForRead(prcUnsafeScroll, sizeof(*prcUnsafeScroll), 1);
-         RECTL_bIntersectRect(&rcScroll, &rcClip, prcUnsafeScroll);
-      }
-      else
-         rcScroll = rcClip;
-
-      if (prcUnsafeClip)
-      {
-         ProbeForRead(prcUnsafeClip, sizeof(*prcUnsafeClip), 1);
-         RECTL_bIntersectRect(&rcClip, &rcClip, prcUnsafeClip);
-      }
-   }
-   _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-   {
-      Status = _SEH2_GetExceptionCode();
-   }
-   _SEH2_END
-
-   if (!NT_SUCCESS(Status))
-   {
-      SetLastNtError(Status);
-      RETURN(ERROR);
-   }
-
-   if (rcClip.right <= rcClip.left || rcClip.bottom <= rcClip.top ||
-         (dx == 0 && dy == 0))
-   {
-      RETURN(NULLREGION);
-   }
-
-   /* We must use a copy of the region, as we can't hold an exclusive lock
-    * on it while doing callouts to user-mode */
-   RgnUpdate = IntSysCreateRectpRgn(0, 0, 0, 0);
-   if(!RgnUpdate)
-   {
-       EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
-       RETURN(ERROR);
-   }
-
-   if (hrgnUpdate)
-   {
-       RgnTemp = RGNOBJAPI_Lock(hrgnUpdate, NULL);
-       if (!RgnTemp)
-       {
-           EngSetLastError(ERROR_INVALID_HANDLE);
-           RETURN(ERROR);
-       }
-       IntGdiCombineRgn(RgnUpdate, RgnTemp, NULL, RGN_COPY);
-       RGNOBJAPI_Unlock(RgnTemp);
-   }
-
-   /* ScrollWindow uses the window DC, ScrollWindowEx doesn't */
-   if (flags & SW_SCROLLWNDDCE)
-   {
-      dcxflags = DCX_USESTYLE;
-
-      if (!(Window->pcls->style & (CS_OWNDC|CS_CLASSDC)))
-         dcxflags |= DCX_CACHE; // AH??? wine~ If not Powned or with Class go Cheap!
-
-      if (flags & SW_SCROLLCHILDREN && Window->style & WS_CLIPCHILDREN)
-         dcxflags |= DCX_CACHE|DCX_NOCLIPCHILDREN;
-   }
-   else
-   {
-       /* So in this case ScrollWindowEx uses Cache DC. */
-       dcxflags = DCX_CACHE|DCX_USESTYLE;
-       if (flags & SW_SCROLLCHILDREN) dcxflags |= DCX_NOCLIPCHILDREN;
-   }
-
-   hDC = UserGetDCEx(Window, 0, dcxflags);
-   if (!hDC)
-   {
-      /* FIXME: SetLastError? */
-      RETURN(ERROR);
-   }
-
-   rdw_flags = (flags & SW_ERASE) && (flags & SW_INVALIDATE) ? RDW_INVALIDATE | RDW_ERASE  : RDW_INVALIDATE ;
-
-   rcCaret = rcScroll;
-   hwndCaret = co_IntFixCaret(Window, &rcCaret, flags);
-
-   Result = UserScrollDC( hDC,
-                          dx,
-                          dy,
-                          &rcScroll,
-                          &rcClip,
-                          RgnUpdate,
-                          prcUnsafeUpdate? &rcUpdate : NULL);
-
-   UserReleaseDC(Window, hDC, FALSE);
-
-   /*
-    * Take into account the fact that some damage may have occurred during
-    * the scroll. Keep a copy in hrgnWinupd to be added to hrngUpdate at the end.
-    */
-
-   RgnTemp = IntSysCreateRectpRgn(0, 0, 0, 0);
-   if (!RgnTemp)
-   {
-       EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
-       RETURN(ERROR);
-   }
-
-   if (co_UserGetUpdateRgn(Window, RgnTemp, FALSE) != NULLREGION)
-   {
-      PREGION RgnClip = IntSysCreateRectpRgnIndirect(&rcClip);
-      if (RgnClip)
-      {
-          if (hrgnUpdate)
-          {
-             RgnWinupd = IntSysCreateRectpRgn( 0, 0, 0, 0);
-             IntGdiCombineRgn( RgnWinupd, RgnTemp, 0, RGN_COPY);
-          }
-          REGION_iOffsetRgn(RgnTemp, dx, dy);
-          IntGdiCombineRgn(RgnTemp, RgnTemp, RgnClip, RGN_AND);
-          if (hrgnUpdate)
-              IntGdiCombineRgn( RgnWinupd, RgnWinupd, RgnTemp, RGN_OR );
-          co_UserRedrawWindow(Window, NULL, RgnTemp, rdw_flags );
-          REGION_Delete(RgnClip);
-      }
-   }
-   REGION_Delete(RgnTemp);
-
-   if (flags & SW_SCROLLCHILDREN)
-   {
-      PWND Child;
-      RECTL rcChild;
-      POINT ClientOrigin;
-      USER_REFERENCE_ENTRY WndRef;
-      RECTL rcDummy;
-
-      IntGetClientOrigin(Window, &ClientOrigin);
-      for (Child = Window->spwndChild; Child; Child = Child->spwndNext)
-      {
-         rcChild = Child->rcWindow;
-         rcChild.left -= ClientOrigin.x;
-         rcChild.top -= ClientOrigin.y;
-         rcChild.right -= ClientOrigin.x;
-         rcChild.bottom -= ClientOrigin.y;
-
-         if (! prcUnsafeScroll || RECTL_bIntersectRect(&rcDummy, &rcChild, &rcScroll))
-         {
-            UserRefObjectCo(Child, &WndRef);
-            co_WinPosSetWindowPos(Child, 0, rcChild.left + dx, rcChild.top + dy, 0, 0,
-                                  SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE |
-                                  SWP_NOREDRAW | SWP_DEFERERASE);
-            UserDerefObjectCo(Child);
-         }
-      }
-   }
-
-   if (flags & (SW_INVALIDATE | SW_ERASE))
-   {
-      co_UserRedrawWindow(Window, NULL, RgnUpdate, rdw_flags |
-                          ((flags & SW_ERASE) ? RDW_ERASENOW : 0) |
-                          ((flags & SW_SCROLLCHILDREN) ? RDW_ALLCHILDREN : 0));
-   }
-
-   if (hwndCaret && (CaretWnd = UserGetWindowObject(hwndCaret)))
+   if (!(Wnd = UserGetWindowObject(hWnd ? hWnd : IntGetDesktopWindow())))
    {
-      UserRefObjectCo(CaretWnd, &CaretRef);
-
-      co_IntSetCaretPos(rcCaret.left + dx, rcCaret.top + dy);
-      co_UserShowCaret(CaretWnd);
-
-      UserDerefObjectCo(CaretWnd);
+      RETURN( FALSE);
    }
 
-   if (prcUnsafeUpdate)
+   if (lprcUpdate)
    {
       _SEH2_TRY
       {
-         /* Probe here, to not fail on invalid pointer before scrolling */
-         ProbeForWrite(prcUnsafeUpdate, sizeof(*prcUnsafeUpdate), 1);
-         *prcUnsafeUpdate = rcUpdate;
+          ProbeForRead(lprcUpdate, sizeof(RECTL), 1);
+          RtlCopyMemory(&SafeUpdateRect, lprcUpdate, sizeof(RECTL));
       }
       _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
       {
          Status = _SEH2_GetExceptionCode();
       }
       _SEH2_END
-
       if (!NT_SUCCESS(Status))
       {
-         SetLastNtError(Status);
-         RETURN(ERROR);
+         EngSetLastError(RtlNtStatusToDosError(Status));
+         RETURN( FALSE);
       }
    }
 
-   RETURN(Result);
-
-CLEANUP:
-   if (hrgnUpdate && (_ret_ != ERROR))
+   if ( flags & ~(RDW_ERASE|RDW_FRAME|RDW_INTERNALPAINT|RDW_INVALIDATE|
+                  RDW_NOERASE|RDW_NOFRAME|RDW_NOINTERNALPAINT|RDW_VALIDATE|
+                  RDW_ERASENOW|RDW_UPDATENOW|RDW_ALLCHILDREN|RDW_NOCHILDREN) )
    {
-       /* Give everything back to the caller */
-       RgnTemp = RGNOBJAPI_Lock(hrgnUpdate, NULL);
-       /* The handle should still be valid */
-       ASSERT(RgnTemp);
-       if (RgnWinupd)
-           IntGdiCombineRgn(RgnTemp, RgnUpdate, RgnWinupd, RGN_OR);
-       else
-           IntGdiCombineRgn(RgnTemp, RgnUpdate, NULL, RGN_COPY);
-       RGNOBJAPI_Unlock(RgnTemp);
+      /* RedrawWindow fails only in case that flags are invalid */
+      EngSetLastError(ERROR_INVALID_FLAGS);
+      RETURN( FALSE);
    }
 
-   if (RgnWinupd)
+   /* We can't hold lock on GDI objects while doing roundtrips to user mode,
+    * so it will be copied.
+    */
+   if (hrgnUpdate > HRGN_WINDOW)
    {
-       REGION_Delete(RgnWinupd);
+       RgnUpdate = REGION_LockRgn(hrgnUpdate);
+       if (!RgnUpdate)
+       {
+           EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
+           RETURN(FALSE);
+       }
+       REGION_UnlockRgn(RgnUpdate);
    }
-
-   if (RgnUpdate)
+   else if (hrgnUpdate == HRGN_WINDOW) // Trap it out.
    {
-      REGION_Delete(RgnUpdate);
+       ERR("NTRW: Caller is passing Window Region 1\n");
    }
 
-   if (Window)
-      UserDerefObjectCo(Window);
+   UserRefObjectCo(Wnd, &Ref);
+
+   Ret = co_UserRedrawWindow( Wnd,
+                              lprcUpdate ? &SafeUpdateRect : NULL,
+                              RgnUpdate,
+                              flags);
 
-   TRACE("Leave NtUserScrollWindowEx, ret=%lu\n",_ret_);
+   UserDerefObjectCo(Wnd);
+
+   RETURN( Ret);
+
+CLEANUP:
+   TRACE("Leave NtUserRedrawWindow, ret=%i\n",_ret_);
    UserLeave();
    END_CLEANUP;
 }
 
 BOOL
 UserDrawCaptionText(
+   PWND pWnd,
    HDC hDc,
    const PUNICODE_STRING Text,
    const RECTL *lpRc,
@@ -1975,12 +1998,14 @@ UserDrawCaptionText(
    NTSTATUS Status;
    BOOLEAN bDeleteFont = FALSE;
    SIZE Size;
+   BOOL Ret = TRUE;
+   ULONG fit = 0, Length;
+   RECTL r = *lpRc;
 
    TRACE("UserDrawCaptionText: %wZ\n", Text);
 
    nclm.cbSize = sizeof(nclm);
-   if(!UserSystemParametersInfo(SPI_GETNONCLIENTMETRICS,
-      sizeof(NONCLIENTMETRICS), &nclm, 0))
+   if (!UserSystemParametersInfo(SPI_GETNONCLIENTMETRICS, nclm.cbSize, &nclm, 0))
    {
       ERR("UserSystemParametersInfo() failed!\n");
       return FALSE;
@@ -2005,33 +2030,68 @@ UserDrawCaptionText(
    IntGdiSetBkMode(hDc, TRANSPARENT);
 
    hOldFont = NtGdiSelectFont(hDc, hFont);
-   if(!hOldFont)
-   {
-      ERR("SelectFont() failed!\n");
-      /* Don't fail */
-   }
 
    if(uFlags & DC_INBUTTON)
       OldTextColor = IntGdiSetTextColor(hDc, IntGetSysColor(COLOR_BTNTEXT));
    else
-      OldTextColor = IntGdiSetTextColor(hDc, IntGetSysColor(uFlags & DC_ACTIVE
-         ? COLOR_CAPTIONTEXT : COLOR_INACTIVECAPTIONTEXT));
+      OldTextColor = IntGdiSetTextColor(hDc,
+                                        IntGetSysColor(uFlags & DC_ACTIVE ? COLOR_CAPTIONTEXT : COLOR_INACTIVECAPTIONTEXT));
+
+   // Adjust for system menu.
+   if (pWnd && pWnd->style & WS_SYSMENU)
+   {
+      r.right -= UserGetSystemMetrics(SM_CYCAPTION) - 1;
+      if ((pWnd->style & (WS_MAXIMIZEBOX | WS_MINIMIZEBOX)) && !(pWnd->ExStyle & WS_EX_TOOLWINDOW))
+      {
+         r.right -= UserGetSystemMetrics(SM_CXSIZE) + 1;
+         r.right -= UserGetSystemMetrics(SM_CXSIZE) + 1;
+      }
+   }
+
+   GreGetTextExtentExW(hDc, Text->Buffer, Text->Length/sizeof(WCHAR), r.right - r.left, &fit, 0, &Size, 0);
 
-   // FIXME: If string doesn't fit to rc, truncate it and add ellipsis.
-   GreGetTextExtentW(hDc, Text->Buffer, Text->Length/sizeof(WCHAR), &Size, 0);
-   GreExtTextOutW(hDc,
-                  lpRc->left, (lpRc->top + lpRc->bottom)/2 - Size.cy/2,
-                  0, NULL, Text->Buffer, Text->Length/sizeof(WCHAR), NULL, 0);
+   Length = (Text->Length/sizeof(WCHAR) == fit ? fit : fit+1);
 
+   if (Text->Length/sizeof(WCHAR) > Length)
+   {
+      Ret = FALSE;
+   }
+
+   if (Ret)
+   {  // Faster while in setup.
+      GreExtTextOutW( hDc,
+                      lpRc->left,
+                      lpRc->top + (lpRc->bottom - lpRc->top) / 2 - Size.cy / 2, // DT_SINGLELINE && DT_VCENTER
+                      ETO_CLIPPED,
+                     (RECTL *)lpRc,
+                      Text->Buffer,
+                      Length,
+                      NULL,
+                      0 );
+   }
+   else
+   {
+      DrawTextW( hDc,
+                 Text->Buffer,
+                 Text->Length/sizeof(WCHAR),
+                (RECTL *)&r,
+                 DT_END_ELLIPSIS|DT_SINGLELINE|DT_VCENTER|DT_NOPREFIX|DT_LEFT);
+   }
    IntGdiSetTextColor(hDc, OldTextColor);
+
    if (hOldFont)
       NtGdiSelectFont(hDc, hOldFont);
+
    if (bDeleteFont)
       GreDeleteObject(hFont);
 
-   return TRUE;
+   return Ret;
 }
 
+//
+// This draws Buttons, Icons and Text...
+//
 BOOL UserDrawCaption(
    PWND pWnd,
    HDC hDc,
@@ -2048,14 +2108,14 @@ BOOL UserDrawCaption(
 
    RECTL_vMakeWellOrdered(lpRc);
 
+   /* Determine whether the icon needs to be displayed */
    if (!hIcon && pWnd != NULL)
    {
-     HasIcon = (uFlags & DC_ICON) && (pWnd->style & WS_SYSMENU)
-        && !(uFlags & DC_SMALLCAP) && !(pWnd->ExStyle & WS_EX_DLGMODALFRAME)
-        && !(pWnd->ExStyle & WS_EX_TOOLWINDOW);
+     HasIcon = (uFlags & DC_ICON) && !(uFlags & DC_SMALLCAP) &&
+               (pWnd->style & WS_SYSMENU) && !(pWnd->ExStyle & WS_EX_TOOLWINDOW);
    }
    else
-     HasIcon = (hIcon != 0);
+     HasIcon = (hIcon != NULL);
 
    // Draw the caption background
    if((uFlags & DC_GRADIENT) && !(uFlags & DC_INBUTTON))
@@ -2139,7 +2199,7 @@ BOOL UserDrawCaption(
          LONG cx = UserGetSystemMetrics(SM_CXSMICON);
          LONG cy = UserGetSystemMetrics(SM_CYSMICON);
          LONG x = Rect.left - cx/2 + 1 + (Rect.bottom - Rect.top)/2; // this is really what Window does
-         LONG y = (Rect.top + Rect.bottom)/2 - cy/2; // center
+         LONG y = (Rect.top + Rect.bottom - cy)/2; // center
          UserDrawIconEx(hDc, x, y, pIcon, cx, cy, 0, NULL, DI_NORMAL);
          UserDereferenceObject(pIcon);
       }
@@ -2154,17 +2214,25 @@ BOOL UserDrawCaption(
 
    if((uFlags & DC_TEXT))
    {
+      BOOL Set = FALSE;
       Rect.left += 2;
 
       if (Str)
-         UserDrawCaptionText(hDc, Str, &Rect, uFlags, hFont);
+         Set = UserDrawCaptionText(pWnd, hDc, Str, &Rect, uFlags, hFont);
       else if (pWnd != NULL) // FIXME: Windows does not do that
       {
          UNICODE_STRING ustr;
          ustr.Buffer = pWnd->strName.Buffer; // FIXME: LARGE_STRING truncated!
          ustr.Length = (USHORT)min(pWnd->strName.Length, MAXUSHORT);
          ustr.MaximumLength = (USHORT)min(pWnd->strName.MaximumLength, MAXUSHORT);
-         UserDrawCaptionText(hDc, &ustr, &Rect, uFlags, hFont);
+         Set = UserDrawCaptionText(pWnd, hDc, &ustr, &Rect, uFlags, hFont);
+      }
+      if (pWnd)
+      {
+         if (Set)
+            pWnd->state2 &= ~WNDS2_CAPTIONTEXTTRUNCATED;
+         else
+            pWnd->state2 |= WNDS2_CAPTIONTEXTTRUNCATED;
       }
    }
 
@@ -2263,8 +2331,26 @@ NtUserDrawCaptionTemp(
    if (str != NULL)
       Ret = UserDrawCaption(pWnd, hDC, &SafeRect, hFont, hIcon, &SafeStr, uFlags);
    else
+   {
+      if ( RECTL_bIsEmptyRect(&SafeRect) && hFont == 0 && hIcon == 0 )
+      {
+         Ret = TRUE;
+         if (uFlags & DC_DRAWCAPTIONMD)
+         {
+            ERR("NC Caption Mode\n");
+            UserDrawCaptionBar(pWnd, hDC, uFlags);
+            goto Exit;
+         }
+         else if (uFlags & DC_DRAWFRAMEMD)
+         {
+            ERR("NC Paint Mode\n");
+            NC_DoNCPaint(pWnd, hDC, uFlags); // Update Menus too!
+            goto Exit;
+         }
+      }
       Ret = UserDrawCaption(pWnd, hDC, &SafeRect, hFont, hIcon, NULL, uFlags);
-
+   }
+Exit:
    UserLeave();
    return Ret;
 }
@@ -2276,7 +2362,7 @@ NtUserDrawCaption(HWND hWnd,
    LPCRECT lpRc,
    UINT uFlags)
 {
-       return NtUserDrawCaptionTemp(hWnd, hDC, lpRc, 0, 0, NULL, uFlags);
+   return NtUserDrawCaptionTemp(hWnd, hDC, lpRc, 0, 0, NULL, uFlags);
 }
 
 BOOL