IConnectionPoint::Unadvise fails in IE7

Hello,

We are testing our BHO with IE7 (7.0.5700.6). Upon browser startup, the BHO calls IConnectionPoint::Advise. At browser shutdown, it calls IConnectionPoint::Unadvise with the same cookie returned by Advise. Unadvise is returns CONNECT_E_NOCONNECTION. One observation is that if I call Unadvise immediately after Advise, then Unadvise returns S_OK.

This behavior is not observed with IE6. Also, I had an earlier build of IE7 installed (not sure what build number, but I installed it around a month ago), and this problem did not occur with that build. Any ideas why Unadvise fails or are there any troubleshooting steps I can use to investigate this further?

Thanks,
Roy

[685 byte] By [rdeal] at [2008-2-17]
# 1
How do you detect browser shutdown? It could help understand when you really call UnAdvise.
SharathUdupa at 2007-8-31 > top of Msdn Tech,Internet Explorer Development,Internet Explorer Extension Development...
# 2
We are seeing the exact same behavior with our BHO. Not that we can offer any solution, but one more voice that this is a legit problem might help.
TomNielsen at 2007-8-31 > top of Msdn Tech,Internet Explorer Development,Internet Explorer Extension Development...
# 3
Hi Sharath. Here's a code snippet that gives the context....

CComQIPtr<IWebBrowser2, &IID_IWebBrowser2> m_spWebBrowser2;
DWORD m_dwCookie = 0;

//
// IOleObjectWithSite implementation
//
STDMETHODIMP CMyImpl::SetSite(IUnknown *pUnkSite)
{
BOOL bNegotiateConnectionResult;

if (!pUnkSite) {
if (m_spWebBrowser2 != NULL) {
bNegotiateConnectionResult = NegotiateConnection(FALSE);
m_spWebBrowser2.Release();
}
}
else {
// Query pUnkSite for the IWebBrowser2 interface.
m_spWebBrowser2 = pUnkSite;

if (m_spWebBrowser2) {
bNegotiateConnectionResult = NegotiateConnection(TRUE);
}
}

return S_OK;
}

// Helper method
BOOL CMyImpl::NegotiateConnection(BOOL bAdvise)
{
if (!m_spWebBrowser2) return FALSE;

HRESULT hr;
CComQIPtr<IConnectionPointContainer, &IID_IConnectionPointContainer> spCPContainer(m_spWebBrowser2);
if (spCPContainer == NULL) return FALSE;

CComPtr<IConnectionPoint> spConnectionPoint;
hr = spCPContainer->FindConnectionPoint(DIID_DWebBrowserEvents2, &spConnectionPoint);
if (FAILED(hr)) return FALSE;

if (bAdvise) {
// Tell the client site to notify us of events
hr = spConnectionPoint->Advise((IDispatch*)this, &m_dwCookie);
if (FAILED(hr)) return FALSE;
}
else {
// Remove us from the list of people interested...
hr = spConnectionPoint->Unadvise(m_dwCookie);
if (FAILED(hr)) return FALSE;
}

return TRUE;
}

rdeal at 2007-8-31 > top of Msdn Tech,Internet Explorer Development,Internet Explorer Extension Development...
# 4
This seems like IE has already disconnected your connection points when it calls SetSite(NULL). I would recommend calling Unadvise on recieving DWebBrowserEvents2::OnQuit event rather than on SetSite(NULL). Also is the success of Unadvise critical for you, since it has already been disconnected?
SharathUdupa at 2007-8-31 > top of Msdn Tech,Internet Explorer Development,Internet Explorer Extension Development...
# 5
Thanks for the recommendation. I'm sure you can understand that rearranging a lot of code that has worked without errors for quite a few years is not necessarily a trivial thing.

Is the success of Unadvise critical? I'm not sure. It seems preferable. I'm not sure if we can safely ignore this error because I'm not sure what's going on "under the hood". Does that error indicate that the connection point has already been disconnected? From all accounts, calling Unadvise is the proper thing to do when you're done with a connection point. Does it result in an interface leak? Is the connection point "cleaned up on my behalf", so to speak? How does this affect other instances of IE7 that might be running?

rdeal at 2007-8-31 > top of Msdn Tech,Internet Explorer Development,Internet Explorer Extension Development...
# 6
OK, I changed the BHO code to call Uunadvise when Invoke receives DISPID_ONQUIT, and Unadvise is completing successfully. Thanks Sharath.
rdeal at 2007-8-31 > top of Msdn Tech,Internet Explorer Development,Internet Explorer Extension Development...
# 7

Yes, IE has disconnected your connection point. The rationale for doing so before calling SetSite(NULL), is that there were certain BHO which had a wrong implementation where they used to unload when we call SetSite(NULL) without disconnecting their connection points. So, when IE is cleaning up and it tries to unadvise these connection points, it would crash. Hence, IE forces the disconnect before calling SetSite(NULL) to protect itself from this happening. Calling Unadvise when you get the DISPID_ONQUIT is the correct thing to do.

thanks
Sharath

SharathUdupa at 2007-8-31 > top of Msdn Tech,Internet Explorer Development,Internet Explorer Extension Development...