Module: wine Branch: master Commit: 013652feeef3a69d43cedb7ad431010f1e4dbcdc URL: http://source.winehq.org/git/wine.git/?a=commit;h=013652feeef3a69d43cedb7ad4...
Author: Dmitry Timoshkov dmitry@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 ); }