添加IObjectSafety接口使MFC写的OCX可信

感谢此篇博客。找了很久没有找到IObjectSafety需要添加哪些代码,这篇代码很详细。
MFC OCX控件实现安全初始化和脚本安全的方法

原文有两个方法,我更推荐用IObjectSafety,原博客的代码不太好看,我这里整理一下。
我的环境是VS2013,用模板生成的项目包含的文件基本相同,不构成影响。一般如下结构:
添加IObjectSafety接口使MFC写的OCX可信_第1张图片

假定我们用模板生成的项目名叫[TestOCX],所以马赛克部分应该都是TestOCX。相应的,本文涉及的两个文件分别为TestOCXCtrl.h和TestOCXCtrl.cpp。 如果需要,则请将代码中的TestOCXCtrl替换成各位自己的名字。

  1. TestOCXCtrl.h中添加如下代码
#include  // for IObjectSafety; in ActiveX SDK

这个代码是实现IObjectSafety的前提。

  1. 依然是在TestOCXCtrl.h中,一般在类的构造函数前有一行
DECLARE_DYNCREATE(CTestOCXCtrl)

在这行代码前添加如下代码:


#pragma region objsafe
//*******************************************************add begin
    //ISafeObject
    DECLARE_INTERFACE_MAP()
    BEGIN_INTERFACE_PART(ObjSafe, IObjectSafety)

    STDMETHOD_(HRESULT, GetInterfaceSafetyOptions) (
    /* [in] */ REFIID riid,
    /* [out] */ DWORD __RPC_FAR *pdwSupportedOptions,
    /* [out] */ DWORD __RPC_FAR *pdwEnabledOptions
    );

    STDMETHOD_(HRESULT, SetInterfaceSafetyOptions) (
        /* [in] */ REFIID riid,
        /* [in] */ DWORD dwOptionSetMask,
        /* [in] */ DWORD dwEnabledOptions
        );
    END_INTERFACE_PART(ObjSafe);

    //ISafeObject
//*******************************************************add end

#pragma endregion

加上#pragma region objsafe只是因为方便折叠…

  1. TestOCXCtrl.cpp中,注意替换下述代码中所有CTestOCXCtrl为自己控件的名称。需要添加的有几个位置
    (1)消息映射内添加如下代码
BEGIN_MESSAGE_MAP(CTestOCXCtrl, COleControl)
    //下面是要添加的
    //{{AFX_MSG_MAP(CTestOCXCtrl)
    // NOTE - ClassWizard will add and remove message map entries
    //    DO NOT EDIT what you see in these blocks of generated code !
    //}}AFX_MSG_MAP
    ON_OLEVERB(AFX_IDS_VERB_PROPERTIES, OnProperties)
    //添加结束
END_MESSAGE_MAP()

(2)紧跟其后如果没有接口映射的话,下述代码完整添加;否则添加到接口映射内即可

//*******************************************************add begin
BEGIN_INTERFACE_MAP(CTestOCXCtrl, COleControl)
    INTERFACE_PART(CTestOCXCtrl, IID_IObjectSafety, ObjSafe)
END_INTERFACE_MAP()
//*******************************************************add end

(3)在文件末尾完整复制粘贴如下代码

增加IObjectSafety接口实现方法
////***************************************************************add begin

// IObjectSafety member functions

// Delegate AddRef, Release, QueryInterface

ULONG FAR EXPORT CTestOCXCtrl::XObjSafe::AddRef()

{

    METHOD_PROLOGUE(CTestOCXCtrl, ObjSafe)

    return pThis->ExternalAddRef();

}

ULONG FAR EXPORT CTestOCXCtrl::XObjSafe::Release()

{

    METHOD_PROLOGUE(CTestOCXCtrl, ObjSafe)

    return pThis->ExternalRelease();

}

HRESULT FAR EXPORT CTestOCXCtrl::XObjSafe::QueryInterface(REFIID iid, void FAR* FAR* ppvObj)

{

    METHOD_PROLOGUE(CTestOCXCtrl, ObjSafe)

    return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj);

}

const DWORD dwSupportedBits = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;

const DWORD dwNotSupportedBits = ~ dwSupportedBits;

//.............................................................................

// CStopLiteCtrl::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 

CTestOCXCtrl::XObjSafe::GetInterfaceSafetyOptions( 

 /* [in] */ REFIID riid,

 /* [out] */ DWORD __RPC_FAR *pdwSupportedOptions,

 /* [out] */ DWORD __RPC_FAR *pdwEnabledOptions)

{

    METHOD_PROLOGUE(CTestOCXCtrl, 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 
CTestOCXCtrl::XObjSafe::SetInterfaceSafetyOptions(

 /* [in] */ REFIID riid,

 /* [in] */ DWORD dwOptionSetMask,

 /* [in] */ DWORD dwEnabledOptions)

{

    METHOD_PROLOGUE(CTestOCXCtrl, 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);
}

//***************************************************************add end

完成上述步骤之后,编译,在HTML中添加

应该就不会弹出安全警告了。

你可能感兴趣的:(C++,MFC,OCX)