使用ATL建立支持IClassFactory2的COM组件

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

使用ATL建立支持IClassFactory2的COM组件

 

关键字:COMIClassFactory2、对象创建权限、LicenseLicense Key

 

本文详细描述了如何使用ATL自身的功能创建具有创建权限功能的COM对象。最后还讲述了如何创建具有固定和临时权限的COM对象,以及如何获取注册码。

1      概述

IClassFactory2接口的作用是为给COM对象增加限制控制的功能。通过这个接口,只能在有合法使用权的电脑上才可以创建COM对象的实例。

COM对象的权限有两种,一种是固定权限,在创建COM对象之前就存在电脑中,创建COM对象时不需要提供附加的信息。另一种是临时的权限,在创建对象的时候必须提供表明具有权限的注册码,临时权限不能保留在电脑中,所以,每次创建实例的时候都需要提供注册码。每个COM对象可以选择使用固定权限方式、临时权限方式或两者都使用。

COM对象可以提供取得注册码的功能。通过这个功能,可以在具有固定权限的电脑上获取的注册码。

COM对象被创建的时候,应该检查注册码或者固定权限的信息,如果COM对象判定用户没有使用权限,可以返回CLASS_E_NOTLICENSED

2      ATL对IClassFactory2的支持

ATL完全支持IClassFactory2。通过宏DECLARE_CLASSFACTORY2声明COM对象支持IClassFactory2接口。DECLARE_CLASSFACTORY2宏需要一个License类实现具体的许可权限验证算法和注册码验证算法。License类可以使用任何名字,其中必须定义如下的几个成员函数。License类的形式如下:

 

class CLicenseCls

{

protected:

  static BOOL VerifyLicenseKey(BSTR bstr);

  static BOOL GetLicenseKey(DWORD dwReserved, BSTR* pBstr);

  static BOOL IsLicenseValid();

};

 

VerifyLicenseKey函数用于验证注册码的合法性。GetLicenseKey用于获取注册码。IsLicenseValid函数用于验证是否存在固定的使用权限。

用户可以根据需要,提供这三个函数的实现。如下表:

所需功能

VerifyLicenseKey

GetLicenseKey

IsLicenseValid

不检查权限

FALSE

FALSE

TRUE

固定权限

FALSE

FALSE

检查固定权限

临时权限

检测注册码

FALSE

FALSE

固定权限和

临时权限

检测注册码

FALSE

检查固定权限

固定权限和

临时权限和

获取注册码

检测注册码

返回注册码

检查固定权限

3      实现方式

3.1     License类

实现License类的成员函数:

 

class CMyLicense

{

protected:

static BOOL VerifyLicenseKey(BSTR bstrLicenseKey)

{

  if (wcscmp(bstrLicenseKey, OLESTR("Template License Key")) == 0)

  {

    return TRUE;

  }

  return FALSE;

}

 

static BOOL GetLicenseKey(DWORD dwReserved, BSTR* pBstrLicenseKey)

{

  if (pBstrLicenseKey)

  {

    * pBstrLicenseKey = SysAllocString(OLESTR("Template License Key "));

  }

  return TRUE;

}

 

static BOOL IsLicenseValid() {  return TRUE; }

};

 

以上例子中,IsLicenseValid函数永远返回真。在实际使用中,要验证电脑中是否存在固定权限。如果存在固定权限则返回真,否则返回假。这个例子中使用的是固定注册码,也可以根据需要使用伪随机注册码。

3.2     实现IClassFactory2接口

ATLCOM对象类中通过DECLARE_CLASSFACTORY2宏声明在类对象中使用IClassFactory2接口。DECLARE_CLASSFACTORY2宏的定义如下:

 

DECLARE_CLASSFACTORY2(lic)

 

其中licLicense类的名称,本例中为CMyLicense

4      创建需要License的COM对象

4.1     具有固定权限的COM对象

创建具有固定权限的COM对象的方法和创建普通COM对象是相同的。不需要提供任何附加的信息。

使用CoCreateInstance可以方便的创见固定权限的COM对象。CoCreateInstance的定义如下:

 

STDAPI CoCreateInstance(

REFCLSID rclsid,

LPUNKNOWN pUnkOuter,

DWORD dwClsContext,

REFIID riid,

LPVOID * ppv

);

 

rclsid是要创建对象的CLSID

pUnkOuter用于聚合的情况,不使用聚合的时候,使用NULL

dwClsContext指定COM对象的运行环境,一般情况使用CLSCTX_ALL表示可以在任何环境运行。

riid是需要返回的接口的IID

ppv是返回的接口指针的地址。

具体代码如下:

 

Iyyy * pObj;

HRESULT hr;

hr = CoCreateInstance(CLSID_xxx, NULL, CLSCTX_ALL, IID_yyy, &pObj);

if (FAILED(hr))

{

    ...

}

 

4.2     使用临时权限

使用临时权限创建COM对象,需要一个注册码。注册码可以从COM对象本身获取,也可以通过其它方式取得(如购买等)。使用临时权限创建COM对象需要两个步骤:取得COM类对象和创建COM对象。

4.2.1        取得COM类对象

通过CoGetClassObject函数,可以获取类对象。CoGetClassObject的定义如下:

 

STDAPI CoGetClassObject(

REFCLSID rclsid,

DWORD dwClsContext,

COSERVERINFO * pServerInfo,

REFIID riid,

LPVOID * ppv

);

 

rclsid是要创建COM对象的CLSID

dwClsContextCOM对象的运行方式,一般情况使用CLSCTX_ALL表示可以在任何环境运行。

pServerInfo用于在另一台电脑上创建COM对象,在本地创建时用NULL

riid是所需要的接口的IID,这里使用IID_IClassFactory2

ppv是返回接口指针的地址。

可以看出,前两个参数和在CoCreateInstance中的定义是相同的。

具体代码:

 

    IClassFactory2 * pCF2;

    HRESULT hr;

  hr = CoGetClassObject(CLSID_xxx, CLSCTX_ALL, NULL,

IID_IClassFactory2, (void **)&pCF2);

    if (FAILED(hr))

{

    ...

}

    ...

       

4.2.2        创建对象

通过IClassFactory2CreateInstanceLic方法,可以使用临时权限创建对象。在取得了COM类对象之后,调用CreateInstanceLic方法,并且把注册码作为参数,就可以得到新建的COM对象的接口指针。

CreateInstanceLic的定义如下:

 

HRESULT CreateInstanceLic(

IUnknown* pUnkOuter,

IUnknown* pUnkReserved,

REFIID riid,

BSTR bstrKey,

void** ppvObject

);

 

pUnkOuter是聚合的外部对象指针,在不使用聚合的时候,用NULL

pUnkReserved是保留的参数,用NULL

riid是所需要返回的接口IID

bstrKey是注册码。

ppvObject是保存返回的接口指针的地址。

具体代码:

 

Ixxx * pObj;

hr = pCF2->CreateInstanceLic(NULL, NULL, IID_Ixxx,

bstrLicenseKey, (void**) &pObj);

if (FAILED(hr))

{

    ...

}

 

创建之后就可以像使用普通COM对象一样使用新建的COM对象。

4.3     获取注册码

首先要取得类对象的指针,详见第4.2.1节。

在取得了IClassFactory2的指针之后,通过RequestLicKey方法可以取得注册码。

RequestLicKey的定义如下:

 

HRESULT RequestLicKey(

  DWORD dwReserved,

  BSTR* pbstrKey

);

 

dwReserved是保留参数,用0

pbstrKey是保存返回的注册码的地址。调用方负责释放返回值的地址。

具体代码:

 

BSTR bstrLicKey;

hr = pCF2->RequestLicKey(0, &bstrLicKey);

if (FAILED(hr))

{

    ...

}

...

SysFreeString(bstrLicKey);

 

COM组件编程—理论知识 1、 COM组件是一个C++类,他从一系列接口派生而来,并实现了所有的接口。这些接口都是纯虚类。 2COM组件有三个最基本的接口类,分别是IUnknown、IClassFactory、IDispatch。     COM规范规定任何组件、任何接口都必须从IUnknown继承。     所以我们使用COM的一个简单流程如下: CoInitialize(NULL); IUnknown 阅读详情

相关推荐

COM组件开发:从接口设计到性能优化实战

组件对象模型(COM)作为Windows平台的核心技术,通过二进制接口标准实现了跨语言、跨进程的组件交互。其核心机制包括接口契约、引用计数和位置透明性,支撑了从OLE到DirectX等重要技术框架。在工程实践中,合理的接口版本控制策略(如继承扩展)和线程模型选择(Apartment/Free)直接影响组件的稳定性和性能表现。通过注册表部署或免注册COM技术,可以灵活适应不同部署场景。对于高频调用的场景,自定义列集和错误处理规范能显著提升系统可靠性。这些技术至今仍在Office自动化、Shell扩展等场景发挥

weixin_33940469的博客 356

com进程内进程外组件

COM进程内组件与进程外组件 1.   COM进程内组件 进程内组件以动态链接库的形式存在(后缀名为dll),客户端需要使用进程内组件提供的服务时只需要将dll加载进客户端进程。进程内组件必须提供自注册功能,这样客户端进程才能在需要的从注册表中查找到相应的信息,并加载该组件。   进程内组件需要导出四个函数 DllRegisterServer: 参数:无 返回值:HRESULT 指示

CCT1990的专栏 3929

ATL/COM备忘

ATL/COMhttp://www.exogenesis.org/notes/atlcom.html#registeringLocal Adding Methods by Hand BSTR Categories CLSIDs (Class IDs) Connection Points Creatablity, m

tianyu的专栏 - Linux site:blog.csdn.net/wishfly 3954

使用Delphi编写COM组件

第一章 在Delphi中使用接口 1.1 定义接口: 目的:什么是接口,以及和抽象类的关联以及不同点。 抽象类(备注理解接口最简单的方法) 永远不能创建一个抽象类的实例; 本身不能实现功能,依靠派生类实现; 接口 被申明为interface类型。接口名从字母I开始。类类型名从T开始。 所有的接口从IUnknown继承; 不能创建接口实例; 不能在接口中指定范围指示。所有的方法都是公有型(pub

qiume的专栏 5934

使用ATL建立支持IClassFactory2COM组件 (转)

使用ATL建立支持IClassFactory2COM组件 (转)[@more@]XML:namespace prefix = o ns = "urn:schemas-microsoft-com:Office:office" /...

ciya3282的博客 244

windows ATL项目简介

COMATL技术结合了COMATL,使开发者能在Windows平台上快速构建COM组件,实现如ShellExtension等win32功能。本文将介绍如何创建VisualStudio的ATL项目

风之岷的开发空间 1766

深入解析ATL服务类:COM组件开发的核心架构与实战应用

组件对象模型(COM)是Windows平台上实现软件组件化与跨语言互操作的核心技术框架。其核心原理在于通过二进制接口标准定义组件契约,使得不同语言编写的模块能够相互通信。这一技术为Windows生态带来了巨大的工程价值,它奠定了ActiveX控件、OLE自动化及众多系统服务的基础,实现了代码复用与系统集成的标准化。在实际应用场景中,COM技术广泛用于构建插件系统、进程间通信模块以及遗留系统的核心组件。本文聚焦于ATL(活动模板库)服务类,它是高效实现COM组件的关键工具,通过精妙的模板技术封装了IUnkno

weixin_30675247的博客 449

深入理解Windows C++ COM编程:从IUnknown到ATL的实战指南

组件对象模型(COM)是微软为实现二进制级别软件复用而设计的核心技术规范,其核心原理基于接口(Interface)和引用计数机制,通过IUnknown接口的QueryInterface、AddRef和Release方法实现对象生命周期管理和多态。这项技术的核心价值在于实现了语言无关的组件交互和跨进程通信能力,为Windows平台的系统级开发奠定了坚实基础。在应用场景上,COM不仅支撑着DirectX图形渲染、Windows Runtime (WinRT) 等现代框架,更是众多遗留系统和工业控制软件的核心。理

weixin_33743661的博客 364

COM一些小知识

参考来源:http://www.host01.com/article/software/VisualC/2006091718392288.htm 1 COM组件是一个C++类,他从一系列接口派生而来,并实现了所有的接口。这些接口都是纯虚类。 2 COM组件有三个最基本的接口类,分别是IUnknown、IClassFactory、IDispatch。     COM规范规定任何组件、任

tianyu的专栏 - Linux site:blog.csdn.net/wishfly 904

COM教程(0-序章)

COMComponent Object Model,组件对象模型(0)从dll到com问题是,不同语言,不同编译器产生的二进制代码如何交互?还有dll升级问题。一个程序更新版本更改了dll的版本,另外一个程序怎么办?这就是所谓的dll hell(1)接口定义语言(IDL)利用VS中自带的MIDL.exe编译器,其可以解析IDL文件,并产生C/C++头文件。几乎每个com方法都会返回一个HRESU

define_us的专栏 1015

ATL和MFC,用哪种框架来创建ActiveX控件:第二部分

ATL基本的COM支持 ATL的目标是使开发者不必重写IUnknown, IDispatch, IClassFactory接口,并且在把常规的DLL和EXE变成基于COM的DLL和EXE时,也不必重写其分支部分。在这个方面,ATL是一个比MFC精简得多的框架,它设计和生成时就考虑了COM支持。它使用基于模板的方法,通过继承ATL提供的模板,开发者可以加入各种COM功能块。 ATL的原始CO...

yingyingol 128

COM组件开发实战:从接口定义到进程内外服务器实现

组件对象模型(COM)是Windows平台实现软件组件化与二进制重用的核心技术。其核心原理基于接口(Interface)与引用计数机制,通过定义清晰的二进制契约,实现了跨语言、跨进程的组件交互能力。这一技术价值在于彻底解决了DLL地狱问题,为Windows生态提供了稳定的组件集成基础。在应用场景上,COM广泛支撑了从系统API、Office自动化到DirectX图形接口等关键领域。本文以实战为导向,通过手把手构建一个完整的数学计算组件,深入解析了进程内(DLL)与进程外(EXE)两种服务器的实现细节,并涵盖

weixin_34389926的博客 347

组件的设计与实现

Com组件从OLE技术上发展而来: Object Linking and Embedding,对象连接与嵌入,简称OLE技术。OLE 不仅是桌面应用程序集成,而且还定义和实现了一种允许应用程序作为软件“对象”(数据集合和操作数据的函数)彼此进行“连接”的机制,这种连接机制和协议称为组件对象模型(COM)。 COM是一种规范而不是实现,是一种面向对象的编程标准(Component ObjectM

Crazy Tortoise 982

ATL实战开发指南-----2.5

当一个COM组件通过某一种语言设计bing

飞翔在蓝天绿水之间 788

Developing COM Components using VC-ATL(2-4)

接口类型    完整的COM编程系统是基于接口的。接口可以分为以下几类:n          标准接口 由COM系统提供的接口n          自定义接口 由开发者创建的接口    大多数由标准接口实现的方法被系统调用。这样的标准接口有IUnknown、IDispatch、IClassFactory、IOle、IDateObject、IStream、IStorage…   

flyforlove的专栏 1087

COM 类工厂有必要存在吗

1. IClassFactory 的用途在 http://www.80diy.com/home/20041120/19/3572410.html 看到几段关于COM 的类厂的话, """类厂用来抽象组件的create过程,客户不需要知道组件的详细情况,也不需要知道类厂的详细情况,只要知道CoCreateInstance可以创建组件即可。而CoCreateInstance内部调用DllG

notebook2001a的专栏 596
上一篇: 在VC++程序中接收COM事件
下一篇: 在COM中使用数组参数--概述
nelsonc
博客等级 码龄25年 1粉丝 16原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值