ActiveX and IObjectSafetySiteLock,IObjectWithSite
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 6 of 6

Thread: ActiveX and IObjectSafetySiteLock,IObjectWithSite

  1. #1
    Join Date
    Feb 2007
    Posts
    247

    Unhappy ActiveX and IObjectSafetySiteLock,IObjectWithSite

    hello,

    i am trying to create a simple MFC activeX control through wizard.
    it has nothing fancy. just a method to display message box

    however, i want to add sitelock to this control. for that i downloaded the
    Sitelock ATL template. form microsoft.
    http://www.microsoft.com/downloads/d...displaylang=en

    i added the sitelock.h file.to the mfc control.

    now if it was a ATL project them i just need to derive from the "IObjectSafetySiteLockImpl" and things works.

    but how do i accomplish it in MFC control.

    for this i read some article at MSDN.

    http://msdn.microsoft.com/en-us/library/ms974305.aspx

    for this i code like this
    in the .h file
    Code:
    BEGIN_INTERFACE_PART(ObjSafe, IObjectSafetySiteLock)
    		STDMETHOD(SetInterfaceSafetyOptions)(REFIID riid,DWORD dwOptionSetMask, DWORD dwEnabledOptions);
    		STDMETHOD(GetInterfaceSafetyOptions)(REFIID riid,DWORD __RPC_FAR *pdwSupportedOptions,DWORD __RPC_FAR *pdwEnabledOptions);
    		STDMETHOD(GetCapabilities)(DWORD * pdwCapability);
    		STDMETHOD(GetApprovedSites)(const SiteList ** pSiteList, DWORD * cSites);
    		STDMETHOD(GetExpiryDate)(DWORD * pdwLifespan, FILETIME * pExpiryDate);
    	END_INTERFACE_PART(ObjSafe);
    
    
    	BEGIN_INTERFACE_PART(ObjWithSite, IObjectWithSite)
    		STDMETHOD(SetSite)(IUnknown *pUnkSite);
    		STDMETHOD(GetSite)(REFIID riid, void **ppvSite);
    		STDMETHOD(SetChildSite)(IUnknown* punkChild);
    		STDMETHOD(SetChildSite)(IUnknown* punkChild, IUnknown* punkParent);
    	END_INTERFACE_PART(ObjWithSite);
    in the .cpp file
    Code:
    const DWORD dwSupportedBits = INTERFACESAFE_FOR_UNTRUSTED_CALLER |INTERFACESAFE_FOR_UNTRUSTED_DATA;
    const DWORD dwNotSupportedBits = ~ dwSupportedBits;
    
    
    
    /////////////////////////////////////////////////////////////////////////////
    // CSWEnforceActiveXCtrl::XObjSafe::GetInterfaceSafetyOptions
    // Allows container to query what interfaces are safe for what. We're
    // optimizing significantly by ignoring which interface the caller is
    // asking for.
    HRESULT STDMETHODCALLTYPE 
    CMFCSiteCtrl::XObjSafe::GetInterfaceSafetyOptions( 
    	/* [in] */ REFIID riid,
    	/* [out] */ DWORD __RPC_FAR *pdwSupportedOptions,
    	/* [out] */ DWORD __RPC_FAR *pdwEnabledOptions)
    {
    	METHOD_PROLOGUE(CMFCSiteCtrl, ObjSafe)
    
    		HRESULT retval = ResultFromScode(S_OK);
    
    	// does interface exist?
    	IUnknown FAR* punkInterface;
    	retval = pThis->ExternalQueryInterface(&riid, (void * *)&punkInterface);
    	if (retval != E_NOINTERFACE) 
    	{	// interface exists
    		punkInterface->Release(); // release it--just checking!
    	}
    
    	// we support both kinds of safety and have always both set,
    	// regardless of interface
    	*pdwSupportedOptions = *pdwEnabledOptions = dwSupportedBits;
    
    	return retval; // E_NOINTERFACE if QI failed
    }
    
    /////////////////////////////////////////////////////////////////////////////
    // CStopLiteCtrl::XObjSafe::SetInterfaceSafetyOptions
    // Since we're always safe, this is a no-brainer--but we do check to make
    // sure the interface requested exists and that the options we're asked to
    // set exist and are set on (we don't support unsafe mode).
    HRESULT STDMETHODCALLTYPE 
    CMFCSiteCtrl::XObjSafe::SetInterfaceSafetyOptions( 
    	/* [in] */ REFIID riid,
    	/* [in] */ DWORD dwOptionSetMask,
    	/* [in] */ DWORD dwEnabledOptions)
    {
    	METHOD_PROLOGUE(CMFCSiteCtrl, ObjSafe)
    
    		// does interface exist?
    		IUnknown FAR* punkInterface;
    	pThis->ExternalQueryInterface(&riid, (void * *)&punkInterface);
    	if (punkInterface) 
    	{	// interface exists
    		punkInterface->Release(); // release it--just checking!
    	}
    	else 
    	{ // interface doesn't exist
    		return ResultFromScode(E_NOINTERFACE);
    	}
    
    	// can't set bits we don't support
    	if (dwOptionSetMask & dwNotSupportedBits) 
    	{ 
    		return ResultFromScode(E_FAIL);
    	}
    
    	// can't set bits we do support to zero
    	dwEnabledOptions &= dwSupportedBits;
    	// (we already know there are no extra bits in mask )
    	if ((dwOptionSetMask & dwEnabledOptions) !=dwOptionSetMask) 
    	{
    		return ResultFromScode(E_FAIL);
    	}								
    
    	// don't need to change anything since we're always safe
    	return ResultFromScode(S_OK);
    }
    
    HRESULT STDMETHODCALLTYPE 
    CMFCSiteCtrl::XObjSafe::GetCapabilities(DWORD * pdwCapability)
    {
    	// Data validation
    	if (!pdwCapability)
    		return E_POINTER;
    
    	// Return the version if 0 is passed in
    	if (0 == *pdwCapability)
    	{
    		*pdwCapability = SITELOCK_VERSION;
    		return S_OK;
    	}
    
    	// Return the options if 1 is passed in
    	if (1 == *pdwCapability)
    	{
    		*pdwCapability =
    #ifdef SITELOCK_USE_IOLEOBJECT
    			Capability::UsesIOleObject |
    #endif
    #ifndef SITELOCK_NO_EXPIRY
    			Capability::HasExpiry |
    #endif
    			0;
    		return S_OK;
    	}			
    
    	// Return not implemented otherwise
    	*pdwCapability = 0;
    	return E_NOTIMPL;
    }
    
    HRESULT STDMETHODCALLTYPE 
    CMFCSiteCtrl::XObjSafe::GetApprovedSites(const SiteList ** pSiteList, DWORD * pcEntries)
    {
    	// Data validation
    	if (!pSiteList || !pcEntries)
    		return E_POINTER;
    
    	// Return specified site lock entries
    #ifdef SITELOCK_USE_MAP
    	// Use the site lock map
    	*pSiteList = T::GetSiteLockMapAndCount(*pcEntries);
    #else
    	// Use the static member
    	*pSiteList = T::rgslTrustedSites;
    	*pcEntries = cElements(T::rgslTrustedSites);
    #endif
    	return S_OK;
    }
    
    HRESULT STDMETHODCALLTYPE 
    CMFCSiteCtrl::XObjSafe::GetExpiryDate(DWORD * pdwLifespan, FILETIME * pExpiryDate)
    {
    	if (!pdwLifespan || !pExpiryDate)
    		return E_POINTER;
    
    #ifdef SITELOCK_NO_EXPIRY
    	*pdwLifespan = 0;
    	::ZeroMemory((void*)pExpiryDate, sizeof(FILETIME));
    	return E_NOTIMPL;
    #else
    	*pdwLifespan = T::dwControlLifespan;
    
    	// Calculate expiry date from life span
    	time_t ttExpire = ImageNtHeaders(&__ImageBase)->FileHeader.TimeDateStamp;
    	ttExpire += T::dwControlLifespan*86400;	// seconds per day
    	_UNIXTimeToFILETIME(ttExpire, pExpiryDate);
    
    	return S_OK;
    #endif
    }
    
    HRESULT STDMETHODCALLTYPE 
    CMFCSiteCtrl::XObjWithSite::SetSite(IUnknown *pUnkSite)
    {
    	ATLTRACE(atlTraceCOM, 2, _T("IObjectWithSiteImpl::SetSite\n"));
    	CMFCSiteCtrl* pT = static_cast<CMFCSiteCtrl*>(this);
    	pT->m_spUnkSite = pUnkSite;
    	return S_OK;
    }
    
    HRESULT STDMETHODCALLTYPE 
    CMFCSiteCtrl::XObjWithSite::GetSite(REFIID riid, void **ppvSite)
    {
    	ATLTRACE(atlTraceCOM, 2, _T("IObjectWithSiteImpl::GetSite\n"));
    	CMFCSiteCtrl* pT = static_cast<CMFCSiteCtrl*>(this);
    	ATLASSERT(ppvSite);
    	HRESULT hRes = E_POINTER;
    	if (ppvSite != NULL)
    	{
    		if (pT->m_spUnkSite)
    			hRes = pT->m_spUnkSite->QueryInterface(riid, ppvSite);
    		else
    		{
    			*ppvSite = NULL;
    			hRes = E_FAIL;
    		}
    	}
    	return hRes;
    }
    HRESULT STDMETHODCALLTYPE 
    CMFCSiteCtrl::XObjWithSite::SetChildSite(IUnknown* punkChild)
    {
    	if (punkChild == NULL)
    		return E_POINTER;
    
    	HRESULT hr;
    	CComPtr<IObjectWithSite> spChildSite;
    	hr = punkChild->QueryInterface(__uuidof(IObjectWithSite), (void**)&spChildSite);
    	if (SUCCEEDED(hr))
    		hr = spChildSite->SetSite((IUnknown*)this);
    
    	return hr;
    }
    HRESULT STDMETHODCALLTYPE 
    CMFCSiteCtrl::XObjWithSite::SetChildSite(IUnknown* punkChild, IUnknown* punkParent)
    {
    	return AtlSetChildSite(punkChild, punkParent);
    }
    some of the code i took from ATL template class
    as they are template class for i tried to repalce the "T" with "CMFCSiteCtrl"

    somewhere they works
    but here is my problem
    the sitelock declare some variable of type that a "CMFCSiteCtrl" must declare
    they are as follows

    static const SiteList rgslTrustedSites[6];
    enum { dwControlLifespan =365 };

    as you could see this is "SiteList" Structure which is defined in the "Sitelock.h" i get undeclare identifier for it. how do i make it accesible??

    i mean how do it get this structure defined in the "Interface" in my MFCCtrl Class??

    Any help would be greatly Appreciated
    regards
    Dingo

  2. #2
    Join Date
    Feb 2007
    Posts
    247

    Re: ActiveX and IObjectSafetySiteLock,IObjectWithSite

    project attached
    Last edited by dingo_kasper; August 7th, 2009 at 04:38 AM.

  3. #3
    Join Date
    Feb 2007
    Posts
    247

    Resolved Re: ActiveX and IObjectSafetySiteLock,IObjectWithSite

    hello,

    i solved this problem
    just to help others if they ever encounter this. i am posting the solution

    there were couple of problems in the code.

    (1) as i was using the MFC ActiveX control so the activeX control class gets inherited from the COleControl. now this is what MSDN says about it that you have to use IOleObject and IObjectWithSite exclusively. means you could not use the both interfaces so the call to "STDMETHOD(SetSite)(IUnknown *pUnkSite);" will not happen. as we have already used IOleObject.

    now how did i resolve this problem is i extracted all related functions from the sitelock template class the wrap them in a diffrent Class. and then referenced this class at what places it was required. the only thing i want to get was the URL of the control and the Zone setting. which was presented in the "Sitelock.h" template class. i added this code to my class with correctly passing the interface pointers. and all done!!

    codeguru is the one of best place to spend time with, thanks you All!!

    thanks
    Dingo

  4. #4
    Join Date
    Feb 2009
    Posts
    2

    Re: ActiveX and IObjectSafetySiteLock,IObjectWithSite

    Hi,

    Since I found dingo_kasper's help very, very useful - but it didn't detail the complete necessary steps, I decided to add my little guide.

    So, what you need is the following:

    Modified sitelock.h (attached)

    Additions to your Ctrl.h file:

    Code:
    #include <ObjSafe.h>
    #define SITELOCK_USE_IOLEOBJECT
    #include <atlbase.h>
    #include "sitelock.h"
    
    .....
    
    class CYourCtrl : public COleControl
    {
    
    .....
    
    BEGIN_INTERFACE_PART(ObjSafe, IObjectSafetySiteLock)
    	STDMETHOD(SetInterfaceSafetyOptions)(REFIID riid,DWORD dwOptionSetMask, DWORD dwEnabledOptions);
    	STDMETHOD(GetInterfaceSafetyOptions)(REFIID riid,DWORD __RPC_FAR *pdwSupportedOptions,DWORD __RPC_FAR *pdwEnabledOptions);
    	STDMETHOD(GetCapabilities)(DWORD * pdwCapability);
    	STDMETHOD(GetApprovedSites)(const SiteList ** pSiteList, DWORD * cSites);
    	STDMETHOD(GetExpiryDate)(DWORD * pdwLifespan, FILETIME * pExpiryDate);
        private:
        
            static const IObjectSafetySiteLock::SiteList rgslTrustedSites[6];
            
            // Number of days before expiration of control
            static const DWORD dwControlLifespan;
        
            // Used internally in said functions
            bool ControlExpired(DWORD dwExpiresDays = dwControlLifespan);	    
            bool InApprovedDomain(const SiteList* rgslTrustedSites = rgslTrustedSites, 
                                  int cTrustedSites = _countof(rgslTrustedSites));
            // Retrieves the activation URL
            bool GetOurUrl(CComBSTR &bstrURL, DWORD &dwZone);                
            // Checks if an activation URL is in an allowed domain / zone
            bool FApprovedDomain(const OLECHAR* wzUrl, DWORD dwZone, 
                                 const SiteList* rgslTrustedSites, 
                                 int cTrustedSites);                             
            // Normalizes an international domain name
            HRESULT NormalizeDomain(OLECHAR* wzDomain, int cchDomain);	                             
            // Extracts a normalized domain and scheme from an activation URL
            HRESULT GetDomainAndScheme(const OLECHAR * wzUrl, 
                                       OLECHAR * wzScheme, 
                                       DWORD cchScheme, 
                                       OLECHAR* wzDomain, 
                                       DWORD cchDomain);
            // Attempts to match an activation URL with a domain name
            bool MatchDomains(const OLECHAR * wzTrustedDomain, 
                              const OLECHAR * wzOurDomain);
                              
            static DWORD m_dwCurrentSafety;
    
    END_INTERFACE_PART(ObjSafe);
    
    ......
    
    };
    
    ......
    Attached Files Attached Files

  5. #5
    Join Date
    Feb 2009
    Posts
    2

    Re: ActiveX and IObjectSafetySiteLock,IObjectWithSite

    and additions to your Ctrl.cpp file:

    Code:
    // Trusted sites, to allow this control to run on
    const IObjectSafetySiteLock::SiteList CYourCtrl::XObjSafe::rgslTrustedSites[6] = 
    {
        { IObjectSafetySiteLock::SiteList::Allow, L"http",  L"microsoft.com"       },
        { IObjectSafetySiteLock::SiteList::Allow, L"http",  SITELOCK_INTRANET_ZONE },
        { IObjectSafetySiteLock::SiteList::Allow, L"https", L"micrososft.com"       },
        { IObjectSafetySiteLock::SiteList::Allow, L"https", SITELOCK_INTRANET_ZONE },
        { IObjectSafetySiteLock::SiteList::Allow, L"http",  L"192.168.2.130"       },
        { IObjectSafetySiteLock::SiteList::Allow, L"https", L"192.168.2.130"       },
    };
    
    // Control lifespan, in days
    const DWORD CYourCtrl::XObjSafe::dwControlLifespan = 30;
    
    DWORD CYourCtrl::XObjSafe::m_dwCurrentSafety = 0;
    
    ......
    
    BEGIN_INTERFACE_MAP(CYourCtrl, COleControl)
       INTERFACE_PART(CYourCtrl, IID_IObjectSafety, ObjSafe)
       INTERFACE_PART(CYourCtrl, IID_IObjectSafetySiteLock, ObjSafe)
    END_INTERFACE_MAP()
    
    ......
    
    const DWORD dwSupportedSafety = 
          INTERFACESAFE_FOR_UNTRUSTED_CALLER |
          INTERFACESAFE_FOR_UNTRUSTED_DATA;
          
    const DWORD dwNotSupportedSafety = ~dwSupportedSafety;
    
    #ifndef SITELOCK_NO_EXPIRY
    // Helper functions for expiry
    #if defined(_WIN64) && defined(_M_IA64)
        #pragma section(".base", long, read, write)
        extern "C" __declspec(allocate(".base")) extern IMAGE_DOS_HEADER __ImageBase;
    #else
        extern "C" IMAGE_DOS_HEADER __ImageBase;
    #endif
    
    #define ImageNtHeaders(pBase) ((PIMAGE_NT_HEADERS)((PCHAR)(pBase) + ((PIMAGE_DOS_HEADER)(pBase))->e_lfanew))
    
    #define LODWORD(_qw)    ((DWORD)(_qw))
    #define HIDWORD(_qw)    ((DWORD)(((_qw) >> 32) & 0xffffffff))
    inline void UNIXTimeToFILETIME(time_t t, LPFILETIME ft)
    {
    	// The time_t is a 32-bit value for the number of seconds since January 1, 1970.
    	// A FILETIME is a 64-bit for the number of 100-nanosecond periods since January 1, 1601.  
    	// Convert by multiplying the time_t value by 1e+7 to get to the same base granularity,
    	// then add the numeric equivalent of January 1, 1970 as FILETIME. 
    
    	ULONGLONG qw = ((ULONGLONG)t * 10000000ui64) + 116444736000000000ui64;
    	ft->dwHighDateTime = HIDWORD(qw);
    	ft->dwLowDateTime = LODWORD(qw);
    }
    inline time_t FILETIMEToUNIXTime(LPFILETIME ft)
    {
    	ULONGLONG qw = (((ULONGLONG)ft->dwHighDateTime)<<32) + ft->dwLowDateTime;
    	return (time_t)((qw - 116444736000000000ui64) / 10000000ui64);
    }
    #endif // SITELOCK_NO_EXPIRY
    
    // Allows container to query what interfaces are safe for what. We're
    // optimizing significantly by ignoring which interface the caller is
    // asking for.
    HRESULT STDMETHODCALLTYPE 
       CYourCtrl::XObjSafe::GetInterfaceSafetyOptions( 
          /* [in] */ REFIID riid,
            /* [out] */ DWORD __RPC_FAR *pdwSupportedOptions,
            /* [out] */ DWORD __RPC_FAR *pdwEnabledOptions)
    {
        METHOD_PROLOGUE(CYourCtrl, ObjSafe)
    
        // Data validation
    	if (!pdwSupportedOptions || !pdwEnabledOptions)
    		return E_POINTER;
    
    	// Declarations
    	HRESULT			hr		= S_OK;
    	IUnknown *		pUnk	= NULL;
    
    	// Check if the requested COM interface is supported
    	hr = pThis->ExternalQueryInterface(&riid, (void**)&pUnk);
    	if (FAILED(hr))
    	{
    		*pdwSupportedOptions = 0;
    		*pdwEnabledOptions   = 0;
    		return hr;
    	}
    
    	// Release the interface
    	pUnk->Release();
    
    	// Check expiry and if the activation URL is allowed
    	if (!ControlExpired() && InApprovedDomain())
    	{
    		*pdwSupportedOptions = dwSupportedSafety;
    		*pdwEnabledOptions   = m_dwCurrentSafety;
    	}
    	else
    	{
    		*pdwSupportedOptions = dwSupportedSafety;
    		*pdwEnabledOptions   = 0;
    	}
    	return S_OK;
    }
    
    // Since we're always safe, this is a no-braineróbut we do check to make
    // sure the interface requested exists and that the options we're asked to
    // set exist and are set on (we don't support unsafe mode).
    HRESULT STDMETHODCALLTYPE 
       CYourCtrl::XObjSafe::SetInterfaceSafetyOptions( 
            /* [in] */ REFIID riid,
            /* [in] */ DWORD dwOptionSetMask,
            /* [in] */ DWORD dwEnabledOptions)
    {
        METHOD_PROLOGUE(CYourCtrl, ObjSafe)
       
        // Declarations
    	HRESULT			hr		= S_OK;
    	IUnknown *		pUnk	= NULL;
    
    	// Check if we support the interface and return E_NOINTERFACE if we don't
    	// Check if the requested COM interface is supported
    	hr = pThis->ExternalQueryInterface(&riid, (void**)&pUnk);
    	if (FAILED(hr))
    		return hr;
    
    	// Release the interface
    	pUnk->Release();
    
    	// Reject unsupported requests
    	if (dwOptionSetMask & ~dwSupportedSafety)
    		return E_FAIL;
    
    	// Calculate safety options
    	DWORD dwNewSafety = (m_dwCurrentSafety  & ~dwOptionSetMask) | (dwOptionSetMask & dwEnabledOptions);
    	if (m_dwCurrentSafety != dwNewSafety)
    	{
    		// Check expiry and if the activation URL is allowed
    		if (ControlExpired() || !InApprovedDomain())
    			return E_FAIL;
    
    		// Set safety options
    		m_dwCurrentSafety = dwNewSafety;
    	}
    	return S_OK;
    }
    
    // Delegate AddRef, Release, QueryInterface
    ULONG FAR EXPORT CYourCtrl::XObjSafe::AddRef()
    {
        METHOD_PROLOGUE(CYourCtrl, ObjSafe)
        return pThis->ExternalAddRef();
    }
    ULONG FAR EXPORT CYourCtrl::XObjSafe::Release()
    {
        METHOD_PROLOGUE(CYourCtrl, ObjSafe)
        return pThis->ExternalRelease();
    }
    HRESULT FAR EXPORT CYourCtrl::XObjSafe::QueryInterface(
        REFIID iid, void FAR* FAR* ppvObj)
    {
        METHOD_PROLOGUE(CYourCtrl, ObjSafe)
        return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj);
    }
    
    
    HRESULT STDMETHODCALLTYPE 
    CYourCtrl::XObjSafe::GetCapabilities(DWORD * pdwCapability)
    {
    	// Data validation
    	if (!pdwCapability)
    		return E_POINTER;
    
    	// Return the version if 0 is passed in
    	if (0 == *pdwCapability)
    	{
    		*pdwCapability = SITELOCK_VERSION;
    		return S_OK;
    	}
    
    	// Return the options if 1 is passed in
    	if (1 == *pdwCapability)
    	{
    		*pdwCapability =
    #ifndef SITELOCK_NO_EXPIRY
    			IObjectSafetySiteLock::UsesIOleObject |
    #endif
    			0;
    		return S_OK;
    	}			
    
    	// Return not implemented otherwise
    	*pdwCapability = 0;
    	return E_NOTIMPL;
    }
    
    HRESULT STDMETHODCALLTYPE 
    CYourCtrl::XObjSafe::GetApprovedSites(const SiteList ** pSiteList, DWORD * pcEntries)
    {
    	// Data validation
    	if (!pSiteList || !pcEntries)
    		return E_POINTER;
    
    	// Return specified site lock entries
    #ifdef SITELOCK_USE_MAP
    	// Use the site lock map
    	*pSiteList = /*T::*/ GetSiteLockMapAndCount(*pcEntries);
    #else
    	// Use the static member
    	*pSiteList = /*T::*/ rgslTrustedSites;
    	*pcEntries = _countof(/*T::*/ rgslTrustedSites);
    #endif
    	return S_OK;
    }
    
    HRESULT STDMETHODCALLTYPE 
    CYourCtrl::XObjSafe::GetExpiryDate(DWORD * pdwLifespan, FILETIME * pExpiryDate)
    {
    	if (!pdwLifespan || !pExpiryDate)
    		return E_POINTER;
    
    #ifdef SITELOCK_NO_EXPIRY
    	*pdwLifespan = 0;
    	::ZeroMemory((void*)pExpiryDate, sizeof(FILETIME));
    	return E_NOTIMPL;
    #else
    	*pdwLifespan = /*T::*/ dwControlLifespan;
    
    	// Calculate expiry date from life span
    	time_t ttExpire = ImageNtHeaders(&__ImageBase)->FileHeader.TimeDateStamp;
    	ttExpire += /*T::*/ dwControlLifespan*86400;	// seconds per day
    	UNIXTimeToFILETIME(ttExpire, pExpiryDate);
    
    	return S_OK;
    #endif
    }
    
    bool CYourCtrl::XObjSafe::ControlExpired(DWORD dwExpiresDays /*= dwControlLifespan*/)
    {
        SYSTEMTIME st = {0};
        FILETIME   ft = {0};
    
        GetSystemTime(&st);
        if (!SystemTimeToFileTime(&st, &ft))
            return true;
    
        time_t ttTime = FILETIMEToUNIXTime(&ft);
        time_t ttExpire = ImageNtHeaders(&__ImageBase)->FileHeader.TimeDateStamp;
        ttExpire += dwExpiresDays*86400;
    
        return (ttTime > ttExpire);
    }
    
    bool CYourCtrl::XObjSafe::InApprovedDomain(const IObjectSafetySiteLock::SiteList* rgslTrustedSites /*= rgslTrustedSites*/, int cTrustedSites /*= _countof(rgslTrustedSites)*/)
    {
        // Retrieve the activation URL
        CComBSTR bstrUrl;
        DWORD    dwZone	= URLZONE_UNTRUSTED;
        if (!GetOurUrl(bstrUrl, dwZone))
            return false;
    
        // Check if the activation URL is in an allowed domain / zone
        return FApprovedDomain(bstrUrl, dwZone, rgslTrustedSites, cTrustedSites);
    }
    
    bool CYourCtrl::XObjSafe::GetOurUrl(CComBSTR &bstrURL, DWORD &dwZone)
    {
        METHOD_PROLOGUE(CYourCtrl, ObjSafe)
    
        // Declarations
        HRESULT	                          hr = S_OK;
        CComPtr<IServiceProvider>         spSrvProv;
        CComPtr<IInternetSecurityManager> spInetSecMgr;
        CComPtr<IWebBrowser2>             spWebBrowser;
        
        // Retrieve the activation site
        CComPtr<IOleClientSite> spClientSite = pThis->GetClientSite();
    	
    	if ((FAILED(hr)) || (spClientSite == NULL))
    		return false;
    	hr = spClientSite->QueryInterface(IID_IServiceProvider, (void **)&spSrvProv);
    
    
        if (FAILED(hr))
            return false;
    
        // Query the site for a web browser object
        hr = spSrvProv->QueryService(SID_SWebBrowserApp, IID_IWebBrowser2, (void **)&spWebBrowser);
        if (FAILED(hr))
        {
            // Local declarations
            CComPtr<IHTMLDocument2>		spDoc;
            CComPtr<IOleContainer>		spContainer;
    
            // Reinitialize
            spSrvProv = NULL;
            spClientSite = NULL;
    
            // Get the client site, container, and provider, etc.
            spClientSite = pThis->GetClientSite();
    
            if (FAILED(hr) || spClientSite == NULL)
                return false;
    
            hr = spClientSite->GetContainer(&spContainer);
            if (FAILED(hr))
                return false;
            hr = spContainer->QueryInterface(IID_IHTMLDocument2, (void **)&spDoc);
            if (FAILED(hr))
                return false;
            if (FAILED(spDoc->get_URL(&bstrURL)))
                return false;
            hr = spClientSite->QueryInterface(IID_IServiceProvider, (void **)&spSrvProv);
            if (FAILED(hr))
                return false;
        }
        else
        {
            // Query the web browser object for the activation URL
            hr = spWebBrowser->get_LocationURL(&bstrURL);
            if (FAILED(hr))
                return false;
        }
    
        // Query the site for its associated security manager
        hr = spSrvProv->QueryService(SID_SInternetSecurityManager, IID_IInternetSecurityManager, (void **)&spInetSecMgr);
        if (FAILED(hr))
            return false;
    
        // Query the security manager for the zone the activation URL belongs to
        hr = spInetSecMgr->MapUrlToZone(bstrURL, &dwZone, 0);
        if (FAILED(hr))
            return false;
        return true;
    }
    
    bool CYourCtrl::XObjSafe::FApprovedDomain(const OLECHAR * wzUrl, DWORD dwZone, const IObjectSafetySiteLock::SiteList * rgslTrustedSites, int cTrustedSites)
    {
        // Declarations
        HRESULT hr                                          = S_OK;
        OLECHAR	wzDomain[INTERNET_MAX_HOST_NAME_LENGTH + 1] = {0};
        OLECHAR	wzScheme[INTERNET_MAX_SCHEME_LENGTH + 1]    = {0};
    
        // Retrieve the normalized domain and scheme
        hr = GetDomainAndScheme(wzUrl, wzScheme, _countof(wzScheme), wzDomain, _countof(wzDomain));
        if (FAILED(hr))
            return false;
    
        // Try to match the activation URL with each entry in order
        DWORD cbScheme = (::lstrlenW(wzScheme) + 1) * sizeof(OLECHAR);
        for (int i=0; i < cTrustedSites; i++)
        {
            // Try to match by scheme
            DWORD cbSiteScheme = (::lstrlenW(rgslTrustedSites[i].szScheme) + 1) * sizeof(OLECHAR);
            if (cbScheme != cbSiteScheme)
                continue;
            if (0 != ::memcmp(wzScheme, rgslTrustedSites[i].szScheme, cbScheme))
                continue;
    
            // Try to match by zone
            if (rgslTrustedSites[i].szDomain == SITELOCK_INTRANET_ZONE)
            {
                if ((dwZone == URLZONE_INTRANET) || (dwZone == URLZONE_TRUSTED))
                    return rgslTrustedSites[i].iAllowType == IObjectSafetySiteLock::SiteList:: Allow;
            }
            else if (rgslTrustedSites[i].szDomain == SITELOCK_MYCOMPUTER_ZONE)
            {
                if (dwZone == URLZONE_LOCAL_MACHINE)
                    return rgslTrustedSites[i].iAllowType == IObjectSafetySiteLock::SiteList:: Allow;
            }
            else if (rgslTrustedSites[i].szDomain == SITELOCK_TRUSTED_ZONE)
            {
                if (dwZone == URLZONE_TRUSTED)
                    return rgslTrustedSites[i].iAllowType == IObjectSafetySiteLock::SiteList:: Allow;
            }
    
            // Try to match by domain name
            else if (MatchDomains(rgslTrustedSites[i].szDomain, wzDomain))
            {
                return rgslTrustedSites[i].iAllowType == IObjectSafetySiteLock::SiteList:: Allow;
            }
        }
        return false;
    }
    
    HRESULT CYourCtrl::XObjSafe::NormalizeDomain(OLECHAR * wzDomain, int cchDomain)
    {
        // Data validation
        if (!wzDomain)
            return E_POINTER;
    
        // If the domain is only 7-bit ASCII, normalization is not required
        bool fFoundUnicode = false;
        for (const OLECHAR * wz = wzDomain; *wz != 0; wz++)
        {
            if (0x80 <= *wz)
            {
                fFoundUnicode = true;
                break;
            }
        }
        if (!fFoundUnicode)
            return S_OK;
    
        // Construct a fully qualified path to the Windows system directory
        static const WCHAR wzNormaliz[] = L"normaliz.dll";
        static const int cchNormaliz = _countof(wzNormaliz);
        WCHAR wzDllPath[MAX_PATH + 1] = {0};
        UINT cchDllPath = ::GetSystemDirectoryW(wzDllPath, _countof(wzDllPath) - cchNormaliz - 1);
        if (cchDllPath == 0 || cchDllPath > _countof(wzDllPath) - cchNormaliz - 1)
            return E_FAIL;
        if (wzDllPath[cchDllPath-1] != L'\\')
            wzDllPath[cchDllPath++] = L'\\';
        ::CopyMemory(wzDllPath + cchDllPath, wzNormaliz, cchNormaliz * sizeof(WCHAR));
    
        // Load the DLL used for domain normalization
        HMODULE hNormaliz = ::LoadLibraryExW(wzDllPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
        if (!hNormaliz)
            return E_FAIL;
    
        HRESULT hr = E_FAIL;
    
        // Locate the entry point used for domain normalization
        PFN_IdnToAscii pfnIdnToAscii = (PFN_IdnToAscii)::GetProcAddress(hNormaliz, "IdnToAscii");
        if (!pfnIdnToAscii)
            goto cleanup;
    
        // Normalize the domain name
        WCHAR wzEncoded[INTERNET_MAX_HOST_NAME_LENGTH + 1] = {0};
        int cchEncode = pfnIdnToAscii(IDN_USE_STD3_ASCII_RULES, wzDomain, ::lstrlenW(wzDomain), wzEncoded, _countof(wzEncoded));
        if (cchEncode <= 0 || cchEncode >= _countof(wzEncoded))
        {
            hr = HRESULT_FROM_WIN32(::GetLastError());
            goto cleanup;
        }
    
        // Copy results to the input buffer
        if (cchEncode >= cchDomain)
        {
            hr = E_OUTOFMEMORY;
            goto cleanup;
        }
    
        ::CopyMemory(wzDomain, wzEncoded, cchEncode * sizeof(WCHAR));
        hr = S_OK;
    
    cleanup:
        if (hNormaliz)
            ::CloseHandle(hNormaliz);
    
        return hr;
    }
    
    HRESULT CYourCtrl::XObjSafe::GetDomainAndScheme(const OLECHAR * wzUrl, OLECHAR * wzScheme, DWORD cchScheme, OLECHAR* wzDomain, DWORD cchDomain)
    {
        // Data validation
        if (!wzDomain || !wzScheme)
            return E_POINTER;
    
        // Extract the scheme
        HRESULT hr = ::UrlGetPartW(wzUrl, wzScheme, &cchScheme, URL_PART_SCHEME, 0);
        if (FAILED(hr))
            return E_FAIL;
    
        // Extract the host name
        DWORD cchDomain2 = cchDomain;
        hr = ::UrlGetPartW(wzUrl, wzDomain, &cchDomain2, URL_PART_HOSTNAME, 0);
        if (FAILED(hr))
            *wzDomain = 0;
    
        // Exclude any URL specifying a user name or password
        if ((0 == ::_wcsicmp(wzScheme, L"http")) || (0 == ::_wcsicmp(wzScheme, L"https")))
        {
            DWORD cch = 1;
            WCHAR wzTemp[1] = {0};
            ::UrlGetPartW(wzUrl, wzTemp, &cch, URL_PART_USERNAME, 0);
            if (1 < cch)
                return E_FAIL;
            ::UrlGetPartW(wzUrl, wzTemp, &cch, URL_PART_PASSWORD, 0);
            if (1 < cch)
                return E_FAIL;
        }
    
        // Normalize the domain name
        return NormalizeDomain(wzDomain, cchDomain);
    }
    
    bool CYourCtrl::XObjSafe::MatchDomains(const OLECHAR * wzTrustedDomain, const OLECHAR * wzOurDomain)
    {
        // Data validation
        if (!wzTrustedDomain)
            return (0 == *wzOurDomain); // match only if empty
    
        // Declarations
        int  cchTrusted   = ::lstrlenW(wzTrustedDomain);
        int  cchOur       = ::lstrlenW(wzOurDomain);
        bool fForcePrefix = false;
        bool fDenyPrefix  = false;
    
        // Check if all activation URLs should be matched
        if (0 == ::wcscmp(wzTrustedDomain, L"*"))
            return true;
    
        // Check if the entry is like *. and setup the comparison range
        if ((2 < cchTrusted) && (L'*' == wzTrustedDomain[0]) && (L'.' == wzTrustedDomain[1]))
        {
            fForcePrefix = true;
            wzTrustedDomain += 2;
            cchTrusted -= 2;
        }
    
        // Check if the entry is like = and setup the comparison range
        else if ((1 < cchTrusted) && (L'=' == wzTrustedDomain[0]))
        {
            fDenyPrefix = true;
            wzTrustedDomain++;
            cchTrusted--;
        };
    
        // Check if there is a count mismatch
        if (cchTrusted > cchOur)
            return false;
    
        // Compare URLs on the desired character range
        if (0 != ::memcmp(wzOurDomain + cchOur - cchTrusted, wzTrustedDomain, cchTrusted * sizeof(OLECHAR)))
            return false;
    
        // Compare URLs without allowing child domains
        if (!fForcePrefix && (cchTrusted == cchOur))
            return true;
    
        // Compare URLs requiring child domains
        if (!fDenyPrefix && (wzOurDomain[cchOur - cchTrusted - 1] == L'.'))
            return true;
    
        return false;
    }
    Finally, so Google finds this:

    sitelock with MFC
    IObjectSafetySiteLock with MFC

  6. #6
    Join Date
    Feb 2010
    Posts
    1

    Smile Re: ActiveX and IObjectSafetySiteLock,IObjectWithSite

    Thanks guys, I thought I'd chip in too. I had some trouble with the above directions. What I basically did was I followed this codeproject article: http://www.codeproject.com/KB/COM/CompleteActiveX.aspx on creating a simple MFC ActiveX control. I then wanted to use the SiteLock template on that example but had a thrilling time banging my head on the wall for a couple of days. This post really helped. I took your modifed sitelock.h and replaced the one I had and added the code you posted to my h and cpp files.

    I found that I needed to add DECLARE_INTERFACE_MAP() (after all the other DECLAREs) to my CYourctrl.h file.

    I also changed the following in GetInterfaceSafetyOptions:

    // Check expiry and if the activation URL is allowed
    if (!ControlExpired() && InApprovedDomain())
    {
    *pdwSupportedOptions = dwSupportedSafety;
    *pdwEnabledOptions = m_dwCurrentSafety;
    }
    else
    {
    *pdwSupportedOptions = 0; // Changed from dwSupportedSafety
    *pdwEnabledOptions = 0;
    }

    This way if the site doesn't belong to the approved list, safety will not be supported ( before I did that safety settings were working for both approved and unapproved sites) not sure what the logic with the m_dwCurrentSafety option is.

    I've attached the example project I was working on in case somebody else is having as much trouble dealing with this. As I understood from this post, the OleObject route is your only choice when you are working with MFC and the SiteLock template.

    Thanks for the effort guys
    Attached Files Attached Files

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Windows Mobile Development Center


Click Here to Expand Forum to Full Width

This is a CodeGuru survey question.


Featured


HTML5 Development Center