使用ATL建立支援IClassFactory2的COM元件 (轉)

amyz發表於2007-08-15
使用ATL建立支援IClassFactory2的COM元件 (轉)[@more@]:namespace prefix = o ns = "urn:schemas--com::office" />

使用ATL建立支援IClasactory2的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(D 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的定義如下:

 

STD CoCreateInstance(

REFCLSID rclsid,

LPUNKNOWN pUnkOuter,

DWORD dwClntext,

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物件。

透過CoGetClass函式,可以獲取類物件。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);

 


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752019/viewspace-958422/,如需轉載,請註明出處,否則將追究法律責任。

相關文章