COM Fundamentals

Introduction to COM

Component Object Model (COM) is a binary-standard for creating reusable, interoperable software components. It enables different applications, written in different languages, to communicate with each other and to leverage each other's functionality. COM is a cornerstone technology in Windows, powering many system services and applications.

Key principles of COM include:

COM is the foundation for many other Microsoft technologies like ActiveX, OLE, and COM+.

Interfaces: The Contract

At the heart of COM are interfaces. An interface defines a set of functions (methods) that an object supports, along with their signatures. It's a contract between the object provider and the object consumer. Importantly, interfaces are abstract; they do not contain implementation details. They are defined using a C++ virtual function table (vtable) mechanism.

An interface is identified by a unique GUID (Globally Unique Identifier), known as an Interface Identifier (IID).

Consider a simple interface definition:


// Forward declaration
interface IUnknown;

// Interface definition
// {00000000-0000-0000-C000-000000000046}
interface DECLSPEC_UUID("00000000-0000-0000-C000-000000000046") IMyInterface : public IUnknown
{
    virtual HRESULT STDMETHODCALLTYPE MyMethod(int value) = 0;
};

            

All COM interfaces must derive from IUnknown, which provides fundamental COM object management methods.

Classes and Implementation

While interfaces define the contract, COM classes provide the implementation for that contract. A COM class is a concrete implementation of one or more COM interfaces. Clients interact with objects through interfaces, never directly with the class implementation.

A COM class is identified by a unique Class Identifier (CLSID).

Here's a conceptual C++ class implementing IMyInterface:


class CMyClass : public IMyInterface
{
public:
    // IUnknown methods
    virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject) override;
    virtual ULONG STDMETHODCALLTYPE AddRef(void) override;
    virtual ULONG STDMETHODCALLTYPE Release(void) override;

    // IMyInterface method
    virtual HRESULT STDMETHODCALLTYPE MyMethod(int value) override;

private:
    ULONG m_cRef; // Reference count
};

            

COM Objects

A COM object is an instance of a COM class. When a client wants to use a COM object, it typically requests an interface pointer to that object. The COM infrastructure (e.g., COM library, registry) is responsible for creating the object instance and returning the requested interface pointer.

Clients interact with the object through the interface pointer, calling its methods without needing to know the underlying class or its implementation details.

Interface Identifiers (IIDs)

Every COM interface is uniquely identified by a GUID, called an Interface Identifier (IID). This GUID is embedded in the interface definition using the uuid attribute (or DECLSPEC_UUID in Microsoft's C++ extensions).

GUIDs are 128-bit numbers, guaranteed to be unique across space and time. This uniqueness ensures that different interfaces, even if they have the same method names, can be distinguished.

The IID for IUnknown is a well-known GUID:

// {00000000-0000-0000-C000-000000000046}
DEFINE_GUID(IID_IUnknown, 0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);

Virtual Tables (VTables)

COM uses a mechanism called the Virtual Table (vtable) to provide early binding and efficient method dispatch. When an interface is defined, a corresponding vtable structure is generated. This vtable is an array of function pointers, where each pointer points to the implementation of a specific interface method in the COM object.

When a client obtains an interface pointer, it is actually pointing to the vtable. The first pointer in the vtable is typically for IUnknown::QueryInterface, followed by IUnknown::AddRef, IUnknown::Release, and then the methods of the specific interface.


// Conceptual vtable structure for IMyInterface
struct IMyInterfaceVtbl
{
    HRESULT (STDMETHODCALLTYPE *QueryInterface)(IMyInterface * This, REFIID riid, void **ppvObject);
    ULONG (STDMETHODCALLTYPE *AddRef)(IMyInterface * This);
    ULONG (STDMETHODCALLTYPE *Release)(IMyInterface * This);
    HRESULT (STDMETHODCALLTYPE *MyMethod)(IMyInterface * This, int value);
};

// Conceptual interface pointer structure
struct IMyInterface
{
    IMyInterfaceVtbl *lpVtbl;
};

            

QueryInterface

The QueryInterface method is fundamental to COM's flexibility and extensibility. It allows a client to query an object to see if it supports a specific interface. If the object supports the requested interface, QueryInterface returns a pointer to that interface and increments its reference count.

HRESULT QueryInterface(REFIID riid, void **ppvObject);

This method is crucial for navigating between different interfaces supported by a single COM object.

AddRef and Release (Reference Counting)

COM uses reference counting for memory management. Every COM object maintains a count of how many references (interface pointers) exist to it. The IUnknown interface provides two methods for managing this count:

Properly managing reference counts is essential to prevent memory leaks or premature deallocation of COM objects.

The COM object is responsible for implementing AddRef and Release correctly to ensure its lifecycle is managed.

COM Registration

For COM objects to be discoverable and creatable by other applications, they need to be registered with the operating system. This registration information is stored in the Windows Registry. Key pieces of information include:

Registration is typically handled by a component's installer or through a utility like regsvr32.exe for in-process COM servers (DLLs).

Active Template Library (ATL)

The Active Template Library (ATL) is a set of C++ template classes that simplify the development of COM objects. ATL provides wizards and helper classes that abstract away much of the boilerplate code required for COM development, such as:

ATL is a powerful tool for creating efficient and small-footprint COM components.

Advanced COM Topics

COM is a rich technology with many advanced concepts:

Understanding these topics is key to mastering COM development.