shell32: Make SHGetDesktopFolder use a cached instance of
IShellFolder. Take 2
Dmitry Timoshkov
dmitry at codeweavers.com
Thu Jun 21 09:50:55 CDT 2007
"Alexandre Julliard" <julliard at winehq.org> wrote:
> You need to initialize the object completely before storing it as
> cached entry.
oops, sorry about that.
---
An application I'm working on at start up calls SHGetDesktopFolder huge amount
of time, and on my system its start up time is 55 seconds. A simple test shows
(attached) that Windows doesn't create IShellFolder over and over again, but
uses a cached interface. This patch reduces start up time of my application
to 35 seconds.
Changelog:
shell32: Make SHGetDesktopFolder use a cached instance of IShellFolder.
---
dlls/shell32/shfldr_desktop.c | 63 +++++++++++++++++++----------------------
1 files changed, 29 insertions(+), 34 deletions(-)
diff --git a/dlls/shell32/shfldr_desktop.c b/dlls/shell32/shfldr_desktop.c
index 3fee311..81aaccf 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,7 +847,7 @@ 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;
@@ -876,26 +858,39 @@ 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 = LocalAlloc( LMEM_ZEROINIT, sizeof (IGenericSFImpl) );
+ if (!sf)
+ return E_OUTOFMEMORY;
+
+ 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->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 );
+ if (InterlockedCompareExchangePointer((void *)&cached_sf, sf, NULL) != NULL)
+ {
+ /* some other thread already been here */
+ SHFree( sf->pidlRoot );
+ SHFree( sf->sPathTarget );
+ LocalFree( sf );
+ }
+ }
- r = IUnknown_QueryInterface( _IUnknown_(sf), riid, ppv );
+ r = IUnknown_QueryInterface( _IUnknown_(cached_sf), riid, ppv );
if (!SUCCEEDED (r))
{
- IUnknown_Release( _IUnknown_(sf) );
+ IUnknown_Release( _IUnknown_(cached_sf) );
return r;
}
- TRACE ("--(%p)\n", sf);
+ TRACE ("--(%p)\n", cached_sf);
return S_OK;
}
--
1.5.1.6
More information about the wine-patches
mailing list