天天看点

COM组件的类厂(COM技术内幕笔记之四)

 在上一篇中,介绍了怎么样用动态链接库去实现COM,但组件对我们来说仍是不透明的,我们需要知道实现组件DLL的位置,必须自己来加载组件的CreateInstance函数来获得组件的指针.在书中第一篇就曾经提到过:COM组件可以透明地在网络上(或本地)被重新分配位置,而不会影响本地客户程序.所以,由客户端来调用DLL并不是什么好主意.必须有一种更好的办法让组件的实现更透明,更灵活!

    于是,就引入了类厂的概念.什么是类厂,类厂也是一个接口,它的职责是帮我们创造组件的对象.并返回给客户程序一个接口的指针.每个组件都必须有一个与之相关的类厂,这个类厂知道怎么样创建组件.当客户请求一个组件对象的实例时,实际上这个请求交给了类厂,由类厂创建组件实例,然后把实例指针交给客户程序。这么说有点难明白.先看一个伪实例.

 1.实现二个接口IX,IY        (上二节中有详细介绍)

 2.实现一个组件CA,实现了IX,IY接口.    (上二节中有详细介绍)

 3.对于这个组件进行注册,把组件的信息加入到注册表中.

     实现DllRegisterServer和DllUnregisterServer函数.函数具体功能就是把本组件的CLSID,ProgID,DLL的位置放入注册表中.这样程序就可以通过查询注册表来获得组件的位置.

 4.创建本组件类厂的实例

class CFactory:public IClassFactory

{

 virtual HRESULT __stdcall QueryInterface(const IID& iid,void** ppv);

 virtual ULONG   __stdcall AddRef();

 virtual ULONG   __stdcall Release();

 virtual HRESULT __stdcall CreateInstance(IUnknown* pUnknownOuter,

  const IID& iid,

  void** ppv);

}

 在类厂实例中,主要的功能就是CreateInstance了,这个函数就是创建组件的相应实例.看它的实现:

HRESULT __stdcall CFactory::CreateInstance(IUnknown* pUnknownOuter,const IID& iid,void** ppv)

{

   //...

 CA* pA = new CA;

 if(pA == NULL)

  return E_OUTOFMEMORY;

 HRESULT hr = pA->QueryInterface(iid,ppv);

 pA->Release();

 return hr;

}

 5.在这个组件的DLL中导出DllGetClassObject函数.这个函数的功能就是创建类厂的实例对象并查询接口.看其实现:

STDAPI DllGetClassObject(const CLSID& clsid,

       const IID& iid,

       void** ppv)

{

 //....

 CFactory* pFactory = new CFactory();

 if(pFactory == NULL)

  return E_OUTOFMEMORY;

 HRESULT hr = pFactory->QueryInterface(iid,ppv);

 pFactory->Release();

 return hr;

}

组件的实现差不多就这么多,下面在客户端怎么调用组件呢?这就需要用到COM函数库了,由COM函数库去查找注册表,调用组件的类厂,创建组件实例,返回接口.如下所示:

IUnknown* pUnk = NULL;

IX* iX = NULL;

CoInitialize(NULL);

CoCreateInstance(CLSID_Component1,CLSCTX_INPROC_SERVER,IID_IUnknown,(void**)&pUnk);

pUnk->QueryInterface(IID_IX,(void**)&iX);

pUnk->Release();

iX->Fx();

iX->Release();

CoUninitialize();

至于客户是通过CoCreateInstance怎么获得组件的类厂,创建组件实例的.下面摘录的一篇文章很清晰的说明了这一切:

-------------------------------------------------------------------------------------

这部分我们将构造一个创建COM组件的最小框架结构,然后看一看其内部处理流程是怎样的

COM组件的运行机制,即COM是怎么跑起来的。

    IUnknown *pUnk=NULL;

    IObject *pObject=NULL;

    CoInitialize(NULL);

    CoCreateInstance(CLSID_Object, CLSCTX_INPROC_SERVER, NULL, IID_IUnknown, (void**)&pUnk);

    pUnk->QueryInterface(IID_IOjbect, (void**)&pObject);

    pUnk->Release();

    pObject->Func();

    pObject->Release();

    CoUninitialize();

  CoCreateInstance身上,让我们来看看它内部做了一些什么事情。以下是它内部实现的一个伪代码:

    CoCreateInstance(....)

    {

      .......

      IClassFactory *pClassFactory=NULL;

      CoGetClassObject(CLSID_Object, CLSCTX_INPROC_SERVER, NULL, IID_IClassFactory, (void **)&pClassFactory);

      pClassFactory->CreateInstance(NULL, IID_IUnknown, (void**)&pUnk);

      pClassFactory->Release();

      ........

    }

  这段话的意思就是先得到类厂对象,再通过类厂创建组件从而得到IUnknown指针。

  继续深入一步,看看CoGetClassObject的内部伪码:

    CoGetClassObject(.....)

    {

      //通过查注册表CLSID_Object,得知组件DLL的位置、文件名

      //装入DLL库

      //使用函数GetProcAddress(...)得到DLL库中函数DllGetClassObject的函数指针。

      //调用DllGetClassObject

    } 

  DllGetClassObject是干什么的,它是用来获得类厂对象的。只有先得到类厂才能去创建组件.

  下面是DllGetClassObject的伪码:

   DllGetClassObject(...)

   {

      ......

      CFactory* pFactory= new CFactory; //类厂对象

      pFactory->QueryInterface(IID_IClassFactory, (void**)&pClassFactory);

      //查询IClassFactory指针

      pFactory->Release();

      ......

   }

CoGetClassObject的流程已经到此为止,现在返回CoCreateInstance,看看CreateInstance的伪码:

   CFactory::CreateInstance(.....)

   {

      ...........

      CObject *pObject = new CObject; //组件对象

      pObject->QueryInterface(IID_IUnknown, (void**)&pUnk);

      pObject->Release();

      ...........

   } 

  下图是从COM+技术内幕中COPY来的一个例图,从图中可以清楚的看到CoCreateInstance的整个流程。

COM组件的类厂(COM技术内幕笔记之四)

接下来就写下完全的源代码,说明类厂的概念:

Component实现:(FacInterFace.dll)

COM组件的类厂(COM技术内幕笔记之四)

// In FACE.H

COM组件的类厂(COM技术内幕笔记之四)

#ifndef _IFACE_H

COM组件的类厂(COM技术内幕笔记之四)

#define  _IFACE_H

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

// interfaces

COM组件的类厂(COM技术内幕笔记之四)

interface IX:IUnknown

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

    virtual void __stdcall Fx() = 0;

COM组件的类厂(COM技术内幕笔记之四)

};

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

interface IY: IUnknown

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

    virtual void __stdcall Fy() = 0;

COM组件的类厂(COM技术内幕笔记之四)

};

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

interface IZ: IUnknown

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

    virtual void __stdcall Fz() = 0;

COM组件的类厂(COM技术内幕笔记之四)

};

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

// Forward references for GUIDs

COM组件的类厂(COM技术内幕笔记之四)

extern   " C "

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

    extern const IID IID_IX;

COM组件的类厂(COM技术内幕笔记之四)

    extern const IID IID_IY;

COM组件的类厂(COM技术内幕笔记之四)

    extern const IID IID_IZ;

COM组件的类厂(COM技术内幕笔记之四)

    extern const CLSID CLSID_Component1;

COM组件的类厂(COM技术内幕笔记之四)

}

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

extern   " C " 

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

// {A33D4226-0F56-4e34-91F3-BF4F85761101}

COM组件的类厂(COM技术内幕笔记之四)

static const IID IID_IX = 

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{ 0xa33d4226, 0xf56, 0x4e34, 

COM组件的类厂(COM技术内幕笔记之四)

{ 0x91, 0xf3, 0xbf, 0x4f, 0x85, 0x76, 0x11, 0x1 } };

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

// {41A5F090-B33A-4ae8-A1BB-EF2D0B4F8B0E}

COM组件的类厂(COM技术内幕笔记之四)

static const IID IID_IY = 

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{ 0x41a5f090, 0xb33a, 0x4ae8, 

COM组件的类厂(COM技术内幕笔记之四)

{ 0xa1, 0xbb, 0xef, 0x2d, 0xb, 0x4f, 0x8b, 0xe } };

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

// {65411881-4E05-4b71-9CB5-943D5E0787C4}

COM组件的类厂(COM技术内幕笔记之四)

static const IID IID_IZ = 

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{ 0x65411881, 0x4e05, 0x4b71, 

COM组件的类厂(COM技术内幕笔记之四)

{ 0x9c, 0xb5, 0x94, 0x3d, 0x5e, 0x7, 0x87, 0xc4 } };

COM组件的类厂(COM技术内幕笔记之四)

}

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

//组件的CLSID,每个组件都有唯一的CLSID,需要把此CLSID添加到注册表中去.如何添加,见Register.cpp文件.

COM组件的类厂(COM技术内幕笔记之四)

//  {282D8F98-BC89-43d5-9225-0B1BB479CBDE}

COM组件的类厂(COM技术内幕笔记之四)

static   const  CLSID CLSID_Component1  = 

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{ 0x282d8f98, 0xbc89, 0x43d5, 

COM组件的类厂(COM技术内幕笔记之四)

{ 0x92, 0x25, 0xb, 0x1b, 0xb4, 0x79, 0xcb, 0xde } };

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

#endif

组件的注册:

COM组件的类厂(COM技术内幕笔记之四)

// In Register.h

COM组件的类厂(COM技术内幕笔记之四)

HRESULT RegisterServer(HMODULE hModule,                const  CLSID &  clsid,                const   char *  szFriendlyName,            const   char *  szVerIndProgID,            const   char *  szProgID);

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

HRESULT UnRegisterServer( const  CLSID &  clsid,          const   char *  szVerIndProgID,          const   char *  szProgID);

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

// In Register.cpp

COM组件的类厂(COM技术内幕笔记之四)

// 此文件是如何注册组件的代码实现,是把CLSID,ProgID,Version,Dll位置添加到

COM组件的类厂(COM技术内幕笔记之四)

// HKEY_CLASSES_ROOT/CLSID,HKEY_CLASSES_ROOT的子键中去.

COM组件的类厂(COM技术内幕笔记之四)

#include  < objbase.h >

COM组件的类厂(COM技术内幕笔记之四)

#include  < assert.h >

COM组件的类厂(COM技术内幕笔记之四)

#include  " Register.h "

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

// set the given key and its value;

COM组件的类厂(COM技术内幕笔记之四)

BOOL setKeyAndValue( const   char *  pszPath,

COM组件的类厂(COM技术内幕笔记之四)

                     const   char *  szSubkey,

COM组件的类厂(COM技术内幕笔记之四)

                     const   char *  szValue);

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

// Convert a CLSID into a char string

COM组件的类厂(COM技术内幕笔记之四)

void  CLSIDtochar( const  CLSID &  clsid,

COM组件的类厂(COM技术内幕笔记之四)

                  char *  szCLSID,

COM组件的类厂(COM技术内幕笔记之四)

                  int  length);

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

// Delete szKeyChild and all of its descendents

COM组件的类厂(COM技术内幕笔记之四)

LONG recursiveDeleteKey(HKEY hKeyParent, const   char *  szKeyChild);

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

// size of a CLSID as a string

COM组件的类厂(COM技术内幕笔记之四)

const   int  CLSID_STRING_SIZE  =   39 ;

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

// Register the component in the registry

COM组件的类厂(COM技术内幕笔记之四)

HRESULT RegisterServer(HMODULE hModule,

COM组件的类厂(COM技术内幕笔记之四)

                        const  CLSID &  clsid,

COM组件的类厂(COM技术内幕笔记之四)

                        const   char *  szFriendlyName,

COM组件的类厂(COM技术内幕笔记之四)

                        const   char *  szVerIndProgID,

COM组件的类厂(COM技术内幕笔记之四)

                        const   char *  szProgID)

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

    //Get the Server location

COM组件的类厂(COM技术内幕笔记之四)

    char szModule[512];

COM组件的类厂(COM技术内幕笔记之四)

    DWORD dwResult = ::GetModuleFileName(hModule,szModule,sizeof(szModule)/sizeof(char));

COM组件的类厂(COM技术内幕笔记之四)

    assert(dwResult!=0);

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    //Convert the CLSID into a char

COM组件的类厂(COM技术内幕笔记之四)

    char szCLSID[CLSID_STRING_SIZE];

COM组件的类厂(COM技术内幕笔记之四)

    CLSIDtochar(clsid,szCLSID,sizeof(szCLSID));

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    //Build the key CLSID//{}

COM组件的类厂(COM技术内幕笔记之四)

    char szKey[64];

COM组件的类厂(COM技术内幕笔记之四)

    strcpy(szKey,"CLSID//");

COM组件的类厂(COM技术内幕笔记之四)

    strcat(szKey,szCLSID);

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    //Add the CLSID to the registry

COM组件的类厂(COM技术内幕笔记之四)

    setKeyAndValue(szKey,NULL,szFriendlyName);

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    //Add the Server filename subkey under the CLSID key

COM组件的类厂(COM技术内幕笔记之四)

    setKeyAndValue(szKey,"InprocServer32",szModule);

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    setKeyAndValue(szKey,"ProgID",szProgID);

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    setKeyAndValue(szKey,"VersionIndependentProgID",szVerIndProgID);

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    //Add the version-independent ProgID subkey under HKEY_CLASSES_ROOT

COM组件的类厂(COM技术内幕笔记之四)

    setKeyAndValue(szVerIndProgID,NULL,szFriendlyName);

COM组件的类厂(COM技术内幕笔记之四)

    setKeyAndValue(szVerIndProgID,"CLSID",szCLSID);

COM组件的类厂(COM技术内幕笔记之四)

    setKeyAndValue(szVerIndProgID,"CurVer",szProgID);

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    //Add the versioned ProgID subkey under HKEY_CLASSES_ROOT

COM组件的类厂(COM技术内幕笔记之四)

    setKeyAndValue(szProgID,NULL,szFriendlyName);

COM组件的类厂(COM技术内幕笔记之四)

    setKeyAndValue(szProgID,"CLSID",szCLSID);

COM组件的类厂(COM技术内幕笔记之四)

    return S_OK;

COM组件的类厂(COM技术内幕笔记之四)

}

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

//

COM组件的类厂(COM技术内幕笔记之四)

// Remove the component from the register

COM组件的类厂(COM技术内幕笔记之四)

//

COM组件的类厂(COM技术内幕笔记之四)

HRESULT UnRegisterServer( const  CLSID &  clsid,            //  Class ID

COM组件的类厂(COM技术内幕笔记之四)

                          const   char *  szVerIndProgID,    //  Programmatic

COM组件的类厂(COM技术内幕笔记之四)

                          const   char *  szProgID)            //  IDs

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

    //Convert the CLSID into a char.

COM组件的类厂(COM技术内幕笔记之四)

    char szCLSID[CLSID_STRING_SIZE];

COM组件的类厂(COM技术内幕笔记之四)

    CLSIDtochar(clsid,szCLSID,sizeof(szCLSID));

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    //Build the key CLSID//{

COM组件的类厂(COM技术内幕笔记之四)

}

COM组件的类厂(COM技术内幕笔记之四)

    char szKey[64];

COM组件的类厂(COM技术内幕笔记之四)

    strcpy(szKey,"CLSID//");

COM组件的类厂(COM技术内幕笔记之四)

    strcat(szKey,szCLSID);

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    //Delete the CLSID key - CLSID/{

COM组件的类厂(COM技术内幕笔记之四)

}

COM组件的类厂(COM技术内幕笔记之四)

    LONG lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT,szKey);

COM组件的类厂(COM技术内幕笔记之四)

    assert((lResult == ERROR_SUCCESS) || (lResult == ERROR_FILE_NOT_FOUND));

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    //Delete the version-independent ProgID Key

COM组件的类厂(COM技术内幕笔记之四)

    lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT,szVerIndProgID);

COM组件的类厂(COM技术内幕笔记之四)

    assert((lResult == ERROR_SUCCESS) || (lResult == ERROR_FILE_NOT_FOUND));

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    //Delete the ProgID key.

COM组件的类厂(COM技术内幕笔记之四)

    lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT,szProgID);

COM组件的类厂(COM技术内幕笔记之四)

    assert((lResult == ERROR_SUCCESS) || (lResult == ERROR_FILE_NOT_FOUND));

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    return S_OK;

COM组件的类厂(COM技术内幕笔记之四)

}

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

// Convert a CLSID to a char string

COM组件的类厂(COM技术内幕笔记之四)

void  CLSIDtochar( const  CLSID &  clsid,

COM组件的类厂(COM技术内幕笔记之四)

                  char *  szCLSID,

COM组件的类厂(COM技术内幕笔记之四)

                  int  length)

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

    assert(length>=CLSID_STRING_SIZE);

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    //Get CLSID

COM组件的类厂(COM技术内幕笔记之四)

    LPOLESTR wszCLSID = NULL;

COM组件的类厂(COM技术内幕笔记之四)

    HRESULT hr = StringFromCLSID(clsid,&wszCLSID);

COM组件的类厂(COM技术内幕笔记之四)

    assert(SUCCEEDED(hr));

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    //Convert from wide characters to non_wide

COM组件的类厂(COM技术内幕笔记之四)

    wcstombs(szCLSID,wszCLSID,length);

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    //Free memory

COM组件的类厂(COM技术内幕笔记之四)

    CoTaskMemFree(wszCLSID);

COM组件的类厂(COM技术内幕笔记之四)

}

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

//

COM组件的类厂(COM技术内幕笔记之四)

//  Delete a Key and all of its descendents

COM组件的类厂(COM技术内幕笔记之四)

//

COM组件的类厂(COM技术内幕笔记之四)

LONG recursiveDeleteKey(HKEY hKeyParent, const   char *  lpszKeyChild)

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

    //Open the child.

COM组件的类厂(COM技术内幕笔记之四)

    HKEY hKeyChild;

COM组件的类厂(COM技术内幕笔记之四)

    LONG lRes = RegOpenKeyEx(hKeyParent,lpszKeyChild,0,KEY_ALL_ACCESS,&hKeyChild);

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    if(lRes != ERROR_SUCCESS)

COM组件的类厂(COM技术内幕笔记之四)

        return lRes;

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    //Enumerate all of the decendents of this child

COM组件的类厂(COM技术内幕笔记之四)

    FILETIME time;

COM组件的类厂(COM技术内幕笔记之四)

    char szBuffer[256];

COM组件的类厂(COM技术内幕笔记之四)

    DWORD dwSize = 256 ;

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    while(RegEnumKeyEx(hKeyChild,0,szBuffer,&dwSize,NULL,

COM组件的类厂(COM技术内幕笔记之四)

        NULL,NULL,&time) == S_OK)

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

        //Delete the decendents of this child.

COM组件的类厂(COM技术内幕笔记之四)

        lRes = recursiveDeleteKey(hKeyChild,szBuffer);

COM组件的类厂(COM技术内幕笔记之四)

        if(lRes != ERROR_SUCCESS)

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

            RegCloseKey(hKeyChild);

COM组件的类厂(COM技术内幕笔记之四)

            return lRes;

COM组件的类厂(COM技术内幕笔记之四)

        }

COM组件的类厂(COM技术内幕笔记之四)

        dwSize = 256;

COM组件的类厂(COM技术内幕笔记之四)

    }

COM组件的类厂(COM技术内幕笔记之四)

    RegCloseKey(hKeyChild);

COM组件的类厂(COM技术内幕笔记之四)

    return RegDeleteKey(hKeyParent,lpszKeyChild);

COM组件的类厂(COM技术内幕笔记之四)

}

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

BOOL setKeyAndValue( const   char *  szKey,

COM组件的类厂(COM技术内幕笔记之四)

                     const   char *  szSubkey,

COM组件的类厂(COM技术内幕笔记之四)

                     const   char *  szValue)

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

    HKEY hKey;

COM组件的类厂(COM技术内幕笔记之四)

    char szKeyBuf[1024];

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    //Copy keyname into buffer.

COM组件的类厂(COM技术内幕笔记之四)

    strcpy(szKeyBuf,szKey);

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    //Add subkey name to buffer.

COM组件的类厂(COM技术内幕笔记之四)

    if(szSubkey!=NULL)

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

        strcat(szKeyBuf,"//");

COM组件的类厂(COM技术内幕笔记之四)

        strcat(szKeyBuf,szSubkey);

COM组件的类厂(COM技术内幕笔记之四)

    }

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    // Create and open key and subkey.

COM组件的类厂(COM技术内幕笔记之四)

    long lResult = RegCreateKeyEx(HKEY_CLASSES_ROOT ,

COM组件的类厂(COM技术内幕笔记之四)

                                  szKeyBuf, 

COM组件的类厂(COM技术内幕笔记之四)

                                  0, NULL, REG_OPTION_NON_VOLATILE,

COM组件的类厂(COM技术内幕笔记之四)

                                  KEY_ALL_ACCESS, NULL, 

COM组件的类厂(COM技术内幕笔记之四)

                                  &hKey, NULL) ;

COM组件的类厂(COM技术内幕笔记之四)

    if (lResult != ERROR_SUCCESS)

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

        return FALSE ;

COM组件的类厂(COM技术内幕笔记之四)

    }

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    // Set the Value.

COM组件的类厂(COM技术内幕笔记之四)

    if (szValue != NULL)

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

        RegSetValueEx(hKey, NULL, 0, REG_SZ, 

COM组件的类厂(COM技术内幕笔记之四)

                      (BYTE *)szValue, 

COM组件的类厂(COM技术内幕笔记之四)

                      strlen(szValue)+1) ;

COM组件的类厂(COM技术内幕笔记之四)

    }

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    RegCloseKey(hKey) ;

COM组件的类厂(COM技术内幕笔记之四)

    return TRUE ;

COM组件的类厂(COM技术内幕笔记之四)

}

组件的实现:

COM组件的类厂(COM技术内幕笔记之四)

// CMPNT.cpp

COM组件的类厂(COM技术内幕笔记之四)

// 此文件是组件CA,组件类厂CFactory的实现,CA的实现与前面讲述的是一样的,关键在于多引入了

COM组件的类厂(COM技术内幕笔记之四)

// 一个CFactory,还有一个是全局函数DllGetClassObject,另外,除了要导出DllGetClassObject之

COM组件的类厂(COM技术内幕笔记之四)

// 外,还要导出三个函数,分别是DllCanUnloadNow / DllRegisterServer / DllUnregisterServer.

COM组件的类厂(COM技术内幕笔记之四)

// 还有一项工作就是在DllMain中保存模块的信息.

COM组件的类厂(COM技术内幕笔记之四)

#include  < iostream.h >

COM组件的类厂(COM技术内幕笔记之四)

#include  < objbase.h >

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

#include  " ../MYIF2/IFACE.h "

COM组件的类厂(COM技术内幕笔记之四)

#include  " Register.h "

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

// #ifndef EXPORTAPI 

COM组件的类厂(COM技术内幕笔记之四)

// #define EXPORTAPI extern "C" __declspec(dllexport)

COM组件的类厂(COM技术内幕笔记之四)

// #endif

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

void  trace( const   char *  msg)

COM组件的类厂(COM技术内幕笔记之四)

{cout<<msg<<endl;}

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

// Gobal variables

COM组件的类厂(COM技术内幕笔记之四)

static  HMODULE g_hModule  =  NULL ; 

COM组件的类厂(COM技术内幕笔记之四)

static   long  g_cComponents     =      0 ;             // Count of active components

COM组件的类厂(COM技术内幕笔记之四)

static   long  g_cServerLocks     =      0 ;             // Count of locks

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

// Friendly name of component

COM组件的类厂(COM技术内幕笔记之四)

const   char  g_szFriendlyName[]  =   " Inside COM.Chapter 7 Example " ;

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

// Version-independent ProgID

COM组件的类厂(COM技术内幕笔记之四)

const   char  g_szVerIndProgID[]  =   " InsideCOM.Chap07 " ;

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

// ProgID

COM组件的类厂(COM技术内幕笔记之四)

const   char  g_szProgID[]  =   " InsideCOM.Chap07.1 " ;

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

// Component

COM组件的类厂(COM技术内幕笔记之四)

class  CA: public  IX, public  IY

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

public:

COM组件的类厂(COM技术内幕笔记之四)

    //IUnknown

COM组件的类厂(COM技术内幕笔记之四)

    virtual HRESULT __stdcall QueryInterface(const IID& iid,void** ppv);

COM组件的类厂(COM技术内幕笔记之四)

    virtual ULONG   __stdcall AddRef();

COM组件的类厂(COM技术内幕笔记之四)

    virtual ULONG   __stdcall Release();

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    //Interface IX

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    virtual void   __stdcall Fx()

COM组件的类厂(COM技术内幕笔记之四)

{cout<<"Fx function"<<endl;}

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    //Interface IY

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    virtual void   __stdcall Fy()

COM组件的类厂(COM技术内幕笔记之四)

{cout<<"Fy function"<<endl;}

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    //Constructor

COM组件的类厂(COM技术内幕笔记之四)

    CA();

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    //Destructor

COM组件的类厂(COM技术内幕笔记之四)

    ~CA();

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

private:

COM组件的类厂(COM技术内幕笔记之四)

    long m_cRef;

COM组件的类厂(COM技术内幕笔记之四)

} ;

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

CA::CA():m_cRef( 1 )

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

    InterlockedIncrement(&g_cComponents);

COM组件的类厂(COM技术内幕笔记之四)

}

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

CA:: ~ CA()

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

    InterlockedDecrement(&g_cComponents);

COM组件的类厂(COM技术内幕笔记之四)

    trace("Component:/t/tDestory self");

COM组件的类厂(COM技术内幕笔记之四)

}

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

// IUnknown implementation

COM组件的类厂(COM技术内幕笔记之四)

HRESULT __stdcall CA::QueryInterface( const  IID &  iid, void **  ppv)

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

    if(iid == IID_IUnknown)

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

        *ppv = static_cast<IX*>(this);

COM组件的类厂(COM技术内幕笔记之四)

    }

COM组件的类厂(COM技术内幕笔记之四)

    else if(iid == IID_IX)

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

        *ppv = static_cast<IX*>(this);

COM组件的类厂(COM技术内幕笔记之四)

        trace("Component:/tReturn pointer to IX.");

COM组件的类厂(COM技术内幕笔记之四)

    }

COM组件的类厂(COM技术内幕笔记之四)

    else if(iid == IID_IY)

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

        *ppv = static_cast<IY*>(this);

COM组件的类厂(COM技术内幕笔记之四)

        trace("Component:/tReturn pointer to IY.");

COM组件的类厂(COM技术内幕笔记之四)

    }

COM组件的类厂(COM技术内幕笔记之四)

    else

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

        *ppv = NULL;

COM组件的类厂(COM技术内幕笔记之四)

        trace("Component:/tCannot Get pointer to IX/IY");

COM组件的类厂(COM技术内幕笔记之四)

        return E_NOINTERFACE;

COM组件的类厂(COM技术内幕笔记之四)

    }

COM组件的类厂(COM技术内幕笔记之四)

    reinterpret_cast<IUnknown*>(*ppv)->AddRef();

COM组件的类厂(COM技术内幕笔记之四)

    return S_OK;

COM组件的类厂(COM技术内幕笔记之四)

}

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

ULONG __stdcall CA::AddRef()

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

    return InterlockedIncrement(&m_cRef);

COM组件的类厂(COM技术内幕笔记之四)

}

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

ULONG __stdcall CA::Release()

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

    if(InterlockedDecrement(&m_cRef)==0)

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

        delete this;

COM组件的类厂(COM技术内幕笔记之四)

        return 0;

COM组件的类厂(COM技术内幕笔记之四)

    }

COM组件的类厂(COM技术内幕笔记之四)

    return m_cRef;

COM组件的类厂(COM技术内幕笔记之四)

}

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

///

COM组件的类厂(COM技术内幕笔记之四)

// class factory

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

///

COM组件的类厂(COM技术内幕笔记之四)

class  CFactory: public  IClassFactory

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

public:

COM组件的类厂(COM技术内幕笔记之四)

    //IUnknown

COM组件的类厂(COM技术内幕笔记之四)

    virtual HRESULT __stdcall QueryInterface(const IID& iid,void** ppv);

COM组件的类厂(COM技术内幕笔记之四)

    virtual ULONG   __stdcall AddRef();

COM组件的类厂(COM技术内幕笔记之四)

    virtual ULONG   __stdcall Release();

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    //Interface IClassFactory

COM组件的类厂(COM技术内幕笔记之四)

    virtual HRESULT __stdcall CreateInstance(IUnknown* pUnknownOuter,

COM组件的类厂(COM技术内幕笔记之四)

        const IID& iid,

COM组件的类厂(COM技术内幕笔记之四)

        void** ppv);

COM组件的类厂(COM技术内幕笔记之四)

    virtual HRESULT __stdcall LockServer(BOOL bLock);

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    //Constructor

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    CFactory():m_cRef(1)

COM组件的类厂(COM技术内幕笔记之四)

{}

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    //Destructor

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    ~CFactory() 

COM组件的类厂(COM技术内幕笔记之四)

{trace("Class factory:/t/tDestory self.");}

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

private:

COM组件的类厂(COM技术内幕笔记之四)

    long m_cRef;

COM组件的类厂(COM技术内幕笔记之四)

} ;

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

HRESULT __stdcall CFactory::QueryInterface( const  IID &  iid, void **  ppv)

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

    if((iid == IID_IUnknown) || (iid == IID_IClassFactory))

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

        *ppv= static_cast<IClassFactory*>(this);

COM组件的类厂(COM技术内幕笔记之四)

    }

COM组件的类厂(COM技术内幕笔记之四)

    else

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

        *ppv = NULL;

COM组件的类厂(COM技术内幕笔记之四)

        return E_NOINTERFACE;

COM组件的类厂(COM技术内幕笔记之四)

    }

COM组件的类厂(COM技术内幕笔记之四)

    reinterpret_cast<IUnknown*>(*ppv)->AddRef();

COM组件的类厂(COM技术内幕笔记之四)

    return S_OK;

COM组件的类厂(COM技术内幕笔记之四)

}

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

ULONG __stdcall CFactory::AddRef()

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

    return InterlockedIncrement(&m_cRef);

COM组件的类厂(COM技术内幕笔记之四)

}

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

ULONG __stdcall CFactory::Release()

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

    if(InterlockedDecrement(&m_cRef)==0)

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

        delete this;

COM组件的类厂(COM技术内幕笔记之四)

        return 0;

COM组件的类厂(COM技术内幕笔记之四)

    }

COM组件的类厂(COM技术内幕笔记之四)

    else

COM组件的类厂(COM技术内幕笔记之四)

        return m_cRef;

COM组件的类厂(COM技术内幕笔记之四)

}

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

HRESULT __stdcall CFactory::CreateInstance(IUnknown *  pUnknownOuter, const  IID &  iid, void **  ppv)

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

    trace("Class factory:/t/tCreate component.");

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    // Cannot aggregate.

COM组件的类厂(COM技术内幕笔记之四)

    if (pUnknownOuter != NULL)

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

        return CLASS_E_NOAGGREGATION ;

COM组件的类厂(COM技术内幕笔记之四)

    }

COM组件的类厂(COM技术内幕笔记之四)

    //if(pUnknownOuter!=NULL)

COM组件的类厂(COM技术内幕笔记之四)

    //    return CLASS_E_NOA

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    CA* pA = new CA;

COM组件的类厂(COM技术内幕笔记之四)

    if(pA == NULL)

COM组件的类厂(COM技术内幕笔记之四)

        return E_OUTOFMEMORY;

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    //Get the request interface

COM组件的类厂(COM技术内幕笔记之四)

    HRESULT hr = pA->QueryInterface(iid,ppv);

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    pA->Release();

COM组件的类厂(COM技术内幕笔记之四)

    return hr;

COM组件的类厂(COM技术内幕笔记之四)

}

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

// LockServer

COM组件的类厂(COM技术内幕笔记之四)

HRESULT __stdcall CFactory::LockServer(BOOL bLock)

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

    if(bLock)

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

        InterlockedIncrement(&g_cServerLocks);

COM组件的类厂(COM技术内幕笔记之四)

    }

COM组件的类厂(COM技术内幕笔记之四)

    else

COM组件的类厂(COM技术内幕笔记之四)

        InterlockedDecrement(&g_cServerLocks);

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    return S_OK;

COM组件的类厂(COM技术内幕笔记之四)

}

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

// Can Dll unload now?

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

int  AddNum( int  a, int  b)

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

    return a+b;

COM组件的类厂(COM技术内幕笔记之四)

}

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

STDAPI DllCanUnloadNow()

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

    if((g_cComponents ==0 ) && (g_cServerLocks==0))

COM组件的类厂(COM技术内幕笔记之四)

        return S_OK;

COM组件的类厂(COM技术内幕笔记之四)

    else

COM组件的类厂(COM技术内幕笔记之四)

        return S_FALSE;

COM组件的类厂(COM技术内幕笔记之四)

}

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

STDAPI DllGetClassObject( const  CLSID &  clsid,

COM组件的类厂(COM技术内幕笔记之四)

                          const  IID &  iid,

COM组件的类厂(COM技术内幕笔记之四)

                          void **  ppv)

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

    trace("DllGetClassObject:/tCreate Class factory");

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    if(clsid != CLSID_Component1)

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

        return CLASS_E_CLASSNOTAVAILABLE;

COM组件的类厂(COM技术内幕笔记之四)

    }

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    CFactory* pFactory = new CFactory();

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    if(pFactory == NULL)

COM组件的类厂(COM技术内幕笔记之四)

        return E_OUTOFMEMORY;

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    //Get request interfaces

COM组件的类厂(COM技术内幕笔记之四)

    HRESULT hr = pFactory->QueryInterface(iid,ppv);

COM组件的类厂(COM技术内幕笔记之四)

    pFactory->Release();

COM组件的类厂(COM技术内幕笔记之四)

    return hr;

COM组件的类厂(COM技术内幕笔记之四)

}

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

// Server registration

COM组件的类厂(COM技术内幕笔记之四)

STDAPI DllRegisterServer()

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

    return RegisterServer(g_hModule,CLSID_Component1,g_szFriendlyName,

COM组件的类厂(COM技术内幕笔记之四)

        g_szVerIndProgID,g_szProgID);

COM组件的类厂(COM技术内幕笔记之四)

}

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

// Server unregistration

COM组件的类厂(COM技术内幕笔记之四)

STDAPI DllUnregisterServer()

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

    return UnRegisterServer(CLSID_Component1,g_szVerIndProgID,g_szProgID);

COM组件的类厂(COM技术内幕笔记之四)

}

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

BOOL APIENTRY DllMain(HANDLE hModule,

COM组件的类厂(COM技术内幕笔记之四)

                      DWORD dwReason,

COM组件的类厂(COM技术内幕笔记之四)

                       void *  lpReserved)

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

    if (dwReason == DLL_PROCESS_ATTACH)

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

        g_hModule = (HMODULE)hModule ;

COM组件的类厂(COM技术内幕笔记之四)

    }

COM组件的类厂(COM技术内幕笔记之四)

    return TRUE ;

COM组件的类厂(COM技术内幕笔记之四)

}

以上是组件的实现。下面是客户端的代码实现:

COM组件的类厂(COM技术内幕笔记之四)

// In Client.cpp

COM组件的类厂(COM技术内幕笔记之四)

int  main()

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

    HRESULT hr;

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    ::CoInitialize(NULL);

COM组件的类厂(COM技术内幕笔记之四)

    trace("Call CoCreateInstance to Create");

COM组件的类厂(COM技术内幕笔记之四)

    trace(" componet and get interface IX");

COM组件的类厂(COM技术内幕笔记之四)

    IX* pIX = NULL;

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    hr = ::CoCreateInstance(CLSID_Component1,

COM组件的类厂(COM技术内幕笔记之四)

        NULL,

COM组件的类厂(COM技术内幕笔记之四)

        CLSCTX_INPROC_SERVER,

COM组件的类厂(COM技术内幕笔记之四)

        IID_IX,

COM组件的类厂(COM技术内幕笔记之四)

        (void**)&pIX);

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    if(SUCCEEDED(hr))

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

        trace("Succeeded getting IX");

COM组件的类厂(COM技术内幕笔记之四)

        pIX->Fx();

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

        trace("Ask for Interface IY");

COM组件的类厂(COM技术内幕笔记之四)

        IY* pIY = NULL;

COM组件的类厂(COM技术内幕笔记之四)

        hr = pIX->QueryInterface(IID_IY,(void**)&pIY);

COM组件的类厂(COM技术内幕笔记之四)

        if(SUCCEEDED(hr))

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

            trace("Succeeded getting IY");

COM组件的类厂(COM技术内幕笔记之四)

            pIY->Fy();

COM组件的类厂(COM技术内幕笔记之四)

            pIY->Release();

COM组件的类厂(COM技术内幕笔记之四)

            trace("Release IY interface");

COM组件的类厂(COM技术内幕笔记之四)

        }

COM组件的类厂(COM技术内幕笔记之四)

        else

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

{

COM组件的类厂(COM技术内幕笔记之四)

            trace("Could not get interface IY.");

COM组件的类厂(COM技术内幕笔记之四)

        }

COM组件的类厂(COM技术内幕笔记之四)

        pIX->Release();

COM组件的类厂(COM技术内幕笔记之四)

    }

COM组件的类厂(COM技术内幕笔记之四)

    else

COM组件的类厂(COM技术内幕笔记之四)

        cout<<"Client: /t/tCould not create component hr="<<hex<<hr<<endl;

COM组件的类厂(COM技术内幕笔记之四)
COM组件的类厂(COM技术内幕笔记之四)

    CoUninitialize();

COM组件的类厂(COM技术内幕笔记之四)

}

再在最后详述一篇,客户端调用CoCreateInstance,导致调用CoGetClassObject,CoGetClassObject通过查找注册表,得知DLL位置,文件名,然后调用DLL中DllGetClassObject,

DllGetClassObject的功能是返回CFactory的实例.

返回后,回到CoCreateInstance,通过CFactory的指针,调用

pClassFactory->CreaetInstance()创建组件实例.

这样就返回了组件实例的指针.

CoCreateInstace  -->  CoGetClassObject  --> DllGetClassObject --> Get CFactory*

                      <-------------------------------------------------------

                 -->  CFactory->CreateInstance(); --> Get IX* 

IX->Fx();

来源:http://www.cnblogs.com/shipfi/archive/2007/02/13/649196.html