HOWTO: Tie ActiveX Controls to a Specific Domain

ID: Q196061


The information in this article applies to:


SUMMARY

When you create an ActiveX control for use under Internet Explorer, you might want to have your controls only function when they are being hosted on a Web page in a specific domain. For instance, you might want to protect your control from being reused without your permission.

This article provides Visual C++ sample code to demonstrate how to determine the domain that your control is running under.


MORE INFORMATION

To determine if the URL of the current Web page is on your domain, follow these steps:

  1. Insert the body of the following ATL class declaration into your Visual C++ project. The following code is an Internet Explorer control that was created by the Visual C++ New ATL Object wizard.

    Sample Code

    
       #include <ExDisp.h>
          #include <shlguid.h>
          #include <WinInet.h>
    
          #define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
    
          class ATL_NO_VTABLE CYourControl :
             public CComObjectRootEx<CComSingleThreadModel>,
             public CComCoClass<CTstDomain, &CLSID_TstDomain>,
             public IObjectWithSiteImpl<CTstDomain>,
             public IDispatchImpl<ITstDomain, &IID_ITstDomain,
                                 &LIBID_TSTCTRLLib>
          {
          public:
             CYourControl() {}
    
          DECLARE_PROTECT_FINAL_CONSTRUCT()
    
          BEGIN_COM_MAP(CTstDomain)
             COM_INTERFACE_ENTRY(ITstDomain)
             COM_INTERFACE_ENTRY(IDispatch)
             COM_INTERFACE_ENTRY(IObjectWithSite)
          END_COM_MAP()
    
             // IObjectWithSite Methods.
             STDMETHODIMP SetSite(IUnknown* pUnkSite)
             {
                _spUnkSite = pUnkSite;
    
                ATLTRACE("Approved Domain: %s", InApprovedDomain()
                                                ? "Yes" : "No");
    
                return S_OK;
             };
    
             STDMETHODIMP GetSite(REFIID riid, LPVOID* ppvSite)
             {
                return _spUnkSite->QueryInterface(riid, ppvSite);
             }
    
             bool InApprovedDomain()
             {
                char ourUrl[INTERNET_MAX_URL_LENGTH];
                if (!GetOurUrl(ourUrl, sizeof ourUrl))
                   return false;
    
                return IsApprovedDomain(ourUrl);
             }
    
             bool GetOurUrl(char* pszURL, int cbBuf)
             {
                HRESULT hr;
                CComPtr<IServiceProvider> spSrvProv;
                CComPtr<IWebBrowser2> spWebBrowser;
    
                hr = GetSite(IID_IServiceProvider, (void**)&spSrvProv);
                if (FAILED(hr))
                   return false;
    
                hr = spSrvProv->QueryService(SID_SWebBrowserApp,
                                             IID_IWebBrowser2,
                                             (void**)&spWebBrowser);
                if (FAILED(hr))
                   return false;
    
                CComBSTR bstrURL;
                if (FAILED(spWebBrowser->get_LocationURL(&bstrURL)))
                   return false;
    
                WideCharToMultiByte(CP_ACP, 0, bstrURL, -1, pszURL, cbURL,
                                    NULL, NULL);
    
                return true;
             }
    
             bool IsApprovedDomain(char* ourUrl)
             {
                // Only allow http access.
                // You can change this to allow file:// access.
                // 
                if (GetScheme(ourUrl) != INTERNET_SCHEME_HTTP)
                   return false;
    
                char ourDomain[256];
                if (!GetDomain(ourUrl, ourDomain, sizeof(ourDomain)))
                   return false;
    
                for (int i = 0; i < ARRAYSIZE(_approvedDomains); i++)
                {
                   if (MatchDomains(const_cast<char*>(_approvedDomains[i]),
                                    ourDomain))
                   {
                      return true;
                   }
                }
    
                return false;
             }
    
             INTERNET_SCHEME GetScheme(char* url)
             {
                char buf[32];
                URL_COMPONENTS uc;
                ZeroMemory(&uc, sizeof uc);
    
                uc.dwStructSize = sizeof uc;
                uc.lpszScheme = buf;
                uc.dwSchemeLength = sizeof buf;
    
                if (InternetCrackUrl(url, lstrlen(url), ICU_DECODE, &uc))
                   return uc.nScheme;
                else
                   return INTERNET_SCHEME_UNKNOWN;
             }
    
             bool GetDomain(char* url, char* buf, int cbBuf)
             {
                URL_COMPONENTS uc;
                ZeroMemory(&uc, sizeof uc);
    
                uc.dwStructSize = sizeof uc;
                uc.lpszHostName = buf;
                uc.dwHostNameLength = cbBuf;
    
                return (InternetCrackUrl(url, lstrlen(url), ICU_DECODE, &uc)
                        != FALSE);
             }
    
             // Return if ourDomain is within approvedDomain.
             // approvedDomain must either match ourDomain
             // or be a suffix preceded by a dot.
             // 
             bool MatchDomains(char* approvedDomain, char* ourDomain)
             {
                int apDomLen  = lstrlen(approvedDomain);
                int ourDomLen = lstrlen(ourDomain);
    
                if (apDomLen > ourDomLen)
                   return false;
    
                if (lstrcmpi(ourDomain+ourDomLen-apDomLen, approvedDomain)
                    != 0)
                   return false;
    
                if (apDomLen == ourDomLen)
                   return true;
    
                if (ourDomain[ourDomLen - apDomLen - 1] == '.')
                   return true;
    
                return false;
             }
    
             private:
                static char* _approvedDomains[2];
          };
    	 


  2. Change the approvedDomains variable to include your domain names.


  3. Call InApprovedDomain(). Make sure that the container site has been set through a call to IOleObjectWithSite::SetSite. Otherwise, this function will fail.


  4. Add WinInet.lib to the list of libraries to link into your control. To set this option, go to the Project menu, click Settings, and click the Link tab. If the current web page is in one of the domains specified by ourDomains, InApprovedDomain will return TRUE.


  5. Initialize the _approvedDomains array in your implementation (.cpp) file as follows:
    
        char* CYourControl::_approvedDomains[] = { "approvedDomain1",
                                                     "approvedDomain2 }; 



REFERENCES

For an alternate approach that is compatible with Internet Explorer 3.x, please see the following article in the Microsoft Knowledge Base:

Q181678 HOWTO: Retrieve the URL of a Web Page from an ActiveX Control
Component Development in the MSDN Online Web Workshop
http://www.msdn.microsoft.com/workshop/c-frame.htm#/workshop/components/default.asp
(c) Microsoft Corporation 1998, All Rights Reserved. Contributions by Scott Roberts, Microsoft Corporation.

Additional query words:


Keywords          : kbcode kbActiveX kbCtrl kbIE400 kbIE401 kbIE401sp1 kbIE500dp1 kbIE500 kbDSupport 
Version           : WINDOWS:4.0,4.01,4.01 SP1,5.0,5.0dp1
Platform          : WINDOWS 
Issue type        : kbhowto 

Last Reviewed: July 22, 1999