Custom Components and COM

The Component Object Model (COM) is a specification (hence "model") that describes, besides the notions of objects, interfaces, and QueryInterface, the mechanisms necessary to access a custom component given only a unique identifier.5 This identifier, called a class identifier (or CLSID), identifies the top-level object within the component, so what COM is really providing is a mechanism to instantiate an object of a given class. This sounds a lot like the C++ new operator, but in OLE the client calls a COM API function CoCreateInstance with the CLSID to obtain an interface pointer to that object rather than calling new with a C++ class name, which results in an object pointer. Of course, we're talking about two different species of objects here, but the analogy still holds.

Not all objects in OLE need to support this sort of creation process, but when support is there, it is the responsibility of the object or component server to package the object appropriately, which is the primary topic of Chapter 5. The mechanics of this depend on whether the server is a DLL or an EXE, but a client always starts the process by calling CoCreateInstance with a CLSID. COM uses information stored with the CLSID in the system registry to locate the server module. It then gets that server into memory (loads the DLL or launches the EXE) and asks the server to create the object, returning an interface pointer. The act of creation involves an object known as a class factory, which implements the interface IClassFactory, whose purpose in life is to manufacture objects of a particular CLSID. This object is part of the server, not part of the component that the client is trying to access, although a client can access the class factory directly if it wants.

In any case, the client is completely isolated from how the object is structured inside a server and from all considerations about the boundaries between it and the object created. The object could be in-proc (in-process, from a DLL server), local (out-of-process, from an EXE server), or even remote (from a DLL or an EXE that is running on another machine).6 In any case, COM's local/remote transparency (see the next section) means that the client doesn't have to care where the object is running—it simply accesses its features through interface pointers, and those calls are transparently routed to other processes or machines as necessary. Clients do, however, have control over what sort of boundaries are involved; for example, a client can specify only in-process or only out-process.

So far I have made no mention about what interfaces the various objects in a component might support, and this is intentional: the custom component facilities in COM make no restrictions on what interfaces an object might have (although local/remote transparency does at times). These facilities can be used anytime and anywhere a client might need to access any sort of component through a CLSID.

As part of these same mechanisms, COM also provides for what is called emulation of one component class by a component from a different class. This is accomplished by mapping one CLSID to another in the system registry. What this does is allow one component to be installed over another and completely replace it without requiring changes to any existing clients that might have hard-coded or persistently stored CLSIDs. When the client instantiates a component of the original CLSID, COM automatically uses the other component that is emulating the first. This is useful for providing alternative implementations of the same component and is a key factor for installing new versions of a component without breaking its existing clients.

Part of the enhancements to OLE that were shipped with the set of technologies called OLE Controls is the ability to license the creation of components. This is handled through an alternative class factory interface named IClassFactory2, which provides a license key that is necessary to create objects later. This class factory would provide such a key only when running on a machine with a fully licensed installation. If the server is illegally copied to another unlicensed machine, the server will refuse outright to create anything.

5 In dealing with specific COM-related features it is conventional to use the term COM in place of or interchangeably with the term OLE because COM identifies the core part of OLE that pro-vides for object creation and local/remote transparency. COM API functions are all named with a Co prefix.

6 Note that at the time of writing OLE/COM does not yet support remote objects also called distributed services as a shipping technology because there are still some things to be worked out.