diff --git a/reactos/win32ss/gdi/ntgdi/misc.h b/reactos/win32ss/gdi/ntgdi/misc.h index addd2591806..22297f05bf7 100644 --- a/reactos/win32ss/gdi/ntgdi/misc.h +++ b/reactos/win32ss/gdi/ntgdi/misc.h @@ -163,6 +163,6 @@ BOOL NTAPI W32kDosPathNameToNtPathName(PCWSTR, PUNICODE_STRING); #define LIST_FOR_EACH_SAFE(cursor, cursor2, list, type, field) \ for ((cursor) = CONTAINING_RECORD((list)->Flink, type, field), \ (cursor2) = CONTAINING_RECORD((cursor)->field.Flink, type, field); \ - &(cursor)->field != (list) && ((&((cursor)->field)) != NULL); \ + &(cursor)->field != (list); \ (cursor) = (cursor2), \ (cursor2) = CONTAINING_RECORD((cursor)->field.Flink, type, field)) diff --git a/reactos/win32ss/user/ntuser/cursoricon.c b/reactos/win32ss/user/ntuser/cursoricon.c index 593e6ae7874..7ba56db0700 100644 --- a/reactos/win32ss/user/ntuser/cursoricon.c +++ b/reactos/win32ss/user/ntuser/cursoricon.c @@ -234,55 +234,54 @@ IntCreateCurIconHandle() } BOOLEAN FASTCALL -IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, BOOL ProcessCleanup) +IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, PPROCESSINFO ppi) { PSYSTEM_CURSORINFO CurInfo; HBITMAP bmpMask, bmpColor; - BOOLEAN Ret; + BOOLEAN Ret, bListEmpty, bFound = FALSE; PCURICON_PROCESS Current = NULL; - PPROCESSINFO W32Process = PsGetCurrentProcessWin32Process(); - - /* Private objects can only be destroyed by their own process */ - if (NULL == CurIcon->hModule) - { - 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; - } + + /* For handles created without any data (error handling) */ + if(IsListEmpty(&CurIcon->ProcessList)) + goto emptyList; /* Now find this process in the list of processes referencing this object and remove it from that list */ 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; } } + + if(!bFound) + { + /* This object doesn't belong to this process */ + EngSetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } ExFreeToPagedLookasideList(pgProcessLookasideList, Current); /* 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; } - - if (! ProcessCleanup) - { - RemoveEntryList(&CurIcon->ListEntry); - } +emptyList: + /* Remove it from the list */ + RemoveEntryList(&CurIcon->ListEntry); CurInfo = IntGetSysCursorInfo(); @@ -320,33 +319,13 @@ VOID FASTCALL IntCleanupCurIcons(struct _EPROCESS *Process, PPROCESSINFO Win32Process) { PCURICON_OBJECT CurIcon, tmp; - PCURICON_PROCESS ProcessData; + /* Run through the list of icon objects */ LIST_FOR_EACH_SAFE(CurIcon, tmp, &gCurIconList, CURICON_OBJECT, ListEntry) { UserReferenceObject(CurIcon); - // if(NT_SUCCESS(UserReferenceObjectByPointer(Object, otCursorIcon))) - { - 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); - } + IntDestroyCurIconObject(CurIcon, Win32Process); } - } @@ -649,7 +628,7 @@ NtUserDestroyCursor( RETURN(FALSE); } - ret = IntDestroyCurIconObject(CurIcon, FALSE); + ret = IntDestroyCurIconObject(CurIcon, PsGetCurrentProcessWin32Process()); /* Note: IntDestroyCurIconObject will remove our reference for us! */ RETURN(ret); diff --git a/reactos/win32ss/user/ntuser/object.c b/reactos/win32ss/user/ntuser/object.c index 94242ef83fe..d7785754073 100644 --- a/reactos/win32ss/user/ntuser/object.c +++ b/reactos/win32ss/user/ntuser/object.c @@ -516,6 +516,38 @@ UserReferenceObjectByHandle(HANDLE handle, USER_OBJECT_TYPE type) 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 * diff --git a/reactos/win32ss/user/ntuser/object.h b/reactos/win32ss/user/ntuser/object.h index 976fd463af6..08ae96ebcb2 100644 --- a/reactos/win32ss/user/ntuser/object.h +++ b/reactos/win32ss/user/ntuser/object.h @@ -40,6 +40,7 @@ PVOID UserGetObjectNoErr(PUSER_HANDLE_TABLE, HANDLE, USER_OBJECT_TYPE); BOOL FASTCALL UserCreateHandleTable(VOID); BOOL FASTCALL UserObjectInDestroy(HANDLE); void DbgUserDumpHandleTable(); +VOID FASTCALL UserSetObjectOwner(PVOID obj, USER_OBJECT_TYPE type, PVOID owner); static __inline VOID UserRefObjectCo(PVOID obj, PUSER_REFERENCE_ENTRY UserReferenceEntry)