[Win32SS]
authorJames Tabor <james.tabor@reactos.org>
Sat, 18 Aug 2012 00:59:35 +0000 (00:59 +0000)
committerJames Tabor <james.tabor@reactos.org>
Sat, 18 Aug 2012 00:59:35 +0000 (00:59 +0000)
- Fixed skip test regression in User32 Win wine test.
- Regressed one scroll control test. AbiWord scrolls and Explorer redraw issue still
the same.
- WIP: Rearranged code for standard structures prior to moving scroll code to Win32k. Proc support will remain in User32 (A2W etc) and redirected to Win32k. Drawing support will be added when this switch is made. Then ReactOS will have 100 percent wine scrolls plus our fixes in one file.

svn path=/trunk/; revision=57091

reactos/include/reactos/undocuser.h
reactos/win32ss/user/ntuser/message.c
reactos/win32ss/user/ntuser/scrollbar.c
reactos/win32ss/user/user32/controls/scrollbar.c

index 14002b7..c0c6b53 100644 (file)
@@ -68,6 +68,9 @@
 #define SWP_NOCLIENTMOVE 0x1000
 #define SWP_STATECHANGED 0x8000
 
+/* NtUserSetScrollInfo mask to return original position before it is change */
+#define SIF_PREVIOUSPOS 4096
+
 /* Non SDK Queue state flags. */
 #define QS_SMRESULT 0x8000 /* see "Undoc. Windows" */
 
index 05e9dab..479e951 100644 (file)
@@ -608,7 +608,7 @@ static LRESULT handle_internal_message( PWND pWnd, UINT msg, WPARAM wparam, LPAR
          pWnd == UserGetMessageWindow() )  // pWnd->fnid == FNID_MESSAGEWND
        return 0;
 
-    TRACE("Internal Event Msg %p\n",msg);
+    TRACE("Internal Event Msg %p hWnd 0x%x\n",msg,pWnd->head.h);
 
     switch(msg)
     {
@@ -742,7 +742,6 @@ co_IntPeekMessage( PMSG Msg,
                    BOOL bGMSG )
 {
     PTHREADINFO pti;
-    //PCLIENTINFO pci;
     LARGE_INTEGER LargeTickCount;
     PUSER_MESSAGE_QUEUE ThreadQueue;
     BOOL RemoveMessages;
@@ -751,11 +750,15 @@ co_IntPeekMessage( PMSG Msg,
 
     pti = PsGetCurrentThreadWin32Thread();
     ThreadQueue = pti->MessageQueue;
-    //pci = pti->pClientInfo;
 
     RemoveMessages = RemoveMsg & PM_REMOVE;
     ProcessMask = HIWORD(RemoveMsg);
 
+    if (ThreadQueue->ptiSysLock && ThreadQueue->ptiSysLock != pti)
+    {
+       ERR("PeekMessage: Thread Q 0x%p is locked 0x%p to another pti 0x%p!\n", ThreadQueue, ThreadQueue->ptiSysLock, pti );
+    }
+
  /* Hint, "If wMsgFilterMin and wMsgFilterMax are both zero, PeekMessage returns
     all available messages (that is, no range filtering is performed)".        */
     if (!ProcessMask) ProcessMask = (QS_ALLPOSTMESSAGE|QS_ALLINPUT);
@@ -1182,6 +1185,7 @@ UserPostMessage( HWND Wnd,
         Window = UserGetWindowObject(Wnd);
         if ( !Window )
         {
+            ERR("UserPostMessage: Invalid handle 0x%p!\n",Wnd);
             return FALSE;
         }
 
@@ -1246,6 +1250,7 @@ co_IntSendMessageTimeoutSingle( HWND hWnd,
 
     if (!(Window = UserGetWindowObject(hWnd)))
     {
+        TRACE("SendMessageTimeoutSingle: Invalid handle 0x%p!\n",hWnd);
         RETURN( FALSE);
     }
 
@@ -1491,6 +1496,7 @@ co_IntSendMessageWithCallBack( HWND hWnd,
 
     if (!(Window = UserGetWindowObject(hWnd)))
     {
+        TRACE("SendMessageWithCallBack: Invalid handle 0x%p!\n",hWnd);
         RETURN(FALSE);
     }
 
@@ -1514,6 +1520,8 @@ co_IntSendMessageWithCallBack( HWND hWnd,
     if (Msg & 0x80000000 &&
         Window->head.pti->MessageQueue == Win32Thread->MessageQueue)
     {
+       if (Win32Thread->TIF_flags & TIF_INCLEANUP) RETURN( FALSE);
+
        ERR("SMWCB: Internal Message!\n");
        Result = (ULONG_PTR)handle_internal_message( Window, Msg, wParam, lParam );
        if (uResult) *uResult = Result;
@@ -1650,6 +1658,7 @@ co_IntPostOrSendMessage( HWND hWnd,
 
     if(!(Window = UserGetWindowObject(hWnd)))
     {
+        TRACE("PostOrSendMessage: Invalid handle 0x%p!\n",hWnd);
         return 0;
     }
 
@@ -2158,6 +2167,8 @@ NtUserTranslateMessage(LPMSG lpMsg, UINT flags)
     return Ret;
 }
 
+LRESULT APIENTRY ScrollBarWndProc(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam);
+
 BOOL APIENTRY
 NtUserMessageCall( HWND hWnd,
                    UINT Msg,
@@ -2178,18 +2189,7 @@ NtUserMessageCall( HWND hWnd,
     {
     case FNID_SCROLLBAR:
         {
-           switch(Msg)
-           {
-               case WM_ENABLE:
-                  {
-                     Window = UserGetWindowObject(hWnd);
-                     if (Window->pSBInfo)
-                     {
-                        Window->pSBInfo->WSBflags = wParam ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH;
-                     }
-                  }
-                  break;
-           }
+           lResult = ScrollBarWndProc(hWnd, Msg, wParam, lParam);
            break;
         }
     case FNID_DEFWINDOWPROC:
@@ -2675,6 +2675,7 @@ NtUserMessageCall( HWND hWnd,
     case FNID_DEFWINDOWPROC:
     case FNID_CALLWNDPROC:
     case FNID_CALLWNDPROCRET:
+    case FNID_SCROLLBAR:
         if (ResultInfo)
         {
             _SEH2_TRY
index c31dcf2..775a543 100644 (file)
@@ -38,42 +38,94 @@ DBG_DEFAULT_CHANNEL(UserScrollbar);
  * 'thumbSize' returns the size of the thumb, and 'thumbPos' returns the position of the thumb relative to the left or to
  * the top. Return TRUE if the scrollbar is vertical, FALSE if horizontal.
  */
+static inline void mirror_rect( const RECT *window_rect, RECT *rect )
+{
+    int width = window_rect->right - window_rect->left;
+    int tmp = rect->left;
+    rect->left = width - rect->right;
+    rect->right = width - tmp;
+}
+
+PSBDATA FASTCALL
+IntGetSBData(PWND pwnd, INT Bar)
+{
+   PSBWND pSBWnd;
+   PSBINFO pSBInfo;
+
+   pSBInfo = pwnd->pSBInfo;
+   switch (Bar)
+   {
+       case SB_HORZ:
+         return &pSBInfo->Horz;
+       case SB_VERT:
+         return &pSBInfo->Vert;
+       case SB_CTL:
+         if ( pwnd->cbwndExtra != (sizeof(SBWND)-sizeof(WND)) )
+         {
+            ERR("IntGetSBData Wrong Extra bytes for CTL Scrollbar!\n");
+            return 0;
+         }
+         pSBWnd = (PSBWND)pwnd;
+         return (PSBDATA)&pSBWnd->SBCalc;
+       default:
+            ERR("IntGetSBData Bad Bar!\n");
+   }
+   return NULL;
+}
+
 BOOL FASTCALL
 IntGetScrollBarRect (PWND Wnd, INT nBar, RECTL *lprect)
 {
    BOOL vertical;
-   RECTL ClientRect = Wnd->rcClient;
-   RECTL WindowRect = Wnd->rcWindow;
+   *lprect = Wnd->rcClient;
+
+   RECTL_vOffsetRect( lprect, -Wnd->rcWindow.left, -Wnd->rcWindow.top );
+   if (Wnd->ExStyle & WS_EX_LAYOUTRTL)
+      mirror_rect( &Wnd->rcWindow, lprect );
 
    switch (nBar)
    {
       case SB_HORZ:
-         lprect->left = ClientRect.left - WindowRect.left;
-         lprect->top = ClientRect.bottom - WindowRect.top;
-         lprect->right = ClientRect.right - WindowRect.left;
-         lprect->bottom = lprect->top + UserGetSystemMetrics (SM_CYHSCROLL);
+         lprect->top = lprect->bottom;
+         lprect->bottom += UserGetSystemMetrics (SM_CYHSCROLL);
+         if (Wnd->style & WS_BORDER)
+         {
+            lprect->left--; 
+            lprect->right++;
+         }
+         else if (Wnd->style & WS_VSCROLL)
+         {
+            lprect->right++;
+         }
          vertical = FALSE;
          break;
 
       case SB_VERT:
          if(Wnd->ExStyle & WS_EX_LEFTSCROLLBAR)
          {
-            lprect->right = ClientRect.left - WindowRect.left;
-            lprect->left = lprect->right - UserGetSystemMetrics(SM_CXVSCROLL);
+            lprect->right = lprect->right;;
+            lprect->left -= UserGetSystemMetrics(SM_CXVSCROLL);
          }
          else
          {
-            lprect->left = ClientRect.right - WindowRect.left;
-            lprect->right = lprect->left + UserGetSystemMetrics(SM_CXVSCROLL);
+            lprect->left = lprect->right;
+            lprect->right += UserGetSystemMetrics(SM_CXVSCROLL);
+         }
+         if (Wnd->style & WS_BORDER)
+         {
+            lprect->top--;   
+            lprect->bottom++;
+         }
+         else if (Wnd->style & WS_HSCROLL)
+         {
+            lprect->bottom++;
          }
-         lprect->top = ClientRect.top - WindowRect.top;
-         lprect->bottom = ClientRect.bottom - WindowRect.top;
          vertical = TRUE;
          break;
 
       case SB_CTL:
          IntGetClientRect (Wnd, lprect);
-         vertical = ((Wnd->style & SBS_VERT) != 0);
+         vertical = !!(Wnd->style & SBS_VERT);
          break;
 
       default:
@@ -84,7 +136,7 @@ IntGetScrollBarRect (PWND Wnd, INT nBar, RECTL *lprect)
 }
 
 BOOL FASTCALL
-IntCalculateThumb(PWND Wnd, LONG idObject, PSCROLLBARINFO psbi, LPSCROLLINFO psi)
+IntCalculateThumb(PWND Wnd, LONG idObject, PSCROLLBARINFO psbi, PSBDATA pSBData)
 {
    INT Thumb, ThumbBox, ThumbPos, cxy, mx;
    RECTL ClientRect;
@@ -127,20 +179,20 @@ IntCalculateThumb(PWND Wnd, LONG idObject, PSCROLLBARINFO psbi, LPSCROLLINFO psi
    }
    else
    {
-      ThumbBox = psi->nPage ? MINTRACKTHUMB : UserGetSystemMetrics(SM_CXHTHUMB);
+      ThumbBox = pSBData->page ? MINTRACKTHUMB : UserGetSystemMetrics(SM_CXHTHUMB);
       cxy -= (2 * Thumb);
       if(cxy >= ThumbBox)
       {
-         if(psi->nPage)
+         if(pSBData->page)
          {
-            ThumbBox = max(EngMulDiv(cxy, psi->nPage, psi->nMax - psi->nMin + 1), ThumbBox);
+            ThumbBox = max(EngMulDiv(cxy, pSBData->page, pSBData->posMax - pSBData->posMin + 1), ThumbBox);
          }
 
          if(cxy > ThumbBox)
          {
-            mx = psi->nMax - max(psi->nPage - 1, 0);
-            if(psi->nMin < mx)
-               ThumbPos = Thumb + EngMulDiv(cxy - ThumbBox, psi->nPos - psi->nMin, mx - psi->nMin);
+            mx = pSBData->posMax - max(pSBData->page - 1, 0);
+            if(pSBData->posMin < mx)
+               ThumbPos = Thumb + EngMulDiv(cxy - ThumbBox, pSBData->pos - pSBData->posMin, mx - pSBData->posMin);
             else
                ThumbPos = Thumb + ThumbBox;
          }
@@ -158,25 +210,25 @@ IntCalculateThumb(PWND Wnd, LONG idObject, PSCROLLBARINFO psbi, LPSCROLLINFO psi
 
    return TRUE;
 }
-
+/*
 static VOID FASTCALL
 IntUpdateSBInfo(PWND Window, int wBar)
 {
    PSCROLLBARINFO sbi;
-   LPSCROLLINFO psi;
+   PSBDATA pSBData;
 
    ASSERT(Window);
    ASSERT(Window->pSBInfo);
    ASSERT(Window->pSBInfoex);
 
    sbi = IntGetScrollbarInfoFromWindow(Window, wBar);
-   psi = IntGetScrollInfoFromWindow(Window, wBar);
+   pSBData = IntGetSBData(Window, wBar);
    IntGetScrollBarRect(Window, wBar, &(sbi->rcScrollBar));
-   IntCalculateThumb(Window, wBar, sbi, psi);
+   IntCalculateThumb(Window, wBar, sbi, pSBData);
 }
-
+*/
 static BOOL FASTCALL
-co_IntGetScrollInfo(PWND Window, INT nBar, LPSCROLLINFO lpsi)
+co_IntGetScrollInfo(PWND Window, INT nBar, PSBDATA pSBData, LPSCROLLINFO lpsi)
 {
    UINT Mask;
    LPSCROLLINFO psi;
@@ -190,7 +242,11 @@ co_IntGetScrollInfo(PWND Window, INT nBar, LPSCROLLINFO lpsi)
       return FALSE;
    }
 
-   if (!Window->pSBInfo) return FALSE;
+   if (!Window->pSBInfo)
+   {
+      ERR("IntGetScrollInfo No window scrollbar info!\n");
+      return FALSE;
+   }
 
    psi = IntGetScrollInfoFromWindow(Window, nBar);
 
@@ -288,6 +344,8 @@ co_IntSetScrollInfo(PWND Window, INT nBar, LPCSCROLLINFO lpsi, BOOL bRedraw)
    PSCROLLBARINFO psbi;
    UINT new_flags;
    INT action = 0;
+   PSBDATA pSBData;
+   DWORD OldPos;
    BOOL bChangeParams = FALSE; /* Don't show/hide scrollbar if params don't change */
 
    ASSERT_REFS_CO(Window);
@@ -310,7 +368,7 @@ co_IntSetScrollInfo(PWND Window, INT nBar, LPCSCROLLINFO lpsi, BOOL bRedraw)
       EngSetLastError(ERROR_INVALID_PARAMETER);
       return 0;
    }
-   if (lpsi->fMask & ~(SIF_ALL | SIF_DISABLENOSCROLL))
+   if (lpsi->fMask & ~(SIF_ALL | SIF_DISABLENOSCROLL | SIF_PREVIOUSPOS))
    {
       EngSetLastError(ERROR_INVALID_PARAMETER);
       return 0;
@@ -318,6 +376,7 @@ co_IntSetScrollInfo(PWND Window, INT nBar, LPCSCROLLINFO lpsi, BOOL bRedraw)
 
    psbi = IntGetScrollbarInfoFromWindow(Window, nBar);
    Info = IntGetScrollInfoFromWindow(Window, nBar);
+   pSBData = IntGetSBData(Window, nBar);
 
    /* Set the page size */
    if (lpsi->fMask & SIF_PAGE)
@@ -325,6 +384,7 @@ co_IntSetScrollInfo(PWND Window, INT nBar, LPCSCROLLINFO lpsi, BOOL bRedraw)
       if (Info->nPage != lpsi->nPage)
       {
          Info->nPage = lpsi->nPage;
+         pSBData->page = lpsi->nPage;
          bChangeParams = TRUE;
       }
    }
@@ -334,7 +394,9 @@ co_IntSetScrollInfo(PWND Window, INT nBar, LPCSCROLLINFO lpsi, BOOL bRedraw)
    {
       if (Info->nPos != lpsi->nPos)
       {
+         OldPos = Info->nPos;
          Info->nPos = lpsi->nPos;
+         pSBData->pos = lpsi->nPos;
          bChangeParams = TRUE;
       }
    }
@@ -348,32 +410,38 @@ co_IntSetScrollInfo(PWND Window, INT nBar, LPCSCROLLINFO lpsi, BOOL bRedraw)
       {
          Info->nMin = 0;
          Info->nMax = 0;
+         pSBData->posMin = 0;
+         pSBData->posMax = 0;
          bChangeParams = TRUE;
       }
       else if (Info->nMin != lpsi->nMin || Info->nMax != lpsi->nMax)
       {
          Info->nMin = lpsi->nMin;
          Info->nMax = lpsi->nMax;
+         pSBData->posMin = lpsi->nMin;
+         pSBData->posMax = lpsi->nMax;
          bChangeParams = TRUE;
       }
    }
 
    /* Make sure the page size is valid */
    if (Info->nPage < 0)
-      Info->nPage = 0;
+   {
+      pSBData->page = Info->nPage = 0;
+   }
    else if ((Info->nMax - Info->nMin + 1UL) < Info->nPage)
    {
-      Info->nPage = Info->nMax - Info->nMin + 1;
+      pSBData->page = Info->nPage = Info->nMax - Info->nMin + 1;
    }
 
    /* Make sure the pos is inside the range */
    if (Info->nPos < Info->nMin)
    {
-      Info->nPos = Info->nMin;
+      pSBData->pos = Info->nPos = Info->nMin;
    }
    else if (Info->nPos > (Info->nMax - max((int)Info->nPage - 1, 0)))
    {
-      Info->nPos = Info->nMax - max(Info->nPage - 1, 0);
+      pSBData->pos = Info->nPos = Info->nMax - max(Info->nPage - 1, 0);
    }
 
    /*
@@ -382,7 +450,8 @@ co_IntSetScrollInfo(PWND Window, INT nBar, LPCSCROLLINFO lpsi, BOOL bRedraw)
     */
    if (!(lpsi->fMask & SIF_ALL))
    {
-      goto done; //return Info->nPos;
+      //goto done;
+      return lpsi->fMask & SIF_PREVIOUSPOS ? OldPos : pSBData->pos;
    }
 
    /* Check if the scrollbar should be hidden or disabled */
@@ -419,7 +488,7 @@ co_IntSetScrollInfo(PWND Window, INT nBar, LPCSCROLLINFO lpsi, BOOL bRedraw)
       }
    }
 
-done:
+//done:
    if ( action & SA_SSI_HIDE )
    {
       co_UserShowScrollBar(Window, nBar, FALSE, FALSE);
@@ -428,7 +497,7 @@ done:
    {
       if ( action & SA_SSI_SHOW )
          if ( co_UserShowScrollBar(Window, nBar, TRUE, TRUE) )
-            return Info->nPos; /* SetWindowPos() already did the painting */
+            return lpsi->fMask & SIF_PREVIOUSPOS ? OldPos : pSBData->pos; /* SetWindowPos() already did the painting */
       if (bRedraw)
       { // FIXME: Arrows and interior.
          RECTL UpdateRect = psbi->rcScrollBar;
@@ -438,7 +507,7 @@ done:
          UpdateRect.bottom -= Window->rcClient.top - Window->rcWindow.top;
          co_UserRedrawWindow(Window, &UpdateRect, 0, RDW_INVALIDATE | RDW_FRAME);
       } // FIXME: Arrows
-      else if( action & SA_SSI_REPAINT_ARROWS )
+/*      else if( action & SA_SSI_REPAINT_ARROWS )
       {
          RECTL UpdateRect = psbi->rcScrollBar;
          UpdateRect.left -= Window->rcClient.left - Window->rcWindow.left;
@@ -447,9 +516,9 @@ done:
          UpdateRect.bottom -= Window->rcClient.top - Window->rcWindow.top;
          co_UserRedrawWindow(Window, &UpdateRect, 0, RDW_INVALIDATE | RDW_FRAME);
       }
-   }
+*/   }
    /* Return current position */
-   return Info->nPos;
+   return lpsi->fMask & SIF_PREVIOUSPOS ? OldPos : pSBData->pos;
 }
 
 BOOL FASTCALL
@@ -457,7 +526,7 @@ co_IntGetScrollBarInfo(PWND Window, LONG idObject, PSCROLLBARINFO psbi)
 {
    INT Bar;
    PSCROLLBARINFO sbi;
-   LPSCROLLINFO psi;
+   PSBDATA pSBData;
    ASSERT_REFS_CO(Window);
 
    Bar = SBOBJ_TO_SBID(idObject);
@@ -471,14 +540,15 @@ co_IntGetScrollBarInfo(PWND Window, LONG idObject, PSCROLLBARINFO psbi)
 
    if(!co_IntCreateScrollBars(Window))
    {
+      ERR("Failed to create scrollbars for window.\n");
       return FALSE;
    }
 
    sbi = IntGetScrollbarInfoFromWindow(Window, Bar);
-   psi = IntGetScrollInfoFromWindow(Window, Bar);
+   pSBData = IntGetSBData(Window, Bar);
 
    IntGetScrollBarRect(Window, Bar, &(sbi->rcScrollBar));
-   IntCalculateThumb(Window, Bar, sbi, psi);
+   IntCalculateThumb(Window, Bar, sbi, pSBData);
 
    RtlCopyMemory(psbi, sbi, sizeof(SCROLLBARINFO));
 
@@ -489,7 +559,7 @@ BOOL FASTCALL
 co_IntCreateScrollBars(PWND Window)
 {
    PSCROLLBARINFO psbi;
-   LPSCROLLINFO psi;
+   PSBDATA pSBData;
    ULONG Size, s;
    INT i;
 
@@ -532,12 +602,10 @@ co_IntCreateScrollBars(PWND Window)
       for (i = 0; i < CCHILDREN_SCROLLBAR + 1; i++)
          psbi->rgstate[i] = 0;
 
-      psi = IntGetScrollInfoFromWindow(Window, s);
-      psi->cbSize = sizeof(LPSCROLLINFO);
-      psi->nMax = 100;
+      pSBData = IntGetSBData(Window, s);
 
       IntGetScrollBarRect(Window, s, &(psbi->rcScrollBar));
-      IntCalculateThumb(Window, s, psbi, psi);
+      IntCalculateThumb(Window, s, psbi, pSBData);
    }
 
    return TRUE;
@@ -607,7 +675,7 @@ co_UserShowScrollBar(PWND Wnd, int nBar, BOOL fShowH, BOOL fShowV)
    {
       case SB_CTL:
          {
-            if (Wnd->pSBInfo) IntUpdateSBInfo(Wnd, SB_CTL); // Is this needed? Was tested w/o!
+            //IntUpdateSBInfo(Wnd, SB_CTL); // Is this needed? Was tested w/o!
 
             co_WinPosShowWindow(Wnd, fShowH ? SW_SHOW : SW_HIDE);
             return TRUE;
@@ -627,20 +695,12 @@ co_UserShowScrollBar(PWND Wnd, int nBar, BOOL fShowH, BOOL fShowV)
          return FALSE;
    }
 
-
-   old_style = Wnd->style;
-   Wnd->style = (Wnd->style | set_bits) & ~clear_bits;
-
-   if (fShowH || fShowV)
-   {
-      if (!Wnd->pSBInfo) co_IntCreateScrollBars(Wnd);
-   }
-
+   old_style = IntSetStyle( Wnd, set_bits, clear_bits );
    if ((old_style & clear_bits) != 0 || (old_style & set_bits) != set_bits)
    {
       /////  Is this needed? Was tested w/o!
-      if (Wnd->style & WS_HSCROLL) IntUpdateSBInfo(Wnd, SB_HORZ);
-      if (Wnd->style & WS_VSCROLL) IntUpdateSBInfo(Wnd, SB_VERT);
+      //if (Wnd->style & WS_HSCROLL) IntUpdateSBInfo(Wnd, SB_HORZ);
+      //if (Wnd->style & WS_VSCROLL) IntUpdateSBInfo(Wnd, SB_VERT);
       /////
          /* Frame has been changed, let the window redraw itself */
       co_WinPosSetWindowPos(Wnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
@@ -650,6 +710,28 @@ co_UserShowScrollBar(PWND Wnd, int nBar, BOOL fShowH, BOOL fShowV)
    return FALSE;
 }
 
+LRESULT APIENTRY
+ScrollBarWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
+{
+   LRESULT lResult = 0;
+   PWND pWnd;
+   pWnd = UserGetWindowObject(hWnd);
+   if (!pWnd) return 0;
+
+   switch(Msg)
+   {
+       case WM_ENABLE:
+       {
+           if (pWnd->pSBInfo)
+           {
+              pWnd->pSBInfo->WSBflags = wParam ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH;
+           }
+       }
+       break;
+   }
+   return lResult;
+}
+
 ////
 
 BOOL
@@ -706,47 +788,53 @@ NtUserSBGetParms(
   PSBDATA pSBData,
   LPSCROLLINFO lpsi)
 {
-   NTSTATUS Status;
    PWND Window;
    SCROLLINFO psi;
-   DWORD sz;
    BOOL Ret;
+   SBDATA SBDataSafe;
    DECLARE_RETURN(BOOL);
    USER_REFERENCE_ENTRY Ref;
 
    TRACE("Enter NtUserGetScrollInfo\n");
-   UserEnterExclusive();
+   UserEnterShared();
 
-   Status = MmCopyFromCaller(&psi.cbSize, &(lpsi->cbSize), sizeof(UINT));
-   if(!NT_SUCCESS(Status) ||
-         !((psi.cbSize == sizeof(SCROLLINFO)) || (psi.cbSize == sizeof(SCROLLINFO) - sizeof(psi.nTrackPos))))
+   _SEH2_TRY
    {
-      SetLastNtError(Status);
-      RETURN(FALSE);
+      RtlCopyMemory(&psi, lpsi, sizeof(SCROLLINFO));
+      if (pSBData)
+      { 
+         RtlCopyMemory(&SBDataSafe, pSBData, sizeof(SBDATA));
+      }
    }
-   sz = psi.cbSize;
-   Status = MmCopyFromCaller(&psi, lpsi, sz);
-   if (!NT_SUCCESS(Status))
+   _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
    {
-      SetLastNtError(Status);
-      RETURN(FALSE);
+      ERR("NtUserGetScrollInfo Failed size.\n");
+      SetLastNtError(_SEH2_GetExceptionCode());
+      _SEH2_YIELD(RETURN(FALSE));
    }
+   _SEH2_END
 
    if(!(Window = UserGetWindowObject(hWnd)))
    {
+      ERR("NtUserGetScrollInfo Bad window.\n");
       RETURN(FALSE);
    }
 
    UserRefObjectCo(Window, &Ref);
-   Ret = co_IntGetScrollInfo(Window, fnBar, &psi);
+   Ret = co_IntGetScrollInfo(Window, fnBar, &SBDataSafe, &psi);
    UserDerefObjectCo(Window);
 
-   Status = MmCopyToCaller(lpsi, &psi, sz);
-   if(!NT_SUCCESS(Status))
+   _SEH2_TRY
    {
-      SetLastNtError(Status);
-      RETURN( FALSE);
+      RtlCopyMemory(lpsi, &psi, sizeof(SCROLLINFO));
    }
+   _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+   {
+      ERR("NtUserGetScrollInfo Failed copy to user.\n");
+      SetLastNtError(_SEH2_GetExceptionCode());
+      _SEH2_YIELD(RETURN(FALSE));
+   }
+   _SEH2_END
 
    RETURN( Ret);
 
@@ -773,7 +861,9 @@ NtUserEnableScrollBar(
    TRACE("Enter NtUserEnableScrollBar\n");
    UserEnterExclusive();
 
-   if (!(Window = UserGetWindowObject(hWnd)))
+   if (!(Window = UserGetWindowObject(hWnd)) || // FIXME:
+         Window == UserGetDesktopWindow() ||    // pWnd->fnid == FNID_DESKTOP
+         Window == UserGetMessageWindow() )     // pWnd->fnid == FNID_MESSAGEWND
    {
       RETURN(FALSE);
    }
@@ -827,6 +917,7 @@ NtUserEnableScrollBar(
 // Done in user32:
 //   SCROLL_RefreshScrollBar( hwnd, nBar, TRUE, TRUE );
 
+   RETURN( Chg);
    if (OrigArrows == wArrows) RETURN( FALSE);
    RETURN( TRUE);
 
@@ -856,7 +947,9 @@ NtUserSetScrollInfo(
    TRACE("Enter NtUserSetScrollInfo\n");
    UserEnterExclusive();
 
-   if(!(Window = UserGetWindowObject(hWnd)))
+   if(!(Window = UserGetWindowObject(hWnd)) || // FIXME:
+        Window == UserGetDesktopWindow() ||    // pWnd->fnid == FNID_DESKTOP
+        Window == UserGetMessageWindow() )     // pWnd->fnid == FNID_MESSAGEWND
    {
       RETURN( 0);
    }
index 9f4c198..af8bd42 100644 (file)
@@ -55,6 +55,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(scrollbar);
   /* Minimum size of the thumb in pixels */
 #define SCROLL_MIN_THUMB 6
 
+  /* Overlap between arrows and thumb */
+#define SCROLL_ARROW_THUMB_OVERLAP 0
+
  /* Thumb-tracking info */
 static HWND ScrollTrackingWin = 0;
 static INT  ScrollTrackingBar = 0;
@@ -86,6 +89,32 @@ const struct builtin_class_descr SCROLL_builtin_class =
 
 /* PRIVATE FUNCTIONS **********************************************************/
 
+static PSBDATA
+IntGetSBData(PWND pwnd, INT Bar)
+{
+   PSBWND pSBWnd;
+   PSBINFO pSBInfo;
+
+   pSBInfo = DesktopPtrToUser(pwnd->pSBInfo);
+   switch (Bar)
+   {
+       case SB_HORZ:
+         return &pSBInfo->Horz;
+       case SB_VERT:
+         return &pSBInfo->Vert;
+       case SB_CTL:
+         if ( pwnd->cbwndExtra != (sizeof(SBWND)-sizeof(WND)) )
+         {
+            ERR("IntGetSBData Wrong Extra bytes for CTL Scrollbar!\n");
+            return 0;
+         }
+         pSBWnd = (PSBWND)pwnd;
+         return (PSBDATA)&pSBWnd->SBCalc;
+       default:
+            ERR("IntGetSBData Bad Bar!\n");
+   }
+   return NULL;
+}
 
 static void
 IntDrawScrollInterior(HWND hWnd, HDC hDC, INT nBar, BOOL Vertical,
@@ -253,25 +282,16 @@ IntScrollDrawMovingThumb(HDC Dc, PSCROLLBARINFO ScrollBarInfo, BOOL Vertical)
   INT OldTop;
 
   if (Vertical)
-    {
       MaxSize = ScrollBarInfo->rcScrollBar.bottom - ScrollBarInfo->rcScrollBar.top;
-    }
   else
-    {
       MaxSize = ScrollBarInfo->rcScrollBar.right - ScrollBarInfo->rcScrollBar.left;
-    }
 
-  MaxSize -= ScrollBarInfo->dxyLineButton + ScrollBarInfo->xyThumbBottom
-             - ScrollBarInfo->xyThumbTop;
+  MaxSize -= ScrollBarInfo->dxyLineButton + ScrollBarInfo->xyThumbBottom - ScrollBarInfo->xyThumbTop;
 
   if (Pos < ScrollBarInfo->dxyLineButton)
-    {
       Pos = ScrollBarInfo->dxyLineButton;
-    }
   else if (MaxSize < Pos)
-    {
       Pos = MaxSize;
-    }
 
   OldTop = ScrollBarInfo->xyThumbTop;
   ScrollBarInfo->xyThumbBottom = Pos + ScrollBarInfo->xyThumbBottom - ScrollBarInfo->xyThumbTop;
@@ -280,21 +300,16 @@ IntScrollDrawMovingThumb(HDC Dc, PSCROLLBARINFO ScrollBarInfo, BOOL Vertical)
   ScrollBarInfo->xyThumbBottom = OldTop + ScrollBarInfo->xyThumbBottom - ScrollBarInfo->xyThumbTop;
   ScrollBarInfo->xyThumbTop = OldTop;
 
-  ScrollMovingThumb = ! ScrollMovingThumb;
+  ScrollMovingThumb = !ScrollMovingThumb;
 }
 
 static LONG FASTCALL
 IntScrollGetObjectId(INT SBType)
 {
-  if (SB_VERT == SBType)
-    {
+  if (SBType == SB_VERT)
       return OBJID_VSCROLL;
-    }
-  if (SB_HORZ == SBType)
-    {
+  if (SBType == SB_HORZ)
       return OBJID_HSCROLL;
-    }
-
   return OBJID_CLIENT;
 }
 
@@ -334,15 +349,15 @@ IntDrawScrollBar(HWND Wnd, HDC DC, INT Bar)
       default:
         return;
     }
-  if (! IntGetScrollBarInfo(Wnd, Bar, &Info))
-    {
+  if (!IntGetScrollBarInfo(Wnd, Bar, &Info))
+  {
       return;
-    }
+  }
 
   if (IsRectEmpty(&Info.rcScrollBar))
-    {
+  {
       return;
-    }
+  }
 
   //ThumbSize = pSBWnd->pSBCalc->pxThumbBottom - pSBWnd->pSBCalc->pxThumbTop;
 
@@ -350,9 +365,9 @@ IntDrawScrollBar(HWND Wnd, HDC DC, INT Bar)
    * Draw the arrows.
    */
   if (Info.dxyLineButton)
-    {
+  {
       IntDrawScrollArrows(DC, &Info, Vertical);
-    }
+  }
 
   /*
    * Draw the interior.
@@ -363,34 +378,44 @@ IntDrawScrollBar(HWND Wnd, HDC DC, INT Bar)
    * If scroll bar has focus, reposition the caret.
    */
   if (Wnd == GetFocus() && SB_CTL == Bar)
-    {
+  {
       if (Vertical)
-        {
+      {
           SetCaretPos(Info.rcScrollBar.top + 1, Info.dxyLineButton + 1);
-        }
+      }
       else
-        {
+      {
            SetCaretPos(Info.dxyLineButton + 1, Info.rcScrollBar.top + 1);
-        }
-    }
+      }
+  }
 }
 
 static BOOL FASTCALL
 IntScrollPtInRectEx(LPRECT Rect, POINT Pt, BOOL Vertical)
 {
   RECT TempRect = *Rect;
+  int scrollbarWidth;
+
+  /* Pad hit rect to allow mouse to be dragged outside of scrollbar and
+   * still be considered in the scrollbar. */
   if (Vertical)
-    {
-      TempRect.left -= Rect->right - Rect->left;
-      TempRect.right += Rect->right - Rect->left;
-    }
-   else
-    {
-      TempRect.top -= Rect->bottom - Rect->top;
-      TempRect.bottom += Rect->bottom - Rect->top;
-    }
+  {
+      scrollbarWidth = Rect->right - Rect->left;
+      TempRect.left -= scrollbarWidth*8;
+      TempRect.right += scrollbarWidth*8;
+      TempRect.top -= scrollbarWidth*2;
+      TempRect.bottom += scrollbarWidth*2;
+  }
+  else
+  {
+      scrollbarWidth = Rect->bottom - Rect->top;
+      TempRect.left -= scrollbarWidth*2;
+      TempRect.right += scrollbarWidth*2;
+      TempRect.top -= scrollbarWidth*8;
+      TempRect.bottom += scrollbarWidth*8;
+  }
 
-   return PtInRect(&TempRect, Pt);
+  return PtInRect(&TempRect, Pt);
 }
 
 static DWORD FASTCALL
@@ -399,63 +424,30 @@ IntScrollHitTest(PSCROLLBARINFO ScrollBarInfo, BOOL Vertical, POINT Pt, BOOL Dra
   INT ArrowSize, ThumbSize, ThumbPos;
 
   if ((Dragging && ! IntScrollPtInRectEx(&ScrollBarInfo->rcScrollBar, Pt, Vertical)) ||
-      ! PtInRect(&ScrollBarInfo->rcScrollBar, Pt))
-    {
-      return SCROLL_NOWHERE;
-    }
+      ! PtInRect(&ScrollBarInfo->rcScrollBar, Pt)) return SCROLL_NOWHERE;
 
   ThumbPos = ScrollBarInfo->xyThumbTop;
   ThumbSize = ScrollBarInfo->xyThumbBottom - ThumbPos;
   ArrowSize = ScrollBarInfo->dxyLineButton;
 
   if (Vertical)
-    {
-      if (Pt.y < ScrollBarInfo->rcScrollBar.top + ArrowSize)
-        {
-          return SCROLL_TOP_ARROW;
-        }
-      if (ScrollBarInfo->rcScrollBar.bottom - ArrowSize <= Pt.y)
-        {
-          return SCROLL_BOTTOM_ARROW;
-        }
-      if (0 == ThumbPos)
-        {
-          return SCROLL_TOP_RECT;
-        }
+  {
+      if (Pt.y < ScrollBarInfo->rcScrollBar.top + ArrowSize) return SCROLL_TOP_ARROW;
+      if (Pt.y >= ScrollBarInfo->rcScrollBar.bottom - ArrowSize) return SCROLL_BOTTOM_ARROW;
+      if (!ThumbPos) return SCROLL_TOP_RECT;
       Pt.y -= ScrollBarInfo->rcScrollBar.top;
-      if (Pt.y < ThumbPos)
-        {
-          return SCROLL_TOP_RECT;
-        }
-      if (ThumbPos + ThumbSize <= Pt.y)
-        {
-          return SCROLL_BOTTOM_RECT;
-        }
-    }
+      if (Pt.y < ThumbPos) return SCROLL_TOP_RECT;
+      if (Pt.y >= ThumbPos + ThumbSize) return SCROLL_BOTTOM_RECT;
+  }
   else
-    {
-      if (Pt.x < ScrollBarInfo->rcScrollBar.left + ArrowSize)
-        {
-          return SCROLL_TOP_ARROW;
-        }
-      if (ScrollBarInfo->rcScrollBar.right - ArrowSize <= Pt.x)
-        {
-          return SCROLL_BOTTOM_ARROW;
-        }
-      if (0 == ThumbPos)
-        {
-          return SCROLL_TOP_RECT;
-        }
+  {
+      if (Pt.x < ScrollBarInfo->rcScrollBar.left + ArrowSize) return SCROLL_TOP_ARROW;
+      if (Pt.x >= ScrollBarInfo->rcScrollBar.right - ArrowSize) return SCROLL_BOTTOM_ARROW;
+      if (!ThumbPos) return SCROLL_TOP_RECT;
       Pt.x -= ScrollBarInfo->rcScrollBar.left;
-      if (Pt.x < ThumbPos)
-        {
-          return SCROLL_TOP_RECT;
-        }
-      if (ThumbPos + ThumbSize <= Pt.x)
-        {
-          return SCROLL_BOTTOM_RECT;
-        }
-    }
+      if (Pt.x < ThumbPos) return SCROLL_TOP_RECT;
+      if (Pt.x >= ThumbPos + ThumbSize) return SCROLL_BOTTOM_RECT;
+  }
 
   return SCROLL_THUMB;
 }
@@ -479,145 +471,113 @@ IntScrollGetScrollBarRect(HWND Wnd, INT Bar, RECT *Rect,
 {
   INT Pixels;
   BOOL Vertical;
-  RECT ClientRect;
-  RECT WindowRect;
-  DWORD Style, ExStyle;
   PWND pWnd;
   PSBINFO pSBInfo;
+  PSBDATA pSBData;
+  PSBWND pSBWnd;
 
   pWnd = ValidateHwnd( Wnd );
+  if (!pWnd) return FALSE;
   pSBInfo = DesktopPtrToUser(pWnd->pSBInfo);
 
-  GetClientRect(Wnd, &ClientRect);
-  if (SB_HORZ == Bar || SB_VERT == Bar)
-    {
-      ClientToScreen(Wnd, (LPPOINT) &ClientRect.left);
-      ClientToScreen(Wnd, (LPPOINT) &ClientRect.right);
-      GetWindowRect(Wnd, &WindowRect);
-    }
-  Style = GetWindowLongPtrW(Wnd, GWL_STYLE);
+  *Rect = pWnd->rcClient;
+  OffsetRect( Rect, -pWnd->rcWindow.left, -pWnd->rcWindow.top );
+  if (pWnd->ExStyle & WS_EX_LAYOUTRTL)
+     mirror_rect( &pWnd->rcWindow, Rect );
 
   switch (Bar)
     {
       case SB_HORZ:
-        Rect->left   = ClientRect.left - WindowRect.left;
-        Rect->top    = ClientRect.bottom - WindowRect.top;
-        Rect->right  = ClientRect.right - WindowRect.left;
-        Rect->bottom = Rect->top + GetSystemMetrics(SM_CYHSCROLL);
-       if (0 != (Style & WS_BORDER))
-          {
+//        WIN_GetRectangles( Wnd, COORDS_WINDOW, NULL, Rect );
+        Rect->top = Rect->bottom;
+        Rect->bottom += GetSystemMetrics(SM_CYHSCROLL);
+       if (pWnd->style & WS_BORDER)
+        {
             Rect->left--;
             Rect->right++;
-         }
-        else if (0 != (Style & WS_VSCROLL))
-          {
+       }
+        else if (pWnd->style & WS_VSCROLL)
+        {
             Rect->right++;
-          }
+        }
         Vertical = FALSE;
+        pSBData = &pSBInfo->Horz;
        break;
 
       case SB_VERT:
-        ExStyle = GetWindowLongPtrW(Wnd, GWL_EXSTYLE);
-        if (0 != (ExStyle & WS_EX_LEFTSCROLLBAR))
-          {
-            Rect->left   = ClientRect.left - WindowRect.left - GetSystemMetrics(SM_CXVSCROLL);
-          }
+//        WIN_GetRectangles( Wnd, COORDS_WINDOW, NULL, Rect );
+        if (pWnd->ExStyle & WS_EX_LEFTSCROLLBAR)
+        {
+            Rect->right = Rect->left;
+            Rect->left -= GetSystemMetrics(SM_CXVSCROLL);
+        }
         else
-          {
-            Rect->left   = ClientRect.right - WindowRect.left;
-          }
-        Rect->top    = ClientRect.top - WindowRect.top;
-        Rect->right  = Rect->left + GetSystemMetrics(SM_CXVSCROLL);
-        Rect->bottom = ClientRect.bottom - WindowRect.top;
-       if (0 != (Style & WS_BORDER))
-          {
+        {
+            Rect->left = Rect->right;
+            Rect->right += GetSystemMetrics(SM_CXVSCROLL);
+        }
+       if (pWnd->style & WS_BORDER)
+        {
             Rect->top--;
             Rect->bottom++;
-          }
-        else if (0 != (Style & WS_HSCROLL))
-          {
+        }
+        else if (pWnd->style & WS_HSCROLL)
+        {
             Rect->bottom++;
-          }
+        }
         Vertical = TRUE;
+        pSBData = &pSBInfo->Vert;
        break;
 
       case SB_CTL:
-        *Rect = ClientRect;
-        Vertical = (0 != (Style & SBS_VERT));
+        GetClientRect( Wnd, Rect );
+        Vertical = (pWnd->style & SBS_VERT);
+        pSBWnd = (PSBWND)pWnd;
+        pSBData = (PSBDATA)&pSBWnd->SBCalc;
        break;
 
       default:
         return FALSE;
     }
 
-  if (Vertical)
-    {
-      Pixels = Rect->bottom - Rect->top;
-    }
-  else
-    {
-      Pixels = Rect->right - Rect->left;
-    }
+  if (Vertical) Pixels = Rect->bottom - Rect->top;
+  else Pixels = Rect->right - Rect->left;
 
   if (Pixels <= 2 * GetSystemMetrics(SM_CXVSCROLL) + SCROLL_MIN_RECT)
-    {
+  {
       if (SCROLL_MIN_RECT < Pixels)
-        {
           *ArrowSize = (Pixels - SCROLL_MIN_RECT) / 2;
-        }
       else
-        {
           *ArrowSize = 0;
-        }
       *ThumbPos = *ThumbSize = 0;
-    }
+  }
   else
   {
-      SCROLLINFO Info;
-
-      NtUserSBGetParms(Wnd, Bar, NULL, &Info);
       *ArrowSize = GetSystemMetrics(SM_CXVSCROLL);
-      Pixels -= (2 * GetSystemMetrics(SM_CXVSCROLL));
-
-      if (0 != Info.nPage)
+      Pixels -= (2 * (GetSystemMetrics(SM_CXVSCROLL) - SCROLL_ARROW_THUMB_OVERLAP));
+      if (pSBData->page)
       {
-          *ThumbSize = MulDiv(Pixels, Info.nPage, (Info.nMax - Info.nMin + 1));
-          if (*ThumbSize < SCROLL_MIN_THUMB)
-          {
-              *ThumbSize = SCROLL_MIN_THUMB;
-          }
-      }
-      else
-      {
-          *ThumbSize = GetSystemMetrics(SM_CXVSCROLL);
+          *ThumbSize = MulDiv(Pixels, pSBData->page, (pSBData->posMax - pSBData->posMin + 1));
+          if (*ThumbSize < SCROLL_MIN_THUMB) *ThumbSize = SCROLL_MIN_THUMB;
       }
+      else *ThumbSize = GetSystemMetrics(SM_CXVSCROLL);
 
-//#if 0 /* FIXME */
       if (((Pixels -= *ThumbSize ) < 0) ||
           (( pSBInfo->WSBflags & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH))
-//#else
-//      if ((Pixels -= *ThumbSize ) < 0)
-//#endif
       {
           /* Rectangle too small or scrollbar disabled -> no thumb */
           *ThumbPos = *ThumbSize = 0;
       }
       else
       {
-          INT Max = Info.nMax - max(Info.nPage - 1, 0);
-          if (Max <= Info.nMin)
-          {
-              *ThumbPos = *ArrowSize;
-          }
+          INT Max = pSBData->posMax - max(pSBData->page - 1, 0);
+          if (pSBData->posMin >= Max)
+              *ThumbPos = *ArrowSize - SCROLL_ARROW_THUMB_OVERLAP;
           else
-          {
-              *ThumbPos = *ArrowSize
-                          + MulDiv(Pixels, (Info.nPos - Info.nMin),
-                                   (Max - Info.nMin));
-          }
+              *ThumbPos = *ArrowSize - SCROLL_ARROW_THUMB_OVERLAP
+              + MulDiv(Pixels, (pSBData->pos - pSBData->posMin),(Max - pSBData->posMin));
       }
   }
-
   return Vertical;
 }
 
@@ -631,70 +591,61 @@ static UINT FASTCALL
 IntScrollGetThumbVal(HWND Wnd, INT SBType, PSCROLLBARINFO ScrollBarInfo,
                      BOOL Vertical, INT Pos)
 {
-  SCROLLINFO si;
+  PWND pWnd;
+  PSBDATA pSBData;
   INT Pixels = Vertical ? ScrollBarInfo->rcScrollBar.bottom
                           - ScrollBarInfo->rcScrollBar.top
                         : ScrollBarInfo->rcScrollBar.right
                           - ScrollBarInfo->rcScrollBar.left;
 
-  si.cbSize = sizeof(SCROLLINFO);
-  si.fMask = SIF_RANGE | SIF_PAGE;
-  NtUserSBGetParms(Wnd, SBType, NULL, &si);
+  pWnd = ValidateHwnd( Wnd );
+  if (!pWnd) return FALSE; 
+
+  pSBData = IntGetSBData(pWnd, SBType);
+
   if ((Pixels -= 2 * ScrollBarInfo->dxyLineButton) <= 0)
-    {
-      return si.nMin;
-    }
+  {
+      return pSBData->posMin;
+  }
 
   if ((Pixels -= (ScrollBarInfo->xyThumbBottom - ScrollBarInfo->xyThumbTop)) <= 0)
-    {
-      return si.nMin;
-    }
+  {
+      return pSBData->posMin;
+  }
 
   Pos = Pos - ScrollBarInfo->dxyLineButton;
   if (Pos < 0)
-    {
+  {
       Pos = 0;
-    }
-  if (Pixels < Pos)
-    {
-      Pos = Pixels;
-    }
+  }
+  if (Pos > Pixels) Pos = Pixels;
 
-  if (0 == si.nPage)
-    {
-      Pos *= si.nMax - si.nMin;
-    }
+  if (!pSBData->page)
+      Pos *= pSBData->posMax - pSBData->posMin;
   else
-    {
-      Pos *= si.nMax - si.nMin - si.nPage + 1;
-    }
-  return si.nMin + ((Pos + Pixels / 2) / Pixels);
+      Pos *= pSBData->posMax - pSBData->posMin - pSBData->page + 1;
+
+  return pSBData->posMin + ((Pos + Pixels / 2) / Pixels);
 }
 
 /***********************************************************************
  *           IntScrollClipPos
  */
-static POINT IntScrollClipPos(PRECT Rect, POINT Pt)
+static POINT IntScrollClipPos(PRECT lpRect, POINT pt)
 {
-  if (Pt.x < Rect->left)
-    {
-      Pt.x = Rect->left;
-    }
-  else if (Rect->right < Pt.x)
-    {
-      Pt.x = Rect->right;
-    }
-
-  if (Pt.y < Rect->top)
-    {
-      Pt.y = Rect->top;
-    }
-  else if (Rect->bottom < Pt.y)
-    {
-      Pt.y = Rect->bottom;
-    }
-
-  return Pt;
+    if( pt.x < lpRect->left )
+        pt.x = lpRect->left;
+    else
+    if( pt.x > lpRect->right )
+        pt.x = lpRect->right;
+
+    if( pt.y < lpRect->top )
+        pt.y = lpRect->top;
+    else
+    if( pt.y > lpRect->bottom )
+        pt.y = lpRect->bottom;
+
+    return pt;
 }
 
 /***********************************************************************
@@ -895,9 +846,9 @@ IntScrollHandleScrollEvent(HWND Wnd, INT SBType, UINT Msg, POINT Pt)
         ScrollBarInfo.rgstate[ScrollTrackHitTest] &= ~STATE_SYSTEM_PRESSED;
         NewInfo.rgstate[ScrollTrackHitTest] = ScrollBarInfo.rgstate[ScrollTrackHitTest];
         NtUserSetScrollBarInfo(Wnd, IntScrollGetObjectId(SBType), &NewInfo);
-               
+
         IntDrawScrollArrows(Dc, &ScrollBarInfo, Vertical);
-               
+
         break;
 
       case WM_SYSTIMER:
@@ -1092,7 +1043,7 @@ static void IntScrollCreateScrollBar(
 
   TRACE("hwnd=%p lpCreate=%p\n", Wnd, lpCreate);
 
-//#if 0 /* FIXME */
+#if 0 /* FIXME */
   if (lpCreate->style & WS_DISABLED)
   {
   //    info->flags = ESB_DISABLE_BOTH;
@@ -1100,7 +1051,7 @@ static void IntScrollCreateScrollBar(
       NtUserMessageCall( Wnd, WM_ENABLE, FALSE, 0, 0, FNID_SCROLLBAR, FALSE);
       ERR("Created WS_DISABLED scrollbar\n");
   }
-//#endif
+#endif
   if (0 != (lpCreate->style & (SBS_SIZEGRIP | SBS_SIZEBOX)))
     {
       if (0 != (lpCreate->style & SBS_SIZEBOXTOPLEFTALIGN))
@@ -1148,42 +1099,6 @@ static void IntScrollCreateScrollBar(
     }
 }
 
-static INT FASTCALL
-IntScrollGetScrollPos(HWND Wnd, INT Bar)
-{
-  SCROLLINFO ScrollInfo;
-
-  ScrollInfo.cbSize = sizeof(SCROLLINFO);
-  ScrollInfo.fMask = SIF_POS;
-  if (!NtUserSBGetParms(Wnd, Bar, NULL, &ScrollInfo))
-  {
-      return 0;
-  }
-
-  return ScrollInfo.nPos;
-}
-
-static BOOL FASTCALL
-IntScrollGetScrollRange(HWND Wnd, int Bar, LPINT MinPos, LPINT MaxPos)
-{
-  BOOL Result;
-  SCROLLINFO ScrollInfo;
-
-  if (NULL == MinPos || NULL == MaxPos)
-  {
-      SetLastError(ERROR_INVALID_PARAMETER);
-      return FALSE;
-  }
-
-  ScrollInfo.cbSize = sizeof(SCROLLINFO);
-  ScrollInfo.fMask = SIF_RANGE;
-  Result = NtUserSBGetParms(Wnd, Bar, NULL, &ScrollInfo);
-  *MinPos = Result ? ScrollInfo.nMin : 0;
-  *MaxPos = Result ? ScrollInfo.nMax : 0;
-
-  return Result;
-}
-
 /* USER32 INTERNAL FUNCTIONS **************************************************/
 
 /***********************************************************************
@@ -1199,13 +1114,13 @@ ScrollTrackScrollBar(HWND Wnd, INT SBType, POINT Pt)
   UINT XOffset = 0, YOffset = 0;
 
   if (SBType != SB_CTL)
-  { // Replace HAX for CMD mouse tracking.
+  { // Used with CMD mouse tracking.
       PWND pwnd = ValidateHwnd(Wnd);
       if (!pwnd) return;
       XOffset = pwnd->rcClient.left - pwnd->rcWindow.left;
       YOffset = pwnd->rcClient.top - pwnd->rcWindow.top;
 //      RECT rect;
-//      GetClientRect(Wnd, &rect);
+//      WIN_GetRectangles( Wnd, COORDS_CLIENT, &rect, NULL );
       ScreenToClient(Wnd, &Pt);
 //      Pt.x -= rect.left;
 //      Pt.y -= rect.top;
@@ -1241,6 +1156,15 @@ ScrollTrackScrollBar(HWND Wnd, INT SBType, POINT Pt)
 }
 
 
+static DWORD FASTCALL
+IntSetScrollInfo(HWND Wnd, LPCSCROLLINFO Info, BOOL bRedraw)
+{
+   DWORD Ret = NtUserSetScrollInfo(Wnd, SB_CTL, Info, bRedraw);
+   if (Ret) IntNotifyWinEvent(EVENT_OBJECT_VALUECHANGE, Wnd, OBJID_CLIENT, CHILDID_SELF, WEF_SETBYWNDPTI);
+   return Ret;
+}
+
+
 /***********************************************************************
  *           ScrollBarWndProc
  */
@@ -1249,12 +1173,21 @@ ScrollBarWndProc_common(WNDPROC DefWindowProc, HWND Wnd, UINT Msg, WPARAM wParam
 {
 #ifdef __REACTOS__ // Do this now, remove after Server side is fixed.
   PWND pWnd;
+  PSBWND pSBWnd;
+  SCROLLINFO ScrollInfo;
 
   pWnd = ValidateHwnd(Wnd);
   if (pWnd)
   {
      if (!pWnd->fnid)
      {
+        ERR("ScrollBar CTL size %d\n",(sizeof(SBWND)-sizeof(WND)));
+        if ( pWnd->cbwndExtra != (sizeof(SBWND)-sizeof(WND)) )
+        {
+           ERR("Wrong Extra bytes for Scrollbar!\n");
+           return 0;
+        }
+     
         if (Msg != WM_CREATE)
         {
            return DefWindowProc(Wnd, Msg, wParam, lParam);
@@ -1277,6 +1210,9 @@ ScrollBarWndProc_common(WNDPROC DefWindowProc, HWND Wnd, UINT Msg, WPARAM wParam
       return 0;
     }
 
+  // Must be a scroll bar control!
+  pSBWnd = (PSBWND)pWnd;
+
   switch (Msg)
     {
       case WM_CREATE:
@@ -1285,17 +1221,8 @@ ScrollBarWndProc_common(WNDPROC DefWindowProc, HWND Wnd, UINT Msg, WPARAM wParam
 
       case WM_ENABLE:
         {
-          PWND pWnd = ValidateHwnd(Wnd);
-          if (pWnd->pSBInfo)
-          { 
-             ERR("ScrollBarWndProc WM_ENABLE\n");
-             //NtUserEnableScrollBar(Wnd,SB_CTL,(wParam ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH));
-             NtUserMessageCall( Wnd, Msg, wParam, lParam, 0, FNID_SCROLLBAR, !unicode);
-             /* Refresh Scrollbars. */
-             SCROLL_RefreshScrollBar(Wnd, SB_CTL, TRUE, TRUE);
-          }
-       }
-       return 0;
+          return SendMessageW( Wnd, SBM_ENABLE_ARROWS, wParam ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH, 0);
+        }
 
       case WM_LBUTTONDBLCLK:
       case WM_LBUTTONDOWN:
@@ -1408,35 +1335,49 @@ ScrollBarWndProc_common(WNDPROC DefWindowProc, HWND Wnd, UINT Msg, WPARAM wParam
         }
         break;
 
-      case SBM_SETPOS:
-        return SetScrollPos(Wnd, SB_CTL, wParam, (BOOL) lParam);
-
       case SBM_GETPOS:
-        return IntScrollGetScrollPos(Wnd, SB_CTL);
-
-      case SBM_SETRANGEREDRAW:
-      case SBM_SETRANGE:
-        {
-          INT OldPos = IntScrollGetScrollPos(Wnd, SB_CTL);
-          SetScrollRange(Wnd, SB_CTL, wParam, lParam, FALSE);
-          if (Msg == SBM_SETRANGEREDRAW)
-             SCROLL_RefreshScrollBar( Wnd, SB_CTL, TRUE, TRUE );
-          if (OldPos != IntScrollGetScrollPos(Wnd, SB_CTL)) return OldPos;
-        }
-        return 0;
+        return pSBWnd->SBCalc.pos;
 
       case SBM_GETRANGE:
-        return IntScrollGetScrollRange(Wnd, SB_CTL, (LPINT) wParam, (LPINT) lParam);
+        *(LPINT)wParam = pSBWnd->SBCalc.posMin;
+        *(LPINT)lParam = pSBWnd->SBCalc.posMax;
+        // This message does not return a value.
+        return 0;
  
       case SBM_ENABLE_ARROWS:
         return EnableScrollBar( Wnd, SB_CTL, wParam );
 
+      case SBM_SETPOS:
+        {
+           ScrollInfo.cbSize = sizeof(SCROLLINFO);
+           ScrollInfo.fMask = SIF_POS|SIF_PREVIOUSPOS;
+           ScrollInfo.nPos = wParam;
+           return IntSetScrollInfo(Wnd, &ScrollInfo, lParam);
+        }
+
+      case SBM_SETRANGEREDRAW:
+      case SBM_SETRANGE:
+        {
+           ScrollInfo.cbSize = sizeof(SCROLLINFO);
+           ScrollInfo.fMask = SIF_RANGE|SIF_PREVIOUSPOS;
+           ScrollInfo.nMin = wParam;
+           ScrollInfo.nMax = lParam;
+           return IntSetScrollInfo(Wnd, &ScrollInfo, Msg == SBM_SETRANGEREDRAW ? TRUE : FALSE);
+        }
+
       case SBM_SETSCROLLINFO:
-        return NtUserSetScrollInfo(Wnd, SB_CTL, (SCROLLINFO *) lParam, wParam);
+        return IntSetScrollInfo(Wnd, (LPCSCROLLINFO)lParam, wParam);
 
       case SBM_GETSCROLLINFO:
-        return NtUserSBGetParms(Wnd, SB_CTL, NULL, (SCROLLINFO *) lParam);
-
+        {
+         PSBDATA pSBData = (PSBDATA)&pSBWnd->SBCalc;
+         DWORD ret = NtUserSBGetParms(Wnd, SB_CTL, pSBData, (SCROLLINFO *) lParam);
+         if (!ret)
+         {
+            ERR("SBM_GETSCROLLINFO No ScrollInfo\n");
+         }
+         return ret;
+        }
       case SBM_GETSCROLLBARINFO:
         ((PSCROLLBARINFO)lParam)->cbSize = sizeof(SCROLLBARINFO);
         return NtUserGetScrollBarInfo(Wnd, OBJID_CLIENT, (PSCROLLBARINFO)lParam);
@@ -1496,8 +1437,7 @@ BOOL WINAPI EnableScrollBar( HWND hwnd, UINT nBar, UINT flags )
    if (!Hook)
    {
       Ret = NtUserEnableScrollBar(hwnd, nBar, flags);
-      if (GetLastError() == ERROR_INVALID_PARAMETER) return Ret;
-      if (nBar == SB_CTL) return Ret;
+      if (!Ret) return Ret;
       SCROLL_RefreshScrollBar( hwnd, nBar, TRUE, TRUE );
       return Ret;
    }
@@ -1519,7 +1459,7 @@ BOOL WINAPI
 RealGetScrollInfo(HWND Wnd, INT SBType, LPSCROLLINFO Info)
 {
   PWND pWnd;
-  PSBDATA pSBData = NULL;
+  PSBDATA pSBData;
 
   if (SB_CTL == SBType)
   {
@@ -1534,7 +1474,12 @@ RealGetScrollInfo(HWND Wnd, INT SBType, LPSCROLLINFO Info)
      SetLastError(ERROR_INVALID_PARAMETER);
      return FALSE;
   }
-  // FIXME add support to set pSBData from pWnd->pSBInfo
+  if (!pWnd->pSBInfo)
+  {
+     SetLastError(ERROR_NO_SCROLLBARS);
+     return FALSE;
+  }
+  pSBData = IntGetSBData(pWnd, SBType);
   return NtUserSBGetParms(Wnd, SBType, pSBData, Info);
 }
 
@@ -1573,17 +1518,33 @@ GetScrollInfo(HWND Wnd, INT SBType, LPSCROLLINFO Info)
 INT WINAPI
 GetScrollPos(HWND Wnd, INT Bar)
 {
+  PWND pwnd;
+  PSBDATA pSBData;
+
   TRACE("Wnd=%p Bar=%d\n", Wnd, Bar);
 
   /* Refer SB_CTL requests to the window */
   if (SB_CTL == Bar)
-    {
+  {
       return SendMessageW(Wnd, SBM_GETPOS, (WPARAM) 0, (LPARAM) 0);
-    }
-  else
-    {
-      return IntScrollGetScrollPos(Wnd, Bar);
-    }
+  }
+  else if (Bar == SB_HORZ || Bar == SB_VERT )
+  {
+     pwnd = ValidateHwnd(Wnd);
+     if (!pwnd) return 0;
+
+     if (pwnd->pSBInfo)
+     {
+        pSBData = IntGetSBData(pwnd, Bar);
+        return pSBData->pos;
+     }
+
+     SetLastError(ERROR_NO_SCROLLBARS);
+     ERR("GetScrollPos No Scroll Info\n");
+     return 0;
+  }
+  SetLastError(ERROR_INVALID_PARAMETER);
+  return 0;
 }
 
 /*
@@ -1592,17 +1553,37 @@ GetScrollPos(HWND Wnd, INT Bar)
 BOOL WINAPI
 GetScrollRange(HWND Wnd, int Bar, LPINT MinPos, LPINT MaxPos)
 {
+  PWND pwnd;
+  PSBDATA pSBData;  
+
   TRACE("Wnd=%x Bar=%d Min=%p Max=%p\n", Wnd, Bar, MinPos, MaxPos);
 
   /* Refer SB_CTL requests to the window */
   if (SB_CTL == Bar)
-    {
+  {
       return SendMessageW(Wnd, SBM_GETRANGE, (WPARAM) MinPos, (LPARAM) MaxPos);
-    }
-  else
-    {
-      return IntScrollGetScrollRange(Wnd, Bar, MinPos, MaxPos);
-    }
+  }
+  else if (Bar == SB_HORZ || Bar == SB_VERT )
+  {
+      pwnd = ValidateHwnd(Wnd);
+      if (!pwnd) return FALSE;
+
+      if (pwnd->pSBInfo)
+      {
+         pSBData = IntGetSBData(pwnd, Bar);
+         *MinPos = pSBData->posMin;
+         *MaxPos = pSBData->posMax;
+      }
+      else
+      {
+         SetLastError(ERROR_NO_SCROLLBARS);
+         *MinPos = 0;
+         *MaxPos = 0;
+      }
+      return TRUE;
+  }
+  SetLastError(ERROR_INVALID_PARAMETER);
+  return FALSE;
 }
 
 INT WINAPI
@@ -1655,32 +1636,13 @@ SetScrollInfo(HWND Wnd, int SBType, LPCSCROLLINFO Info, BOOL bRedraw)
 INT WINAPI
 SetScrollPos(HWND hWnd, INT nBar, INT nPos, BOOL bRedraw)
 {
-  PWND pWnd;
-  INT Result = 0;
   SCROLLINFO ScrollInfo;
 
-  pWnd = ValidateHwnd(hWnd);
-  if ( !pWnd || !pWnd->pSBInfo ) return 0;
-
   ScrollInfo.cbSize = sizeof(SCROLLINFO);
-  ScrollInfo.fMask = SIF_POS;
+  ScrollInfo.fMask = SIF_POS|SIF_PREVIOUSPOS;
+  ScrollInfo.nPos = nPos;
 
-  /*
-   * Call NtUserSBGetParms() to get the previous position that
-   * we will later return.
-   */
-  if (NtUserSBGetParms(hWnd, nBar, NULL, &ScrollInfo))
-  {
-      Result = ScrollInfo.nPos;
-      if (Result != nPos)
-      {
-          ScrollInfo.nPos = nPos;
-          /* Finally set the new position */
-          NtUserSetScrollInfo(hWnd, nBar, &ScrollInfo, bRedraw);
-      }
-  }
-
-  return Result;
+  return RealSetScrollInfo(hWnd, nBar, &ScrollInfo, bRedraw);
 }
 
 /*
@@ -1706,6 +1668,5 @@ SetScrollRange(HWND hWnd, INT nBar, INT nMinPos, INT nMaxPos, BOOL bRedraw)
   ScrollInfo.nMin = nMinPos;
   ScrollInfo.nMax = nMaxPos;
   SetScrollInfo(hWnd, nBar, &ScrollInfo, bRedraw); // do not bypass themes.
-
   return TRUE;
 }