- Properly handle deletion of cursor/Icon objects
- Gracefully change object owner when process closes
- Remove useless check in a macro

svn path=/trunk/; revision=57641
This commit is contained in:
Jérôme Gardou 2012-10-28 14:45:35 +00:00
parent 2108e7256c
commit b6e5342bce
4 changed files with 64 additions and 52 deletions

View file

@ -163,6 +163,6 @@ BOOL NTAPI W32kDosPathNameToNtPathName(PCWSTR, PUNICODE_STRING);
#define LIST_FOR_EACH_SAFE(cursor, cursor2, list, type, field) \ #define LIST_FOR_EACH_SAFE(cursor, cursor2, list, type, field) \
for ((cursor) = CONTAINING_RECORD((list)->Flink, type, field), \ for ((cursor) = CONTAINING_RECORD((list)->Flink, type, field), \
(cursor2) = CONTAINING_RECORD((cursor)->field.Flink, type, field); \ (cursor2) = CONTAINING_RECORD((cursor)->field.Flink, type, field); \
&(cursor)->field != (list) && ((&((cursor)->field)) != NULL); \ &(cursor)->field != (list); \
(cursor) = (cursor2), \ (cursor) = (cursor2), \
(cursor2) = CONTAINING_RECORD((cursor)->field.Flink, type, field)) (cursor2) = CONTAINING_RECORD((cursor)->field.Flink, type, field))

View file

@ -234,55 +234,54 @@ IntCreateCurIconHandle()
} }
BOOLEAN FASTCALL BOOLEAN FASTCALL
IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, BOOL ProcessCleanup) IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, PPROCESSINFO ppi)
{ {
PSYSTEM_CURSORINFO CurInfo; PSYSTEM_CURSORINFO CurInfo;
HBITMAP bmpMask, bmpColor; HBITMAP bmpMask, bmpColor;
BOOLEAN Ret; BOOLEAN Ret, bListEmpty, bFound = FALSE;
PCURICON_PROCESS Current = NULL; PCURICON_PROCESS Current = NULL;
PPROCESSINFO W32Process = PsGetCurrentProcessWin32Process();
/* Private objects can only be destroyed by their own process */ /* For handles created without any data (error handling) */
if (NULL == CurIcon->hModule) if(IsListEmpty(&CurIcon->ProcessList))
{ goto emptyList;
ASSERT(CurIcon->ProcessList.Flink->Flink == &CurIcon->ProcessList);
Current = CONTAINING_RECORD(CurIcon->ProcessList.Flink, CURICON_PROCESS, ListEntry);
if (Current->Process != W32Process)
{
ERR("Trying to destroy private icon/cursor of another process\n");
return FALSE;
}
}
else if (! ProcessCleanup)
{
TRACE("Trying to destroy shared icon/cursor\n");
return FALSE;
}
/* Now find this process in the list of processes referencing this object and /* Now find this process in the list of processes referencing this object and
remove it from that list */ remove it from that list */
LIST_FOR_EACH(Current, &CurIcon->ProcessList, CURICON_PROCESS, ListEntry) LIST_FOR_EACH(Current, &CurIcon->ProcessList, CURICON_PROCESS, ListEntry)
{ {
if (Current->Process == W32Process) if (Current->Process == ppi)
{ {
RemoveEntryList(&Current->ListEntry); bFound = TRUE;
bListEmpty = RemoveEntryList(&Current->ListEntry);
break; break;
} }
} }
if(!bFound)
{
/* This object doesn't belong to this process */
EngSetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
ExFreeToPagedLookasideList(pgProcessLookasideList, Current); ExFreeToPagedLookasideList(pgProcessLookasideList, Current);
/* If there are still processes referencing this object we can't destroy it yet */ /* If there are still processes referencing this object we can't destroy it yet */
if (! IsListEmpty(&CurIcon->ProcessList)) if (!bListEmpty)
{ {
if(CurIcon->head.ppi == ppi)
{
/* Set the first process of the list as owner */
Current = CONTAINING_RECORD(CurIcon->ProcessList.Flink, CURICON_PROCESS, ListEntry);
UserSetObjectOwner(CurIcon, otCursorIcon, Current->Process);
}
UserDereferenceObject(CurIcon);
return TRUE; return TRUE;
} }
emptyList:
if (! ProcessCleanup) /* Remove it from the list */
{
RemoveEntryList(&CurIcon->ListEntry); RemoveEntryList(&CurIcon->ListEntry);
}
CurInfo = IntGetSysCursorInfo(); CurInfo = IntGetSysCursorInfo();
@ -320,33 +319,13 @@ VOID FASTCALL
IntCleanupCurIcons(struct _EPROCESS *Process, PPROCESSINFO Win32Process) IntCleanupCurIcons(struct _EPROCESS *Process, PPROCESSINFO Win32Process)
{ {
PCURICON_OBJECT CurIcon, tmp; PCURICON_OBJECT CurIcon, tmp;
PCURICON_PROCESS ProcessData;
/* Run through the list of icon objects */
LIST_FOR_EACH_SAFE(CurIcon, tmp, &gCurIconList, CURICON_OBJECT, ListEntry) LIST_FOR_EACH_SAFE(CurIcon, tmp, &gCurIconList, CURICON_OBJECT, ListEntry)
{ {
UserReferenceObject(CurIcon); UserReferenceObject(CurIcon);
// if(NT_SUCCESS(UserReferenceObjectByPointer(Object, otCursorIcon))) IntDestroyCurIconObject(CurIcon, Win32Process);
{
LIST_FOR_EACH(ProcessData, &CurIcon->ProcessList, CURICON_PROCESS, ListEntry)
{
if (Win32Process == ProcessData->Process)
{
RemoveEntryList(&CurIcon->ListEntry);
IntDestroyCurIconObject(CurIcon, TRUE);
CurIcon = NULL;
break;
} }
}
// UserDereferenceObject(Object);
}
if (CurIcon)
{
UserDereferenceObject(CurIcon);
}
}
} }
@ -649,7 +628,7 @@ NtUserDestroyCursor(
RETURN(FALSE); RETURN(FALSE);
} }
ret = IntDestroyCurIconObject(CurIcon, FALSE); ret = IntDestroyCurIconObject(CurIcon, PsGetCurrentProcessWin32Process());
/* Note: IntDestroyCurIconObject will remove our reference for us! */ /* Note: IntDestroyCurIconObject will remove our reference for us! */
RETURN(ret); RETURN(ret);

View file

@ -516,6 +516,38 @@ UserReferenceObjectByHandle(HANDLE handle, USER_OBJECT_TYPE type)
return object; return object;
} }
VOID
FASTCALL
UserSetObjectOwner(PVOID obj, USER_OBJECT_TYPE type, PVOID owner)
{
PUSER_HANDLE_ENTRY entry = handle_to_entry(gHandleTable, ((PHEAD)obj)->h );
PPROCESSINFO ppi, oldppi;
/* This must be called with a valid object */
ASSERT(entry);
/* For now, only supported for CursorIcon object */
switch(type)
{
case otCursorIcon:
ppi = (PPROCESSINFO)owner;
entry->pi = ppi;
oldppi = ((PPROCMARKHEAD)obj)->ppi;
((PPROCMARKHEAD)obj)->ppi = ppi;
break;
default:
ASSERT(FALSE);
return;
}
oldppi->UserHandleCount--;
ppi->UserHandleCount++;
#if DBG
oldppi->DbgHandleCount[type]--;
ppi->DbgHandleCount[type]++;
#endif
}
/* /*
* NtUserValidateHandleSecure * NtUserValidateHandleSecure
* *

View file

@ -40,6 +40,7 @@ PVOID UserGetObjectNoErr(PUSER_HANDLE_TABLE, HANDLE, USER_OBJECT_TYPE);
BOOL FASTCALL UserCreateHandleTable(VOID); BOOL FASTCALL UserCreateHandleTable(VOID);
BOOL FASTCALL UserObjectInDestroy(HANDLE); BOOL FASTCALL UserObjectInDestroy(HANDLE);
void DbgUserDumpHandleTable(); void DbgUserDumpHandleTable();
VOID FASTCALL UserSetObjectOwner(PVOID obj, USER_OBJECT_TYPE type, PVOID owner);
static __inline VOID static __inline VOID
UserRefObjectCo(PVOID obj, PUSER_REFERENCE_ENTRY UserReferenceEntry) UserRefObjectCo(PVOID obj, PUSER_REFERENCE_ENTRY UserReferenceEntry)