COM+ represents each context by an object called the
context object.
Every context has exactly one context
object. Objects can obtain a pointer to their context object by
calling CoGetObjectContext( )
(see Figure 2-5). All objects in the same context
get the same context object.
CoGetObjectContext( )
is defined as:
Figure 2-5. By calling CoGetObjectContext( ), objects can get a pointer to their context’s context object
HRESULT CoGetObjectContext(REFIID riid, void** ppInterface);
The context object supports a few interfaces, so the first parameter
of CoGetObjectContext( )
is always an IID that
specifies which interface to retrieve. Two of the context
object’s interfaces, IObjectContext
and
IObjectContextActivity
, are legacy interfaces from
MTS and are provided primarily for backward compatibility with MTS
components running under COM+. The other two interfaces,
IContextState
and
IObjectContextInfo
, are specific to COM+. Throughout
this book, all chapters use these two interfaces, rather than the
legacy MTS interfaces.
The IContextState
interface controls object
deactivation (discussed in Chapter 3) and
transaction voting (discussed in Chapter 4) by
manipulating state bits in the context object.
IObjectContextInfo
gains access to various aspects
of the current transaction, retrieves the current
activity ID
(discussed in Chapter 5), and retrieves the
current context ID. The
IObjectContextInfo
interface is defined as:
interface IObjectContextInfo : IUnknown
{
BOOL IsInTransaction( );
HRESULT GetTransaction([out]IUnknown** ppTransaction);
HRESULT GetTransactionId([out]GUID* pTransactionId);
HRESULT GetActivityId([out]GUID* pActivityId);
HRESULT GetContextId
([out]GUID* pContextId);
};
Every COM+ context has a unique ID (a GUID) associated with it.
Retrieving the current context ID is sometimes useful for tracing and
debugging purposes. Example 2-1 shows how to trace
the current context ID by calling CoGetObjectContext( )
, requesting the
IObjectContextInfo
interface, and then calling the
IObjectContextInfo::GetContextId( )
method.
Example 2-1. Retrieving the current context ID with IObjectContextInfo::GetContextId( )
HRESULT hres = S_OK; IObjectContextInfo* pObjectContextInfo = NULL; GUID guidContextID = GUID_NULL; hres =::CoGetObjectContext
(IID_IObjectContextInfo,(void**)&pObjectContextInfo); ASSERT(pObjectContextInfo != NULL);//not a configured component? hres = pObjectContextInfo->GetContextId
(&guidContextID); pObjectContextInfo->Release( ); USES_CONVERSION; WCHAR pwsGUID[150]; ::StringFromGUID2(guidContextID,pwsGUID,150); TRACE("The object is in context with ID %s",W2A(pwsGUID));
Note that only COM+-configured components should call
CoGetObjectContext( )
. When a nonconfigured
component calls CoGetObjectContext( )
, the call
will fail with the return value of E_NOINTERFACE
,
and the returned interface pointer will be set to
NULL
. The assertion check in Example 2-1 tests for that condition.
One more point regarding the context object: the context object and its interfaces are private to the specific context they represent and should not be shared with or passed to objects in other contexts. Doing so may introduce hard-to-detect bugs and nondeterministic behavior of object deactivation and destruction, and it may affect transaction semantics and accuracy.