Basic COM   «Prev  Next»
Lesson 4 How IClassFactory creates objects
Objective Discover how IClassFactory creates objects.

How IClassFactory Creates Objects

Recall that there is a one-to-one association between a class object/factory and a COM object. If we implement two COM objects, namely
  1. O1 and
  2. O2
we must implement two class factories, one for each type of COM object.
Assume CF01 is the class factory for O1 and CF02 is the class factory for O2. A call to CF01::CreateInstance does the following:
  1. Creates an instance of COM object O1.
  2. Within CreateInstance, after object O1 is created, calls O1::QueryInterface to have O1 return the requested interface pointer to the client.
A call to CF02::CreateInstance does the following:
  1. Creates an instance of O2.
  2. Calls O2::QueryInterface to have O2 return the requested interface pointer to the client.

We will revisit class factories in a follow-up lesson.
IClassFactory shows C++-style logic that demonstrates how to implement a class factory (See code below, Implementing IClassFactory).
One question that still needs to be addressed is how does a client get a pointer into a class factory to create instances of COM object? We will discuss this in the next set of lessons when we examine COM servers and clients.

Implementing IClassFactory

ULONG g_lock = 0;

//Assume COM object MyComObject is implemented
//by class CMyComObject using the multiple inheritance technique. 

class CMyComObject : public IMyComInterface,
  public IYourComInterface { ... }

struct CFMyComObject : public IClassFactory {
  ULONG m_refcnt;

  HRESULT QueryInterface
    (const IID& riid, VOID **ppv) {
    //class  factories normally only respond to
    //IID_IUnknown and IClassFactory
  
    if (IID_IUnknown == riid ||
   IID_IClassFactory == riid) {
    *ppv = this;
    ((IUnknown *) *ppv)->AddRef();
      return S_OK;
    }
    return E_NOINTERFACE;
   }

   ULONG AddRef() { return ++m_refcnt; }

   ULONG Release() {
    //When the reference count goes to zero we
    //normally delete the class factory
   
     if (--m_refcnt == 0) {
       delete this;
       return 0;
      }
      return m_refcnt;
   }

   HRESULT CreateInstance(IUnknown *pOuter,
     const IID& riid, void **ppv) {
  
     CMyComObject *pc;

    //if pOuter is not NULL, return an ERROR
  
   if (pOuter != NULL)
     return E_NOAGGREGATION;

    //Create a new instance of the C++ class that
    //implements our COM object and call
  
  pc = new CMyComObject();

    //QueryInterface in it to see
    //if the object supports the interface
    //requested by the client.
  
      HRESULT hr = pc->QueryInterface(riid, ppv);

    //If the client has asked for an interface not   
    //supported by the newly created COM object
    //delete the COM object and
    //return the error code
    //from the QueryInterface call. This
    //will usually be E_NOINTERFACE.
     if (FAILED(hr)) {
       delete pc;
       return hr;
     }
     return S_OK;
   }

   HRESULT LockServer(BOOL fLock) {
     if (fLock) ++g_lock;
     else --g_lock;
   }

   CFMyComObject() : m_refcnt(0) { }
};

Debug Class Factory - Exercise

Click the Exercise link below to apply what you have learned about class factories.
Debug Class Factory - Exercise