The ATL Object Map

[Previous] [Next]

ATL servers keep track of the objects they contain in the object map. The map is declared in the main .cpp file for your project and begins with the BEGIN_OBJECT_MAP(x) macro. A typical object map with one object in it might look like this:

 BEGIN_OBJECT_MAP(ObjectMap) OBJECT_ENTRY(CLSID_MyObj, CMyObj) END_OBJECT_MAP() 

The relevant macros are defined in atlcom.h:

 #define BEGIN_OBJECT_MAP(x) static _ATL_OBJMAP_ENTRY x[] = { #define END_OBJECT_MAP()   {NULL, NULL, NULL, NULL, NULL,\     NULL, NULL, NULL}}; #define OBJECT_ENTRY(clsid, class) {&clsid, class::UpdateRegistry,\     class::_ClassFactoryCreatorClass::CreateInstance,\     class::_CreatorClass::CreateInstance, NULL, 0,\     class::GetObjectDescription, class::GetCategoryMap,\     class::ObjectMain }, #define OBJECT_ENTRY_NON_CREATEABLE(class) {&CLSID_NULL,\     class::UpdateRegistry, NULL, NULL, NULL, 0, NULL,\     class::GetCategoryMap, class::ObjectMain }, 

An object map is an array of _ATL_OBJMAP_ENTRY structures, the first element of which is identified by the name passed to BEGIN_OBJECT_MAP. This name (ObjectMap by default) is passed in to the _Module.Init call, where ATL caches it in the CComModule::m_pObjMap member. The map is used whenever ATL needs to iterate over the objects contained in the server, particularly for registration and class object initialization.

There is one OBJECT_ENTRY per class of object in the server, defined by the individual OBJECT_ENTRY macros between the beginning and ending macros. OBJECT_ENTRY fills an _ATL_OBJMAP_ENTRY structure based on the CLSID of your object and its C++ implementation class name. The structure is defined as follows:

 struct _ATL_OBJMAP_ENTRY {     const CLSID* pclsid;     HRESULT (WINAPI *pfnUpdateRegistry)(BOOL bRegister);     _ATL_CREATORFUNC* pfnGetClassObject;     _ATL_CREATORFUNC* pfnCreateInstance;     IUnknown* pCF;     DWORD dwRegister;     _ATL_DESCRIPTIONFUNC* pfnGetObjectDescription;     _ATL_CATMAPFUNC* pfnGetCategoryMap;     HRESULT WINAPI RevokeClassObject()     {         return CoRevokeClassObject(dwRegister);     }     HRESULT WINAPI RegisterClassObject(DWORD dwClsContext,         DWORD dwFlags)     {         IUnknown* p = NULL;         if(pfnGetClassObject == NULL)             return S_OK;         HRESULT hRes = pfnGetClassObject(pfnCreateInstance,             IID_IUnknown, (LPVOID*) &p);         if(SUCCEEDED(hRes))             hRes = CoRegisterClassObject(*pclsid, p,                 dwClsContext, dwFlags, &dwRegister);         if(p != NULL)             p->Release();         return hRes;     } // Added in ATL 3.0     void (WINAPI *pfnObjectMain)(bool bStarting); }; 

Many of these elements relate directly to the registration and class objects discussed earlier in the chapter. The structure is more familiar if we look at it in terms of the OBJECT_ENTRY macro definition in Table 7-4.

Table 7-4. _ATL_OBJMAP_ENTRY Structure Data Members.

_ATL_OBJMAP_ENTRY Member OBJECT_ENTRY Macro Part
const CLSID* pclsid &clsid
HRESULT (WINAPI *pfnUpdateRegistry) (BOOL bRegister) Class::UpdateRegistry (BOOL bRegister)
_ATL_CREATORFUNC* pfnGetClassObject Class::_ClassFactoryCreatorClass::CreateInstance
_ATL_CREATORFUNC* pfnCreateInstance Class::_CreatorClass::CreateInstance
IUnknown* pCF NULL
DWORD dwRegister 0
_ATL_DESCRIPTIONFUNC* pfnGetObjectDescription Class::GetObjectDescription
_ATL_CATMAPFUNC* pfnGetCategoryMap class::GetCategoryMap
void (WINAPI *pfnObjectMain)(bool bStarting) class::ObjectMain(bool bStarting)

UpdateRegistry is the same registration function we looked at in self-registration. The _CreatorClass typedefs are used to create a class object and initialize it with a function that creates this kind of object, as outlined in the previous section on class objects. IUnknown* pCF is a cached pointer to the class object. DLL servers create the class object for an object the first time it is requested in DllGetClassObject, initializing pCF in the process. EXE servers leave this member NULL and instead use CoRegisterClassObject to maintain an instance. The other class:: entries use the same pattern we've seen before, in which ATL calls static initialization functions on your object. Only EXE servers use the RegisterClassObject and RevokeClassObject functions (along with the dwRegister member), as we'll see in the next section.

The object map is a vital piece of the ATL module support, enabling efficient enumeration of the items needed to bring objects into existence.



Inside Atl
Inside ATL (Programming Languages/C)
ISBN: 1572318589
EAN: 2147483647
Year: 1998
Pages: 127

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net