shell32: Make SHGetDesktopFolder use a cached instance of IShellFolder.

This commit is contained in:
Dmitry Timoshkov 2007-06-21 23:50:55 +09:00 committed by Alexandre Julliard
parent 9a67bded8c
commit 013652feee
1 changed files with 27 additions and 41 deletions

View File

@ -117,30 +117,12 @@ static HRESULT WINAPI ISF_Desktop_fnQueryInterface(
static ULONG WINAPI ISF_Desktop_fnAddRef (IShellFolder2 * iface) static ULONG WINAPI ISF_Desktop_fnAddRef (IShellFolder2 * iface)
{ {
IGenericSFImpl *This = (IGenericSFImpl *)iface; return 2; /* non-heap based object */
ULONG refCount = InterlockedIncrement(&This->ref);
TRACE ("(%p)->(count=%u)\n", This, refCount - 1);
return refCount;
} }
static ULONG WINAPI ISF_Desktop_fnRelease (IShellFolder2 * iface) static ULONG WINAPI ISF_Desktop_fnRelease (IShellFolder2 * iface)
{ {
IGenericSFImpl *This = (IGenericSFImpl *)iface; return 1; /* non-heap based object */
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;
} }
/************************************************************************** /**************************************************************************
@ -865,9 +847,8 @@ static const IShellFolder2Vtbl vt_MCFldr_ShellFolder2 =
HRESULT WINAPI ISF_Desktop_Constructor ( HRESULT WINAPI ISF_Desktop_Constructor (
IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv) IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv)
{ {
IGenericSFImpl *sf; static IGenericSFImpl *cached_sf;
WCHAR szMyPath[MAX_PATH]; WCHAR szMyPath[MAX_PATH];
HRESULT r;
TRACE ("unkOut=%p %s\n", pUnkOuter, shdebugstr_guid (riid)); TRACE ("unkOut=%p %s\n", pUnkOuter, shdebugstr_guid (riid));
@ -876,6 +857,10 @@ HRESULT WINAPI ISF_Desktop_Constructor (
if (pUnkOuter) if (pUnkOuter)
return CLASS_E_NOAGGREGATION; return CLASS_E_NOAGGREGATION;
if (!cached_sf)
{
IGenericSFImpl *sf;
if (!SHGetSpecialFolderPathW( 0, szMyPath, CSIDL_DESKTOPDIRECTORY, TRUE )) if (!SHGetSpecialFolderPathW( 0, szMyPath, CSIDL_DESKTOPDIRECTORY, TRUE ))
return E_UNEXPECTED; return E_UNEXPECTED;
@ -883,19 +868,20 @@ HRESULT WINAPI ISF_Desktop_Constructor (
if (!sf) if (!sf)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
sf->ref = 0; sf->ref = 1;
sf->lpVtbl = &vt_MCFldr_ShellFolder2; sf->lpVtbl = &vt_MCFldr_ShellFolder2;
sf->pidlRoot = _ILCreateDesktop(); /* my qualified pidl */ sf->pidlRoot = _ILCreateDesktop(); /* my qualified pidl */
sf->sPathTarget = SHAlloc( (lstrlenW(szMyPath) + 1)*sizeof(WCHAR) ); sf->sPathTarget = SHAlloc( (lstrlenW(szMyPath) + 1)*sizeof(WCHAR) );
lstrcpyW( sf->sPathTarget, szMyPath ); lstrcpyW( sf->sPathTarget, szMyPath );
r = IUnknown_QueryInterface( _IUnknown_(sf), riid, ppv ); if (InterlockedCompareExchangePointer((void *)&cached_sf, sf, NULL) != NULL)
if (!SUCCEEDED (r))
{ {
IUnknown_Release( _IUnknown_(sf) ); /* some other thread already been here */
return r; SHFree( sf->pidlRoot );
SHFree( sf->sPathTarget );
LocalFree( sf );
}
} }
TRACE ("--(%p)\n", sf); return IUnknown_QueryInterface( _IUnknown_(cached_sf), riid, ppv );
return S_OK;
} }