CComObjectRootEx

template< class ThreadModel >
class CComObjectRootEx
: public CComObjectRootBase

Parameters

ThreadModel The class whose methods implement the desired threading model. You can explicitly choose the threading model by setting ThreadModel to CComSingleThreadModel, CComMultiThreadModel, or CComMultiThreadModelNoCS. You can accept the default thread model by setting ThreadModel to CComObjectThreadModel or CComGlobalsThreadModel.

CComObjectRootEx handles object reference count management for both nonaggregated and aggregated objects. It holds the object reference count if your object is not being aggregated, and holds the pointer to the outer unknown if your object is being aggregated. For aggregated objects, CComObjectRootEx methods can be used to handle the failure of the inner object to construct, and to protect the outer object from deletion when inner interfaces are released or the inner object is deleted.

A class that implements a COM server must inherit from CComObjectRootEx or CComObjectRoot.

If your class definition specifies the DECLARE_POLY_AGGREGATABLE macro, ATL creates an instance of CComPolyObject<CYourClass> when IClassFactory::CreateInstance is called. During creation, the value of the outer unknown is checked. If it is NULL, IUnknown is implemented for a nonaggregated object. If the outer unknown is not NULL, IUnknown is implemented for an aggregated object.

If your class does not specify the DECLARE_POLY_AGGREGATABLE macro, ATL creates an instance of CComObject<CYourClass> for aggregated objects or an instance of CComAggObject<CYourClass> for nonaggregated objects.

The advantage of using CComPolyObject is that you avoid having both CComAggObject and CComObject in your module to handle the aggregated and nonaggregated cases. A single CComPolyObject object handles both cases. Therefore, only one copy of the vtable and one copy of the functions exist in your module. If your vtable is large, this can substantially decrease your module size. However, if your vtable is small, using CComPolyObject can result in a slightly larger module size because it is not optimized for an aggregated or nonaggregated object, as are CComAggObject and CComObject.

The DECLARE_POLY_AGGREGATABLE macro is automatically added to your class definition by the ATL Object Wizard when you create a full control or Internet Explorer control.

If your object is aggregated, IUnknown is implemented by CComAggObject or CComPolyObject. These classes delegate QueryInterface, AddRef, and Release calls to CComObjectRootExs OuterQueryInterface, OuterAddRef, and OuterRelease to forward to the outer unknown. Typically, you override CComObjectRootEx’s FinalConstruct method in your class to create any aggregated objects, and override CComObjectRootEx’s FinalRelease to free any aggregated objects.

If your object is not aggregated, IUnknown is implemented by CComObject or CComPolyObject. In this case, calls to QueryInterface, AddRef, and Release are delegated to CComObjectRootEx’s InternalQueryInterface, InternalAddRef, and InternalRelease to perform the actual operations.

#include <atlcom.h>

See Also CComAggObject, CComObject, CComPolyObject


CComObjectRootEx Class Members

Methods
CComObjectRootExConstructor.
InternalAddRefIncrements the reference count for a nonaggregated object.
InternalQueryInterfaceDelegates to the IUnknown of a nonaggregated object.
InternalReleaseDecrements the reference count for a nonaggregated object.
LockIf the thread model is multithreaded, obtains ownership of a critical section object.
UnlockIf the thread model is multithreaded, releases ownership of a critical section object.
CComObjectRootBase Methods
FinalConstructOverride in your class to create any aggregated objects.
FinalReleaseOverride in your class to release any aggregated objects.
OuterAddRefIncrements the reference count for an aggregated object.
OuterQueryInterfaceDelegates to the outer IUnknown of an aggregated object.
OuterReleaseDecrements the reference count for an aggregated object.
Data Members
m_critsecA CComAutoCriticalSection object or CComFakeCriticalSection object, depending on the thread model.
m_dwRefWith m_pOuterUnknown, part of a union. Used when the object is not aggregated to hold the reference count of AddRef and Release.
m_pOuterUnknownWith m_dwRef, part of a union. Used when the object is aggregated to hold a pointer to the outer unknown.

Methods


CComObjectRootEx::CComObjectRootEx

CComObjectRootEx( );

Remarks

The constructor initializes the reference count to 0.

CComObjectRootEx Overview | Class Members


CComObjectRootEx::FinalConstruct

HRESULT FinalConstruct( );

Return Value

One of the standard HRESULT values.

Remarks

 Typically, override this method in the class derived from CComObjectRootEx to create any aggregated objects. For example:

class CMyAggObject : public CComObjectRootEx< ... >
{ 
   ... 
   DECLARE_GET_CONTROLLING_UNKNOWN 
   HRESULT FinalConstruct( ) 
   { 
      return CoCreateInstance(CLSID_SomeServer, GetControllingUnknown(), 
                              CLSCTX_ALL, IID_ISomeServer, &m_pSomeServer); 
   } 
   ...
};

If the construction fails, you can return an error. You can also use the macro DECLARE_PROTECT_FINAL_CONSTRUCT to protect your outer object from being deleted if (during construction) the internal aggregated object increments the reference count then decrements the count to 0.

By default, CComObjectRootEx::FinalConstruct simply returns S_OK.

Here is a typical way to create an aggregate:

CComObjectRootEx Overview | Class Members

See Also CComObjectRootEx::FinalRelease, DECLARE_GET_CONTROLLING_UNKNOWN


CComObjectRootEx::FinalRelease

void FinalRelease( );

Remarks

Typically, override this method in the class derived from CComObjectRootEx to free any aggregated objects before deletion.

CComObjectRootEx Overview | Class Members

See Also CComObjectRootEx::FinalConstruct


CComObjectRootEx::InternalAddRef

ULONG InternalAddRef( );

Return Value

A value that may be useful for diagnostics and testing.

Remarks

Increments the reference count of a nonaggregated object by 1. If the thread model is multithreaded, InterlockedIncrement is used to prevent more than one thread from changing the reference count at the same time.

CComObjectRootEx Overview | Class Members

See Also CComObjectRootEx::InternalRelease, CComObjectRootEx::InternalQueryInterface, InterlockedIncrement in the Win32 SDK


CComObjectRootEx::InternalQueryInterface

static HRESULT InternalQueryInterface( void* pThis, const _ATL_INTMAP_ENTRY* pEntries, REFIID iid, void** ppvObject ) ;

Return Value

One of the standard HRESULT values.

Parameters

pThis [in] A pointer to the object that contains the COM map of interfaces exposed to QueryInterface.

pEntries [in] A pointer to the _ATL_INTMAP_ENTRY structure, which accesses the map of interfaces.

iid [in] The GUID of the interface being requested.

ppvObject [out] A pointer to the interface pointer identified by iid, or NULL if the interface is not found.

Remarks

Retrieves a pointer to the requested interface.

InternalQueryInterface only handles interfaces in the COM map table. If your object is aggregated, InternalQueryInterface does not delegate to the outer unknown. You can enter interfaces into the COM map table with the macro COM_INTERFACE_ENTRY(InterfaceName) or one of its variants.

CComObjectRootEx Overview | Class Members

See Also CComObjectRootEx::InternalAddRef, CComObjectRootEx::InternalRelease


CComObjectRootEx::InternalRelease

ULONG InternalRelease( );

Return Value

In non-debug builds, always returns 0. In debug builds, returns a value that may be useful for diagnostics or testing.

Remarks

Decrements the reference count of a nonaggregated object by 1. If the thread model is multithreaded, InterlockedDecrement is used to prevent more than one thread from changing the reference count at the same time.

CComObjectRootEx Overview | Class Members

See Also CComObjectRootEx::InternalAddRef, CComObjectRootEx::InternalQueryInterface, InterlockedDecrement in the Win32 SDK


CComObjectRootEx::Lock

void Lock( );

Remarks

If the thread model is multithreaded, this method calls the Win32 API function EnterCriticalSection, which waits until the thread can take ownership of the critical section object obtained through the m_critsec data member. When the protected code finishes executing, the thread must call Unlock to release ownership of the critical section.

If the thread model is single-threaded, this method does nothing.

CComObjectRootEx Overview | Class Members

See Also CComObjectRootEx::Unlock, CComObjectRootEx::m_critsec


CComObjectRootEx::OuterAddRef

ULONG OuterAddRef( );

Return Value

A value that may be useful for diagnostics and testing.

Remarks

Increments the reference count of the outer unknown of an aggregation.

CComObjectRootEx Overview | Class Members

See Also CComObjectRootEx::OuterRelease, CComObjectRootEx::OuterQueryInterface


CComObjectRootEx::OuterQueryInterface

HRESULT OuterQueryInterface( REFIID iid, void** ppvObject );

Return Value

One of the standard HRESULT values.

Parameters

iid [in] The GUID of the interface being requested.

ppvObject [out] A pointer to the interface pointer specified in iid, or NULL if the aggregation does not support the interface.

Remarks

Retrieves a pointer to the requested interface.

CComObjectRootEx Overview | Class Members

See Also CComObjectRootEx::OuterAddRef, CComObjectRootEx::OuterRelease


CComObjectRootEx::OuterRelease

ULONG OuterRelease( );

Return Value

In non-debug builds, always returns 0. In debug builds, returns a value that may be useful for diagnostics or testing.

Remarks

Decrements the reference count of the outer unknown of an aggregation.

CComObjectRootEx Overview | Class Members

See Also CComObjectRootEx::OuterAddRef, CComObjectRootEx::OuterQueryInterface


CComObjectRootEx::Unlock

void Unlock( );

Remarks

If the thread model is multithreaded, this method calls the Win32 API function LeaveCriticalSection, which releases ownership of the critical section object obtained through the m_critsec data member. To obtain ownership, the thread must call Lock. Each call to Lock requires a corresponding call to Unlock to release ownership of the critical section.

If the thread model is single-threaded, this method does nothing.

CComObjectRootEx Overview | Class Members

See Also CComObjectRootEx::Lock, CComObjectRootEx::m_critsec


Data Members


CComObjectRootEx::m_critsec

_CritSec m_critsec;

Remarks

A CComAutoCriticalSection or CComFakeCriticalSection object. The critical section class _CritSec is determined by the thread model: CComAutoCriticalSection if multithreaded, and CComFakeCriticalSection if single-threaded.

If the thread model is multithreaded, m_critsec is a CComAutoCriticalSection object and provides access to CComAutoCriticalSection's methods and a CRITICAL_SECTION object.

If the thread model is single-threaded, a critical section is not needed and m_critsec is a CComFakeCriticalSection object.

CComObjectRootEx Overview | Class Members

See Also CComObjectRootEx::Lock, CComObjectRootEx::Unlock


CComObjectRootEx::m_dwRef

long m_dwRef;

Remarks

Part of a union that accesses four bytes of memory.

union
{
   long m_dwRef;
   IUnknown* m_pOuterUnknown;
};

If the object is not aggregated, the reference count accessed by AddRef and Release is stored in m_dwRef. If the object is aggregated, the pointer to the outer unknown is stored in m_pOuterUnknown.

CComObjectRootEx Overview | Class Members


CComObjectRootEx::m_pOuterUnknown

IUnknown* m_pOuterUnknown;

Remarks

Part of a union that accesses four bytes of memory.

union
{
   long m_dwRef;
   IUnknown* m_pOuterUnknown;
};

If the object is aggregated, the pointer to the outer unknown is stored in m_pOuterUnknown. If the object is not aggregated, the reference count accessed by AddRef and Release is stored in m_dwRef.

CComObjectRootEx Overview | Class Members