Next Previous Contents

6.1 Background: a COM creation primer

The user's view

From a client's point of view, an instance of a particular COM component is created as follows:

The component view

What does the component author need to provide in order for clients to be able to create instances using CoCreateInstance()? The answer is an implementation of a class factory, a component instance constructor for that particular COM component.

There's a standard COM interface for class factories:

[
    object,
    uuid(00000001-0000-0000-C000-000000000046),
    pointer_default(unique)
]
interface IClassFactory : IUnknown {
    [local] 
    HRESULT CreateInstance(
        ( [in, unique] IUnknown * pUnkOuter
        , [in] REFIID riid
        , [out, iid_is(riid)] void **ppvObject
        );

    [local]
    HRESULT LockServer([in] BOOL fLock);
}

The method of interest here is CreateInstance():

    HRESULT CreateInstance
        ( [in, unique] IUnknown * pUnkOuter
        , [in] REFIID riid
        , [out, iid_is(riid)] void **ppvObject
        );

Given an interface identifier and a pointer to an interface pointer as arguments, CreateInstance() tries to create a COM object with the desired IID (failure or otherwise is reported back via the HRESULT return value). But how do we get at the class factory corresponding to a particular CLSID in the first place? Using CoGetClassObject() from the COM library:

HRESULT CoGetClassObject 
    ( [in]  REFCLSID rclsid
    , [in]  DWORD grfContext
    , [in]  COMSERVERINFO* pServerInfo
    , [in]  REFIID riid,
    , [out] void** ppv
    );

It locates and creates the class factory corresponding to rclsid. (Notice that CoGetClassObject() takes a REFIID argument specifying the factory interface we want to access. This is usually the interface id of IClassFactory, but doesn't have to be, IClassFactory is just the common/standardised way of exposing component constructors).

Assuming the component is provided in a DLL (and we're looking for an in-process instance), the system implementation of CoGetClassObject() will perform the following steps when trying to locate and create a class factory:

Having got the interface pointer for the class factory back, the client can now invoke its CreateInstance() method.

The COM library provides a convenience function, CoCreateInstance(), which hides the class factory from programmer view. It combines CoGetClassObject() and CreateInstance() into one, just returning the component instance (and releasing the factory.)

Registration

To make a COM class generally visible on a machine, you need to register it in the system-wide mapping which associates a CLSID withe the code that implements the component class.

Registration is normally done by the installer program, or assuming the COM class is packaged up in a DLL, through the use of the regsvr32 util. Provided the DLL follows the COM registration conventions by naming the DLL entry points that registers (and unregisters) as follows:

HRESULT DllRegisterServer(void);
HRESULT DllUnregisterServer(void);

regsvr32 will perform the registration for you. The implementation of regsvr32 itself is straightforward: load the DLL, followed by a lookup and invocation of one of the above two entry points.

COM also defines/suggests a set of guidelines to ease the registration of process servers (EXE).


Next Previous Contents