ATL Internals 2ed复习.chapter 5.Object Map

由于有3种COM Server,ATL提供了CAtlModule的派生类对应

CAtlDllModuleT:in-process dll

CAtlExeModuleT:out-process exe

CAtlServiceModuleT:system service exe

 

CAtlModule使用了Object Map管理server中所有的类

CAtlModule的职责

找到每个class,注册/反注册

为每个createable class创建class object

在SCM中注册/反注册class object

为一个class查找component categories

调用class的静态初始化和静态终结函数

注册Server

Inproc Server Registration

template <class T>                                            
class ATL_NO_VTABLE CAtlDllModuleT : public CAtlModuleT<T> {  
public:                                                       
  ...                                                         
  HRESULT DllRegisterServer(BOOL bRegTypeLib = TRUE) {        
    ...                                                       
    T* pT = static_cast<T*>(this);                            
    HRESULT hr = pT->RegisterAppId(); // execute server script
    ...                                                       
    return hr;                                                
  }                                                           
  ...                                                         
};                                                            


Local Server and Windows Service Registration

template <class T>                                                 
class CAtlExeModuleT : public CAtlModuleT<T> {                     
public :                                                           
                                                                   
  int WinMain(int nShowCmd) throw() {                              
    ...                                                            
    HRESULT hr = S_OK;                                             
                                                                   
    LPTSTR lpCmdLine = GetCommandLine();                           
    if (pT->ParseCommandLine(lpCmdLine, &hr) == true)              
      hr = pT->Run(nShowCmd);                                      
                                                                   
    ...                                                            
  }                                                                
                                                                   
  bool ParseCommandLine(LPCTSTR lpCmdLine, HRESULT* pnRetCode) {   
    *pnRetCode = S_OK;                                             
                                                                   
    TCHAR szTokens[] = _T("-/");                                   
                                                                   
    T* pT = static_cast<T*>(this);                                 
    LPCTSTR lpszToken = FindOneOf(lpCmdLine, szTokens);            
    while (lpszToken != NULL) {                                    
      if (WordCmpI(lpszToken, _T("UnregServer"))==0) {             
        *pnRetCode = pT->UnregisterServer(TRUE); // server script  
        if (SUCCEEDED(*pnRetCode))                                 
          *pnRetCode = pT->UnregisterAppId(); // all class scripts 
        return false;                                              
    }                                                              
                                                                   
    // Register as Local Server                                    
    if (WordCmpI(lpszToken, _T("RegServer"))==0) {                 
      *pnRetCode = pT->RegisterAppId(); // server script           
      if (SUCCEEDED(*pnRetCode))                                   
        *pnRetCode = pT->RegisterServer(TRUE); // all class scripts
      return false;                                                
    }                                                              
                                                                   
    lpszToken = FindOneOf(lpszToken, szTokens);                    
   }                                                               
                                                                   
   return true;                                                    
  }                                                                
};                                                                 


 

The Object Map

每一个createable class都类似:

class CMyClass : public CComCoClass< ... >, ...
{
public:


   ...
};

OBJECT_ENTRY_AUTO(__uuidof(MyClass), CMyClass)	//第一个参数是clsid


在ATL3中,我们使用BEGIN_OBJECT_MAP和END_OBJECT_MAP,到了ATL7之后不再需要了。

_ATL_OBJMAP_ENTRY Structure

Object Map就是一个_ATL_OBJMAP_ENTRY的数组:

 

struct _ATL_OBJMAP_ENTRY30 {                            
    const CLSID* pclsid;                                //CLSID
    HRESULT (WINAPI *pfnUpdateRegistry)(BOOL bRegister);//用于注册
    _ATL_CREATORFUNC* pfnGetClassObject;                //用于创建class object
    _ATL_CREATORFUNC* pfnCreateInstance;                //用于创建instance
    IUnknown* pCF;                                      //class object的IUnknown*
    DWORD dwRegister;                                   //CoRegisterClassObject的cookie返回
    _ATL_DESCRIPTIONFUNC* pfnGetObjectDescription;      //用于返回object description
    _ATL_CATMAPFUNC* pfnGetCategoryMap;                 //用于component category
    void (WINAPI *pfnObjectMain)(bool bStarting);       //initilization/termination function
};                                                      
                                                        
                                                        
typedef _ATL_OBJMAP_ENTRY30 _ATL_OBJMAP_ENTRY;          

OBJECT_ENTRY_AUTO Macro

当我们使用这个宏来指定COM-createable class,默认情况下这个类需要派生自CComCoClass,然后用户可以使用CoCreateInstance()来创建它们

OBJECT_ENTRY_NON_CREATEABLE_EX_AUTO macro

使用这个宏用于noncreateable class,如果这个类需要class-level initialization/termination或者在注册表注册

 

Methods Required of an Object Map Class

为了支持Object Map,用户需要提供下列函数:

Static Member Function

Description

UpdateRegistry

Registers and unregisters the class. The DECLARE_REGISTRY_RESOURCE macros provide various implementations of this method for nonattributed projects. Attributed projects have an implementation injected by the attribute provider.

ObjectMain

Initializes and uninitializes the class. CComObjectRootBase provides a default implementation of this method.

GetCategoryMap

Returns a pointer to a component category map. The BEGIN_CATEGORY_MAP macro provides an implementation.CComObjectRootBase provides a default implementation of this method.

CreatorClass::CreateInstance

_The DECLARE_AGGREGATABLE macros set the _CreatorClass typedef to the name of the class that creates instances. CComCoClass provides a default definition of this typedef.

_ClassFactoryCreatorClass:: CreateInstance

The DECLARE_CLASSFACTORY macros set the _ClassFactoryCreatorClass typedef to the name of the class that creates class objects.CComCoClass provides a default definition of this typedef.

GetObjectDescription

Returns the object description text string. CComCoClass provides a default implementation of this method.

其中前三条不管使用OBJECT_ENTRY_NON_CREATEABLE_EX_AUTO还是OBJECT_ENTRY_AUTO都必须提供

使用OBJECT_ENTRY_AUTO必须提供所有

The GetObjectDescription Method

使用DECLARE_OBJECT_DESCRIPTION macro,例如:

class CMyClass : public CComCoClass< ... >, ... {
public:
   DECLARE_OBJECT_DESCRIPTION("MyClass Object Description")

   ...
};


The UpdateRegistry Method

class必须提供一个静态函数:

static HRESULT WINAPI UpdateRegistry(BOOL bRegister) ;


可以使用DECLARE_REGISTRY:

#define DECLARE_NO_REGISTRY()\                                      
    static HRESULT WINAPI UpdateRegistry(BOOL /*bRegister*/) \      
    {return S_OK;}                                                  
                                                                    
                                                                    
#define DECLARE_REGISTRY(class, pid, vpid, nid, flags)\             
    static HRESULT WINAPI UpdateRegistry(BOOL bRegister) {\         
        return _Module.UpdateRegistryClass(GetObjectCLSID(), \      
            pid, vpid, nid,\                                        
            flags, bRegister);\                                     
    }                                                               
                                                                    
                                                                    
#define DECLARE_REGISTRY_RESOURCE(x)\                               
    static HRESULT WINAPI UpdateRegistry(BOOL bRegister) {\         
    ...                                                             
    return ATL::_pAtlModule->UpdateRegistryFromResource(_T(#x), \   
        bRegister); \                                               
    ...                                                             
    }                                                               
                                                                    
                                                                    
#define DECLARE_REGISTRY_RESOURCEID(x)\                             
    static HRESULT WINAPI UpdateRegistry(BOOL bRegister) {\         
    ...                                                             
    return ATL::_pAtlModule->UpdateRegistryFromResource(x, \        
        bRegister); \                                               
    ...                                                             
    }                                                               

注意,DECLARE_REGISTRY只能在ATL3中使用,在ATL7+版本将会出现编译错误
如果使用DECLARE_REGISTRY_RESOURCE或者使用DECLARE_REGISTRY_RESOURCEID,需要指定脚本,详见原书

The GetCategoryMap Method

需要一个静态函数:

static const struct _ATL_CATMAP_ENTRY* GetCategoryMap() { return NULL; }


通常可以使用宏来解决,例如:

// {0D22FF22-28CC-11d2-ABDD-00A0C9C8E50D}
static const GUID CATID_ATLINTERNALS_SAMPLES =
{0xd22ff22, 0x28cc, 0x11d2, {0xab, 0xdd, 0x0, 0xa0, 0xc9, 0xc8,
     0xe5, 0xd}};

BEGIN_CATEGORY_MAP(CDemagogue)
IMPLEMENTED_CATEGORY(CATID_ATLINTERNALS_SAMPLES)
END_CATEGORY_MAP()

这3个宏详见原书

The ObjectMain Method

需要一个静态函数:

static void WINAPI ObjectMain(bool /* bStarting */ ) {};


例如:

class ATL_NO_VTABLE CSoapBox :
    public CComObjectRootEx<CComSingleThreadModel>,
    ...
{
public:
    DECLARE_NO_REGISTRY()
    ...
    static void WINAPI ObjectMain(bool bStarting) ;
};

 

The _ClassFactoryCreatorClass and _CreatorClass Typedefs

OBJECT_ENTRY_AUTO中

class::_ClassFactoryCreatorClass::CreateInstance用于创建class object

class::_CreatorClass::CreateInstance用于创建instance

在CComCoClass中,有_ClassFactoryCreatorClass定义:

template <class T, const CLSID* pclsid = &CLSID_NULL>          
class CComCoClass {                                            
public:                                                        
    DECLARE_CLASSFACTORY()                                     
    DECLARE_AGGREGATABLE(T)                                    
    ...                                                        
};                                                             

其中:

#define DECLARE_CLASSFACTORY() DECLARE_CLASSFACTORY_EX(ATL::CComClassFactory)  
                                                                  1            
#if defined(_WINDLL) | defined(_USRDLL)                                      
#define DECLARE_CLASSFACTORY_EX(cf) \                                          
  typedef ATL::CComCreator< \                                                  
       ATL::CComObjectCached< cf > > _ClassFactoryCreatorClass;                
#else                                                                          
// don't let class factory refcount influence lock count                       
#define DECLARE_CLASSFACTORY_EX(cf) \                                          
  typedef ATL::CComCreator< \                                                  
       ATL::CComObjectNoLock< cf > > _ClassFactoryCreatorClass;                
#endif                                                                         


上面的代码,当使用inproc dll时,CComCreator创建一个CComObjectCached<>作为cf,当使用exe时,创建一个CComObjectNoLock<>作为cf
 

 而其中的CComClassFactory定义如下:

class CComClassFactory :                                                
    public IClassFactory,                                               
    public CComObjectRootEx<CComGlobalsThreadModel> {                   
public:                                                                 
  ...                                                                   
  void SetVoid(void* pv) { m_pfnCreateInstance = (_ATL_CREATORFUNC*)pv;}
  _ATL_CREATORFUNC* m_pfnCreateInstance;                                
};                                                                      


上面SetVoid重载了CComObjectRootBase中的定义

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值