Dmitry Timoshkov : shell32: Make SHGetDesktopFolder use a cached instance of IShellFolder.

Alexandre Julliard julliard at wine.codeweavers.com
Fri Jun 22 07:35:38 CDT 2007


Module: wine
Branch: master
Commit: 013652feeef3a69d43cedb7ad431010f1e4dbcdc
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=013652feeef3a69d43cedb7ad431010f1e4dbcdc

Author: Dmitry Timoshkov <dmitry at codeweavers.com>
Date:   Thu Jun 21 23:50:55 2007 +0900

shell32: Make SHGetDesktopFolder use a cached instance of IShellFolder.

---

 dlls/shell32/shfldr_desktop.c |   64 ++++++++++++++++-------------------------
 1 files changed, 25 insertions(+), 39 deletions(-)

diff --git a/dlls/shell32/shfldr_desktop.c b/dlls/shell32/shfldr_desktop.c
index 3fee311..14571b1 100644
--- a/dlls/shell32/shfldr_desktop.c
+++ b/dlls/shell32/shfldr_desktop.c
@@ -117,30 +117,12 @@ static HRESULT WINAPI ISF_Desktop_fnQueryInterface(
 
 static ULONG WINAPI ISF_Desktop_fnAddRef (IShellFolder2 * iface)
 {
-    IGenericSFImpl *This = (IGenericSFImpl *)iface;
-    ULONG refCount = InterlockedIncrement(&This->ref);
-
-    TRACE ("(%p)->(count=%u)\n", This, refCount - 1);
-
-    return refCount;
+    return 2; /* non-heap based object */
 }
 
 static ULONG WINAPI ISF_Desktop_fnRelease (IShellFolder2 * iface)
 {
-    IGenericSFImpl *This = (IGenericSFImpl *)iface;
-    ULONG refCount = InterlockedDecrement(&This->ref);
-
-    TRACE ("(%p)->(count=%u)\n", This, refCount + 1);
-
-    if (!refCount)
-    {
-        TRACE ("-- destroying IShellFolder(%p)\n", This);
-        SHFree (This->pidlRoot);
-        SHFree (This->sPathTarget);
-        LocalFree ((HLOCAL) This);
-        return 0;
-    }
-    return refCount;
+    return 1; /* non-heap based object */
 }
 
 /**************************************************************************
@@ -865,9 +847,8 @@ static const IShellFolder2Vtbl vt_MCFldr_ShellFolder2 =
 HRESULT WINAPI ISF_Desktop_Constructor (
                 IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv)
 {
-    IGenericSFImpl *sf;
+    static IGenericSFImpl *cached_sf;
     WCHAR szMyPath[MAX_PATH];
-    HRESULT r;
 
     TRACE ("unkOut=%p %s\n", pUnkOuter, shdebugstr_guid (riid));
 
@@ -876,26 +857,31 @@ HRESULT WINAPI ISF_Desktop_Constructor (
     if (pUnkOuter)
         return CLASS_E_NOAGGREGATION;
 
-    if (!SHGetSpecialFolderPathW( 0, szMyPath, CSIDL_DESKTOPDIRECTORY, TRUE ))
-        return E_UNEXPECTED;
+    if (!cached_sf)
+    {
+        IGenericSFImpl *sf;
 
-    sf = LocalAlloc( LMEM_ZEROINIT, sizeof (IGenericSFImpl) );
-    if (!sf)
-        return E_OUTOFMEMORY;
+        if (!SHGetSpecialFolderPathW( 0, szMyPath, CSIDL_DESKTOPDIRECTORY, TRUE ))
+            return E_UNEXPECTED;
 
-    sf->ref = 0;
-    sf->lpVtbl = &vt_MCFldr_ShellFolder2;
-    sf->pidlRoot = _ILCreateDesktop();    /* my qualified pidl */
-    sf->sPathTarget = SHAlloc( (lstrlenW(szMyPath) + 1)*sizeof(WCHAR) );
-    lstrcpyW( sf->sPathTarget, szMyPath );
+        sf = LocalAlloc( LMEM_ZEROINIT, sizeof (IGenericSFImpl) );
+        if (!sf)
+            return E_OUTOFMEMORY;
 
-    r = IUnknown_QueryInterface( _IUnknown_(sf), riid, ppv );
-    if (!SUCCEEDED (r))
-    {
-        IUnknown_Release( _IUnknown_(sf) );
-        return r;
+        sf->ref = 1;
+        sf->lpVtbl = &vt_MCFldr_ShellFolder2;
+        sf->pidlRoot = _ILCreateDesktop();    /* my qualified pidl */
+        sf->sPathTarget = SHAlloc( (lstrlenW(szMyPath) + 1)*sizeof(WCHAR) );
+        lstrcpyW( sf->sPathTarget, szMyPath );
+
+        if (InterlockedCompareExchangePointer((void *)&cached_sf, sf, NULL) != NULL)
+        {
+            /* some other thread already been here */
+            SHFree( sf->pidlRoot );
+            SHFree( sf->sPathTarget );
+            LocalFree( sf );
+        }
     }
 
-    TRACE ("--(%p)\n", sf);
-    return S_OK;
+    return IUnknown_QueryInterface( _IUnknown_(cached_sf), riid, ppv );
 }




More information about the wine-cvs mailing list