MFC ActiveX ISafeObject的實現

默認情況下,編譯的MFC Activex控件,只能在本地代碼中運行,即便是網頁,也只能在本地運行,一旦要想放在Web服務器通過IE訪問,需要設置其初始化和腳本運行的安全性,爲此您需要作出如下修改:

在“工程名.cpp”文件中,增加以下方法:

 

// 創建組件種類

HRESULT CreateComponentCategory(CATID catid, WCHAR* catDescription) 

{    

       ICatRegister* pcr = NULL ;    

       HRESULT hr = S_OK ;    

       hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr);    

       if (FAILED(hr)) return hr;    

       // Make sure the HKCR\Component Categories\{..catid...}    

       // key is registered.    

       CATEGORYINFO catinfo;    

       catinfo.catid = catid;    

       catinfo.lcid = 0x0409 ; // english    

       // Make sure the provided description is not too long.    

       // Only copy the first 127 characters if it is.    

       int len = wcslen(catDescription);    

       if (len>127) len = 127;    

       wcsncpy_s(catinfo.szDescription, catDescription, len);    

       // Make sure the description is null terminated.    

       catinfo.szDescription[len] = '\0';

       hr = pcr->RegisterCategories(1, &catinfo);    

       pcr->Release();    

       return hr;    

}  

 

// 註冊組件種類

HRESULT RegisterCLSIDInCategory(REFCLSID clsid, CATID catid)

{    

       // Register your component categories information.    

       ICatRegister* pcr = NULL ;    

       HRESULT hr = S_OK ;    

       hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr);    

       if (SUCCEEDED(hr)) {    

              // Register this category as being "implemented" by the class.    

              CATID rgcatid[1];    

              rgcatid[0] = catid;    

              hr = pcr->RegisterClassImplCategories(clsid, 1, rgcatid);    

       }    

       if (pcr != NULL) pcr->Release();    

       return hr;    

}    

// 卸載組件種類

HRESULT UnRegisterCLSIDInCategory(REFCLSID clsid, CATID catid)

{    

       ICatRegister* pcr = NULL ;    

       HRESULT hr = S_OK ;    

       hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr,    

              NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr);    

       if (SUCCEEDED(hr)) {    

              // Unregister this category as being "implemented" by the class.    

              CATID rgcatid[1] ;    

              rgcatid[0] = catid;    

              hr = pcr->UnRegisterClassImplCategories(clsid, 1, rgcatid);    

       }    

       if (pcr != NULL) pcr->Release();    

       return hr;    

}

 

然後修改DllRegisterServer和DllUnregisterServer這個兩個方法做如下修改:

 

// DllRegisterServer - 將項添加到系統註冊表

STDAPI DllRegisterServer(void)

{

       HRESULT hr;    

       AFX_MANAGE_STATE(_afxModuleAddrThis);    

       if (!AfxOleRegisterTypeLib(AfxGetInstanceHandle(), _tlid))    

              return ResultFromScode(SELFREG_E_TYPELIB);    

       if (!COleObjectFactoryEx::UpdateRegistryAll(TRUE))    

              return ResultFromScode(SELFREG_E_CLASS);    

       // 標記控件初始化安全.

       // 創建初始化安全組件種類

       hr = CreateComponentCategory(CATID_SafeForInitializing, L"Controls safely initializable from persistent data!");    

       if (FAILED(hr)) return hr;    

       // 註冊初始化安全

       hr = RegisterCLSIDInCategory(BASED_CODE _tlid , CATID_SafeForInitializing);    

       if (FAILED(hr)) return hr;    

       // 標記控件腳本安全

       // 創建腳本安全組件種類

       hr = CreateComponentCategory(CATID_SafeForScripting, L"Controls safely scriptable!");    

       if (FAILED(hr)) return hr;    

       // 註冊腳本安全組件種類

       hr = RegisterCLSIDInCategory(BASED_CODE _tlid , CATID_SafeForScripting);    

       if (FAILED(hr)) return hr;

 

       return NOERROR;

}

 

// DllUnregisterServer - 將項從系統註冊表中移除

STDAPI DllUnregisterServer(void)

{

       HRESULT hr;    

       AFX_MANAGE_STATE(_afxModuleAddrThis);    

       if (!AfxOleUnregisterTypeLib(_tlid, _wVerMajor, _wVerMinor))    

              return ResultFromScode(SELFREG_E_TYPELIB);    

       if (!COleObjectFactoryEx::UpdateRegistryAll(FALSE))    

              return ResultFromScode(SELFREG_E_CLASS);    

       // 刪除控件初始化安全入口.

       hr=UnRegisterCLSIDInCategory(BASED_CODE _tlid , CATID_SafeForInitializing);    

       if (FAILED(hr)) return hr;    

       // 刪除控件腳本安全入口

       hr=UnRegisterCLSIDInCategory(BASED_CODE _tlid , CATID_SafeForScripting);    

       if (FAILED(hr)) return hr;

 

       return NOERROR;

}

 

其中CATID_SafeForInitializing和CATID_SafeForScripting兩個是guid,可以通過VC自帶的guid生成工具自動生成。

 

下一步,實現IobjectSafety接口,步驟:

 

打開 “工程名Ctrl.h”

 

加入#include<objsafe.h>,

 

搜索

DECLARE_DYNCREATE(C工程名Ctrl)

 

在其下面添加:

DECLARE_INTERFACE_MAP()

       BEGIN_INTERFACE_PART(ObjSafe, IObjectSafety)

              STDMETHOD_(HRESULT, GetInterfaceSafetyOptions) (

              REFIID riid,

              DWORD __RPC_FAR *pdwSupportedOptions,

              DWORD __RPC_FAR *pdwEnabledOptions

              );

 

              STDMETHOD_(HRESULT, SetInterfaceSafetyOptions) (

                     REFIID riid,

                     DWORD dwOptionSetMask,

                     DWORD dwEnabledOptions

                     );

       END_INTERFACE_PART(ObjSafe);

 

打開“工程名Ctl.cpp”

 

在

BOOL C工程名Ctrl::C工程名CtrlFactory::UpdateRegistry(BOOL bRegister)

方法上面添加以下代碼:

 

/////////////////////////////////////////////////////////////////////////////

// Interface map for IObjectSafety

BEGIN_INTERFACE_MAP(C工程名Ctrl, COleControl)

       INTERFACE_PART(C工程名Ctrl, IID_IObjectSafety, ObjSafe)

END_INTERFACE_MAP()

/////////////////////////////////////////////////////////////////////////////

// IObjectSafety member functions

// Delegate AddRef, Release, QueryInterface

ULONG FAR EXPORT C工程名Ctrl::XObjSafe::AddRef()

{

       METHOD_PROLOGUE(C工程名Ctrl, ObjSafe)

              return pThis->ExternalAddRef();

}

ULONG FAR EXPORT C工程名Ctrl::XObjSafe::Release()

{

       METHOD_PROLOGUE(C工程名Ctrl, ObjSafe)

              return pThis->ExternalRelease();

}

HRESULT FAR EXPORT C工程名Ctrl::XObjSafe::QueryInterface(

       REFIID iid, void FAR* FAR* ppvObj)

{

       METHOD_PROLOGUE(C工程名Ctrl, 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

       C工程名Ctrl::XObjSafe::GetInterfaceSafetyOptions(

       REFIID riid,

       DWORD __RPC_FAR *pdwSupportedOptions,

       DWORD __RPC_FAR *pdwEnabledOptions)

{

       METHOD_PROLOGUE(C工程名Ctrl, 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

       C工程名Ctrl::XObjSafe::SetInterfaceSafetyOptions(

       REFIID riid,

       DWORD dwOptionSetMask,

       DWORD dwEnabledOptions)

{

       METHOD_PROLOGUE(C工程名Ctrl, 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);

}


至此,該ActiveX組件就註冊爲安全組件了。

發佈了197 篇原創文章 · 獲贊 35 · 訪問量 32萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章