[Previous] [Next]

When a client needs to use an object, it relies on COM to find the necessary information to load the DLL or start the EXE server that contains the object. In most cases, the client can remain unaware of which housing contains the object and use CoCreateInstanceEx or CoGetClassObject to instantiate an object.

Server implementors have the task of following the activation protocol required by the COM service control manager (SCM) to make the instantiation process transparent to the client. Although the mechanisms differ for DLL and EXE servers, ATL makes handling the different mechanisms as painless as possible by utilizing the object map and CComModule to perform much of the work.

DLL Server Activation

When a client requests an object that resides in a DLL, COM loads the DLL into the client's process and calls the DllMain entry point with DLL_PROCESS_ATTACH, in which _Module.Init is called. The most important service _Module.Init performs for activation is to cache the object map pointer.

Once the DLL is initialized and DllMain has returned, DllGetClassObject will be called to retrieve the class object for the desired object CLSID. A one-line call to _Module.GetClassObject completes the task. The implementation of CComModule::GetClassObject uses the cached object map pointer to iterate over the object map, looking for an entry with the same CLSID as the one requested. If the entry is found, the following code executes:

 if(pEntry->pCF == NULL) {     EnterCriticalSection(&pM->m_csObjMap);     if(pEntry->pCF == NULL)         hRes = pEntry->pfnGetClassObject(             pEntry->pfnCreateInstance, IID_IUnknown,             (LPVOID*)&pEntry->pCF);     LeaveCriticalSection(&pM->m_csObjMap); } if(pEntry->pCF != NULL)     hRes = pEntry->pCF->QueryInterface(riid, ppv); break; 

Remember that the _ATL_OBJMAP_ENTRY structure has an IUnknown* pCF member. The first time a class object for a certain CLSID is requested, ATL creates the class object and caches its IUnknown pointer in pCF. ATL maintains the class object instance internally for the lifetime of the server. This cached instance won't keep the server alive, as we'll see in the section "Server Lifetime Management" below. The cached pointer is then used to query the class object for the requested interface—usually IClassFactory.

EXE Server Activation

Because an EXE server is itself a process, that process must be launched by COM if it isn't already running. Unlike DLL servers, EXE servers have no equivalent of DllGetClassObject that the SCM can call. Instead, the server adds its class objects to a map maintained by the SCM using CoRegisterClassObject. An ATL EXE server can register all its class objects using _Module.RegisterClassObjects. The ATL COM AppWizard adds this call to your _tWinMain function:

 hRes = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER,              REGCLS_MULTIPLEUSE); 

This function delegates to AtlModuleRegisterClassObjects, which loops through the object map calling RegisterClassObject on each entry.

 ATLINLINE ATLAPI AtlModuleRegisterClassObjects(_ATL_MODULE* pM,     DWORD dwClsContext, DWORD dwFlags) {     ATLASSERT(pM != NULL);     if(pM == NULL)         return E_INVALIDARG;     ATLASSERT(pM->m_pObjMap != NULL);     _ATL_OBJMAP_ENTRY* pEntry = pM->m_pObjMap;     HRESULT hRes = S_OK;     while (pEntry->pclsid != NULL && hRes == S_OK)     {         hRes = pEntry->RegisterClassObject(dwClsContext,             dwFlags);         pEntry = _NextObjectMapEntry(pM, pEntry);     }     return hRes; } 

As promised in our earlier object map discussion, the RegisterClassObject member of the _ATL_OBJMAP_ENTRY structure is called on to actually do the CoRegisterClassObject API call. Once the class objects are registered, the SCM happily continues with the activation as requested by the client.

Inside Atl
Inside ATL (Programming Languages/C)
ISBN: 1572318589
EAN: 2147483647
Year: 1998
Pages: 127 © 2008-2017.
If you may any questions please contact us: