分享
 
 
 

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

王朝vc·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

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

关键字:COM、IClassFactory2、对象创建权限、License、License 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接口

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

DECLARE_CLASSFACTORY2(lic)

其中lic是License类的名称,本例中为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。

dwClsContext是COM对象的运行方式,一般情况使用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 创建对象

通过IClassFactory2的CreateInstanceLic方法,可以使用临时权限创建对象。在取得了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);

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有