From eb207003e7ec028bb8688e6c513b556e26d035e8 Mon Sep 17 00:00:00 2001 From: James Tabor Date: Wed, 28 Sep 2016 16:51:53 +0000 Subject: [PATCH] [Win32SS] - Fix menu crash, marking the menu object destroyed if the access count is more than one. Must remember these are not GDI objects. Expect a retooling of user objects soon. Set CORE-11892. svn path=/trunk/; revision=72837 --- reactos/win32ss/include/ntuser.h | 3 ++- reactos/win32ss/user/ntuser/menu.c | 28 +++++++------------------ reactos/win32ss/user/ntuser/object.c | 22 +++++++++++++++++++ reactos/win32ss/user/ntuser/object.h | 1 + reactos/win32ss/user/ntuser/window.c | 3 ++- reactos/win32ss/user/user32/misc/misc.c | 2 +- 6 files changed, 36 insertions(+), 23 deletions(-) diff --git a/reactos/win32ss/include/ntuser.h b/reactos/win32ss/include/ntuser.h index 46178df0faa..6d305010a26 100644 --- a/reactos/win32ss/include/ntuser.h +++ b/reactos/win32ss/include/ntuser.h @@ -13,7 +13,8 @@ typedef HANDLE HIMC; #define FIRST_USER_HANDLE 0x0020 /* first possible value for low word of user handle */ #define LAST_USER_HANDLE 0xffef /* last possible value for low word of user handle */ -#define HANDLEENTRY_INDESTROY 1 +#define HANDLEENTRY_DESTROY 1 +#define HANDLEENTRY_INDESTROY 2 typedef struct _USER_HANDLE_ENTRY { diff --git a/reactos/win32ss/user/ntuser/menu.c b/reactos/win32ss/user/ntuser/menu.c index c468499c2f4..bbdf8099895 100644 --- a/reactos/win32ss/user/ntuser/menu.c +++ b/reactos/win32ss/user/ntuser/menu.c @@ -322,13 +322,9 @@ UserDestroyMenuObject(PVOID Object) BOOL FASTCALL IntDestroyMenuObject(PMENU Menu, BOOL bRecurse) { - if(Menu) + if (Menu) { PWND Window; - ULONG Error; - - /* Remove all menu items */ - IntDestroyMenu( Menu, bRecurse); if (PsGetCurrentProcessSessionId() == Menu->head.rpdesk->rpwinstaParent->dwSessionId) { @@ -350,22 +346,14 @@ IntDestroyMenuObject(PMENU Menu, BOOL bRecurse) } } } - if (UserObjectInDestroy(Menu->head.h)) - { - WARN("Menu already dead!\n"); - return FALSE; - } + + if (!UserMarkObjectDestroy(Menu)) return TRUE; + + /* Remove all menu items */ + IntDestroyMenu( Menu, bRecurse); + ret = UserDeleteObject(Menu->head.h, TYPE_MENU); - if (!ret) - { // Make sure it is really dead or just marked for deletion. - Error = EngGetLastError(); - ret = UserObjectInDestroy(Menu->head.h); - if (ret && EngGetLastError() == ERROR_INVALID_HANDLE) - { - EngSetLastError(Error); - ret = FALSE; - } - } // See test_subpopup_locked_by_menu tests.... + TRACE("IntDestroyMenuObject %d\n",ret); return ret; } } diff --git a/reactos/win32ss/user/ntuser/object.c b/reactos/win32ss/user/ntuser/object.c index ec30a718d5b..8fac269c1c8 100644 --- a/reactos/win32ss/user/ntuser/object.c +++ b/reactos/win32ss/user/ntuser/object.c @@ -582,6 +582,28 @@ UserCreateObject( PUSER_HANDLE_TABLE ht, return Object; } +BOOL +FASTCALL +UserMarkObjectDestroy(PVOID Object) +{ + PUSER_HANDLE_ENTRY entry; + PHEAD ObjHead = Object; + + entry = handle_to_entry(gHandleTable, ObjHead->h); + + ASSERT(entry != NULL); + + entry->flags |= HANDLEENTRY_DESTROY; + + if (ObjHead->cLockObj > 1) + { + entry->flags &= ~HANDLEENTRY_INDESTROY; + TRACE("Count %d\n",ObjHead->cLockObj); + return FALSE; + } + + return TRUE; +} BOOL FASTCALL diff --git a/reactos/win32ss/user/ntuser/object.h b/reactos/win32ss/user/ntuser/object.h index 7fbe46bf631..b30a77b5cc6 100644 --- a/reactos/win32ss/user/ntuser/object.h +++ b/reactos/win32ss/user/ntuser/object.h @@ -19,6 +19,7 @@ BOOL FASTCALL UserObjectInDestroy(HANDLE); void DbgUserDumpHandleTable(); PVOID FASTCALL ValidateHandle(HANDLE handle, HANDLE_TYPE type); BOOLEAN UserDestroyObjectsForOwner(PUSER_HANDLE_TABLE Table, PVOID Owner); +BOOL FASTCALL UserMarkObjectDestroy(PVOID); static __inline VOID UserRefObjectCo(PVOID obj, PUSER_REFERENCE_ENTRY UserReferenceEntry) diff --git a/reactos/win32ss/user/ntuser/window.c b/reactos/win32ss/user/ntuser/window.c index d231ccd4ced..dac7df3faca 100644 --- a/reactos/win32ss/user/ntuser/window.c +++ b/reactos/win32ss/user/ntuser/window.c @@ -641,7 +641,7 @@ LRESULT co_UserFreeWindow(PWND Window, } UserReferenceObject(Window); - UserDeleteObject(UserHMGetHandle(Window), TYPE_WINDOW); + UserMarkObjectDestroy(Window); IntDestroyScrollBars(Window); @@ -670,6 +670,7 @@ LRESULT co_UserFreeWindow(PWND Window, UserFreeWindowInfo(Window->head.pti, Window); UserDereferenceObject(Window); + UserDeleteObject(UserHMGetHandle(Window), TYPE_WINDOW); return 0; } diff --git a/reactos/win32ss/user/user32/misc/misc.c b/reactos/win32ss/user/user32/misc/misc.c index d2525af4a38..994ff5aaae6 100644 --- a/reactos/win32ss/user/user32/misc/misc.c +++ b/reactos/win32ss/user/user32/misc/misc.c @@ -283,7 +283,7 @@ ValidateHandle(HANDLE handle, UINT uType) if ( (!pEntry) || (pEntry->type != uType) || !pEntry->ptr || - (pEntry->flags & HANDLEENTRY_INDESTROY) ) + (pEntry->flags & HANDLEENTRY_DESTROY) || (pEntry->flags & HANDLEENTRY_INDESTROY) ) { switch ( uType ) { // Test (with wine too) confirms these results! -- 2.17.1