使你的ActiveX控件执行时不弹出安全性提示(转载)
我们编写一个ActiveX控件在IE中运行,一般会弹出一个安全提示,如何避免这种情况?下面是我在参考前人的文章后,总结出“在浏览器中执行时不弹出警告的ActiveX控件”的两种编写方法,予以备忘。注意,这里不会弹出警告是说在执行时不会弹出,也就是说已经安装了这个ActiveX控件。如果要下载安装这个ActiveX控件时不会弹出安全警告,恐怕就得去买数字证书了。不过即使有数字证书,还是得用户同意后才会下载安装。
以下两种方法在WINXP-SP2+VC6下通过。
方法1:修改注册表 可能你在看完下面的过程后会发现,程序没有一个地方对注册表操作过。其实不然,这里所谓的修改注册表的方法就是使用组件类型管理器(Component Categories Manager)创建一个正确的入口到系统注册表。IE通过检测注册表判断一个控件是否可以安全地初始化和脚本操作。IE会通过调用 ICatInformation::IsClassOfCategories 方法确定控件是否支持给出的安全性分组。其中对注册表的操作都已经封装起来,隐藏在底层了,所以看不到。
必须包括两个头文件
#include <comcat.h>
#include <Objsafe.h> const GUID CDECL CLSID_SafeItem =
{0xD321B11E, 0x8E79, 0x4829, 0xAB, 0x80, 0x9E, 0x59, 0x92, 0x06, 0xAB, 0xB7};//用你的控件类GUID替换
// 注册组件种类为安全
HRESULT AddCategorySafty(CATID catid, TCHAR* 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; CATEGORYINFO catinfo;
catinfo.catid = catid;
catinfo.lcid = 0x0409 ; // 英语语言 // 最长只拷贝127个字符。
int len = lstrlen(catDescription);
if (len > )
{
len = ;
}
lstrcpyn((TCHAR*)(catinfo.szDescription), catDescription, len+); hr = pcr->RegisterCategories(, &catinfo);
pcr->Release(); return hr;
} //移除已经注册为安全的组件种类
HRESULT RemoveCategorySafty(CATID catid)
{
ICatRegister* pcr = NULL ;
HRESULT hr = S_OK ; hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr,
NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr);
if (FAILED(hr))
return hr; hr = pcr->UnRegisterCategories(, &catid);
pcr->Release(); return hr;
} // 把你的控件注册到已经注册为安全的组件种类
HRESULT RegisterCLSIDInCategory(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))
{
CATID rgcatid[] ;
rgcatid[] = catid;
hr = pcr->RegisterClassImplCategories(clsid, , 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[] ;
rgcatid[] = catid;
hr = pcr->UnRegisterClassImplCategories(clsid, , rgcatid);
} if (pcr != NULL)
pcr->Release(); return hr;
} //使你的控件不弹出警告地执行
HRESULT MakeActiveXSafty(REFCLSID clsid)
{
HRESULT hr; hr = AddCategorySafty(CATID_SafeForInitializing,
_T("Controls safely initializable!"));
if (FAILED(hr))
return hr;
hr = RegisterCLSIDInCategory(clsid, CATID_SafeForInitializing);
if (FAILED(hr))
return hr; hr = AddCategorySafty(CATID_SafeForScripting, _T("Controls safely scriptable!"));
if (FAILED(hr))
return hr;
hr = RegisterCLSIDInCategory(clsid, CATID_SafeForScripting); return hr;
} //去除控件的安全执行性
HRESULT UnMakeActiveXSafty(REFCLSID clsid)
{
HRESULT hr;
hr = UnRegisterCLSIDInCategory(clsid, CATID_SafeForInitializing);
if (FAILED(hr))
return hr;
hr = UnRegisterCLSIDInCategory(clsid, CATID_SafeForScripting);
if (FAILED(hr))
return hr; //下面的代码是把安全组件种类去掉。去掉的话,如果有其他的控件注册为这两个种类
//那么其他的控件执行时就会弹出警告。需不需要下面的代码就见仁见智,看实际情况了
hr = RemoveCategorySafty(CATID_SafeForInitializing);
if (FAILED(hr))
return hr;
hr = RemoveCategorySafty(CATID_SafeForScripting); return hr;
}
然后在DllRegisterServer函数的“return NOERROR;”前添加如下代码:
HRESULT hr = MakeActiveXSafty(CLSID_SafeItem);
if (FAILED(hr))
return hr;
在DllUnregisterServer函数的“AFX_MANAGE_STATE(_afxModuleAddrThis);”后添加如下代码:
HRESULT hr = UnMakeActiveXSafty(CLSID_SafeItem);
if (FAILED(hr))
OutputDebugString(_T("去除控件的安全执行性时出错!"));
方法2:实现ObjectSafe接口
我创建了一个MFC ActiveX ControlWizard的工程,工程为TestAX,它的控件类是CTestAXCtrl,下面所有的代码和操作都是在这个类的头文件和实现文件中进行。红色的部分是为了实现ObjectSafe接口而增加的代码。
在头文件中:
#if !defined(AFX_TESTAXCTL_H__C2084528_F93E_42D8_A13D_7E38775A0481__INCLUDED_)
#define AFX_TESTAXCTL_H__C2084528_F93E_42D8_A13D_7E38775A0481__INCLUDED_ #if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000 // #include <ComCat.h>
#include <ObjSafe.h>//增加这个头文件 // TestAXCtl.h : Declaration of the CTestAXCtrl ActiveX Control class. /////////////////////////////////////////////////////////////////////////////
// CTestAXCtrl : See TestAXCtl.cpp for implementation. class CTestAXCtrl : public COleControl
{
DECLARE_DYNCREATE(CTestAXCtrl) // Constructor
public:
CTestAXCtrl(); //增加如下代码:
DECLARE_INTERFACE_MAP() BEGIN_INTERFACE_PART(MyObjSafe, 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(MyObjSafe); 。。。。。。 在实现文件中: // TestAXCtl.cpp : Implementation of the CTestAXCtrl ActiveX Control class. #include "stdafx.h"
#include "testAX.h"
#include "TestAXCtl.h"
#include "TestAXPpg.h" #ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif IMPLEMENT_DYNCREATE(CTestAXCtrl, COleControl) //接口映射
BEGIN_INTERFACE_MAP(CTestAXCtrl, COleControl )
INTERFACE_PART(CTestAXCtrl, IID_IObjectSafety, MyObjSafe)
END_INTERFACE_MAP() 。。。。。。(其他代码省略) //接口的函数实现
ULONG FAR EXPORT CTestAXCtrl::XMyObjSafe::AddRef()
{
METHOD_PROLOGUE(CTestAXCtrl, MyObjSafe)
return pThis->ExternalAddRef();
} ULONG FAR EXPORT CTestAXCtrl::XMyObjSafe::Release()
{
METHOD_PROLOGUE(CTestAXCtrl, MyObjSafe)
return pThis->ExternalRelease();
} HRESULT FAR EXPORT CTestAXCtrl::XMyObjSafe::QueryInterface(REFIID iid, void FAR* FAR* ppvObj)
{
METHOD_PROLOGUE(CTestAXCtrl, MyObjSafe)
return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj);
} //调用方法与数据是否可信任,设置这两个标志位就可以了
const DWORD g_dwSupportedBits = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;
const DWORD g_dwNotSupportedBits = ~g_dwSupportedBits; HRESULT FAR EXPORT CTestAXCtrl::XMyObjSafe::GetInterfaceSafetyOptions(REFIID riid,
DWORD __RPC_FAR *pdwSupportedOptions,
DWORD __RPC_FAR *pdwEnabledOptions)
{
METHOD_PROLOGUE(CTestAXCtrl, MyObjSafe)
*pdwSupportedOptions = *pdwEnabledOptions = g_dwSupportedBits;
return S_OK;
} HRESULT FAR EXPORT CTestAXCtrl::XMyObjSafe::SetInterfaceSafetyOptions(REFIID riid,
DWORD dwOptionSetMask,
DWORD dwEnabledOptions)
{
METHOD_PROLOGUE(CTestAXCtrl, MyObjSafe) //如果有任何一个不支持的设置位,则返回不支持错误。
if (dwOptionSetMask & g_dwNotSupportedBits)
{
return CO_E_NOT_SUPPORTED;
}
//不需要做其他的事情
return S_OK;
}
详细的接口实现步骤请参考MSDN的《TN038: MFC/OLE IUnknown Implementation》。
使你的ActiveX控件执行时不弹出安全性提示(转载)的更多相关文章
- 已安全化的ActiveX控件卸载时出现"DllUnregisterServer函数出错,错误代码:0x80070002"问题解决
已安全化的ActiveX控件卸载时出现"DllUnregisterServer函数出错,错误代码:0x80070002"问题解决 情况一:当该控件未注册或者已经卸载时,你尝试卸 ...
- 配置Info.plist (设置状态栏样式、自定义定位时系统弹出的提示语、配置3DTouch应用快捷菜单)
一.概述 iOS中很多功能需要配置Info.plist才能实现,如设置后台运行.支持打开的文件类型.自定义访问隐私内容时弹出的提示等.了解Info.plist中各字段及其含义,可以访问苹果开发网站相关 ...
- android中RecyclerView控件实现长按弹出PopupMenu菜单功能
之前写过一篇文章:android中实现简单的聊天功能 现在是在之前功能的基础上,添加一个长按聊天记录,删除对应聊天记录的功能 RecyclerView控件,没有对应的长按事件,我们需要自己手工添加,修 ...
- 自己写个activex控件,如何知道他的classid(转载)
在网页里用的时候需要知道他的classid我在代码中看到有 const GUID CDECL BASED_CODE _tlid = { 0x89201950, 0x2CAC, 0x4CF7, { 0x ...
- VC6.0 MFC中WebBrowser控件禁止新窗口弹出的解决办法
http://blog.csdn.net/gnorth/article/details/7258293 分类: WebBrowser MFC 禁止新窗口2012-02-14 15:25 1787人阅读 ...
- VB动态添加WebBrowser控件,并拦截弹出窗口(不用引用任何组件)
新建空白窗体,然后粘帖下面代码: Option ExplicitPublic WithEvents br As VBControlExtender Private Sub br_ObjectEvent ...
- jqgrid 获取远端数据失败时,弹出错误提示
有时,我们给jqgrid绑定的远端数据获取失败,此时,需要把错误信息反馈给用户展示,如何实现? 可通过jqgrid的 loadError 来处理错误数据的返回.详细如下: $("#jqGri ...
- Xcode调试项目时取消弹出框提示授权
问题2: instruments wants permission to analyze other processes.'DTServiceHub'需要控制另外一个进程,以便继续调试,键入密码以允许 ...
- 解决IE打开时,弹出的提示调用active的问题,阻止js运行。
在html和head中间加上: <!-- saved from url=(0014)about:internet -->
随机推荐
- TCP基础知识(二)三次握手与四次挥手
TCP详解(2):三次握手与四次挥手 TCP(Transmission Control Protocol,传输控制协议)是基于连接的协议,也就是说,在正式收发数据前,必须和对方建立可靠的连接,就好像你 ...
- jsp实现html页面静态化
一.实现原因 1.网站访问量过大,导致服务器压力加大以及数据库数据交换频繁.生成静态页面提供访问以缓解压力. 2.静态页面是动态页面的备份,若动态页面出现异常,静态页面可以暂时替代. 二.使用场合 ...
- sql:查询创建表的结构
--显示所有用户表: --1 SELECT SCHEMA_NAME(schema_id) As SchemaName , name As TableName from sys.tables ORDER ...
- IE8 td元素 width无效的bug;
不经意间做项目发现IE的td在某种情况下好奇怪,自己设置的width不起作用: 后经google大法,发现解决方案:已验证过完美解决bug; <table style="width: ...
- 简单理解C#中的抽象工厂模式是什么概念!
抽象工厂模式向客户端提供一个接口,使得客户端在不必指定具体类型的情况下,创建多个产品族中的对象.本文采取的仍然是接着以前的那个快餐店的例子.现在,快餐店经常良好,逐渐发展壮大,为了适合不同地方人的饮食 ...
- create-react-native-app
create-react-native-app官网介绍链接,github文档,可以看看了解一下,总之是一个5分钟快速搭建react native项目并能看到效果的方法. 假设你已经安装了Node,你可 ...
- 无需安装 vsftpd , 直接使用 FTP 来管理 docker 容器中的文件
无图无真相,先放个效果图: 背景 使用 docker 来跑一些服务很方便,但是有的时候想管理容器里面的文件却很麻烦 -- 一般常规做法有3种: 通过数据卷或数据卷容器的方式 启动容器的时候时候 ...
- 爬虫入门之Scrapy 框架基础功能(九)
Scrapy是用纯Python实现一个为了爬取网站数据.提取结构性数据而编写的应用框架,用途非常广泛. 框架的力量,用户只需要定制开发几个模块就可以轻松的实现一个爬虫,用来抓取网页内容以及各种图片,非 ...
- cocos2d在IOS嵌入UM应用推荐
因为cocos2d默认建立的项目,没用使用导航界面,所以如果直接导航到应用推荐页面将无法返回. 所以我做了一些修改: AppController.mm中 用导航界面包装一下默认的viewControl ...
- 【Leetcode】【Medium】Unique Binary Search Trees
Given n, how many structurally unique BST's (binary search trees) that store values 1...n? For examp ...