Q:
VC6生成MFC ActiveX,使用htm调用,
CLASSID="CLSID:12342234-3234-4234-5234-623472348234"
CODEBASE="testocx.cab#version=1,0,0,1"
在WinXPSp1上,http://www.smth.org/,ok
在WinXPSp2/2k3SP1/Vista上,http://www.smth.org/,红X
在WinXPSp2/2k3SP1/Vista上,file:///C:/ActiveX.htm,ok
A:
ActiveX在远程IE页面上执行,需要实现安全接口。
在ATL写的ActiveX中,用IObjectSafety。
http://support.microsoft.com/kb/168371/en-us
在MFC写的ActiveX中,直接修改注册表。
http://support.microsoft.com/kb/161873/en-us
mfc实现的ocx,要在app实现文件中包括两个文件:
#include <comcat.h> #include <objsafe.h> // 本控件的CLSID,注册表用 const GUID CDECL CLSID_SafeItem ={ 0x12342234, 0x3234, 0x4234, { 0x52,0x34,0x62,0x34,0x72,0x34,0x82,0x34 } }; // 版本控制 const WORD _wVerMajor = 1; // 次版本号 const WORD _wVerMinor = 0; 实现 // CTestApp::InitInstance - DLL initialization BOOL CTestApp::InitInstance() { return COleControlModule::InitInstance(); } // CTestApp::ExitInstance - DLL termination int CTestApp::ExitInstance() { return COleControlModule::ExitInstance(); } // 创建组件种类 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; } // 注册组件种类 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 - Adds entries to the system registry 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(CLSID_SafeItem, CATID_SafeForInitializing); if (FAILED(hr)) return hr; // 标记控件脚本安全 // 创建脚本安全组件种类 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; } // DllUnregisterServer - Removes entries from the system registry 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(CLSID_SafeItem, CATID_SafeForInitializing); if (FAILED(hr)) return hr; // 删除控件脚本安全入口 hr=UnRegisterCLSIDInCategory(CLSID_SafeItem, CATID_SafeForScripting); if (FAILED(hr)) return hr; return NOERROR; }
atl实现的ocx,在声明文件CTestCtl.h中:
class CTestCtl : .... , public IObjectSafetyImpl<CTestCtl, INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA> { ... BEGIN_COM_MAP(CTestCtl) COM_INTERFACE_ENTRY(IObjectSafety) END_COM_MAP() ... }
或者:
BEGIN_CATEGORY_MAP(CTestCtl) IMPLEMENTED_CATEGORY(CATID_SafeForInitializing) IMPLEMENTED_CATEGORY(CATID_SafeForScripting) END_CATEGORY_MAP()