Have a look at the following MFC source code in Visual Studio .NET 2003.
void CHtmlView::OnFilePrint()
{
// get the HTMLDocument
if (m_pBrowserApp != NULL)
{
CComPtr<IDispatch> spDisp = GetHtmlDocument();
if (spDisp != NULL)
{
// the control will handle all printing UI
CComQIPtr<IOleCommandTarget> spTarget = spDisp;
if (spTarget != NULL)
spTarget->Exec(NULL, OLECMDID_PRINT, 0, NULL, NULL);
}
}
}
LPDISPATCH CHtmlView::GetHtmlDocument() const
{
ASSERT(m_pBrowserApp != NULL);
LPDISPATCH result;
HRESULT hr = m_pBrowserApp->get_Document(&result);
if(FAILED(hr))
{
ASSERT(FALSE);
return NULL;
}
return result;
}
CHtmlView::GetHtmlDocument() calls m_pBrowserApp->get_Document() to get the IDispatch. So the RefCount is increased by one. Then in CHtmlView::OnFilePrint(), the returned interface pointer is passed to CComPtr. The constructor of CComPtr will call AddRef() on the interface pointer. So now the RefCount is increased by two. In the end, the destructor of CComPtr will call Release() once. But the original RefCount returned by CHtmlView::GetHtmlDocument() is never released. All the functions using GetHtmlDocument() have this bug, including
CHtmlView::OnFilePrint
CHtmlView::ExecFormsCommand
CHtmlView::QueryFormsCommand
CHtmlView::GetSource
This is a new bug in VC7. The bug was not in VC6 in that it didn't use CComPtr.