* Sync up to trunk head (r64921).
[reactos.git] / win32ss / user / ntuser / cursoricon_new.c
index ece23ce..2fbfe99 100644 (file)
@@ -2,7 +2,7 @@
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS Win32k subsystem
  * PURPOSE:          Cursor and icon functions
- * FILE:             subsystems/win32/win32k/ntuser/cursoricon.c
+ * FILE:             win32ss/user/ntuser/cursoricon.c
  * PROGRAMER:        ReactOS Team
  */
 /*
@@ -63,9 +63,9 @@ PCURICON_OBJECT FASTCALL UserGetCurIconObject(HCURSOR hCurIcon)
         return NULL;
     }
 
-    if(UserObjectInDestroy(hCurIcon))
+    if (UserObjectInDestroy(hCurIcon))
     {
-        ERR("Requesting destroyed cursor.\n");
+        WARN("Requesting invalid/destroyed cursor.\n");
         EngSetLastError(ERROR_INVALID_CURSOR_HANDLE);
         return NULL;
     }
@@ -133,7 +133,7 @@ IntCreateCurIconHandle(BOOLEAN Animated)
     CurIcon = UserCreateObject(
         gHandleTable,
         NULL,
-        NULL,
+        GetW32ThreadInfo(),
         &hCurIcon,
         TYPE_CURSOR,
         Animated ? sizeof(ACON) : sizeof(CURICON_OBJECT));
@@ -149,35 +149,53 @@ IntCreateCurIconHandle(BOOLEAN Animated)
     return hCurIcon;
 }
 
-BOOLEAN FASTCALL
-IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, BOOLEAN bForce)
+BOOLEAN
+IntDestroyCurIconObject(
+    _In_ PVOID Object)
 {
-    if(CurIcon->CURSORF_flags & CURSORF_CURRENT)
-    {
-        /* Mark the object as destroyed, and fail, as per tests */
-        TRACE("Cursor is current, marking as destroyed.\n");
-        UserDeleteObject(CurIcon->head.h, TYPE_CURSOR);
-        return FALSE;
-    }
+    PCURICON_OBJECT CurIcon = Object;
 
-    if(CurIcon->head.ppi != PsGetCurrentProcessWin32Process())
-    {
-        /* This object doesn't belong to the current process */
-        WARN("Trying to delete foreign cursor!\n");
-        UserDereferenceObject(CurIcon);
-        EngSetLastError(ERROR_DESTROY_OBJECT_OF_OTHER_THREAD);
-        return FALSE;
-    }
-    
-    /* Do not destroy it if it is shared. (And we're not forced to) */
-    if((CurIcon->CURSORF_flags & CURSORF_LRSHARED) && !bForce)
+    /* Try finding it in its process cache */
+    if (CurIcon->CURSORF_flags & CURSORF_LRSHARED)
     {
-        /* Tests show this is a valid call */
-        WARN("Trying to destroy shared cursor!\n");
-        UserDereferenceObject(CurIcon);
-        return TRUE;
+        PPROCESSINFO ppi;
+
+        ppi = CurIcon->head.ppi;
+        if (ppi->pCursorCache == CurIcon)
+        {
+            ppi->pCursorCache = CurIcon->pcurNext;
+            UserDereferenceObject(CurIcon);
+        }
+        else
+        {
+            PCURICON_OBJECT CacheCurIcon = ppi->pCursorCache;
+            while (CacheCurIcon)
+            {
+                if (CacheCurIcon->pcurNext == CurIcon)
+                {
+                    CacheCurIcon->pcurNext = CurIcon->pcurNext;
+                    break;
+                }
+                CacheCurIcon = CacheCurIcon->pcurNext;
+            }
+
+            /* We must have found it! */
+            ASSERT(CacheCurIcon != NULL);
+            UserDereferenceObject(CurIcon);
+        }
     }
 
+    /* We just mark the handle as being destroyed.
+     * Deleting all the stuff will be deferred to the actual struct free. */
+    return UserDeleteObject(CurIcon->head.h, TYPE_CURSOR);
+}
+
+void
+FreeCurIconObject(
+    _In_ PVOID Object)
+{
+    PCURICON_OBJECT CurIcon = Object;
+    
     if(!(CurIcon->CURSORF_flags & CURSORF_ACON))
     {
         HBITMAP bmpMask = CurIcon->hbmMask;
@@ -210,7 +228,7 @@ IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, BOOLEAN bForce)
         UINT i;
 
         for(i = 0; i < AniCurIcon->cpcur; i++)
-            IntDestroyCurIconObject(AniCurIcon->aspcur[i], TRUE);
+            IntDestroyCurIconObject(AniCurIcon->aspcur[i]);
         ExFreePoolWithTag(AniCurIcon->aspcur, USERTAG_CURSOR);
     }
 
@@ -224,29 +242,24 @@ IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, BOOLEAN bForce)
         CurIcon->atomModName = 0;
     }
 
-    /* We were given a pointer, no need to keep the reference any longer! */
-    UserDereferenceObject(CurIcon);
-    return UserDeleteObject(CurIcon->head.h, TYPE_CURSOR);
+    /* Finally free the thing */
+    FreeProcMarkObject(CurIcon);
 }
 
 VOID FASTCALL
-IntCleanupCurIcons(struct _EPROCESS *Process, PPROCESSINFO Win32Process)
+IntCleanupCurIconCache(PPROCESSINFO Win32Process)
 {
     PCURICON_OBJECT CurIcon;
 
     /* Run through the list of icon objects */
-    while(Win32Process->pCursorCache)
+    while (Win32Process->pCursorCache)
     {
         CurIcon = Win32Process->pCursorCache;
         Win32Process->pCursorCache = CurIcon->pcurNext;
-        /* One ref for the handle, one for the list,
-         * and potentially one from an other process via SetCursor */
-        ASSERT(CurIcon->head.cLockObj <= 3);
-        IntDestroyCurIconObject(CurIcon, TRUE);
+        UserDereferenceObject(CurIcon);
     }
 }
 
-
 /*
  * @implemented
  */
@@ -610,7 +623,7 @@ NtUserClipCursor(
         prcl = &rclLocal;
     }
 
-       UserEnterExclusive();
+    UserEnterExclusive();
 
     /* Call the internal function */
     bResult = UserClipCursor(prcl);
@@ -630,27 +643,54 @@ NtUserDestroyCursor(
   _In_   HANDLE hCurIcon,
   _In_   BOOL bForce)
 {
-    PCURICON_OBJECT CurIcon;
     BOOL ret;
-    DECLARE_RETURN(BOOL);
+    PCURICON_OBJECT CurIcon = NULL;
 
-    TRACE("Enter NtUserDestroyCursorIcon\n");
+    TRACE("Enter NtUserDestroyCursorIcon (%p, %u)\n", hCurIcon, bForce);
     UserEnterExclusive();
 
-    if (!(CurIcon = UserGetCurIconObject(hCurIcon)))
+    CurIcon = UserGetCurIconObject(hCurIcon);
+    if (!CurIcon)
     {
-        RETURN(FALSE);
+        ret = FALSE;
+        goto leave;
     }
 
-    ret = IntDestroyCurIconObject(CurIcon, bForce);
-    /* Note: IntDestroyCurIconObject will remove our reference for us! */
+    if (!bForce)
+    {
+        /* Maybe we have good reasons not to destroy this object */
+        if (CurIcon->head.ppi != PsGetCurrentProcessWin32Process())
+        {
+            /* No way, you're not touching my cursor */
+            ret = FALSE;
+            goto leave;
+        }
 
-    RETURN(ret);
+        if (CurIcon->CURSORF_flags & CURSORF_CURRENT)
+        {
+            WARN("Trying to delete current cursor!\n");
+            ret = FALSE;
+            goto leave;
+        }
 
-CLEANUP:
-    TRACE("Leave NtUserDestroyCursorIcon, ret=%i\n",_ret_);
+        if (CurIcon->CURSORF_flags & CURSORF_LRSHARED)
+        {
+            WARN("Trying to delete shared cursor.\n");
+            /* This one is not an error */
+            ret = TRUE;
+            goto leave;
+        }
+    }
+
+    /* Destroy the handle */
+    ret = IntDestroyCurIconObject(CurIcon);
+
+leave:
+    if (CurIcon)
+        UserDereferenceObject(CurIcon);
+    TRACE("Leave NtUserDestroyCursorIcon, ret=%i\n", ret);
     UserLeave();
-    END_CLEANUP;
+    return ret;
 }
 
 
@@ -810,7 +850,7 @@ NtUserSetCursor(
     PCURICON_OBJECT pcurOld, pcurNew;
     HCURSOR hOldCursor = NULL;
 
-    TRACE("Enter NtUserSetCursor\n");
+    TRACE("Enter NtUserSetCursor: %p\n", hCursor);
     UserEnterExclusive();
 
     if (hCursor)
@@ -832,17 +872,11 @@ NtUserSetCursor(
     if (pcurOld)
     {
         hOldCursor = pcurOld->head.h;
-        pcurOld->CURSORF_flags &= ~CURSORF_CURRENT;
-        if(UserObjectInDestroy(hOldCursor))
-        {
-            /* Destroy it once and for all */
-            IntDestroyCurIconObject(pcurOld, TRUE);
+        /* See if it was destroyed in the meantime */
+        if (UserObjectInDestroy(hOldCursor))
             hOldCursor = NULL;
-        }
-        else
-        {
-            UserDereferenceObject(pcurOld);
-        }
+        pcurOld->CURSORF_flags &= ~CURSORF_CURRENT;
+        UserDereferenceObject(pcurOld);
     }
 
 leave:
@@ -1028,7 +1062,7 @@ done:
         for(i = 0; i < numFrames; i++)
         {
             if(AniCurIcon->aspcur[i])
-                IntDestroyCurIconObject(AniCurIcon->aspcur[i], TRUE);
+                IntDestroyCurIconObject(AniCurIcon->aspcur[i]);
         }
         AniCurIcon->cicur = 0;
         AniCurIcon->cpcur = 0;
@@ -1135,7 +1169,7 @@ UserDrawIconEx(
     RECTL_vOffsetRect(&rcDest, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y);
     
     /* Prepare the underlying surface */
-    DC_vPrepareDCsForBlit(pdc, rcDest, NULL, rcDest);
+    DC_vPrepareDCsForBlit(pdc, &rcDest, NULL, NULL);
 
     /* We now have our destination surface and rectangle */
     psurfDest = pdc->dclevel.pSurface;
@@ -1231,7 +1265,7 @@ UserDrawIconEx(
         /* We now have our destination surface */
         psurfDest = psurfOffScreen;
 #else
-        pdcClipObj = pdc->rosdc.CombinedClip;
+        pdcClipObj = &pdc->co.ClipObj;
         /* Paint the brush */
         EBRUSHOBJ_vInit(&eboFill, pbrush, psurfDest, 0x00FFFFFF, 0, NULL);
         
@@ -1262,14 +1296,14 @@ UserDrawIconEx(
     {
         /* We directly draw to the DC */
         TRACE("Performing on screen rendering.\n");
-        pdcClipObj = pdc->rosdc.CombinedClip;
+        pdcClipObj = &pdc->co.ClipObj;
         // psurfOffScreen = NULL;
     }
 
     /* Now do the rendering */
-       if(hbmAlpha && ((diFlags & DI_NORMAL) == DI_NORMAL))
-       {
-           BLENDOBJ blendobj = { {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA } };
+    if(hbmAlpha && ((diFlags & DI_NORMAL) == DI_NORMAL))
+    {
+        BLENDOBJ blendobj = { {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA } };
         PSURFACE psurf = NULL;
 
         psurf = SURFACE_ShareLockSurface(hbmAlpha);
@@ -1294,7 +1328,7 @@ UserDrawIconEx(
         EXLATEOBJ_vCleanup(&exlo);
         SURFACE_ShareUnlockSurface(psurf);
         if(Ret) goto done;
-               ERR("NtGdiAlphaBlend failed!\n");
+        ERR("NtGdiAlphaBlend failed!\n");
     }
 NoAlpha:
     if (diFlags & DI_MASK)
@@ -1327,7 +1361,7 @@ NoAlpha:
 
     if(diFlags & DI_IMAGE)
     {
-               if (psurfColor)
+        if (psurfColor)
         {
             DWORD rop4 = (diFlags & DI_MASK) ? ROP4_SRCINVERT : ROP4_SRCCOPY ;