ATL是怎么创建类厂的

现在来看ATL是怎么创建类厂的。

对inproc   server,类厂现取现用。就是说只有当DllGetClassObject时,才创建类厂并缓存。如果存在,则使用现有类厂。

=======================    inproc    =======================  
//    Obtain   a   Class   Factory 
HRESULT   GetClassObject(REFCLSID   rclsid,   REFIID   riid,   LPVOID *    ppv)    throw () 


#ifndef   _ATL_OLEDB_CONFORMANCE_TESTS 
    ATLASSERT(ppv   
!=    NULL); 
#endif  

    
return    AtlComModuleGetClassObject( & _AtlComModule,   rclsid,   riid,   ppv); 


ATLINLINE   ATLAPI   AtlComModuleGetClassObject(_ATL_COM_MODULE
*    pComModule,   REFCLSID   rclsid,   REFIID   riid,   LPVOID *    
ppv) 

    ATLASSERT(pComModule   
!=    NULL); 
    
if    (pComModule    ==    NULL) 
        
return    E_INVALIDARG; 
    
if    (pComModule ->  cbSize    ==     0 )      //    Module   hasn 't   been   initialized 
         return    E_UNEXPECTED; 

    
if    (ppv    ==    NULL) 
    
return    E_POINTER; 
    
* ppv    =    NULL; 

    HRESULT   hr   
=    S_OK; 

    
for    (_ATL_OBJMAP_ENTRY **    ppEntry    =    pComModule ->  m_ppAutoObjMapFirst;   ppEntry    <    pComModule -  
    
>  m_ppAutoObjMapLast;   ppEntry ++
    { 
        
if    ( * ppEntry    !=    NULL) 
        { 
            _ATL_OBJMAP_ENTRY
*    pEntry    =     * ppEntry; 
            
if    ((pEntry ->  pfnGetClassObject    !=    NULL)    &&    InlineIsEqualGUID(rclsid,    * pEntry ->  pclsid)) 
            { 
                
if    (pEntry ->  pCF    ==    NULL) 
                { 
                    CComCritSecLock 
< CComCriticalSection >     lock (pComModule ->  m_csObjMap,   

                    
false ); 
                    hr   
=     lock .Lock(); 
                    
if    (FAILED(hr)) 
                    { 
                        ATLTRACE(atlTraceCOM,   
0 ,   _T(  " ERROR   :   Unable   to   lock   critical   

                        section   
in    AtlComModuleGetClassObject   " )); 
                        ATLASSERT( 0 ); 
                        
break
                    } 
                    
if    (pEntry ->  pCF    ==    NULL) 
                    hr   
=    pEntry ->  pfnGetClassObject(pEntry ->  pfnCreateInstance,   

                    __uuidof(IUnknown),   (LPVOID
* ) & pEntry ->  pCF); 
                } 
                
if    (pEntry ->  pCF    !=    NULL) 
                hr   
=    pEntry ->  pCF ->  QueryInterface(riid,   ppv); 
                
break
            } 
        } 
    } 

    
if    ( * ppv    ==    NULL    &&    hr    ==    S_OK) 
    hr   
=    CLASS_E_CLASSNOTAVAILABLE; 
    
return    hr; 

而对于local   server   or   service,一次性创建(pfnGetClassObject)并注册(CoRegisterClassObject)所有类厂。

=======================    local   server   or   service    =======================  
//    Register/Revoke   All   Class   Factories   with   the   OS   (EXE   only) 
HRESULT   RegisterClassObjects(DWORD   dwClsContext,   DWORD   dwFlags)    throw () 

    
return    AtlComModuleRegisterClassObjects( & _AtlComModule,   dwClsContext,   dwFlags); 


HRESULT   RevokeClassObjects()   
throw () 

    
return    AtlComModuleRevokeClassObjects( & _AtlComModule); 


ATLINLINE   ATLAPI   AtlComModuleRegisterClassObjects(_ATL_COM_MODULE
*    pComModule,   DWORD   dwClsContext,   DWORD   
dwFlags) 

    ATLASSERT(pComModule   
!=    NULL); 
    
if    (pComModule    ==    NULL) 
        
return    E_INVALIDARG; 

    HRESULT   hr   
=    S_FALSE; 
    
for    (_ATL_OBJMAP_ENTRY **    ppEntry    =    pComModule ->  m_ppAutoObjMapFirst;   ppEntry    <    pComModule -  
    
>  m_ppAutoObjMapLast    &&    SUCCEEDED(hr);   ppEntry ++
    { 
        
if    ( * ppEntry    !=    NULL) 
        hr   
=    ( * ppEntry) ->  RegisterClassObject(dwClsContext,   dwFlags); 
    } 
    
return    hr; 


ATLINLINE   ATLAPI   AtlComModuleRevokeClassObjects(_ATL_COM_MODULE
*    pComModule) 

    ATLASSERT(pComModule   
!=    NULL); 
    
if    (pComModule    ==    NULL) 
        
return    E_INVALIDARG; 

    HRESULT   hr   
=    S_OK; 
    
for    (_ATL_OBJMAP_ENTRY **    ppEntry    =    pComModule ->  m_ppAutoObjMapFirst;   ppEntry    <    pComModule -  
    
>  m_ppAutoObjMapLast    &&    hr    ==    S_OK;   ppEntry ++
    { 
        
if    ( * ppEntry    !=    NULL) 
        hr   
=    ( * ppEntry) ->  RevokeClassObject(); 
    } 
    
return    hr; 


AtlComModuleGetClassObject和AtlComModuleRegisterClassObjects中_ATL_OBJMAP_ENTRY定义如下: 
(其中包含RegisterClassObject和RevokeClassObject定义) 

typedef   _ATL_OBJMAP_ENTRY30   _ATL_OBJMAP_ENTRY; 

//    Can 't   inherit   from   _ATL_OBJMAP_ENTRY20   
//    because   it   messes   up   the   OBJECT_MAP   macros 
struct    _ATL_OBJMAP_ENTRY30   

    
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() 
    { 
        
if    (dwRegister    ==     0
        
return    S_OK; 
        
return    CoRevokeClassObject(dwRegister); 
    } 
    HRESULT   WINAPI   RegisterClassObject(DWORD   dwClsContext,   DWORD   dwFlags) 
    { 
        IUnknown
*    p    =    NULL; 
        
if    (pfnGetClassObject    ==    NULL) 
        
return    S_OK; 
        HRESULT   hRes   
=    pfnGetClassObject(pfnCreateInstance,   __uuidof(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); 
}; 

注意:对于inproc   server是没有注册类厂一说的。只有local   server   or   service才需要注册类厂。

注意:对local   server   or   service,并没有缓存创建了的类厂。它将其传送给了SCM,只是保存了dwRegister在object   map中。
CoRegisterClassObject(*pclsid,   p,   dwClsContext,   dwFlags,   &dwRegister);
然后释放了类厂指针:
p-> Release();

对于local   server   or   service来说,因为ATL不保存类厂指针,所以要获得类厂指针只能调用CoGetClassObject从SCM获得。

你可能感兴趣的:(server,struct,service,Module,null,winapi)