Component Object Model (COM)

COM, or Component Object Model, is an object-based software architecture that allows applications to be built from binary software components. Component Object Model (COM) is a binary-interface standard for software components introduced by Microsoft in 1993. It is used to enable inter-process communication object creation in a large range of programming languages. COM is the basis for several other Microsoft technologies and frameworks, including OLE, OLE Automation, Browser Helper Object, ActiveX, COM+, DCOM, the Windows shell, DirectX, UMDF and Windows Runtime.

The essence of COM is a language-neutral way of implementing objects that can be used in environments different from the one in which they were created, even across machine boundaries. For well-authored components, COM allows reuse of objects with no knowledge of their internal implementation, as it forces component implementers to provide well-defined interfaces that are separated from the implementation. The different allocation semantics of languages are accommodated by making objects responsible for their own creation and destruction through reference-counting. Type conversion casting between different interfaces of an object is achieved through the QueryInterface method. The preferred method of “inheritance” within COM is the creation of sub-objects to which method “calls” are delegated.

Component Object Model (COM)

As defined by Microsoft, the Component Object Model (COM) is an object-based software architecture that allows applications to be built from binary software components. COM is the foundation for various Microsoft technologies including OLE, ActiveX, Distributed COM (DCOM), COM+, and Microsoft Transaction Server (MTS).

COM is not a programming language, rather it is a specification. The goal of COM is to allow applications to be built using components. These COM components can be created by different vendors, at different times, and using different programming languages. Also, COM components can run on different machines and different operating systems.

The following concepts are fundamental to the way COM works:

 

COM Interfaces

A group of related functions implemented by the COM class. COM interfaces are the mechanisms by which COM objects expose their functionality to applications and other components. An interface is a table of pointers to functions that are implemented by the object. The table represents the interface and the functions to which the table points represent the methods of that interface. COM objects can expose multiple interfaces. Each interface has its own unique interface ID (IID).

IUnknown

This is the basic Component Object Model interface on which all other interfaces are based; it provides reference counting and interface querying mechanisms. IUnknown allows navigation to all other interfaces exposed by the object.

Reference counting

This is a mechanism by which an interface determines it is no longer being used and is, therefore, free to remove itself. IUnknown uses the methods AddRef and Release to implement reference counting.

QueryInterface

This is the IUnknown method used to query an object for a given interface.

Aggregation

This is a technique by which one object can make use of another.

Marshaling

This mechanism lets objects be used across thread, process, and network boundaries, thus providing location independence.

The Component Object Model defines several fundamental concepts that provide the model’s structural underpinnings. These include:

  • A binary standard for function calling between components.
  • A provision for strongly-typed groupings of functions into interfaces.
  • A base interface providing:
    • A way for components to dynamically discover the interfaces implemented by other components.
    • Reference counting to allow components to track their own lifetime and delete themselves when appropriate.
  • A mechanism to identify components and their interfaces uniquely, worldwide.
  • A “component loader” to set up component interactions and, additionally (in the cross-process and cross-network cases), to help manage component interactions.

For any given platform (hardware and operating system combination), COM defines a standard way to lay out virtual function tables (vtables) in memory, and a standard way to call functions through the vtables. Thus, any language that can call functions via pointers (C, C++, Smalltalk, Ada, and even BASIC) all can be used to write components that can interoperate with other components written to the same binary standard. Indirection (the client holds a pointer to a vtable) allows for vtable sharing among multiple instances of the same object class. On a system with hundreds of object instances, vtable sharing can reduce memory requirements considerably, because additional vtables pointing to the same component instance consume much less memory than multiple instances of the same component.

The word object tends to mean something different to everyone. To clarify: In COM, an object is a piece of compiled code that provides some service to the rest of the system. To avoid confusion, it is probably best to refer to an object used in COM as a COM component or simply as a component. This avoids confusing COM components with source-code OOP objects such as those defined in C++. COM components support a base interface called IUnknown (described later), along with a combination of other interfaces, depending on what functionality the COM component chooses to expose.

COM components usually have some associated data, but unlike C++ objects, a given COM component will never have direct access to another COM component in its entirety. Instead, COM components always access other COM components through interface pointers. This is a primary architectural feature of the Component Object Model, because it allows COM to completely preserve encapsulation of data and processing, a fundamental requirement of a true component software standard. It also allows for transparent remoting (cross-process or cross-network calling) because all data access is through methods that can be accessed through a proxy-stub pair that forward the request from the client component to the server component and also send back the response.

COM and ActiveX components are run as native code on the user’s machine, with no sandboxing. There are therefore few restrictions on what the code can do. The prior practice of embedding ActiveX components on web pages with Internet Explorer did therefore lead to problems with malware infections. Microsoft recognized the problem with ActiveX as far back as 1996 when Charles Fitzgerald said, “We never made the claim up front that ActiveX is intrinsically secure”. Recent[when?] versions of Internet Explorer prompt the user before installing ActiveX controls, enabling the user to disallow installation of controls from sites that the user does not trust.

The ActiveX controls are signed with digital signatures to guarantee their authenticity. It is also possible to disable ActiveX controls altogether, or to allow only a selected few. The transparent support for out-of-process COM servers still promotes software safety in terms of process isolation. This can be useful for decoupling subsystems of large application into separate processes. Process isolation limits state corruption in one process from negatively affecting the integrity of the other processes, since they only communicate through strictly defined interfaces. Thus, only the affected subsystem needs to be restarted in order to regain valid state. This is not the case for subsystems within the same process, where a rogue pointer in one subsystem can randomly corrupt other subsystems.

Status codes used by COM (HRESULT codes) are supported by our What Is service.