From 3ef47314926aad388d5d09339a8832f4a5ded691 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Thu, 23 Oct 2014 19:41:52 +0000 Subject: [PATCH] [WIN32K] - Properly free classes small icon handles - Do not use LR_SHARED when copying them from the large icon. There's no reason for them to outlive the class. Should fix remaining failures in user32:class that I introduced. svn path=/trunk/; revision=64939 --- reactos/win32ss/user/ntuser/class.c | 69 +++++++++++++++++++++++++--- reactos/win32ss/user/ntuser/window.c | 4 +- 2 files changed, 65 insertions(+), 8 deletions(-) diff --git a/reactos/win32ss/user/ntuser/class.c b/reactos/win32ss/user/ntuser/class.c index 98e6b1a12d3..4c0db763055 100644 --- a/reactos/win32ss/user/ntuser/class.c +++ b/reactos/win32ss/user/ntuser/class.c @@ -9,7 +9,6 @@ #include DBG_DEFAULT_CHANNEL(UserClass); -BOOL FASTCALL IntClassDestroyIcon(HANDLE hCurIcon); static NTSTATUS IntDeregisterClassAtom(IN RTL_ATOM Atom); REGISTER_SYSCLASS DefaultServerClasses[] = @@ -251,7 +250,13 @@ IntDestroyClass(IN OUT PCLS Class) if (Class->spcur) UserDereferenceObject(Class->spcur); if (Class->spicnSm) + { UserDereferenceObject(Class->spicnSm); + /* Destroy the icon if we own it */ + if ((Class->CSF_flags & CSF_CACHEDSMICON) + && !(UserObjectInDestroy(UserHMGetHandle(Class->spicnSm)))) + IntDestroyCurIconObject(Class->spicnSm); + } #else if (Class->hIconSmIntern) IntClassDestroyIcon(Class->hIconSmIntern); @@ -1969,6 +1974,7 @@ UserSetClassLongPtr(IN PCLS Class, { /* We will change the small icon */ UserDereferenceObject(Class->spicnSm); + IntDestroyCurIconObject(Class->spicnSm); Class->spicnSm = NULL; Class->CSF_flags &= ~CSF_CACHEDSMICON; } @@ -1985,7 +1991,7 @@ UserSetClassLongPtr(IN PCLS Class, IMAGE_ICON, UserGetSystemMetrics( SM_CXSMICON ), UserGetSystemMetrics( SM_CYSMICON ), - LR_COPYFROMRESOURCE | LR_SHARED); + LR_COPYFROMRESOURCE); } if (!SmallIconHandle) { @@ -1995,7 +2001,7 @@ UserSetClassLongPtr(IN PCLS Class, IMAGE_ICON, UserGetSystemMetrics( SM_CXSMICON ), UserGetSystemMetrics( SM_CYSMICON ), - LR_SHARED); + 0); } if (SmallIconHandle) { @@ -2062,6 +2068,7 @@ UserSetClassLongPtr(IN PCLS Class, #ifdef NEW_CURSORICON { PCURICON_OBJECT NewSmallIcon = NULL; + BOOLEAN NewIconFromCache = FALSE; if (NewLong) { @@ -2072,10 +2079,54 @@ UserSetClassLongPtr(IN PCLS Class, return 0; } } + else + { + /* Create the new small icon from the large one */ + HICON SmallIconHandle = NULL; + if((Class->spicn->CURSORF_flags & (CURSORF_LRSHARED | CURSORF_FROMRESOURCE)) + == (CURSORF_LRSHARED | CURSORF_FROMRESOURCE)) + { + SmallIconHandle = co_IntCopyImage( + UserHMGetHandle(Class->spicn), + IMAGE_ICON, + UserGetSystemMetrics( SM_CXSMICON ), + UserGetSystemMetrics( SM_CYSMICON ), + LR_COPYFROMRESOURCE); + } + if (!SmallIconHandle) + { + /* Retry without copying from resource */ + SmallIconHandle = co_IntCopyImage( + UserHMGetHandle(Class->spicn), + IMAGE_ICON, + UserGetSystemMetrics( SM_CXSMICON ), + UserGetSystemMetrics( SM_CYSMICON ), + 0); + } + if (SmallIconHandle) + { + /* So use it */ + NewSmallIcon = UserGetCurIconObject(SmallIconHandle); + NewIconFromCache = TRUE; + } + else + { + ERR("Failed getting a small icon for the class.\n"); + } + } if (Class->spicnSm) { - Ret = (ULONG_PTR)UserHMGetHandle(Class->spicnSm); + if (Class->CSF_flags & CSF_CACHEDSMICON) + { + /* We must destroy the icon if we own it */ + IntDestroyCurIconObject(Class->spicnSm); + Ret = 0; + } + else + { + Ret = (ULONG_PTR)UserHMGetHandle(Class->spicnSm); + } UserDereferenceObject(Class->spicnSm); } else @@ -2083,7 +2134,10 @@ UserSetClassLongPtr(IN PCLS Class, Ret = 0; } - Class->CSF_flags &= ~CSF_CACHEDSMICON; + if (NewIconFromCache) + Class->CSF_flags |= CSF_CACHEDSMICON; + else + Class->CSF_flags &= ~CSF_CACHEDSMICON; Class->spicnSm = NewSmallIcon; /* Update the clones */ @@ -2094,7 +2148,10 @@ UserSetClassLongPtr(IN PCLS Class, UserDereferenceObject(Class->spicnSm); if (NewSmallIcon) UserReferenceObject(NewSmallIcon); - Class->CSF_flags &= ~CSF_CACHEDSMICON; + if (NewIconFromCache) + Class->CSF_flags |= CSF_CACHEDSMICON; + else + Class->CSF_flags &= ~CSF_CACHEDSMICON; Class->spicnSm = NewSmallIcon; Class = Class->pclsNext; } diff --git a/reactos/win32ss/user/ntuser/window.c b/reactos/win32ss/user/ntuser/window.c index 669703b8485..22ce972902b 100644 --- a/reactos/win32ss/user/ntuser/window.c +++ b/reactos/win32ss/user/ntuser/window.c @@ -1686,7 +1686,7 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs, IMAGE_ICON, UserGetSystemMetrics( SM_CXSMICON ), UserGetSystemMetrics( SM_CYSMICON ), - LR_COPYFROMRESOURCE | LR_SHARED); + LR_COPYFROMRESOURCE); } if (!IconSmHandle) { @@ -1696,7 +1696,7 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs, IMAGE_ICON, UserGetSystemMetrics( SM_CXSMICON ), UserGetSystemMetrics( SM_CYSMICON ), - LR_SHARED); + 0); } if (IconSmHandle)