shell32: Make SHGetDesktopFolder use a cached instance of
IShellFolder
Dmitry Timoshkov
dmitry at codeweavers.com
Wed Jun 20 09:06:56 CDT 2007
Hello,
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.
---
#include <stdio.h>
#define COBJMACROS
#include <windows.h>
#include <shlobj.h>
int main(void)
{
HRESULT hres;
IShellFolder *sf = NULL;
LONG ref;
hres = SHGetDesktopFolder(&sf);
if (hres || !sf)
{
printf("SHGetDesktopFolder error %lx\n", hres);
return -1;
}
ref = IShellFolder_AddRef(sf);
printf("ref count %ld\n", ref);
ref = IShellFolder_AddRef(sf);
printf("ref count %ld\n", ref);
ref = IShellFolder_AddRef(sf);
printf("ref count %ld\n", ref);
ref = IShellFolder_Release(sf);
printf("ref count %ld\n", ref);
ref = IShellFolder_Release(sf);
printf("ref count %ld\n", ref);
ref = IShellFolder_Release(sf);
printf("ref count %ld\n", ref);
return 0;
}
---
dlls/shell32/shfldr_desktop.c | 60 +++++++++++++++++-----------------------
1 files changed, 26 insertions(+), 34 deletions(-)
diff --git a/dlls/shell32/shfldr_desktop.c b/dlls/shell32/shfldr_desktop.c
index 3fee311..6359083 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,36 @@ 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;
+
+ if (InterlockedCompareExchangePointer((void *)&cached_sf, sf, NULL) != NULL)
+ LocalFree( sf ); /* some other thread already been here */
+ else
+ {
+ 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 );
+ }
+ }
- 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