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;
}
CurIcon = UserCreateObject(
gHandleTable,
NULL,
- NULL,
+ GetW32ThreadInfo(),
&hCurIcon,
TYPE_CURSOR,
Animated ? sizeof(ACON) : sizeof(CURICON_OBJECT));
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;
UINT i;
for(i = 0; i < AniCurIcon->cpcur; i++)
- IntDestroyCurIconObject(AniCurIcon->aspcur[i], TRUE);
+ IntDestroyCurIconObject(AniCurIcon->aspcur[i]);
ExFreePoolWithTag(AniCurIcon->aspcur, USERTAG_CURSOR);
}
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;
}
/*
_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;
}
PCURICON_OBJECT pcurOld, pcurNew;
HCURSOR hOldCursor = NULL;
- TRACE("Enter NtUserSetCursor\n");
+ TRACE("Enter NtUserSetCursor: %p\n", hCursor);
UserEnterExclusive();
if (hCursor)
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:
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;