I'm maintaining an application which uses Windows Explorer overlay icons. Occasionally some operations require me to forcibly refresh explorers view for a particular folder. I do so using the following function which uses COM:
void RefreshExplorerView(CString strPath)
{
CComPtr<IShellWindows> pShellWindows;
CoInitialize(NULL);
if(SUCCEEDED(pShellWindows.CoCreateInstance(CLSID_ShellWindows)))
{
IDispatch* pFolder=NULL;
VARIANT variant;
V_VT(&variant) = VT_I4;
for(V_I4(&variant) = 0; pShellWindows->Item(variant, &pFolder) == S_OK; V_I4(&variant)++)
{
CComPtr<IWebBrowserApp> pWebBrowserApp;
if(SUCCEEDED(pFolder->QueryInterface(IID_PPV_ARGS(&pWebBrowserApp))))
{
BSTR LocationURL = NULL;
pWebBrowserApp->get_LocationURL(&LocationURL);
if(LocationURL != NULL && strPath.CompareNoCase(LocationURL) == 0)
{
CComPtr<IServiceProvider> pServiceProvider;
if(SUCCEEDED(pWebBrowserApp->QueryInterface(IID_PPV_ARGS(&pServiceProvider))))
{
CComPtr<IShellBrowser> pShellBrowser;
if(SUCCEEDED(pServiceProvider->QueryInterface(IID_PPV_ARGS(&pShellBrowser))))
{
IShellView* pShellView;
if(SUCCEEDED(pShellBrowser->QueryActiveShellView(&pShellView)))
{
pShellView->Refresh();
pShellView->Release();
}
}
}
}
SysFreeString(LocationURL);
}
pFolder->Release();
pFolder = NULL;
}
}
CoUninitialize();
}
I've noticed that when my program does this refresh regularly it slowly grows in size and UMDH has shown me that I appear to be leaking pFolder
and pShellWindow
instances every time this runs. I can't work out why on earth this happens since as far as I can tell these are released properly. Can anyone see what I'm missing?
You release pShellWindows
after CoUninitialize
, which is incorrect.
The rest of interfaces seem to be released fine. Note that you could improve cleanless and readability greatly by using CComQIPtr
instead of QueryInterface
, and not using raw pointers at all (BSTR
, IFoo*
) and replace them with smart auto-releasing wrappers.
pFolder
might be leaking too, if Item
call is successful but returns code other than S_OK
. Again, use of CComPtr<IFolder>
instead of IFolder*
would immediately resolve this problem without even drawing any attention to it.