Figure 2   OBJECT_CONTEXT

struct OBJECT_CONTEXT : IObjectContextInfo,
                        IContextState,
                        IObjectContext, ...
{
// context properties
    GUID id;      // ID of this context
    ACTIVITY           *pActivity;
    APARTMENT          *pApt;
    bool                bJITAEnabled;
    bool                bDone;
    long                nCallsInProgress;
    IUnknown           *pPrimaryObject;
    TX_STREAM          *pTxStm;
    bool                bRootOfStream;
    bool                bHappy;
// interface methods deleted for clarity
};

Figure 4   TotallyCompatible


bool TotallyCompatible(ATTRIBUTES *pTarget,
                       OBJECT_CONTEXT *pParent) {
// try to put non-configured components in parent
  if (!pTarget->bConfiguredComponent)
    return ApartmentCompatible(
              pTarget->ThreadingModel,
              pParent->pApt);
// JIT activation forces new context
  if (pTarget->bJITAEnabled) return false;
// check for shared activity
  switch (pTarget->Synchronization) {
    case REQUIRES_NEW:
      return false;
    case REQUIRED: // needs one
      if (pParent->pActivity == NULL)
        return false;
      break;
    case NOT_SUPPORTED: // can't have one
      if (pParent->pActivity != NULL)
        return false;
      break;
  }    
// remaining comparisons deleted for clarity
}

Figure 5   ComplexCreate


 HRESULT ComplexCreate(REFCLSID rclsid, 
                       ATTRIBUTES *pTarget, 
                       OBJECT_CONTEXT *pParent,
                       REFIID riid, 
                       void **ppv) {
// find/create target context
  OBJECT_CONTEXT *pChild 
       = FindContext(pTarget, pParent);
// check to see if this thread can enter target
  if (!ThisThreadCanEnterCtx(pChild))
    return EvenMoreComplexCreate(...);
// create new interceptor
  IYourInterface *pNew = new Interceptor();
// associate child context with interceptor
  pNew->pOC = pChild;
// switch context and create
  tls_pCurCtx = pChild;
  SimpleCreate(rclsid, ..., &pNew->pRealObj);
// set "primary object" of context for JIT activation
  if (pTarget->bJITAEnabled)
    pChild->pPrimaryObject = pNew;
// switch back and return interceptor
  tls_pCurCtx = pParent;
  return pNew->QueryInterface(riid, ppv);
}

Figure 6   PropagateActivity


void PropagateActivity(pParent, pChild, 
                       pTarget){
  switch (pTarget->Synchronization) {
    case DISABLED:      // don't need one
    case NOT_SUPPORTED: // can't have one
      pChild->pActivity = NULL;
      break;
    case SUPPORTED:     // always share
      pChild->pActivity = pParent->pActivity;
      break;
    case REQUIRED:    // needs one but can share
      if (pParent->pActivity) {
        pChild->pActivity = pParent->pActivity;
        break;
     } // else fall through to REQUIRES_NEW
    case REQUIRES_NEW:  // needs new one
      pChild->pActivity = new ACTIVITY();
      break;
  }
// activities are refcounted so AddRef
  if (pChild->pActivity)
    pChild->pActivity->AddRef();
}

Figure 7   PropagateTxStream


void PropagateTxStream(pParent, pChild, 
                       pTarget){
// default to non-root and happy
  pChild->bRootOfStream = false;
  pChild->bHappy = true;

// propagate tx_stream if possible
  switch (pTarget->Transaction) {
    case IGNORED:       // don't need one
    case NOT_SUPPORTED: // can't have one
      pChild->pTxStream = NULL;
      break;
    case SUPPORTED:     // always share
      pChild->pTxStream = pParent->pTxStream;
      break;
    case REQUIRED:    // needs one but can share
      if (pParent->pTxStream) {
        pChild->pTxStream = pParent->pTxStream;
        break;
     } // else fall through to REQUIRES_NEW
    case REQUIRES_NEW:  // must be root of new one
      pChild->pTxStream = new TX_STREAM();
      pChild->bRootOfStream = true;
      break;
  }
// tx streams are refcounted so AddRef
  if (pChild->pTxStream)
    pChild->pTxStream->AddRef();
}

Figure 8   PropagateApartment


void PropagateApartment(pParent, pChild, 
                       pTarget){
  switch (pTarget->ThreadingModel) {
    case BOTH: // always blindly share
      pChild->pApt = pParent->pApt;
      break;
    case FREE: // always blindly use MTA
      pChild->pApt = GetDistinguishedApt(MTA);
      break;
    case NEUTRAL: // always blindly use TNA
      pChild->pApt = GetDistinguishedApt(TNA);
      break;
    case ABSENT: // always blindly use main apt
      pChild->pApt = GetDistinguishedApt(MAIN);
      break;
    case APARTMENT:
// grab home apt of thread (set at CoInit time)
      APARTMENT *pHome = GetHomeAptOfThread();
      if (pHome->apt_type == MTA)
        pChild->pApt = GetDistinguishedApt(HOST);
      else // STA or MAIN
        pChild->pApt = pHome;
  }
// apartments are refcounted so AddRef
  if (pChild->pApt)
    pChild->pApt->AddRef();
}


Figure 9   GetDistinguishedApt


// four references to processwide globals
APARTMENT *g_pMTA  = 0;
APARTMENT *g_pTNA  = 0;
APARTMENT *g_pMain = 0;
APARTMENT *g_pHost = 0;

APARTMENT *GetDistinguishedApt(APT_TYPE type) {
  switch (type) {
    case MTA:  
      if (g_pMTA == 0) // create first time
        g_pMTA = new APARTMENT(MTA);
      return g_pMTA;
    case TNA:
      if (g_pTNA == 0) // create first time
        g_pTNA = new APARTMENT(TNA);
      return g_pTNA;
    case HOST: 
      if (g_pHost == 0) {
// spawn host thread
        CreateThread(HostThreadProc, &g_pHost);
// set main to host if no main yet
        if (g_pMain == 0)
          g_pMain = g_pHost;
      }
      return g_pHost;
    case MAIN: 
      if (g_pMain == 0) // create host if no main
        return GetDistinguishedApt(HOST);
      else
        return g_pMain;
  }
}

Figure 10   CoInitializeEx


HRESULT CoInitializeEx(void *, DWORD dwFlags) {
  if (dwFlags == COINIT_MULTITHREADED) {
    if (tls_pHomeApt == 0) {// 1st call for thread
      tls_pHomeApt = GetDistinguishedApt(MTA);
      return S_OK;
    }
    else if (tls_pHomeApt->apt_type != MTA)
      return RPC_E_CHANGED_MODE;
    else
      return S_FALSE;
  }
  else if (dwFlags == COINIT_APARTMENTTHEADED){
    if (tls_pHomeApt == 0) {// 1st call for thread
// become main if we're the first
      if (g_pMain == 0) {
        tls_pHomeApt = new APARTMENT(MAIN);
        g_pMain = tls_pHomeApt;
      }
      else 
        tls_pHomeApt = new APARTMENT(STA);
      return S_OK;
    }
    else if (tls_pHomeApt->apt_type == MTA)
      return RPC_E_CHANGED_MODE;
    else
      return S_FALSE;
  }
  else return E_INVALIDARG;
}