COM is a mechanism that was developed to allow people to distribute binaries that could be reused even if the caller was using another vendor's C++ compiler or (ultimately) a different language altogether.
COM is a mechanism that allows the re-use of objects (or rather components), independently of the languages used by the programmer who implemented the component and the programmer who uses it, and independently of whether the component was implemented in the client's program or elsewhere on the machine (or network).
Broadly speaking, each COM component provides an implementation of one or more interfaces. Those interfaces are defined in a language-neutral manner using the Interface Definition Language (IDL). As an example, one of the fundamental interfaces in COM, IUnknown, is defined like this:
This little interface is fundamental in COM, because each COM component must implement it. It defines two important aspects of the COM machinery:
QueryInterface allows calling code to get an implementation for a known interface. In COM, interfaces are referenced by GUIDs (also known as Interface Identifiers, IID). If an object implements several interfaces, that's how client code gets a reference to each of those interfaces. It acts as a sort of casting operator, if you will.
AddRef() and Release() implement the memory management mechanism for COM objects. As their name suggests, the most common model is the reference counting mechanism, where an instance is destroyed after the last client has released its reference to it.
All COM components are registered with the system upon installation. If a programmer wants to use a certain component, he needs to:
Make sure the component is installed at a reachable location. Most of the time it is on the system of the running application, but COM+ also allows components to exist on remote computers.
Know the GUID of the given component. With this GUID, the client can then ask the system to instantiate the component (in C, the function to do this is called CoCreateInstance()). You can look in the registry under HKEY_CLASSES_ROOT\CLSID: each GUID in there is (most probably) an identifier for a COM component or interface, and the entries below that key tell the system how it should be instanciated.
The COM machinery is extremely complex. For example, implementing or using COM components in C requires a horrendous amount of work, but higher-level languages like Visual Basic have done a lot to ease the implementation and use of COM components. The benefits are however very real. It makes it possible to write an application in, say, Visual Basic, but to still implement the performance-critical algorithms in C or C++ as COM objects, which can be used directly from the VB code. The system takes care of marshalling method-call arguments, passing them through threads, processes and network connections as needed so that the client code has the impression of using a normal object.
Many fundamental parts of Windows are based on COM. Windows Explorer (the file manager), for instance, is basically an empty shell. It defines a bunch of COM Interfaces for navigating and displaying tree hierarchies, and all the code that actually displays "My Computer", the drives, the folders and the files is as a set of COM components that implement those interfaces.
With the advent of .NET, COM is slowly becoming obsolete.