branch update for HEAD-2003091401
[reactos.git] / subsys / win32k / eng / mouse.c
index ca740f1..51c8dda 100644 (file)
@@ -1,6 +1,6 @@
 /*
- *  ReactOS kernel
- *  Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
+ *  ReactOS W32 Subsystem
+ *  Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
 #include <windows.h>
 #include <ddk/ntddk.h>
 #include <ddk/ntddmou.h>
+#include <win32k/win32k.h>
 #include <win32k/dc.h>
 #include "objects.h"
 #include "include/msgqueue.h"
 #include "include/object.h"
 #include "include/winsta.h"
+#include <include/mouse.h>
 
 #define NDEBUG
 #include <debug.h>
 
+
+#define GETSYSCURSOR(x) ((x) - OCR_NORMAL)
+
 /* GLOBALS *******************************************************************/
 
-static BOOLEAN SafetySwitch = FALSE;
-static BOOLEAN SafetySwitch2 = FALSE;
-static BOOLEAN MouseEnabled = FALSE;
-static LONG mouse_x, mouse_y;
-static UINT mouse_width = 0, mouse_height = 0;
 static ULONG PointerStatus;
 
 static UCHAR DefaultCursor[256] = {
@@ -117,7 +117,71 @@ static UCHAR DefaultCursor[256] = {
 
 /* FUNCTIONS *****************************************************************/
 
-INT
+BOOL FASTCALL
+IntCheckClipCursor(LONG *x, LONG *y, PSYSTEM_CURSORINFO CurInfo)
+{
+  if(CurInfo->CursorClipInfo.IsClipped)
+  {
+    if(*x > CurInfo->CursorClipInfo.Right)
+      *x = CurInfo->CursorClipInfo.Right;
+    if(*x < CurInfo->CursorClipInfo.Left)
+      *x = CurInfo->CursorClipInfo.Left;
+    if(*y > CurInfo->CursorClipInfo.Bottom)
+      *y = CurInfo->CursorClipInfo.Bottom;
+    if(*y < CurInfo->CursorClipInfo.Top)
+      *y = CurInfo->CursorClipInfo.Top;
+    return TRUE;
+  }
+  return TRUE;
+}
+
+BOOL FASTCALL
+IntDetectDblClick(PSYSTEM_CURSORINFO CurInfo, DWORD TickCount)
+{
+  LONG dX, dY;
+  BOOL res = ((TickCount - CurInfo->LastBtnDown) < CurInfo->DblClickSpeed);
+  if(res)
+  {
+    /* check if the second click is within the DblClickWidth and DblClickHeight values */
+    dX = CurInfo->LastBtnDownX - CurInfo->x;
+    dY = CurInfo->LastBtnDownY - CurInfo->y;
+    if(dX < 0) dX = -dX;
+    if(dY < 0) dY = -dY;
+    
+    res = (dX <= CurInfo->DblClickWidth) &&
+          (dY <= CurInfo->DblClickHeight);
+
+    if(res)
+    {
+      CurInfo->LastBtnDown = 0; /* prevent sending 2 or more DBLCLK messages */
+      CurInfo->LastBtnDownX = CurInfo->x;
+      CurInfo->LastBtnDownY = CurInfo->y;
+    }
+    else
+    {
+      CurInfo->LastBtnDown = TickCount;
+      CurInfo->LastBtnDownX = CurInfo->x;
+      CurInfo->LastBtnDownY = CurInfo->y;
+    }
+  }
+  else
+  {
+    CurInfo->LastBtnDown = TickCount;
+    CurInfo->LastBtnDownX = CurInfo->x;
+    CurInfo->LastBtnDownY = CurInfo->y;
+  }
+  return res;
+}
+
+BOOL FASTCALL
+IntSwapMouseButton(PWINSTATION_OBJECT WinStaObject, BOOL Swap)
+{
+  BOOL res = WinStaObject->SystemCursor.SwapButtons;
+  WinStaObject->SystemCursor.SwapButtons = Swap;
+  return res;
+}
+
+INT STDCALL
 MouseSafetyOnDrawStart(PSURFOBJ SurfObj, PSURFGDI SurfGDI, LONG HazardX1,
                       LONG HazardY1, LONG HazardX2, LONG HazardY2)
 /*
@@ -127,24 +191,42 @@ MouseSafetyOnDrawStart(PSURFOBJ SurfObj, PSURFGDI SurfGDI, LONG HazardX1,
 {
   RECTL MouseRect;
   LONG tmp;
+  PSYSTEM_CURSORINFO CurInfo;
+  PSYSCURSOR SysCursor;
+  BOOL MouseEnabled = FALSE;
 
 
   /* Mouse is not allowed to move if GDI is busy drawing */
-  SafetySwitch2 = TRUE;
-
+   
+  if(IntGetWindowStationObject(InputWindowStation))
+  {
+    CurInfo = &InputWindowStation->SystemCursor;
+    
+    SysCursor = &CurInfo->SystemCursors[CurInfo->CurrentCursor];
+    MouseEnabled = CurInfo->Enabled && SysCursor->hCursor;
+  }
+  else
+    return FALSE;
+    
+  CurInfo->SafetySwitch2 = TRUE;
+    
   if (SurfObj == NULL)
     {
+      ObDereferenceObject(InputWindowStation);
       return(FALSE);
     }
 
+
   if (SurfObj->iType != STYPE_DEVICE || MouseEnabled == FALSE)
     {
+      ObDereferenceObject(InputWindowStation);
       return(FALSE);
     }
 
   if (SPS_ACCEPT_NOEXCLUDE == PointerStatus)
     {
       /* Hardware cursor, no need to remove it */
+      ObDereferenceObject(InputWindowStation);
       return(FALSE);
     }
 
@@ -157,63 +239,158 @@ MouseSafetyOnDrawStart(PSURFOBJ SurfObj, PSURFGDI SurfGDI, LONG HazardX1,
       tmp = HazardY2; HazardY2 = HazardY1; HazardY1 = tmp;
     }
 
-  if (((mouse_x + mouse_width) >= HazardX1)  && (mouse_x <= HazardX2) &&
-      ((mouse_y + mouse_height) >= HazardY1) && (mouse_y <= HazardY2))
+  if (((CurInfo->x + SysCursor->cx) >= HazardX1)  && (CurInfo->x <= HazardX2) &&
+      ((CurInfo->y + SysCursor->cy) >= HazardY1) && (CurInfo->y <= HazardY2))
     {
-      SafetySwitch = TRUE;
+      /* Mouse is not allowed to move if GDI is busy drawing */
+      ExAcquireFastMutexUnsafe(&CurInfo->CursorMutex);
+      CurInfo->SafetySwitch = TRUE;
       SurfGDI->MovePointer(SurfObj, -1, -1, &MouseRect);
+      ExReleaseFastMutexUnsafe(&CurInfo->CursorMutex);
     }
-
+    
+  ObDereferenceObject(InputWindowStation);
   return(TRUE);
 }
 
-INT
+INT FASTCALL
 MouseSafetyOnDrawEnd(PSURFOBJ SurfObj, PSURFGDI SurfGDI)
 /*
  * FUNCTION: Notify the mouse driver that drawing has finished on a surface.
  */
 {
   RECTL MouseRect;
-
-  if (SurfObj == NULL)
-    {
-      SafetySwitch2 = FALSE;
-      return(FALSE);
-    }
+  PSYSTEM_CURSORINFO CurInfo;
+  PSYSCURSOR SysCursor;
+  BOOL MouseEnabled = FALSE;
+    
+  if(IntGetWindowStationObject(InputWindowStation))
+  {
+    CurInfo = &InputWindowStation->SystemCursor;
+  }
+  else
+    return FALSE;
+    
+  if(SurfObj == NULL)
+  {
+    CurInfo->SafetySwitch2 = FALSE;
+    ObDereferenceObject(InputWindowStation);
+    return FALSE;
+  }
+  
+  SysCursor = &CurInfo->SystemCursors[CurInfo->CurrentCursor];
+  MouseEnabled = CurInfo->Enabled && SysCursor->hCursor;
 
   if (SurfObj->iType != STYPE_DEVICE || MouseEnabled == FALSE)
     {
-      SafetySwitch2 = FALSE;
+      CurInfo->SafetySwitch2 = FALSE;
+      ObDereferenceObject(InputWindowStation);
       return(FALSE);
     }
 
   if (SPS_ACCEPT_NOEXCLUDE == PointerStatus)
     {
       /* Hardware cursor, it wasn't removed so need to restore it */
-      SafetySwitch2 = FALSE;
+      CurInfo->SafetySwitch2 = FALSE;
+      ObDereferenceObject(InputWindowStation);
       return(FALSE);
     }
 
-  if (SafetySwitch)
+  if (CurInfo->SafetySwitch)
     {
-      SurfGDI->MovePointer(SurfObj, mouse_x, mouse_y, &MouseRect);
-      SafetySwitch = FALSE;
+      ExAcquireFastMutexUnsafe(&CurInfo->CursorMutex);
+      SurfGDI->MovePointer(SurfObj, CurInfo->x, CurInfo->y, &MouseRect);
+      CurInfo->SafetySwitch = FALSE;
+      ExReleaseFastMutexUnsafe(&CurInfo->CursorMutex);
     }
-
-  SafetySwitch2 = FALSE;
-
+  
+  CurInfo->SafetySwitch2 = FALSE;
+  ObDereferenceObject(InputWindowStation);
   return(TRUE);
 }
 
-VOID
+BOOL FASTCALL
+MouseMoveCursor(LONG X, LONG Y)
+{
+  HDC hDC;
+  PDC dc;
+  RECTL MouseRect;
+  BOOL res = FALSE;
+  PSURFOBJ SurfObj;
+  PSURFGDI SurfGDI;
+  PSYSTEM_CURSORINFO CurInfo;
+  MSG Msg;
+  LARGE_INTEGER LargeTickCount;
+  ULONG TickCount;
+  static ULONG ButtonsDown = 0;
+  
+  if(!InputWindowStation)
+    return FALSE;
+  
+  if(IntGetWindowStationObject(InputWindowStation))
+  {
+    CurInfo = &InputWindowStation->SystemCursor;
+    if(!CurInfo->Enabled)
+    {
+      ObDereferenceObject(InputWindowStation);
+      return FALSE;
+    }
+    hDC = IntGetScreenDC();
+    if(!hDC)
+    {
+      ObDereferenceObject(InputWindowStation);
+      return FALSE;
+    }
+    dc = DC_LockDc(hDC);
+    SurfObj = (PSURFOBJ)AccessUserObject((ULONG) dc->Surface);
+    SurfGDI = (PSURFGDI)AccessInternalObject((ULONG) dc->Surface);
+    DC_UnlockDc( hDC );
+    IntCheckClipCursor(&X, &Y, CurInfo);
+    if((X != CurInfo->x) || (Y != CurInfo->y))
+    {
+      /* send MOUSEMOVE message */
+      KeQueryTickCount(&LargeTickCount);
+      TickCount = LargeTickCount.u.LowPart;
+      Msg.wParam = ButtonsDown;
+      Msg.lParam = MAKELPARAM(X, Y);
+      Msg.message = WM_MOUSEMOVE;
+      Msg.time = TickCount;
+      Msg.pt.x = X;
+      Msg.pt.y = Y;
+      MsqInsertSystemMessage(&Msg, TRUE);
+      /* move cursor */
+      CurInfo->x = X;
+      CurInfo->y = Y;
+      if(CurInfo->Enabled)
+      {
+        ExAcquireFastMutexUnsafe(&CurInfo->CursorMutex);
+        SurfGDI->MovePointer(SurfObj, CurInfo->x, CurInfo->y, &MouseRect);
+        ExReleaseFastMutexUnsafe(&CurInfo->CursorMutex);
+      }
+      res = TRUE;
+    }
+        
+    ObDereferenceObject(InputWindowStation);
+    return res;
+  }
+  else
+    return FALSE;
+}
+
+VOID /* STDCALL */
 MouseGDICallBack(PMOUSE_INPUT_DATA Data, ULONG InputCount)
 /*
  * FUNCTION: Call by the mouse driver when input events occur.
  */
 {
   ULONG i;
+  PSYSTEM_CURSORINFO CurInfo;
+  PSYSCURSOR SysCursor;
+  BOOL MouseEnabled = FALSE;
+  BOOL MouseMoveAdded = FALSE;
+  LONG mouse_ox, mouse_oy;
   LONG mouse_cx = 0, mouse_cy = 0;
-  HDC hDC = W32kGetScreenDC();
+  HDC hDC;
   PDC dc;
   PSURFOBJ SurfObj;
   PSURFGDI SurfGDI;
@@ -222,59 +399,111 @@ MouseGDICallBack(PMOUSE_INPUT_DATA Data, ULONG InputCount)
   LARGE_INTEGER LargeTickCount;
   ULONG TickCount;
   static ULONG ButtonsDown = 0;
+  
+  hDC = IntGetScreenDC();
+  
+  if(!hDC || !InputWindowStation)
+    return;
 
-  KeQueryTickCount(&LargeTickCount);
-  TickCount = LargeTickCount.u.LowPart;
-
-  if (hDC == 0)
+  if(IntGetWindowStationObject(InputWindowStation))
   {
-    return;
+    CurInfo = &InputWindowStation->SystemCursor;
+    SysCursor = &CurInfo->SystemCursors[CurInfo->CurrentCursor];
+    MouseEnabled = CurInfo->Enabled;
+    if(!MouseEnabled)
+    {
+      ObDereferenceObject(InputWindowStation);
+      return;
+    }
+    mouse_ox = CurInfo->x;
+    mouse_oy = CurInfo->y;
   }
+  else
+    return;
 
-  dc = DC_HandleToPtr(hDC);
+  dc = DC_LockDc(hDC);
   SurfObj = (PSURFOBJ)AccessUserObject((ULONG) dc->Surface);
   SurfGDI = (PSURFGDI)AccessInternalObject((ULONG) dc->Surface);
-  DC_ReleasePtr( hDC );
+  DC_UnlockDc( hDC );
 
   /* Compile the total mouse movement change and dispatch button events. */
   for (i = 0; i < InputCount; i++)
   {
     mouse_cx += Data[i].LastX;
     mouse_cy += Data[i].LastY;
+    
+    CurInfo->x += Data[i].LastX;
+    CurInfo->y += Data[i].LastY;
+    
+    CurInfo->x = max(CurInfo->x, 0);
+    CurInfo->y = max(CurInfo->y, 0);
+    CurInfo->x = min(CurInfo->x, SurfObj->sizlBitmap.cx - 1);
+    CurInfo->y = min(CurInfo->y, SurfObj->sizlBitmap.cy - 1);
+    
+    IntCheckClipCursor(&CurInfo->x, &CurInfo->y, CurInfo);
+    
+    KeQueryTickCount(&LargeTickCount);
+    TickCount = LargeTickCount.u.LowPart;
 
     Msg.wParam = ButtonsDown;
-    Msg.lParam = MAKELPARAM(mouse_x + mouse_cx, mouse_y + mouse_cy);
+    Msg.lParam = MAKELPARAM(CurInfo->x, CurInfo->y);
     Msg.message = WM_MOUSEMOVE;
     Msg.time = TickCount;
-    Msg.pt.x = mouse_x + mouse_cx;
-    Msg.pt.y = mouse_y + mouse_cy;
-    if ((0 != Data[i].LastX) || (0 != Data[i].LastY))
-    {
-      MsqInsertSystemMessage(&Msg);
-    }
-
+    Msg.pt.x = CurInfo->x;
+    Msg.pt.y = CurInfo->y;
+    
+    MouseMoveAdded = FALSE;
+    
     if (Data[i].ButtonFlags != 0)
     {
+
       if ((Data[i].ButtonFlags & MOUSE_LEFT_BUTTON_DOWN) > 0)
       {
-       Msg.wParam  = MK_LBUTTON;
-        Msg.message = WM_LBUTTONDOWN;
+        /* insert WM_MOUSEMOVE messages before Button down messages */
+        if ((0 != Data[i].LastX) || (0 != Data[i].LastY))
+        {
+          MsqInsertSystemMessage(&Msg, FALSE);
+          MouseMoveAdded = TRUE;
+        }
+       Msg.wParam  = CurInfo->SwapButtons ? MK_RBUTTON : MK_LBUTTON;
+       if(IntDetectDblClick(CurInfo, TickCount))
+          Msg.message = CurInfo->SwapButtons ? WM_RBUTTONDBLCLK : WM_LBUTTONDBLCLK;
+        else
+          Msg.message = CurInfo->SwapButtons ? WM_RBUTTONDOWN : WM_LBUTTONDOWN;
       }
       if ((Data[i].ButtonFlags & MOUSE_MIDDLE_BUTTON_DOWN) > 0)
       {
+        /* insert WM_MOUSEMOVE messages before Button down messages */
+        if ((0 != Data[i].LastX) || (0 != Data[i].LastY))
+        {
+          MsqInsertSystemMessage(&Msg, FALSE);
+          MouseMoveAdded = TRUE;
+        }
        Msg.wParam  = MK_MBUTTON;
-        Msg.message = WM_MBUTTONDOWN;
+       if(IntDetectDblClick(CurInfo, TickCount))
+         Msg.message = WM_MBUTTONDBLCLK;
+       else
+          Msg.message = WM_MBUTTONDOWN;
       }
       if ((Data[i].ButtonFlags & MOUSE_RIGHT_BUTTON_DOWN) > 0)
       {
-       Msg.wParam  = MK_RBUTTON;
-        Msg.message = WM_RBUTTONDOWN;
+        /* insert WM_MOUSEMOVE messages before Button down messages */
+        if ((0 != Data[i].LastX) || (0 != Data[i].LastY))
+        {
+          MsqInsertSystemMessage(&Msg, FALSE);
+          MouseMoveAdded = TRUE;
+        }
+       Msg.wParam  = CurInfo->SwapButtons ? MK_LBUTTON : MK_RBUTTON;
+       if(IntDetectDblClick(CurInfo, TickCount))
+         Msg.message = CurInfo->SwapButtons ? WM_LBUTTONDBLCLK : WM_RBUTTONDBLCLK;
+       else
+          Msg.message = CurInfo->SwapButtons ? WM_LBUTTONDOWN : WM_RBUTTONDOWN;
       }
 
       if ((Data[i].ButtonFlags & MOUSE_LEFT_BUTTON_UP) > 0)
       {
-       Msg.wParam  = MK_LBUTTON;
-        Msg.message = WM_LBUTTONUP;
+       Msg.wParam  = CurInfo->SwapButtons ? MK_RBUTTON : MK_LBUTTON;
+        Msg.message = CurInfo->SwapButtons ? WM_RBUTTONUP : WM_LBUTTONUP;
       }
       if ((Data[i].ButtonFlags & MOUSE_MIDDLE_BUTTON_UP) > 0)
       {
@@ -283,33 +512,53 @@ MouseGDICallBack(PMOUSE_INPUT_DATA Data, ULONG InputCount)
       }
       if ((Data[i].ButtonFlags & MOUSE_RIGHT_BUTTON_UP) > 0)
       {
-       Msg.wParam  = MK_RBUTTON;
-        Msg.message = WM_RBUTTONUP;
+       Msg.wParam  = CurInfo->SwapButtons ? MK_LBUTTON : MK_RBUTTON;
+        Msg.message = CurInfo->SwapButtons ? WM_LBUTTONUP : WM_RBUTTONUP;
       }
 
-      MsqInsertSystemMessage(&Msg);
+      MsqInsertSystemMessage(&Msg, FALSE);
+      
+      /* insert WM_MOUSEMOVE messages after Button up messages */
+      if(!MouseMoveAdded && ((0 != Data[i].LastX) || (0 != Data[i].LastY)))
+      {
+        Msg.wParam = ButtonsDown;
+        Msg.message = WM_MOUSEMOVE;
+        MsqInsertSystemMessage(&Msg, FALSE);
+        MouseMoveAdded = TRUE;
+      }
     }
   }
 
   /* If the mouse moved then move the pointer. */
   if ((mouse_cx != 0 || mouse_cy != 0) && MouseEnabled)
   {
-    mouse_x += mouse_cx;
-    mouse_y += mouse_cy;
-
-    mouse_x = max(mouse_x, 0);
-    mouse_y = max(mouse_y, 0);
-    mouse_x = min(mouse_x, 620);
-    mouse_y = min(mouse_y, 460);
 
-    if (SafetySwitch == FALSE && SafetySwitch2 == FALSE)
+    if(!MouseMoveAdded)
     {
-      SurfGDI->MovePointer(SurfObj, mouse_x, mouse_y, &MouseRect);
+     KeQueryTickCount(&LargeTickCount);
+     TickCount = LargeTickCount.u.LowPart;
+      Msg.wParam = ButtonsDown;
+      Msg.message = WM_MOUSEMOVE;
+      Msg.pt.x = CurInfo->x;
+      Msg.pt.y = CurInfo->y;
+      Msg.time = TickCount;
+      Msg.lParam = MAKELPARAM(CurInfo->x, CurInfo->y);
+      MsqInsertSystemMessage(&Msg, TRUE);
+    }
+    
+    if (!CurInfo->SafetySwitch && !CurInfo->SafetySwitch2 &&
+        ((mouse_ox != CurInfo->x) || (mouse_oy != CurInfo->y)))
+    {
+      ExAcquireFastMutexUnsafe(&CurInfo->CursorMutex);
+      SurfGDI->MovePointer(SurfObj, CurInfo->x, CurInfo->y, &MouseRect);
+      ExReleaseFastMutexUnsafe(&CurInfo->CursorMutex);
     }
   }
+
+  ObDereferenceObject(InputWindowStation);
 }
 
-VOID
+VOID FASTCALL
 EnableMouse(HDC hDisplayDC)
 {
   PDC dc;
@@ -319,42 +568,64 @@ EnableMouse(HDC hDisplayDC)
   PSURFOBJ MouseSurf;
   SIZEL MouseSize;
   RECTL MouseRect;
+  PSYSTEM_CURSORINFO CurInfo;
+  PSYSCURSOR SysCursor;
 
-  if( hDisplayDC )
+  if( hDisplayDC && InputWindowStation)
   {
-    dc = DC_HandleToPtr(hDisplayDC);
+    if(!IntGetWindowStationObject(InputWindowStation))
+    {
+       InputWindowStation->SystemCursor.Enabled = FALSE;
+       return;
+    }
+    
+    CurInfo = &InputWindowStation->SystemCursor;
+    SysCursor = &CurInfo->SystemCursors[CurInfo->CurrentCursor];
+    
+    dc = DC_LockDc(hDisplayDC);
     SurfObj = (PSURFOBJ)AccessUserObject((ULONG) dc->Surface);
     SurfGDI = (PSURFGDI)AccessInternalObject((ULONG) dc->Surface);
-    DC_ReleasePtr( hDisplayDC );
+    DC_UnlockDc( hDisplayDC );
+    
+    /* Tell the display driver to set the pointer shape. */
+    CurInfo->x = SurfObj->sizlBitmap.cx / 2;
+    CurInfo->y = SurfObj->sizlBitmap.cy / 2;
 
     /* Create the default mouse cursor. */
-    mouse_width = 32;
-    mouse_height = 32;
-    MouseSize.cx = 32;
-    MouseSize.cy = 64;
+    MouseSize.cx = SysCursor->cx;
+    MouseSize.cy = SysCursor->cy * 2;
     hMouseSurf = EngCreateBitmap(MouseSize, 4, BMF_1BPP, BMF_TOPDOWN, DefaultCursor);
     MouseSurf = (PSURFOBJ)AccessUserObject((ULONG) hMouseSurf);
 
-    /* Tell the display driver to set the pointer shape. */
-#if 0
-    mouse_x = SurfObj->sizlBitmap.cx / 2;
-    mouse_y = SurfObj->sizlBitmap.cy / 2;
-#else
-    mouse_x = 320;
-    mouse_y = 240;
-#endif
+    DPRINT("Setting Cursor up at 0x%x, 0x%x\n", CurInfo->x, CurInfo->y);
+    IntCheckClipCursor(&CurInfo->x, 
+                       &CurInfo->y,
+                       CurInfo);
+
     PointerStatus = SurfGDI->SetPointerShape(SurfObj, MouseSurf, NULL, NULL,
-                                             0, 0, mouse_x, mouse_y, &MouseRect,
+                                             SysCursor->hx,
+                                             SysCursor->hy, 
+                                             CurInfo->x, 
+                                             CurInfo->y, 
+                                             &MouseRect,
                                              SPS_CHANGE);
 
-    MouseEnabled = (SPS_ACCEPT_EXCLUDE == PointerStatus ||
-                    SPS_ACCEPT_NOEXCLUDE == PointerStatus);
+    InputWindowStation->SystemCursor.Enabled = (SPS_ACCEPT_EXCLUDE == PointerStatus ||
+                                                SPS_ACCEPT_NOEXCLUDE == PointerStatus);
 
     EngDeleteSurface(hMouseSurf);
+    ObDereferenceObject(InputWindowStation);
+    
   }
   else
   {
-    MouseEnabled = FALSE;
+    if(IntGetWindowStationObject(InputWindowStation))
+    {
+       InputWindowStation->SystemCursor.Enabled = FALSE;
+       InputWindowStation->SystemCursor.CursorClipInfo.IsClipped = FALSE;
+          ObDereferenceObject(InputWindowStation);
+       return;
+    }
   }
 }
-
+/* EOF */