Click here to Skip to main content
15,885,757 members
Articles / Desktop Programming / ATL

Web Site Blocker

Rate me:
Please Sign up or sign in to vote.
3.84/5 (13 votes)
23 Mar 20062 min read 115.4K   1.7K   51   18
An article on a BHO (Browser Helper Object) that can be used to block a particular site(s)

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)
{
  // Retrieve and store the IWebBrowser2 pointer 
  m_spWebBrowser2 = pUnkSite; 
  if (m_spWebBrowser2 == NULL)
   return E_INVALIDARG;

  // Retrieve and store the IConnectionPointerContainer pointer 
  m_spCPC = m_spWebBrowser2;
  if (m_spCPC == NULL)
   return E_POINTER;

   // Connect to the container for receiving event notifications
  return Connect();
}

Here connect function would look like,

HRESULT CBhoApp::Connect()
{
  HRESULT hr;
  CComPtr<IConnectionPoint> spCP;

  // Receives the connection point for WebBrowser events
  hr = m_spCPC->FindConnectionPoint(DIID_DWebBrowserEvents2, &spCP);
  if (FAILED(hr))
   return hr;

  // Pass our event handlers to the container. Each time an event occurs
  // the container will invoke the functions of the IDispatch interface 
  // we implemented.
  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; //This macro should be called when using ATL string conversion 
     //macros to avoid compile time errors (here we are using OLE2T)
 
 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));

  // Here, I am directly comparing with xyz.com. You can maintain a list of all sites to 
  // be blocked and then compare. Or you can also keep this data in a database, but I guess
  // that might affect the performance. (Experts! please comment on this.)


<pre>  if(stricmp("<a href="http://www.xyz.com/%22,(const%20char%20*)psz">http://www.xyz.com/",(const%20char%20*)psz</a>) == 0) 
  // Here you can also use strstr instead of stricmp
  // which will help to allow all domain originating from xyz. 
  {
     VARIANT vFlags = {0},vTargetFrameName = {0};
     // Instead of "about:blank", you can redirect user to some page saying site has been blocked. :-)
     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) 
 // This checking is done to avoid post-navigation
 // loading of a page. 
 {
  BSTR bstrUrlName;
  HRESULT hr = m_spWebBrowser2->get_LocationURL(&bstrUrlName);
  if(FAILED(hr))
   return hr;

  // Convert the text from Unicode to ANSI
  LPTSTR psz = new TCHAR[SysStringLen(bstrUrlName)];
  lstrcpy(psz, OLE2T(bstrUrlName));
  ::OutputDebugString("In Navigate Complete");
  ::OutputDebugString(psz);
  if(stricmp("<a href="http://www.xyz.com/%22,psz">http://www.xyz.com/",psz</a>) == 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.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
India India
I am working as a Senior Software Engineer. In my spare time I enjoy going on a 3-4 days trip on my bike.

Comments and Discussions

 
GeneralMy vote of 4 Pin
ballistic7726-Dec-12 17:38
ballistic7726-Dec-12 17:38 
QuestionConnect Database SQL SV 2005 Pin
nckh25-Oct-11 23:15
nckh25-Oct-11 23:15 
GeneralQuestion about the VARIANT data type used by DWebBrowserEvents2 Pin
Diver18216-Apr-07 5:00
Diver18216-Apr-07 5:00 
Generalin C#... Help Pin
han qiao1-Feb-07 16:10
han qiao1-Feb-07 16:10 
QuestionIs this a memory leak? Pin
Hu Yi Fan15-Dec-06 2:53
Hu Yi Fan15-Dec-06 2:53 
General0x80040202 (CONNECT_E_CANNOTCONNECT) Pin
nir_nir2-Jul-06 4:04
nir_nir2-Jul-06 4:04 
QuestionHow about firefox? Pin
dwtung11-Jun-06 14:00
dwtung11-Jun-06 14:00 
AnswerRe: How about firefox? Pin
Hu Yi Fan15-Dec-06 2:58
Hu Yi Fan15-Dec-06 2:58 
Generaldisable the BHO for windows explorer Pin
nir_nir1-Jun-06 0:32
nir_nir1-Jun-06 0:32 
GeneralFix Pin
dimag15-May-06 7:04
dimag15-May-06 7:04 
QuestionRe: Fix Pin
EugeneKim9-Apr-07 6:42
EugeneKim9-Apr-07 6:42 
GeneralLogging Pin
KoSS103317-Apr-06 19:39
KoSS103317-Apr-06 19:39 
GeneralRe: Logging Pin
Milind Mehendale17-Apr-06 23:34
Milind Mehendale17-Apr-06 23:34 
GeneralRe: Logging Pin
KoSS103318-Apr-06 6:11
KoSS103318-Apr-06 6:11 
GeneralRe: Logging Pin
Milind Mehendale20-Apr-06 6:23
Milind Mehendale20-Apr-06 6:23 
GeneralCool! Pin
Blake Miller29-Mar-06 5:21
Blake Miller29-Mar-06 5:21 
GeneralRe: Cool! Pin
Milind Mehendale30-Mar-06 19:33
Milind Mehendale30-Mar-06 19:33 
GeneralRe: Cool! Pin
Adnan Siddiqi22-May-06 0:10
Adnan Siddiqi22-May-06 0:10 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.