* Sync up to trunk head (r64921).
[reactos.git] / win32ss / user / ntuser / cursoricon_new.c
index 40e2845..2fbfe99 100644 (file)
@@ -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,87 +242,22 @@ 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);
-    }
-}
-
-HCURSOR FASTCALL
-IntSetCursor(
-    HCURSOR hCursor)
-{
-    PCURICON_OBJECT pcurOld, pcurNew;
-    HCURSOR hOldCursor = NULL;
-
-    if (hCursor)
-    {
-        pcurNew = UserGetCurIconObject(hCursor);
-        if (!pcurNew)
-        {
-            EngSetLastError(ERROR_INVALID_CURSOR_HANDLE);
-            goto leave;
-        }
-        pcurNew->CURSORF_flags |= CURSORF_CURRENT;
-    }
-    else
-    {
-        pcurNew = NULL;
-    }
-
-    pcurOld = UserSetCursor(pcurNew, FALSE);
-    if (pcurOld)
-    {
-        hOldCursor = pcurOld->head.h;
-        pcurOld->CURSORF_flags &= ~CURSORF_CURRENT;
-        if(UserObjectInDestroy(hOldCursor))
-        {
-            /* Destroy it once and for all */
-            IntDestroyCurIconObject(pcurOld, TRUE);
-            hOldCursor = NULL;
-        }
-        else
-        {
-            UserDereferenceObject(pcurOld);
-        }
-    }
-leave:
-    return hOldCursor;
-}
-
-BOOL FASTCALL
-IntDestroyCursor(
-  HANDLE hCurIcon,
-  BOOL bForce)
-{
-    PCURICON_OBJECT CurIcon;
-    BOOL ret;
-
-    if (!(CurIcon = UserGetCurIconObject(hCurIcon)))
-    {
-        return(FALSE);
+        UserDereferenceObject(CurIcon);
     }
-
-    ret = IntDestroyCurIconObject(CurIcon, bForce);
-    /* Note: IntDestroyCurIconObject will remove our reference for us! */
-
-    return ret;
 }
 
 /*
@@ -690,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;
 }
 
 
@@ -870,7 +850,7 @@ NtUserSetCursor(
     PCURICON_OBJECT pcurOld, pcurNew;
     HCURSOR hOldCursor = NULL;
 
-    TRACE("Enter NtUserSetCursor\n");
+    TRACE("Enter NtUserSetCursor: %p\n", hCursor);
     UserEnterExclusive();
 
     if (hCursor)
@@ -892,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:
@@ -1088,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;