Basic COM   «Prev  Next»
Lesson 7In-process COM servers and DllGetClassObject
ObjectiveDescribe what DllGetClassObject does.

In-process COM Servers and DllGetClassObject

In-process servers provide class factories via function DllGetClassObject:
STDAPI DllGetClassObject(const CLSID&
rclsid, const IID& riid, VOID ** ppv);

COM calls DllGetClassObject on behalf of a COM client passing in a CLSID, an IID, and a VOID ** output parameter.

Local and remote Transparency

Recall from previous lessons that COM clients do not directly access a COM server. Instead they ask the COM runtime subsystem for a class factory that "knows how to create" a specific type of COM object by calling
CoGetClassObject

passing in the CLSID of the COM class. In response, the COM runtime subsystem looks the CLSID up in the registry to find the location of the server. COM loads the server and calls DllGetClassObject. We will discuss CoGetClassObject later in this module. COM imposes itself as an intermediary between the client and the server. This is called Local/Remote Transparency because the details of how the server is activated, connecting the client and server, and of how a client's COM call is routed to server is transparent to both the client and the server. The code to make an in-process call looks just like the code that makes a remote call. As needed, COM will handle the details involved with managing local and remote connections between the client and the server.
  • CoGetClassObject function
    Provides a pointer to an interface on a class object associated with a specified CLSID. CoGetClassObject locates, and if necessary, dynamically loads the executable code required to do this. Call CoGetClassObject directly to create multiple objects through a class object for which there is a CLSID in the system registry. You can also retrieve a class object from a specific remote computer. Most class objects implement the IClassFactory interface. You would then call CreateInstance to create an uninitialized object. It is not always necessary to go through this process however. To create a single object, call the
    CoCreateInstanceEx
    

    function, which allows you to create an instance on a remote machine. This replaces the CoCreateInstance function, which can still be used to create an instance on a local computer. Both functions encapsulate connecting to the class object, creating the instance, and releasing the class object.
    Two other functions,
    1. CoGetInstanceFromFile and
    2. CoGetInstanceFromIStorage,
    provide both instance creation on a remote system and object activation. There are numerous functions and interface methods whose purpose is to create objects of a single type and provide a pointer to an interface on that object.
The CLSID is the CLSID of the COM object we want a class factory for; the IID is IID_IClassFactory. If the server supports the requested COM object, it creates a class factory and calls QueryInterface in the new class factory. The following code demonstrates an implementation of DllGetClassObject.
CClass Factory
// CClassFactory01 implements
// O1's class factory
struct CClassFactory01 : public IClassFactory {
    ULONG m_refcnt;

    // IUnknown Methods
    HRESULT QueryInterface(const IID& riid, VOID **ppv) { ... }
    ULONG AddRef() { ... }
    ULONG Release() { ... }

    // IClassFactory Methods
    HRESULT CreateInstance(IUnknown *pOuter, const IID& iid, VOID **ppv) { ... }
    HRESULT LockServer(BOOL fLock) { ... }
};

STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) {
    HRESULT hr;
    if (CLSID_O1 == rclsid) {
        CClassFactory01 *pcfO1 = new CClassFactory01();

        hr = pcfO1->QueryInterface(riid, ppv);
        if (FAILED(hr)) {
            delete pcfO1;
            return hr;
        }
    }
    else
        return CLASS_E_CLASSNOTAVAILABLE;
    return S_OK;
}

The `CClassFactory01` struct in Microsoft COM (Component Object Model) implements a class factory for creating instances of a specific COM class, referred to here as `O1`. Let's break down the functionality and components of the provided code.
  1. Structure CClassFactory01 Overview

    The CClassFactory01 struct inherits from IClassFactory, which is a standard interface in the COM framework that provides methods for creating class objects and controlling object lifetimes. The class factory is a fundamental part of the COM architecture, as it is used to create instances of a COM class when requested by a client.

  2. Members of CClassFactory01
    • ULONG m_refcnt:

      This is a reference count used for managing the lifetime of the class factory object. COM uses reference counting to manage object lifetimes, and this counter is incremented or decremented as clients acquire or release references to the object.

  3. Methods Implemented
    1. IUnknown Methods:
      • QueryInterface:

        This method is part of the IUnknown interface and is used to obtain pointers to the supported interfaces on an object. It takes the interface identifier (IID) and a pointer to hold the interface pointer. The implementation will check if the requested interface is supported and return the appropriate interface if available.

      • AddRef:

        Increases the reference count (m_refcnt) when a client holds a new reference to the object. This ensures the object remains alive while references exist.

      • Release:

        Decreases the reference count and deletes the object when the count reaches zero, freeing resources.

    2. IClassFactory Methods:
      • CreateInstance:

        This method is responsible for creating an instance of the COM class O1. It takes a pointer to the controlling IUnknown (if the object is being aggregated), the interface identifier (iid), and a pointer to receive the created instance. The method would typically initialize the new object and return it to the client.

      • LockServer:

        Used to lock or unlock the server, ensuring that the DLL containing the class factory does not unload until explicitly released. This method is useful for keeping the COM server loaded when it is expected to be frequently used.

  4. DllGetClassObject Function:
    The `DllGetClassObject` function is a standard exported function used by the COM infrastructure to obtain a class factory object. Here's a breakdown of its role:
    • Parameters:
      • REFCLSID rclsid: The class ID of the object to be created. The function checks if the requested CLSID matches the CLSID_O1 (the class ID for O1).
      • REFIID riid: The interface ID requested on the class factory.
      • LPVOID *ppv: A pointer to receive the class factory interface.
    • Functionality:
      • If the requested rclsid matches CLSID_O1, a new instance of CClassFactory01 is created.
      • The QueryInterface method is called to get the requested interface on the class factory.
      • If QueryInterface fails, the created class factory is deleted, and an error is returned.
      • If the rclsid does not match CLSID_O1, the function returns CLASS_E_CLASSNOTAVAILABLE, indicating that the requested class is not available.
      • If everything is successful, the function returns S_OK.

Summary The `CClassFactory01` class factory is responsible for creating instances of the COM class `O1`. It implements methods from both `IUnknown` and `IClassFactory` to manage object lifetimes and provide the necessary functionality for object creation. The `DllGetClassObject` function acts as the entry point for obtaining this class factory and ensures that the correct class factory is returned based on the requested `CLSID`.
  1. These declare and implement a class factory for O1. IClassFactory, like all COM interfaces, must implement IUnknown as its first three methods. Following that are the methods of IClassFactory. CreateInstance and LockServer were covered earlier in this module.
  2. We use the standard declaration of DllGetClassObject. REFCLSID and REFIID are macros that preprocess to const CLSID& and const IID& when compiling in C++; LPVOID is VOID *.
  3. We check to see if this server supports the COM object by checking rclsid. If the requested COM object is not supported, CLASS_E_CLASSNOTAVAILABLE is returned.
  4. An instance of the class factory for the requested COM class is instantiated.
  5. A call is made to IClassFactory::QueryInterface to ask the newly created class factory if it supports the requested object creation interface in parameter riid. Normally this is IID_IClassFactory. QueryInterface will also call AddRef if the requested interface is supported.
  6. A check of the return status of the IClassFactory::QueryInterface call.
  7. Executed if the caller (COM) asked for an object creation interface not support by the class factory. The only reason this would fail (barring bugs) is if the caller did not ask for either IID_IUnknown or IID_IClassFactory.
  8. Returns S_OK to indicate, to the caller, that the requested COM object is supported by the server and the object's object creation interface; IClassFactory, has been placed in output parameter ppv.


SEMrush SoftwareW