以前工作的时候写过一个ActiveX控件,一直想将其用在网页上,但始终没有成功,今天无意中在MSDN上看到了《Using ActiveX Controls to Automate Your Web Pages》-http://msdn.microsoft.com/library/default.asp?url=/workshop/components/activex/tutorial.asp,似乎与之相关。此文中设计了一个基于Timer的时钟ActiveX控件并将其嵌入到web页面上。当然,本文的重点是在强调基于web页面的ActiveX控件的安全性问题。要使得安全的ActiveX控件在web页面上也安全的话,必须确保调用它的页面脚本(Script)也是安全的,即safe for initialization and/or scripting。要做到这后一点,有两种方法:
在第一种方法中,Component Categories Manager会在注册表中为每个组件包含一个Component Categories key ,并且每个key都有两个subkey,一个是CATID_SafeForScripting ,另一个是CATID_SafeForInitializing。创建subkey的方法是:
将以下步骤写成一个函数CreateComponentCategory 如下:
#include "comcat.h"
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(catinfo.szDescription, catDescription, len);
// Make sure the description is null terminated
catinfo.szDescription[len] = '/0';
hr = pcr->RegisterCategories(1, &catinfo);
pcr->Release();
return hr;
}
在创建了subkey以后,控件必须注册成为该类别(category),要做到这一点,必须:
以上步骤写成以下函数(RegisterCLSIDInCategory ):
#include "comcat.h"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;
}
当DllRegisterServer函数被调用时,控件应该调用以上两个函数,以实现safe for initilization
以及safe for scripting,示例如下:STDAPI DllRegisterServer(void){ HRESULT hr; // return for safety functions AFX_MANAGE_STATE(_afxModuleAddrThis); if (!AfxOleRegisterTypeLib(AfxGetInstanceHandle(), _tlid)) return ResultFromScode(SELFREG_E_TYPELIB); if (!COleObjectFactoryEx::UpdateRegistryAll(TRUE)) return ResultFromScode(SELFREG_E_CLASS); // Mark the control as safe for initializing. hr = CreateComponentCategory(CATID_SafeForInitializing, L"Controls safely initializable from persistent data!"); if (FAILED(hr)) return hr; hr = RegisterCLSIDInCategory(CLSID_SafeItem, CATID_SafeForInitializing); if (FAILED(hr)) return hr; // Mark the control as safe for scripting. hr = CreateComponentCategory(CATID_SafeForScripting, L"Controls safely scriptable!"); if (FAILED(hr)) return hr; hr = RegisterCLSIDInCategory(CLSID_SafeItem, CATID_SafeForScripting); if (FAILED(hr)) return hr; return NOERROR;}
同上一样,也必须对类别进行unregister,相应的函数为: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;}在对应的DllUnRegisterServer中,也应该调用上面函数:STDAPI DllUnregisterServer(void){ HRESULT hr; // HResult used by Safety Functions AFX_MANAGE_STATE(_afxModuleAddrThis); if (!AfxOleUnregisterTypeLib(_tlid)) return ResultFromScode(SELFREG_E_TYPELIB); if (!COleObjectFactoryEx::UpdateRegistryAll(FALSE)) return ResultFromScode(SELFREG_E_CLASS); // Remove entries from the registry. hr=UnRegisterCLSIDInCategory(CLSID_SafeItem, CATID_SafeForInitializing); if (FAILED(hr)) return hr; hr=UnRegisterCLSIDInCategory(CLSID_SafeItem, CATID_SafeForScripting); if (FAILED(hr)) return hr; return NOERROR;}以上调用可以改为以下:BOOL CONotesCtlCtrl::CONotesCtlCtrlFactory::UpdateRegistry(BOOL bRegister)
{
// TODO: Verify that your control follows apartment-model threading rules.
// Refer to MFC TechNote 64 for more information.
// If your control does not conform to the apartment-model rules, then
// you must modify the code below, changing the 6th parameter from
// afxRegInsertable | afxRegApartmentThreading to afxRegInsertable.
HRESULT hr;if (bRegister)
{
if(!AfxOleRegisterControlClass(
AfxGetInstanceHandle(),
m_clsid,
m_lpszProgID,
IDS_ONOTESCTL,
IDB_ONOTESCTL,
afxRegInsertable | afxRegApartmentThreading,
_dwONotesCtlOleMisc,
_tlid,
_wVerMajor,
_wVerMinor)) return FALSE;hr = CreateComponentCategory(CATID_SafeForScripting,L"Controls that are safely scriptable") ;
hr = CreateComponentCategory (CATID_SafeForInitializing,L"Controls safely initializable from persistent data");
hr = RegisterCLSIDInCategory (m_clsid, CATID_SafeForScripting) ;
hr = RegisterCLSIDInCategory (m_clsid,CATID_SafeForInitializing);return TRUE;
}
else
{
if(!AfxOleUnregisterClass(m_clsid, m_lpszProgID))
return FALSE;
hr = UnRegisterCLSIDInCategory (m_clsid,CATID_SafeForScripting);
hr = UnRegisterCLSIDInCategory (m_clsid,CATID_SafeForInitializing) ;return TRUE;
}
}
本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。