Download source code - 16.82 KB
Introduction
This article describes how a BHO (Browser Helper Object) could be used to block a particular web-site.
Background
BHO is a simple ATL COM object that Internet Explorer will load each time it runs, i.e. for every instance of Internet Explorer. BHOs run in Internet Explorer’s address space and can perform any operations on available objects (windows, modules etc.). BHO instantiates and gets destructed with browser’s instance as it is tied to a browser’s main window.
If your system has got active desktop enabled the BHO gets instantiated along with the windows explorer as well. To disable the BHO for windows explorer, you can add following code snippet to DllMain,
TCHAR strLoader[MAX_PATH];
::GetModuleFileName (NULL, strLoader, MAX_PATH);
if(stricmp("explorer.exe", strLoader) == 0)
return FALSE;
BHO’s COM Server must implement IObjectWithSite that will help our object to hook on browser’s events. Internet Explorer will pass a pointer to its IUnknown interface by the means of IObjectWithSite. Only SetSite method of IObjectWithSite will need to be implemented as follows,
STDMETHODIMP CBhoApp::SetSite(IUnknown *pUnkSite)
{
m_spWebBrowser2 = pUnkSite;
if (m_spWebBrowser2 == NULL)
return E_INVALIDARG;
m_spCPC = m_spWebBrowser2;
if (m_spCPC == NULL)
return E_POINTER;
return Connect();
}
Here connect function would look like,
HRESULT CBhoApp::Connect()
{
HRESULT hr;
CComPtr<IConnectionPoint> spCP;
hr = m_spCPC->FindConnectionPoint(DIID_DWebBrowserEvents2, &spCP);
if (FAILED(hr))
return hr;
hr = spCP->Advise(reinterpret_cast<IDispatch*>(this),&m_dwCookie);
return hr;
}
By calling Advise method we tell the browser that BHO would be eager to receive notifications about events. By this, what we mean is, BHO will provide the browser with the pointer to IDispatch (this is due to Component’s event handling). Browser then calls IDispatch’s Invoke method and passes it the ID of an event as an argument. So our BHO must implement Invoke method to handle the events.
STDMETHODIMP CBhoApp::Invoke(DISPID dispidMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS *pDispParams,VARIANT
*pvarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
{
USES_CONVERSION;
if(dispidMember == DISPID_BEFORENAVIGATE2)
{
BSTR bstrUrlName;
HRESULT hr = m_spWebBrowser2->get_LocationURL(&bstrUrlName);
if(FAILED(hr))
return hr;
LPTSTR psz = new TCHAR[SysStringLen(bstrUrlName)];
lstrcpy(psz, OLE2T(bstrUrlName));
if(stricmp("http:) == 0)
{
VARIANT vFlags = {0},vTargetFrameName = {0};
m_spWebBrowser2->Navigate(SysAllocString(L"about:blank"),&vFlags,&vTargetFrameName,NULL,NULL);
m_spWebBrowser2->put_Visible(VARIANT_TRUE);
return S_FALSE;
}
return S_OK;
}
else if(dispidMember == DISPID_NAVIGATECOMPLETE2)
{
BSTR bstrUrlName;
HRESULT hr = m_spWebBrowser2->get_LocationURL(&bstrUrlName);
if(FAILED(hr))
return hr;
LPTSTR psz = new TCHAR[SysStringLen(bstrUrlName)];
lstrcpy(psz, OLE2T(bstrUrlName));
::OutputDebugString("In Navigate Complete");
::OutputDebugString(psz);
if(stricmp("http:) == 0)
{
VARIANT vFlags = {0},vTargetFrameName = {0};
m_spWebBrowser2->Navigate(SysAllocString(L"about:blank"),&vFlags,&vTargetFrameName,NULL,NULL);
m_spWebBrowser2->put_Visible(VARIANT_TRUE);
}
return S_OK;
}
return S_FALSE;
}
You also need to change .rgs file of your project. Add following code snippet to it,
HKLM
{
SOFTWARE
{
Microsoft
{
Windows
{
CurrentVersion
{
Explorer
{
'Browser Helper Objects'
{
ForceRemove {0CB66BA8-5E1F-4963-93D1-E1D6B78FE9A2}
}
}
}
}
}
}
}
Using the code
Once you are done with the compilation, register your component using regsvr32. Whenever you want to disable the BHO, simply use regsvr32 with /u option. One can also provide a simple UI to do this.
Improvements
- A UI element could be added to add a URL to the list of “sites to be blocked”.
References
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwebgen/html/bho.asp.