Jump to content

Component Object Model: Difference between revisions

From Wikipedia, the free encyclopedia
Content deleted Content added
Tôi đéo thích bạn
Tags: Mobile edit Mobile web edit
m v2.05b - Bot T20 CW#61 - Fix errors for CW project (Reference before punctuation)
(41 intermediate revisions by 15 users not shown)
Line 1: Line 1:
{{Short description|Application Binary Interface by Microsoft}}
{{Short description|Software component technology from Microsoft}}
{{Use mdy dates|date=January 2019}}
{{Use mdy dates|date=January 2019}}
{{Use American English|date=January 2019}}
{{Use American English|date=January 2019}}
Line 24: Line 24:
| domain = Component Interfacing
| domain = Component Interfacing
| license =
| license =
| website = {{URL|https://docs.microsoft.com/en-us/windows/win32/com/the-component-object-model}}
| website = {{URL|https://learn.microsoft.com/en-us/windows/win32/com/the-component-object-model}}
| first_published = {{Start date and age|1993}}
| first_published = {{Start date and age|1993}}
| authors =
| authors =
| series = [https://docs.microsoft.com/en-us/windows/win32/system-services System Services]
| series = [https://learn.microsoft.com/en-us/windows/win32/system-services System Services]
| editors =
| editors =
| base_standards = [[Microsoft Interface Definition Language|MIDL]], [[Universally unique identifier|UUID]]
| base_standards = [[Microsoft Interface Definition Language|MIDL]], [[Universally unique identifier|UUID]]
}}
}}
'''Component Object Model''' ('''COM''') is a [[Application Binary Interface|binary-interface]] technology for [[software component]]s from [[Microsoft]] that enables using [[object (computer science)|objects]] in a [[language-neutral]] way between different [[programming languages]], programming contexts, [[Process (computing)|processes]] and [[computer|machines]].
'''Component Object Model''' ('''COM''') is a [[Application Binary Interface|binary-interface]] standard for [[Component-based software engineering|software components]] introduced by [[Microsoft]] in 1993. It is used to enable [[inter-process communication]] [[object (computer science)|object]] creation in a large range of [[programming languages]]. COM is the basis for several other Microsoft technologies and frameworks, including [[Object Linking and Embedding|OLE]], [[OLE Automation]], [[Browser Helper Object]], [[ActiveX]], [[#COM+|COM+]], [[Distributed Component Object Model|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 [[interface (object-oriented programming)|interface]]s 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|reference-counting]]. [[Type conversion|Type conversion casting]] between different interfaces of an object is achieved through the <code>QueryInterface</code> method. The preferred method of "inheritance" within COM is the creation of sub-objects to which method "calls" are delegated.


COM is the basis for other Microsoft domain specific component technologies including [[Object Linking and Embedding|OLE]], [[OLE Automation]], [[ActiveX]], [[#COM+|COM+]], and [[Distributed Component Object Model|DCOM]] as well as [[implementation]]s such as [[DirectX]], [[Windows shell]], [[User-Mode Driver Framework|UMDF]], [[Windows Runtime]], and [[Browser Helper Object]].
COM is an interface technology defined and implemented as standard only on [[Microsoft Windows]] and Apple's [[Core Foundation]] 1.3 and later plug-in [[application programming interface]] (API).<ref>{{cite web|url=https://developer.apple.com/library/mac/#documentation/CoreFoundation/Conceptual/CFPlugIns/Concepts/conceptual.html#//apple_ref/doc/uid/20001160-102910-BAJFDFFC|title=Documentation Archive|website=developer.apple.com}}</ref> The latter only implements a subset of the whole COM interface.<ref name="COM on MacOS">{{cite web | url = https://developer.apple.com/library/mac/#documentation/CoreFoundation/Conceptual/CFPlugIns/Concepts/com.html#//apple_ref/doc/uid/20001158-CJBEJBHH | title = Plug-ins and Microsoft's COM | publisher = [[Apple Inc.]] | access-date = 2010-10-05}}</ref> For some applications, COM has been replaced at least to some extent by the [[.NET Framework|Microsoft .NET]] framework, and support for [[Web Services]] through the [[Windows Communication Foundation]] (WCF). However, COM objects can be used with all .NET languages through .NET [[COM Interop]]. Networked DCOM uses binary [[proprietary format]]s, while WCF encourages the use of [[XML]]-based [[SOAP (protocol)|SOAP]] messaging. COM is very similar to other [[component software]] interface technologies, such as [[CORBA]] and [[Enterprise JavaBeans]], although each has its own strengths and weaknesses. Unlike C++, COM provides a stable [[application binary interface]] (ABI) that does not change between compiler releases.<ref>Microsoft forum: [https://archive.today/20130216110824/http://social.msdn.microsoft.com/Forums/en/vcgeneral/thread/86eda6a7-4d90-4e19-a9d4-6cbe22b661f4 Binary compatibility across Visual C++ versions]</ref> This makes COM interfaces attractive for object-oriented C++ libraries that are to be used by clients compiled using different compiler versions.

COM enables object use with only knowing its interface; not its internal implementation. The component implementer defines [[interface (object-oriented programming)|interface]]s that are separate from the implementation.

Support for multiple programming contexts is handled by relying on the object for aspects that would be challenging to implement as a facility. Supporting multiple uses of an object is handled by requiring each object to destroy itself via [[reference counting|reference-counting]]. Access to an object's interfaces (similar to [[Type conversion]]) is provided by each object as well.

COM is available only in [[Microsoft Windows]] and Apple's [[Core Foundation]] 1.3 and later plug-in [[application programming interface]] (API).<ref>{{cite web|url=https://developer.apple.com/library/mac/#documentation/CoreFoundation/Conceptual/CFPlugIns/Concepts/conceptual.html#//apple_ref/doc/uid/20001160-102910-BAJFDFFC|title=Documentation Archive|website=developer.apple.com}}</ref> The latter only implements a subset of the whole COM interface.<ref name="COM on MacOS">{{cite web | url = https://developer.apple.com/library/mac/#documentation/CoreFoundation/Conceptual/CFPlugIns/Concepts/com.html#//apple_ref/doc/uid/20001158-CJBEJBHH | title = Plug-ins and Microsoft's COM | publisher = [[Apple Inc.]] | access-date = 2010-10-05}}</ref>

Over time, COM is being replaced with other technologies such as [[.NET Framework|Microsoft .NET]] and [[web services]] (i.e. via [[Windows communication foundation|WCF]]). However, COM objects can be used in a .NET language via [[COM Interop]].

COM is similar to other component technologies such as [[IBM System Object Model|SOM]], [[CORBA]] and [[Enterprise JavaBeans]], although each has its strengths and weaknesses.

Unlike [[C++]], COM provides a stable [[application binary interface]] (ABI) that is unaffected by compiler differences.<ref>Microsoft forum: [https://archive.today/20130216110824/http://social.msdn.microsoft.com/Forums/en/vcgeneral/thread/86eda6a7-4d90-4e19-a9d4-6cbe22b661f4 Binary compatibility across Visual C++ versions]</ref> This makes using COM advantageous for object-oriented C++ libraries that are to be used by clients compiled via different compilers.


==History==
==History==

One of the first methods of [[interprocess communication]] in Windows was [[Dynamic Data Exchange]] (DDE),<ref>{{cite web
Introduced in 1987, [[Dynamic Data Exchange]] (DDE) was one of the first [[interprocess communication]] technologies in [[Windows]].<ref>{{cite web
|title=About Network DDE - Windows applications |website=[[Microsoft]].com
|title=About Network DDE - Windows applications |website=[[Microsoft]].com
|url=https://docs.microsoft.com/en-us/windows/desktop/ipc/about-network-dde
|url=https://docs.microsoft.com/en-us/windows/desktop/ipc/about-network-dde
|date=May 30, 2018}}</ref> first introduced in 1987,<ref>{{cite web |website=[[McAfee]].com
|date=May 30, 2018}}</ref><ref>{{cite web |website=[[McAfee]].com
|title=Code Execution Technique Takes Advantage of Dynamic Data Exchange
|title=Code Execution Technique Takes Advantage of Dynamic Data Exchange
|url=https://securingtomorrow.mcafee.com/other-blogs/mcafee-labs/code-execution-technique-takes-advantage-of-dynamic-data-exchange
|url=https://securingtomorrow.mcafee.com/other-blogs/mcafee-labs/code-execution-technique-takes-advantage-of-dynamic-data-exchange
|date=October 27, 2017}}</ref> It allowed sending and receiving messages in so-called ''conversations'' between applications.
|date=October 27, 2017}}</ref> that allowed sending and receiving messages in so-called "conversations" between applications. [[Antony Williams (technologist)|Antony Williams]], who was involved in the creation of the COM architecture, later distributed two internal papers in Microsoft that embraced the concept of software components: ''Object Architecture: Dealing With the Unknown – or – Type Safety in a Dynamically Extensible Class Library'' in 1988 and ''On Inheritance: What It Means and How To Use It'' in 1990. These provided the foundation of many of the ideas behind COM. [[Object Linking and Embedding]] (OLE), Microsoft's first object-based framework, was built on top of DDE and designed specifically for [[compound document]]s. It was introduced with [[Word for Windows]] and [[Microsoft Excel|Excel]] in 1991, and was later included with Windows, starting with version 3.1 in 1992. An example of a compound document is a [[spreadsheet]] embedded in a Word for Windows document: as changes are made to the spreadsheet within Excel, they appear automatically inside the Word document.

Antony Williams, involved in architecting COM, distributed two papers within Microsoft that embraced the concept of software components: ''Object Architecture: Dealing With the Unknown – or – Type Safety in a Dynamically Extensible Class Library'' in 1988 and ''On Inheritance: What It Means and How To Use It'' in 1990. These provided the foundation of many of the ideas behind COM.

[[Object Linking and Embedding]] (OLE), Microsoft's first object-based framework, was built on DDE and designed specifically for [[compound document]]s. It was introduced with [[Microsoft Word|Word]] and [[Microsoft Excel|Excel]] in 1991, and was later included with Windows, starting with version 3.1 in 1992. An example of a compound document is a [[spreadsheet]] embedded in a Word document. As changes are made to the spreadsheet in Excel, they appear automatically in the Word document.

In 1991, Microsoft introduced the [[Visual Basic Extension]] (VBX) technology with [[Visual Basic]] 1.0. A VBX is a packaged extension in the form of a [[dynamic-link library]] (DLL) that allows objects to be graphically placed in a form and manipulated by [[property (programming)|properties]] and [[method (computer science)|methods]]. These were later adapted for use by other languages such as [[Visual C++]].

In 1992, with [[Windows 3.1x|Windows 3.1]], Microsoft released OLE 2 with its new underlying [[object model]], COM. The COM [[application binary interface]] (ABI) was the same as the MAPI ABI (released in 1992), and like it was based on [[MSRPC]] and ultimately on the [[Open Group]]'s [[DCE/RPC]]. COM was created to replace DDE since its text-based conversation and Windows messaging design was not flexible enough to allow sharing application features in a robust and extensible way.

In 1994, the [[OLE custom control]] (OCX) technology, based on COM, was introduced as the successor to VBX. At the same time, Microsoft stated that OLE 2 would be known simply as "OLE".

In early 1996, Microsoft found a new use for OCX {{endash}} extending their web browser's capability. Microsoft renamed some parts of OLE relating to the [[Internet]] as [[ActiveX]], and gradually renamed all OLE technologies to ActiveX, except the compound document technology that was used in [[Microsoft Office]].


In 1991, Microsoft introduced [[Visual Basic Extension]]s (VBX) with [[Visual Basic]] 1.0. A VBX is a packaged extension in the form of a [[dynamic-link library]] (DLL) that allows objects to be graphically placed in a form and manipulated by [[property (programming)|properties]] and [[method (computer science)|methods]]. These were later adapted for use by other languages such as [[Visual C++]]. In 1992, when version [[Windows 3.1x|3.1 of Windows]] was released, Microsoft released OLE 2 with its underlying [[object model]]. The COM [[Application binary interface]] (ABI) was the same as the MAPI ABI (released in 1992), and like it was based on [[MSRPC]] and ultimately on the [[Open Group]]'s [[DCE/RPC]]. While OLE 1 was focused on compound documents, COM and OLE 2 were designed to address software components in general. Text conversations and Windows messages had proved not to be flexible enough to allow sharing application features in a robust and extensible way, so COM was created as a new foundation, and OLE changed to OLE2. In 1994 [[OLE custom control]]s (OCXs) were introduced as the successor to VBX controls. At the same time, Microsoft stated that OLE 2 would just be known as "OLE", and that OLE was no longer an acronym, but a name for all of the company's component technologies. In early 1996, Microsoft found a new use for OLE Custom Controls, expanding their Web browser's capability to present content, renamed some parts of OLE relating to the [[Internet]] "[[ActiveX]]", and gradually renamed all OLE technologies to ActiveX, except the compound document technology that was used in [[Microsoft Office]]. Later that year, Microsoft extended COM to work across the network with [[Distributed Component Object Model|DCOM]].<ref>{{Cite journal|url=https://datatracker.ietf.org/doc/draft-brown-dcom-v1-spec/|title=draft-brown-dcom-v1-spec-03 - Distributed Component Object Model Protocol -- DCOM/1.0|newspaper=Ietf Datatracker|date=March 11, 1998|access-date=2019-08-29|last1=Brown|first1=Nina|last2=Kindel|first2=Charlie}}</ref>
Later in 1996, Microsoft extended COM to work across the network with [[Distributed Component Object Model|DCOM]].<ref>{{Cite journal|url=https://datatracker.ietf.org/doc/draft-brown-dcom-v1-spec/|title=draft-brown-dcom-v1-spec-03 - Distributed Component Object Model Protocol -- DCOM/1.0|newspaper=Ietf Datatracker|date=March 11, 1998|access-date=2019-08-29|last1=Brown|first1=Nina|last2=Kindel|first2=Charlie}}</ref>


==Related technologies==
==Related technologies==
COM was the major software development platform for Windows and, as such, influenced development of a number of supporting technologies. It was likewise heavily influenced by earlier technologies.


===DDE===
===MSRPC===
COM replaced [[Dynamic Data Exchange|DDE]] as the preferred form of interprocess communication.


The COM IDL is based on the feature-rich DCE/RPC IDL, with object-oriented extensions. Microsoft's implementation of DCE/RPC, '''MSRPC''', is used as the primary inter-process communication mechanism for Windows NT services and internal components, making it an obvious choice of foundation.
===[[DCE/RPC]] and [[MSRPC]]===
As a cross-language component model, COM relies on an interface definition language, or IDL, to describe the objects and associated functions. The COM IDL is based heavily on the feature-rich DCE/RPC IDL, with object-oriented extensions. Microsoft's own implementation of DCE/RPC, known as MSRPC, is heavily used as the primary inter-process communication mechanism for Windows NT services and internal components, making it an obvious choice of foundation.


===[[Distributed Component Object Model|DCOM]]===
===DCOM===
{{Main article|Distributed Component Object Model}}
DCOM (''Distributed COM'') extended the reach of COM from merely supporting a single user with separate applications communicating on the Windows desktop, to activating objects running under different security contexts, and on different machines across the network. With this were added necessary features for configuring which users have authority to create, activate and call objects, for identifying the calling user, as well as specifying required encryption for security of calls.

DCOM extends COM from merely supporting a single user with separate applications communicating on the Windows desktop, to activating objects running under different security contexts, and on different machines across the network. With this were added necessary features for configuring which users have authority to create, activate and call objects, for identifying the calling user, as well as specifying required encryption for security of calls.


===COM+===
===COM+===

In order for Microsoft to provide developers with support for [[distributed transaction]]s, resource pooling, disconnected applications, event publication and subscription, better memory and processor (thread) management, as well as to position Windows as an alternative to other enterprise-level operating systems, Microsoft introduced a technology called [[Microsoft Transaction Server]] (MTS) on Windows NT 4. With Windows 2000, that significant extension to COM was incorporated into the operating system (as opposed to the series of external tools provided by [[Microsoft Transaction Server|MTS]]) and renamed '''COM+'''. At the same time, Microsoft de-emphasized [[Distributed Component Object Model|DCOM]] as a separate entity. Components that made use of COM+ services were handled more directly by the added layer of COM+, in particular by operating system support for interception. In the first release of MTS, interception was tacked on - installing an MTS component would modify the [[Windows Registry]] to call the MTS software, and not the component directly. Windows 2000 also revised the Component Services control panel application used to configure COM+ components.
Microsoft introduced [[Microsoft Transaction Server]] (MTS) in Windows NT 4 in order to provide developers with support for [[distributed transaction]]s, resource pooling, disconnected applications, event publication and subscription, better memory and processor (thread) management, as well as to position Windows as an alternative to other enterprise-level operating systems.

Renamed to '''COM+''' in Windows 2000, the feature set was incorporated into the operating system as opposed to the series of external tools provided by MTS. At the same time, Microsoft de-emphasized [[Distributed Component Object Model|DCOM]] as a separate entity. Components that used COM+ were handled more directly by the added layer of COM+; in particular by operating system support for interception. In the first release of MTS, interception was tacked on {{endash}} installing an MTS component would modify the [[Windows Registry]] to call the MTS software, and not the component directly.

Windows 2000 included Component Services control panel updates for configuring COM+ components.


An advantage of COM+ was that it could be run in "component farms". Instances of a component, if coded properly, could be pooled and reused by new calls to its initializing routine without unloading it from memory. Components could also be distributed (called from another machine). COM+ and [[Microsoft Visual Studio]] provided tools to make it easy to generate client-side proxies, so although DCOM was used to make the remote call, it was easy to do for developers. COM+ also introduced a subscriber/publisher event mechanism called '''COM+ Events''', and provided a new way of leveraging [[Microsoft Message Queuing|MSMQ]] (a technology that provides inter-application asynchronous messaging) with components called '''Queued Components'''. COM+ events extend the COM+ programming model to support late-bound (see [[Late binding]]) events or method calls between the publisher or subscriber and the event system.
An advantage of COM+ was that it could be run in "component farms". Instances of a component, if coded properly, could be pooled and reused by new calls to its initializing routine without unloading it from memory. Components could also be distributed (called from another machine). COM+ and [[Microsoft Visual Studio]] provided tools to make it easy to generate client-side proxies, so although DCOM was used to make the remote call, it was easy to do for developers. COM+ also introduced a subscriber/publisher event mechanism called '''COM+ Events''', and provided a new way of leveraging [[Microsoft Message Queuing|MSMQ]] (a technology that provides inter-application asynchronous messaging) with components called '''Queued Components'''. COM+ events extend the COM+ programming model to support late-bound (see [[Late binding]]) events or method calls between the publisher or subscriber and the event system.
Line 65: Line 94:
===.NET===
===.NET===
{{Main|.NET Framework}}
{{Main|.NET Framework}}

Microsoft .NET provides means both to provide component technology, and to interact with COM+ (via COM-interop-assemblies); .NET provides wrappers to most of the commonly used COM controls. Microsoft .NET hides most detail from component creation and therefore eases development. .NET can leverage COM+ via the System.EnterpriseServices namespace, and several of the services that COM+ provides have been duplicated in recent releases of .NET. For example, the System.Transactions namespace in .NET provides the TransactionScope class, which provides transaction management without resorting to COM+. Similarly, [[Queue (data structure)|queued components]] can be replaced by [[Windows Communication Foundation]] with an [[MSMQ]] transport. (MSMQ is a native COM component, however.) There is limited support for backward compatibility. A COM object may be used in .NET by implementing a [[Runtime Callable Wrapper]] (RCW).<ref>{{cite web|url=http://msdn.microsoft.com/en-us/library/8bwh56xe.aspx|title=Runtime Callable Wrapper|last=rpetrusha|website=msdn.microsoft.com}}</ref> NET objects that conform to certain interface restrictions may be used in COM objects by calling a ''COM callable wrapper'' (CCW).<ref>{{cite web|url=http://msdn.microsoft.com/f07c8z1c.aspx|title=COM Callable Wrapper|last=rpetrusha|website=msdn.microsoft.com}}</ref> From both the COM and .NET sides, objects using the other technology appear as native objects. See [[COM Interop]].
'''.NET''' is Microsoft's component technology that supersedes COM. .NET hides many details of component creation and therefore eases development.
[[Windows Communication Foundation|WCF]] (Windows Communication Foundation) eases a number of COM's remote execution challenges. For instance, it allows objects to be transparently marshalled by value across process or machine boundaries more easily.

.NET provides wrappers to commonly used COM controls.

.NET can leverage COM+ via the <code>System.EnterpriseServices</code> namespace, and several of the services that COM+ provides have been duplicated in .NET. For example, the <code>System.Transactions</code> namespace provides the <code>TransactionScope</code> class, which provides transaction management without resorting to COM+. Similarly, [[Queue (data structure)|queued components]] can be replaced by [[Windows Communication Foundation]] (WCF) with an [[MSMQ]] transport.

There is limited support for backward compatibility. A COM object may be used in .NET by implementing a [[Runtime Callable Wrapper]] (RCW).<ref>{{cite web|url=http://msdn.microsoft.com/en-us/library/8bwh56xe.aspx|title=Runtime Callable Wrapper|last=rpetrusha|website=msdn.microsoft.com}}</ref> NET objects that conform to certain interface restrictions may be used in COM objects by calling a ''COM callable wrapper'' (CCW).<ref>{{cite web|url=http://msdn.microsoft.com/f07c8z1c.aspx|title=COM Callable Wrapper|last=rpetrusha|website=msdn.microsoft.com}}</ref> From both the COM and .NET sides, objects using the other technology appear as native objects. See [[COM Interop]].

WCF eases a number of COM's remote execution challenges. For instance, it allows objects to be transparently [[Marshalling (computer science)|marshalled]] by value across process or machine boundaries more easily.


=== Windows Runtime ===
=== Windows Runtime ===
{{Main|Windows Runtime}}
{{Main|Windows Runtime}}
Microsoft's Windows Runtime (or WinRT, not to be confused with [[Windows RT]]) programming and application model is essentially a COM-based API, although it relies on an enhanced COM. Because of its COM-like basis, Windows Runtime allows relatively easy interfacing from multiple languages, just as COM does, but it is essentially an unmanaged, native API. The API definitions are, however, stored in ".winmd" files, which are encoded in ECMA 335 metadata format, the same [[metadata (CLI)|CLI metadata]] format that .NET uses with a few modifications. This common metadata format allows for significantly less overhead than P/Invoke when WinRT is invoked from .NET applications, and its syntax is much simpler.


'''Windows Runtime''' ('''WinRT''') is a COM-based API, albeit an enhanced COM variant. Because of its COM-like basis, WinRT supports interfacing from multiple programming contexts, but it is an unmanaged, native API. The API definitions are stored in ".winmd" files, which are encoded in ECMA 335 metadata format; the same [[metadata (CLI)|CLI metadata]] format that .NET uses with a few modifications. This metadata format allows for significantly lower overhead than P/Invoke when WinRT is invoked from .NET applications.
=== Nano-COM (a.k.a XPCOM) ===

Nano-COM is an extremely small subset of the Component Object Model that is focused exclusively on the Application Binary Interface (ABI) aspects of COM to that enable function and method calls across independently compiled modules/components. Nano-COM can be expressed easily in a single C++ header file that is portable to all C++ compilers. Nano-COM extends the native ABI of the underlying instruction architecture and OS to add support for typed object references (typical ABIs focus only on atomic types, structures, arrays and function calling conventions). The basis of Nano-COM was used by Mozilla to bootstrap Firefox (called [[XPCOM]]), and is currently in use as the base ABI technology for [[DirectX]]/[[Direct3D]]/[[DirectML]].
=== Nano-COM ===

'''Nano-COM''' is a subset of COM focused on the [[application binary interface]] (ABI) aspects of COM that enable function and method calls across independently compiled modules/components. Nano-COM can be expressed in a portable C++ header file. Nano-COM extends the native ABI of the underlying instruction architecture and OS to support typed object references {{endash}} whereas a typical ABI focuses on atomic types, structures, arrays and function calling conventions.


A Nano-COM header file defines or names at least three types:
A Nano-COM header file defines or names at least three types:
* GUID to identify interface types - this is effectively a 128 bit number
*HRESULT to identify error codes from method calls - this is effectively a standardized usage of 32-bit ints to well known values (S_OK, E_FAIL, E_OUTOFMEMORY, etc)
* IUnknown as the base type for all typed object references - this is effectively abstract virtual functions to support <code>dynamic_cast<T></code>-style acquisition of new interface types and ref counting a la <code>shared_ptr<T></code>


* GUID {{endash}} identifies an interface type
Many uses of Nano-COM also define two functions to address callee-allocated memory buffers as results

* <NanoCom>Alloc – called by method implementations to allocate raw buffers (not objects) that are returned to the caller
* HRESULT {{endash}} method result codes such as S_OK, E_FAIL, E_OUTOFMEMORY
* <NanoCom>Free – called by method callers to free callee-allocated buffers once no longer in use

* IUnknown {{endash}} base type for object references; abstract virtual functions to support <code>dynamic_cast<T></code>-style acquisition of new interface types and ref counting a la <code>shared_ptr<T></code>

Many uses of Nano-COM define two functions to address callee-allocated memory buffers as results:

* <NanoCom>Alloc {{endash}} called by method implementations to allocate raw buffers (not objects) that are returned to the caller

* <NanoCom>Free {{endash}} called by method callers to free callee-allocated buffers when no longer in use


Some implementations of Nano-COM such as Direct3D eschew the allocator functions and restrict themselves to only use caller-allocated buffers.
Some implementations of Nano-COM such as Direct3D eschew the allocator functions and restrict themselves to only use caller-allocated buffers.


Nano-COM has no notion of classes, apartments, marshaling, registration, etc. Rather, object references are simply passed across function boundaries and allocated via standard language constructs (e.g., C++ new operator).
Nano-COM has no notion of classes, apartments, marshaling, registration, etc. Rather, object references are simply passed across function boundaries and allocated via standard language constructs (e.g., C++ <code>new</code> operator).

The basis of Nano-COM was used by Mozilla to bootstrap Firefox (called [[XPCOM]]), and is currently in use as the base ABI technology for [[DirectX]]/[[Direct3D]]/[[DirectML]].


==Security==
==Security==
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".<ref>{{cite web |last1=Steinberg |first1=Jill |date=1997-03-01 |df=mdy |url=https://www.infoworld.com/article/2077623/competing-components-make-for-prickly-panelists.html |title=Competing components make for prickly panelists |work=[[JavaWorld]] |access-date=2020-07-16}}</ref> Recent {{when|date=August 2016}} 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 [[code signing|signed]] with [[digital signature]]s 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.


===In Internet Explorer===
==Technical details==

COM programmers build their software using COM-aware [[software componentry|component]]s. Different component types are identified by class IDs (CLSIDs), which are [[Globally Unique Identifier]]s (GUIDs). Each COM component exposes its functionality through one or more [[interface (object-oriented programming)|interface]]s. The different interfaces supported by a component are distinguished from each other using interface IDs (IIDs), which are GUIDs too. COM interfaces have [[language binding|binding]]s in several languages, such as [[C (programming language)|C]], [[C++]], [[Visual Basic]], [[Delphi (programming language)|Delphi]], [[Python (programming language)|Python]]<ref>{{cite web|url=http://docs.activestate.com/activepython/2.4/pywin32/html/com/win32com/HTML/docindex.html|title=win32com Documentation Index|website=docs.activestate.com}}</ref><ref>{{cite web|url=http://www.boddie.org.uk/python/COM.html|title=Python and COM|website=www.boddie.org.uk}}</ref> and several of the scripting languages implemented on the Windows platform. All access to components is done through the [[Method (computer science)|methods]] of the interfaces. This allows techniques such as inter-process, or even inter-computer programming (the latter using the support of DCOM).
Since an ActiveX control (any COM component) runs as native code, with no [[Sandbox_(computer_security)|sandboxing]] protection, there are few restrictions on what it can do. Using ActiveX components, as [[Internet Explorer]] supported, in a web page lead to problems with [[malware]] infections.
Microsoft recognized the problem as far back as 1996 when Charles Fitzgerald said, "We never made the claim up front that ActiveX is intrinsically secure".<ref>{{cite web |last1=Steinberg |first1=Jill |date=1997-03-01 |df=mdy |url=https://www.infoworld.com/article/2077623/competing-components-make-for-prickly-panelists.html |title=Competing components make for prickly panelists |work=[[JavaWorld]] |access-date=2020-07-16}}</ref> Later versions of Internet Explorer prompt the user before installing an ActiveX control, allowing them to block installation.

As a level of protection, an ActiveX control is [[code signing|signed]] with a [[digital signature]] to guarantee authenticity.

It is also possible to disable ActiveX controls altogether, or to allow only a selected few.

===Process corruption===

The transparent support for out-of-process COM servers 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 (computer programming)|pointer]]'' in one subsystem can randomly corrupt other subsystems.

==Binding==

COM is supported via [[language binding|binding]]s in several languages, such as [[C (programming language)|C]], [[C++]], [[Visual Basic]], [[Delphi (programming language)|Delphi]], [[Python (programming language)|Python]]<ref>{{cite web|url=http://docs.activestate.com/activepython/2.4/pywin32/html/com/win32com/HTML/docindex.html|title=win32com Documentation Index|website=docs.activestate.com}}</ref><ref>{{cite web|url=http://www.boddie.org.uk/python/COM.html|title=Python and COM|website=www.boddie.org.uk}}</ref> and several of the Windows scripting contexts. Component access is via interface [[Method (computer science)|methods]]. This allows for direct calling in-process and via the COM/DCOM sub-system access between processes and computers.

==Type system==

===Coclass===

A '''coclass''', a COM class, implements one or more interfaces. It is identified by a class ID, called [[CLSID]] which is [[globally unique identifier|GUID]], and by a [[human-readable]] programmatic identifier, called [[ProgID]]. A coclass is created via one of these identifiers.

===Interface===

Each COM '''interface''' extends the <code>[[IUnknown]]</code> interface, which exposes methods for [[reference counting]] and for accessing the other interfaces of the object {{endash}} similar to [[type conversion]], a.k.a. type casting.

An interface is identified by an interface ID (IID), a GUID.

A '''custom interface''', anything derived from <code>[[IUnknown]]</code>, provides early bound access via a [[Pointer (computer programming)|pointer]] to a [[virtual method table]] that contains a list of pointers to the functions that implement the functions declared in the interface, in the order they are declared. An in-process invocation overhead is, therefore, comparable to a C++ virtual method call.

Dispatching, a.k.a. [[late bound]] access, is provided by implementing <code>[[IDispatch]]</code>. Dispatching allows access from a wider range of programming contexts than a custom interface.

Like many object-oriented languages, COM provides a separation of interface from implementation. This distinction is especially strong in COM where an object has no default interface. A client must request an interface to have any access. COM supports multiple implementations of the same interface, so that clients can choose which implementation of an interface to use.

===Type library===

A COM '''type library''' defines COM metadata, such as coclasses and interfaces. A library can be defined as [[Microsoft Interface Definition Language|Interface definition language]] (IDL); a programming language independent syntax. IDL is similar to C++ with additional syntax for defining interfaces and coclasses. IDL also supports bracketed attributes before declarations to define metadata such as identifiers and relationships between parameters.


An IDL file is compiled via the MIDL compiler. For use with C/C++, the MIDL compiler generates a header file with <code>struct</code> definitions to match the [[virtual method table|vtbl]]s of the declared interfaces and a C file containing declarations of the interface [[Globally Unique Identifier|GUIDs]]. C++ source code for a proxy module can also be generated by the MIDL compiler. This proxy contains method stubs for converting COM calls into [[remote procedure call]]s to enable DCOM for out-of-process communication.
===Interfaces===
All COM components implement the [[IUnknown]] (''custom'') interface, which exposes methods for [[reference counting]] and [[type conversion]] (casting). A ''custom'' IUnknown interface consists of a pointer to a [[virtual method table]] that contains a list of pointers to the functions that implement the functions declared in the interface, in the same order that they are declared in the interface. The in-process invocation overhead is therefore comparable to virtual method calls in [[C++]]. In addition to ''custom'' interfaces, COM also supports ''dispatch'' interfaces inheriting from [[IDispatch]]. Dispatch interfaces support [[late binding]] for [[OLE Automation]]. This allows ''dispatch'' interfaces to be natively accessed from a wider range of programming languages than ''custom'' interfaces.


MIDL can generate a binary type library (TLB) that can be used by other tools to support access from other context.
===Classes===
A COM class ("coclass") is a concrete implementation of one or more interfaces, and closely resembles classes in [[object-oriented programming]] languages. Classes are created based on their class ID ([[CLSID]]) or based on their programmatic identifier string ([[ProgID]]). Like many object-oriented languages, COM provides a separation of interface from implementation. This distinction is especially strong in COM, where objects cannot be accessed directly, but only through their interfaces. COM also has support for multiple implementations of the same interface, so that clients at [[run time (program lifecycle phase)|runtime]] can choose which implementation of an interface to instantiate.


===Examples===
===Interface Definition Language and type libraries===
Type libraries contain metadata to represent COM types. These types are described using [[Microsoft Interface Definition Language]] (MSIDL/IDL). IDL files define object-oriented classes, interfaces, structures, enumerations and other user-defined types in a language independent manner. IDL is similar in appearance to C++ declarations with some additional keywords such as "interface" and "library" for defining interfaces and collections of classes. IDL also supports the use of bracketed attributes before declarations to provide additional information, such as interface GUIDs and the relationships between pointer parameters and length fields. IDL files are compiled by the MIDL [[compiler]]. For C/C++, the MIDL compiler generates a compiler-independent header file containing struct definitions to match the [[virtual method table|vtbl]]s of the declared interfaces and a C file containing declarations of the interface [[Globally Unique Identifier|GUIDs]]. C++ source code for a proxy module can also be generated by the MIDL compiler. This proxy contains method stubs for converting COM calls into [[remote procedure call]]s to enable DCOM for out-of-process communication. IDL files can also be compiled by the MIDL compiler into a type library (TLB). TLB files contain binary metadata that can be processed by different language compilers and runtime environments (e.g. VB, Delphi, .NET etc.) to generate language-specific constructs to represent the COM types defined in the TLB. For C++, this will convert the TLB back to its IDL representation.


The following IDL code declares a coclass named <code>SomeClass</code> which implements an interface named <code>ISomeInterface</code>.
===Object framework===
Because COM is a runtime framework, types have to be individually identifiable and specifiable at runtime. To achieve this, ''globally unique identifiers'' (GUIDs) are used. Each COM type is designated its own GUID for identification at runtime. In order for information on COM types to be accessible at both compile time and runtime, COM uses type libraries. It is through the effective use of ''type libraries'' that COM achieves its capabilities as a dynamic framework for the interaction of objects.


Consider the following example coclass definition in an IDL:
<syntaxhighlight lang="idl">
<syntaxhighlight lang="idl">
coclass SomeClass {
coclass SomeClass {
Line 112: Line 188:
};
};
</syntaxhighlight>
</syntaxhighlight>
The above code fragment declares a COM class named <code>SomeClass</code> which implements an interface named <code>ISomeInterface</code>.


This is conceptually equivalent to defining the following C++ class:
This is conceptually equivalent to the following C++ code where ISomeInterface is a [[pure virtual class]], a.k.a. abstract base class.

<syntaxhighlight lang="cpp">
<syntaxhighlight lang="cpp">
class ISomeInterface {};
class SomeClass : public ISomeInterface {
class SomeClass : public ISomeInterface {
...
...
};
};
</syntaxhighlight>
</syntaxhighlight>
where ISomeInterface is a C++ [[pure virtual class]] (sometimes called an abstract base class).


In C++, COM objects are instantiated via the COM subsystem <code>CoCreateInstance</code> function that takes the CLSID and IID. <code>SomeClass</code> can be created as follows:
The IDL files containing COM interfaces and classes are compiled into type libraries (TLB) files, which can later be parsed by clients at runtime to determine which interfaces an object supports, and invoke an object's interface methods.


In C++, COM objects are instantiated with the <code>CoCreateInstance</code> function that takes the class ID (CLSID) and interface ID (IID) as arguments. Instantiation of <code>SomeClass</code> can be implemented as follows:
<syntaxhighlight lang="cpp">
<syntaxhighlight lang="cpp">
ISomeInterface* interface_ptr = NULL;
ISomeInterface* interface_ptr = NULL;
HRESULT hr = CoCreateInstance(CLSID_SomeClass, NULL, CLSCTX_ALL,
HRESULT hr = CoCreateInstance(CLSID_SomeClass, NULL, CLSCTX_ALL, IID_ISomeInterface, (void**)&interface_ptr);
IID_ISomeInterface, (void**)&interface_ptr);
</syntaxhighlight>
</syntaxhighlight>
In this example, the COM sub-system is used to obtain a pointer to an object that implements <code>ISomeInterface</code> interface, and coclass CLSID_SomeClass's particular implementation of this interface is required.


===Reference counting===
==Reference counting==
All COM objects utilize [[reference counting]] to manage object lifetimes. The reference counts are controlled by the clients through the ''AddRef'' and ''Release'' methods in the mandatory IUnknown interface that all COM objects implement. COM objects are then responsible for freeing their own memory when the reference count drops to zero. Certain languages (e.g. [[Visual Basic]]) provide automatic reference counting so that COM object developers need not explicitly maintain any internal reference counter in their source codes. In C++, a coder may either perform explicit reference counting or use [[smart pointer]]s to automatically manage the reference counts.


A COM object uses [[reference counting]] to manage object lifetime. An object's reference count is controlled by the clients through the <code>IUnknown</code> <code>AddRef</code> and <code>Release</code> methods. COM objects are responsible for freeing their own memory when the reference count drops to zero. Some programming contexts (e.g. [[Visual Basic]]) provide automatic reference counting to simplify object use. In C++, a [[smart pointer]] can be used to automate reference count management.
The following are guidelines for when to call ''AddRef'' and ''Release'' on COM objects:
* Functions and methods that return interface references (via return value or via "out" parameter) shall increment the reference count of the returned object before returning.
* ''Release'' must be called on an interface pointer before the pointer is overwritten or goes out of scope.
* If a copy is made on an interface reference pointer, ''AddRef'' should be called on that pointer.
* ''AddRef'' and ''Release'' must be called on the specific interface which is being referenced since an object may implement per-interface reference counts in order to allocate internal resources only for the interfaces which are being referenced.


The following are guidelines for when to ''AddRef'' and ''Release'' should called:
Not all reference count calls are sent to remote objects over the wire; a proxy keeps only one reference on the remote object and maintains its own local reference count. To simplify COM development, Microsoft introduced [[Active Template Library|ATL (Active Template Library)]] for C++ developers. ATL provides for a higher-level COM development paradigm. It also shields COM client application developers from the need to directly maintain reference counting, by providing [[smart pointer]] objects. Other libraries and languages that are COM-aware include the [[Microsoft Foundation Classes]], the [[Visual C++|VC]] Compiler COM Support,<ref>{{cite web|url=http://msdn.microsoft.com/en-us/library/h31ekh7e.aspx |title=Compiler COM Support|publisher=Microsoft|work=MSDN}}</ref> [[VBScript]], [[Visual Basic 2005 Express Edition|Visual Basic]], [[ECMAScript]] ([[JavaScript]]) and [[Borland Delphi]].


* A functions that returns an interface reference (via return value or via "out" parameter) increments the count of the returned object
===Programming===
COM is a [[Language-independent specification|language agnostic]] binary standard that can be developed in any programming language capable of understanding and implementing its binary defined data types and interfaces. COM implementations are responsible for entering and leaving the COM environment, instantiating and reference-counting COM objects, querying objects for supported interfaces, as well as handling errors. The Microsoft Visual C++ compiler supports extensions to the [[C++]] language referred to as ''C++ Attributes''.<ref>Microsoft MSDN: [http://msdn.microsoft.com/en-US/library/f520z3b3.aspx C++ Attributes Reference]</ref> These extensions are designed to simplify COM development and remove much of the [[boilerplate code]] required to implement COM servers in C++.<ref>MSDN Magazine: [http://msdn.microsoft.com/en-us/magazine/cc301337.aspx C++ Attributes: Make COM Programming a Breeze with New Feature in Visual Studio .NET]</ref>


* ''Release'' is called before the interface pointer is overwritten or goes out of scope
===Registry usage===
In Windows, COM classes, interfaces and type libraries are listed by GUIDs in the [[Windows Registry|registry]], under ''HKEY_CLASSES_ROOT\CLSID'' for classes and ''HKEY_CLASSES_ROOT\Interface'' for interfaces. COM libraries use the registry to locate either the correct local libraries for each COM object or the network location for a remote service.


* If a copy is made on an interface reference pointer, ''AddRef'' is called
===Registration-free COM===

Registration-Free COM (RegFree COM) is a technology introduced with [[Windows XP]] that allows Component Object Model (COM) [[software componentry|components]] to store activation [[metadata]] and CLSID (<code>[[Class (computing)|Class]] ID</code>) for the component without using the [[Windows Registry|registry]]. Instead, the metadata and CLSIDs of the classes implemented in the component are declared in an [[Manifest (CLI)|assembly manifest]] (described using [[XML]]), stored either as a resource in the executable or as a separate file installed with the component.<ref name="msdndocs">{{cite web | url = http://msdn.microsoft.com/en-us/library/aa374219(VS.85).aspx | title = Assembly Manifests | publisher = [[MSDN]] | access-date = 2009-11-05}}</ref> This allows multiple versions of the same component to be installed in different directories, described by their own manifests, as well as [[XCOPY deployment]].<ref name="msdnmag">{{cite web | url = http://msdn.microsoft.com/en-us/magazine/cc188708.aspx | title = Simplify App Deployment with ClickOnce and Registration-Free COM | author = Dave Templin | publisher = [[MSDN]] Magazine | access-date = 2008-04-22}}</ref> This technique has limited support for EXE COM servers<ref>{{cite web | url = https://stackoverflow.com/questions/2369181/how-to-use-an-out-of-process-com-server-without-its-tlb-file | title = How to use an out-of-process COM server without its tlb file | access-date = 2011-04-16}}</ref> and cannot be used for system-wide components such as [[Microsoft Data Access Components|MDAC]], [[MSXML]], [[DirectX]] or [[Internet Explorer]].
* ''AddRef'' and ''Release'' are called on the interface which is being referenced (not a different interface of the same object) since an object may implement per-interface reference counts in order to allocate internal resources only for the interfaces which are being referenced

For remote objects, not all reference count calls are sent over the wire. A a proxy keeps only one reference on the remote object and maintains its own local reference count.

To simplify COM development for C++ developers, Microsoft introduced [[Active Template Library|ATL (Active Template Library)]]. ATL provides a relatively high-level COM development paradigm. It also shields COM client application developers from the need to directly maintain reference counting, by providing [[smart pointer]] types. Other libraries and languages that are COM-aware include the [[Microsoft Foundation Classes]], the [[Visual C++|VC]] Compiler COM Support,<ref>{{cite web|url=http://msdn.microsoft.com/en-us/library/h31ekh7e.aspx |title=Compiler COM Support|publisher=Microsoft|work=MSDN}}</ref> [[VBScript]], [[Visual Basic 2005 Express Edition|Visual Basic]], [[ECMAScript]] ([[JavaScript]]) and [[Borland Delphi]].

==Programming context==

COM is a [[Language-independent specification|language agnostic]] binary standard that allows objects to be used in any programming context able to access its binary interfaces.

COM client software is responsible for enabling the COM sub-system, instantiating and reference-counting COM objects and querying objects for supported interfaces.

The Microsoft Visual C++ compiler supports extensions to the C++ language, referred to as ''C++ Attributes'', <ref>Microsoft MSDN: [http://msdn.microsoft.com/en-US/library/f520z3b3.aspx C++ Attributes Reference]</ref> that are designed to simplify COM development and minimize [[boilerplate code]] required to implement COM servers in C++.<ref>MSDN Magazine: [http://msdn.microsoft.com/en-us/magazine/cc301337.aspx C++ Attributes: Make COM Programming a Breeze with New Feature in Visual Studio .NET]</ref>

==Type metadata storage==

Originally, type library metadata was required to be stored in the system registry. A COM client would use the registry information for object creation.

Registration-free (RegFree) COM was introduced with [[Windows XP]] to allow storing type library metadata as an [[Manifest (CLI)|assembly manifest]] either as a resource in the executable file or in a separate file installed with the component.<ref name="msdndocs">{{cite web | url = http://msdn.microsoft.com/en-us/library/aa374219(VS.85).aspx | title = Assembly Manifests | publisher = [[MSDN]] | access-date = 2009-11-05}}</ref> This allows multiple versions of the same component to be installed on the same computer, in different directories. And it allows for [[XCOPY deployment]].<ref name="msdnmag">{{cite web | url = http://msdn.microsoft.com/en-us/magazine/cc188708.aspx | title = Simplify App Deployment with ClickOnce and Registration-Free COM | author = Dave Templin | publisher = [[MSDN]] Magazine | access-date = 2008-04-22}}</ref> This technology has limited support for EXE COM servers<ref>{{cite web | url = https://stackoverflow.com/questions/2369181/how-to-use-an-out-of-process-com-server-without-its-tlb-file | title = How to use an out-of-process COM server without its tlb file | access-date = 2011-04-16}}</ref> and cannot be used for system-wide components such as [[Microsoft Data Access Components|MDAC]], [[MSXML]], [[DirectX]] or [[Internet Explorer]].


During application loading, the Windows loader searches for the manifest.<ref name="isoconcept">{{cite web | url=https://msdn.microsoft.com/en-us/library/ms235531(v=vs.140).aspx | title = Concepts of Isolated Applications and Side-by-side Assemblies | publisher = [[MSDN]] | access-date = 2016-02-05}}</ref> If it is present, the loader adds information from it to the activation context.<ref name="msdnmag"/> When the COM class factory tries to instantiate a class, the activation context is first checked to see if an implementation for the CLSID can be found. Only if the lookup fails, the [[Windows Registry|registry]] is scanned.<ref name="msdnmag"/>
During application loading, the Windows loader searches for the manifest.<ref name="isoconcept">{{cite web | url=https://msdn.microsoft.com/en-us/library/ms235531(v=vs.140).aspx | title = Concepts of Isolated Applications and Side-by-side Assemblies | publisher = [[MSDN]] | access-date = 2016-02-05}}</ref> If it is present, the loader adds information from it to the activation context.<ref name="msdnmag"/> When the COM class factory tries to instantiate a class, the activation context is first checked to see if an implementation for the CLSID can be found. Only if the lookup fails, the [[Windows Registry|registry]] is scanned.<ref name="msdnmag"/>


A COM object can be created without type library information; with only a path to the [[Dynamic-link library|DLL]] file and CLSID. A client can use the COM DLL function <code>DllGetClassObject</code> with the CLSID and IID_IClassFactory to create an instance of a [[Factory (object-oriented programming)|factory object]]. The client can then use the factory object's <code>CreateInstance</code> to create an instance.<ref>{{cite web|last1=Arkhipov|first1=Mikhail|title=Registration-free COM|url=https://blogs.msdn.microsoft.com/mikhailarkhipov/2005/04/01/registration-free-com/|website=MSDN Blogs|access-date=29 April 2016|date=1 April 2005}}</ref> This is the same process the COM sub-system uses.<ref>{{cite web|title=DllGetClassObject entry point (COM)|url=https://msdn.microsoft.com/en-us/library/windows/desktop/ms680760%28v=vs.85%29.aspx|website=MSDN|quote=If a call to the CoGetClassObject function finds the class object that is to be loaded in a DLL, CoGetClassObject uses the DLL's exported DllGetClassObject function.}}</ref> If an object created this way creates another object, it will do so in the usual way (using the registry or manifest). But it <!--what does it refer to?--> can create internal objects (which may not be registered at all), and hand out references to interfaces to them, using its own private knowledge.
===Manually instantiating COM objects===

COM objects can also be created manually, given the path of the [[Dynamic-link library|DLL]] file and [[GUID]] of the object. This does not require the DLL or GUID to be registered in the system registry, and does not make use of manifest files. A COM DLL exports a function named DllGetClassObject. Calling DllGetClassObject with the desired GUID and IID_IClassFactory provides an instance of a [[Factory (object-oriented programming)|factory object]]. The Factory object has a CreateInstance method, which can create instances of an object given an interface GUID.<ref>{{cite web|last1=Arkhipov|first1=Mikhail|title=Registration-free COM|url=https://blogs.msdn.microsoft.com/mikhailarkhipov/2005/04/01/registration-free-com/|website=MSDN Blogs|access-date=29 April 2016|date=1 April 2005}}</ref> This is the same process internally used when creating instances of registered COM components.<ref>{{cite web|title=DllGetClassObject entry point (COM)|url=https://msdn.microsoft.com/en-us/library/windows/desktop/ms680760%28v=vs.85%29.aspx|website=MSDN|quote=If a call to the CoGetClassObject function finds the class object that is to be loaded in a DLL, CoGetClassObject uses the DLL's exported DllGetClassObject function.}}</ref>
==Marshalling==


A COM object can be transparently be created and used from within the same process (in-process), across process boundaries (out-of-process), or remotely over the network (DCOM). Out-of-process and remote objects use [[serialization|marshalling]] to serialize method calls and return values over process or network boundaries. This marshalling is invisible to the client, which accesses the object as if it were a local in-process object.
If the created COM object instantiates another COM object using the generic CoCreateInstance API, it will try to do so in the usual generic way, using the registry or manifest files. But it can create internal objects (which may not be registered at all), and hand out references to interfaces to them, using its own private knowledge.


==Threading==
===Process and network transparency===
COM objects can be transparently instantiated and referenced from within the same process (in-process), across process boundaries (out-of-process), or remotely over the network (DCOM). Out-of-process and remote objects use [[serialization|marshalling]] to serialize method calls and return values over process or network boundaries. This marshalling is invisible to the client, which accesses the object as if it were a local in-process object.


===Threading===
In COM, threading is addressed through a concept known as ''apartments''.<ref>Microsoft MSDN: [http://msdn.microsoft.com/en-us/library/windows/desktop/ms693344.aspx Processes, Threads, and Apartments]</ref> An individual COM object lives in exactly one apartment, which might either be single-threaded or multi-threaded. There are three types of apartments in COM: ''[[Single threading|Single-Threaded]] Apartment (STA)'', ''Multi-Threaded Apartment (MTA)'', and ''Thread Neutral Apartment'' (NA). Each apartment represents one mechanism whereby an object's internal state may be synchronized across multiple threads. A process can consist of multiple COM objects, some of which may use STA and others of which may use MTA. All threads accessing COM objects similarly live in one apartment. The choice of apartment for COM objects and threads are determined at run-time, and cannot be changed.
In COM, threading is addressed through a concept known as ''apartments''.<ref>Microsoft MSDN: [http://msdn.microsoft.com/en-us/library/windows/desktop/ms693344.aspx Processes, Threads, and Apartments]</ref> An individual COM object lives in exactly one apartment, which might either be single-threaded or multi-threaded. There are three types of apartments in COM: ''[[Single threading|Single-Threaded]] Apartment (STA)'', ''Multi-Threaded Apartment (MTA)'', and ''Thread Neutral Apartment'' (NA). Each apartment represents one mechanism whereby an object's internal state may be synchronized across multiple threads. A process can consist of multiple COM objects, some of which may use STA and others of which may use MTA. All threads accessing COM objects similarly live in one apartment. The choice of apartment for COM objects and threads are determined at run-time, and cannot be changed.


{| class="wikitable"
{| class="wikitable"
|-
|-
! Apartment type!! Description
! Apartment type!!Threading model!!Description
|-
|-
| '''Single-Threaded Apartment'''<ref>Microsoft MSDN: [http://msdn.microsoft.com/en-us/library/windows/desktop/ms680112.aspx Single-Threaded Apartments]</ref> (''STA''), (ThreadingModel=''Apartment'')|| A single thread is dedicated to execute the methods of the object. In such an arrangement, method calls from threads outside of the apartment are [[Marshalling (computer science)|marshalled]] and automatically queued by the system (via a standard Windows message queue). Thus, the COM run-time provides automatic synchronization to ensure that each method call of an object is always executed to completion before another is invoked. The developer therefore does not need to worry about thread locking or race conditions.
| Single-Threaded Apartment<ref>Microsoft MSDN: [http://msdn.microsoft.com/en-us/library/windows/desktop/ms680112.aspx Single-Threaded Apartments]</ref> (STA)
||
Apartment
||
A single thread is dedicated to execute the methods of the object. Method calls from threads outside of the apartment are [[Marshalling (computer science)|marshalled]] and automatically queued by the system (via Windows messaging). Thus, the COM run-time provides synchronization to ensure that each method call to the object is executed to completion before another is invoked.
|-
|-
| '''Multi-Threaded Apartment'''<ref>Microsoft MSDN: [http://msdn.microsoft.com/en-us/library/windows/desktop/ms693421.aspx Multithreaded Apartments]</ref> (''MTA''), (ThreadingModel=''Free'') || The COM run-time provides no synchronization, and multiple threads are allowed to call COM objects simultaneously. COM objects therefore need to perform their own synchronization to prevent simultaneous access from multiple threads from causing a race condition. Calls to an MTA object from a thread in an STA are also marshalled.
| Multi-Threaded Apartment<ref>Microsoft MSDN: [http://msdn.microsoft.com/en-us/library/windows/desktop/ms693421.aspx Multithreaded Apartments]</ref> (MTA)
||
Free
||
The COM run-time provides no synchronization, and multiple threads are allowed to call object methods simultaneously. The object need to handle synchronization to prevent simultaneous access from multiple threads from problems. Calls to an MTA object from a thread in an STA are also marshalled.
|-
|-
| Dynamically determined apartment
| Dynamically determined apartment (ThreadingModel=''Both'') || In the ''Both'' apartment mode, the server auto-selects STA or MTA at object creation to match the apartment type of the calling thread.<ref>Microsoft MSDN: [http://msdn.microsoft.com/en-us/library/ms809971.aspx Understanding and Using COM Threading Models]</ref> This can be useful to avoid marshaling overhead when MTA servers are accessed by a STA thread.
||
Both
||
The server auto-selects STA or MTA at object creation to match the apartment type of the calling thread.<ref>Microsoft MSDN: [http://msdn.microsoft.com/en-us/library/ms809971.aspx Understanding and Using COM Threading Models]</ref> This can be useful to avoid marshalling overhead when MTA servers are accessed by a STA thread.
|-
|-
| Thread Neutral Apartment (NA)
| '''Thread Neutral Apartment''' (''NA''), (ThreadingModel=''Neutral'')|| A special apartment without any assigned threads. When an STA or MTA thread calls an NA object in the same process, then the calling thread temporarily leaves its apartment and executes code directly in the NA without any thread switching.<ref>Codeguru: [http://www.codeguru.com/cpp/com-tech/activex/apts/article.php/c5529/Understanding-COM-Apartments-Part-I.htm Understanding COM Apartments]</ref> Therefore, one can think of NA as an optimization for efficient interapartment method calls.
||
Neutral
||
A special apartment without any assigned threads. When an STA or MTA thread calls an NA object in the same process, then the calling thread temporarily leaves its apartment and executes code directly in the NA without any thread switching.<ref>Codeguru: [http://www.codeguru.com/cpp/com-tech/activex/apts/article.php/c5529/Understanding-COM-Apartments-Part-I.htm Understanding COM Apartments]</ref> Therefore, one can think of NA as an optimization for efficient interapartment method calls.
|}
|}


Line 182: Line 280:


==Criticisms==
==Criticisms==
{{Unreferenced section|date=January 2024}}
Since COM has a fairly complex implementation, programmers can be distracted by some of the "plumbing" issues.

===Complexity===
COM is relatively complex especially compared to more modern component technologies such as .NET.


===Message pumping===
===Message pumping===
Line 194: Line 295:


==See also==
==See also==
* {{Annotated link|Calling convention}}
* [[Portable object (computing)]] cross language cross platform Object Model definition
* {{Annotated link|Common Language Infrastructure}}
* [[Distributed Component Object Model]] (DCOM), extension making COM able to work in networks
* {{Annotated link|D-Bus}}
* [[Common Language Infrastructure]] current .NET cross language cross platform Object Model
* {{Annotated link|Foreign function interface}}
* [[Windows Runtime]], an application model, evolved version of COM targeting [[Windows 8]]
* {{Annotated link|Internet Communications Engine}}
* [[CORBA]] Common Object Request Broker Architecture, open cross language cross platform object model
* {{Annotated link|Java remote method invocation}}
* [[D-Bus]] open cross language cross platform Object Model
* {{Annotated link|KDE Frameworks}}
* [[KParts]] [[KDE]] component framework
* {{Annotated link|Name mangling}}
* [[IBM System Object Model|SOM]] IBM System Object Model, feature-rich alternative to COM
* {{Annotated link|Portable object (computing)}}
* [[XPCOM]] Mozilla applications cross Platform Component Object Model
* {{Annotated link|SWIG}}
* [[Enterprise JavaBeans]]
* [[Java Remote Method Invocation]]
* [[Internet Communications Engine]]
* [[Language binding]]
* [[Foreign function interface]]
* [[Calling convention]]
* [[Name mangling]]
* [[Application programming interface]] - API
* [[Application Binary Interface]] - ABI
* [[SWIG]] opensource automatic interfaces bindings generator from many languages to other languages


==Notes==
==Notes==
Line 218: Line 310:


==References==
==References==
*{{cite web | title=COM: A Brief Introduction (powerpoint) | url=http://alumni.cs.ucr.edu/~dberger/Documents/Presentations/com-intro.ppt | access-date=March 7, 2006 }}
*{{cite web |title=COM: A Brief Introduction (powerpoint) |url=http://alumni.cs.ucr.edu/~dberger/Documents/Presentations/com-intro.ppt |access-date=March 7, 2006 |type=Direct link to PowerPoint (PPT) file}}
*{{cite book | last=Box | first=Don | author-link=Don Box | title=Essential COM | publisher=Addison-Wesley | year=1998 | isbn=978-0-201-63446-4 | url=https://archive.org/details/essentialcom00boxd }}
*{{cite book | last=Box | first=Don | author-link=Don Box | title=Essential COM | publisher=Addison-Wesley | year=1998 | isbn=978-0-201-63446-4 | url=https://archive.org/details/essentialcom00boxd }}
*{{cite book | last = Chappell | first = David | title = Understanding ActiveX and OLE | publisher = Microsoft Press | year = 1996 | isbn = 978-1-57231-216-6 | url = https://archive.org/details/understandingact00chap }}
*{{cite book | last = Chappell | first = David | title = Understanding ActiveX and OLE | publisher = Microsoft Press | year = 1996 | isbn = 978-1-57231-216-6 | url = https://archive.org/details/understandingact00chap }}
Line 228: Line 320:
*[http://support.microsoft.com/kb/159621/en-us Info: Difference Between OLE Controls and ActiveX Controls] from Microsoft
*[http://support.microsoft.com/kb/159621/en-us Info: Difference Between OLE Controls and ActiveX Controls] from Microsoft
*[http://theircorp.byethost11.com/index.php?vw=TypeLib TypeLib Data Format Specification (unofficial)] with open source dumper utility.
*[http://theircorp.byethost11.com/index.php?vw=TypeLib TypeLib Data Format Specification (unofficial)] with open source dumper utility.
*[https://web.archive.org/web/20090215185257/http://innovatia.com/software/papers/com.htm The COM / DCOM Glossary]
*[https://web.archive.org/web/20090215185257/http://innovatia.com/software/papers/com.htm The COM / DCOM Glossary] (archive.org)


{{Microsoft APIs}}
{{Microsoft APIs}}

Revision as of 04:12, 28 June 2024

COM
Component Object Model
AbbreviationCOM
StatusIn force
First published1993; 31 years ago (1993)
Latest versionLiving standard
2021
OrganizationMicrosoft
SeriesSystem Services
Base standardsMIDL, UUID
Related standards
DomainComponent Interfacing
Websitelearn.microsoft.com/en-us/windows/win32/com/the-component-object-model

Component Object Model (COM) is a binary-interface technology for software components from Microsoft that enables using objects in a language-neutral way between different programming languages, programming contexts, processes and machines.

COM is the basis for other Microsoft domain specific component technologies including OLE, OLE Automation, ActiveX, COM+, and DCOM as well as implementations such as DirectX, Windows shell, UMDF, Windows Runtime, and Browser Helper Object.

COM enables object use with only knowing its interface; not its internal implementation. The component implementer defines interfaces that are separate from the implementation.

Support for multiple programming contexts is handled by relying on the object for aspects that would be challenging to implement as a facility. Supporting multiple uses of an object is handled by requiring each object to destroy itself via reference-counting. Access to an object's interfaces (similar to Type conversion) is provided by each object as well.

COM is available only in Microsoft Windows and Apple's Core Foundation 1.3 and later plug-in application programming interface (API).[1] The latter only implements a subset of the whole COM interface.[2]

Over time, COM is being replaced with other technologies such as Microsoft .NET and web services (i.e. via WCF). However, COM objects can be used in a .NET language via COM Interop.

COM is similar to other component technologies such as SOM, CORBA and Enterprise JavaBeans, although each has its strengths and weaknesses.

Unlike C++, COM provides a stable application binary interface (ABI) that is unaffected by compiler differences.[3] This makes using COM advantageous for object-oriented C++ libraries that are to be used by clients compiled via different compilers.

History

Introduced in 1987, Dynamic Data Exchange (DDE) was one of the first interprocess communication technologies in Windows.[4][5] It allowed sending and receiving messages in so-called conversations between applications.

Antony Williams, involved in architecting COM, distributed two papers within Microsoft that embraced the concept of software components: Object Architecture: Dealing With the Unknown – or – Type Safety in a Dynamically Extensible Class Library in 1988 and On Inheritance: What It Means and How To Use It in 1990. These provided the foundation of many of the ideas behind COM.

Object Linking and Embedding (OLE), Microsoft's first object-based framework, was built on DDE and designed specifically for compound documents. It was introduced with Word and Excel in 1991, and was later included with Windows, starting with version 3.1 in 1992. An example of a compound document is a spreadsheet embedded in a Word document. As changes are made to the spreadsheet in Excel, they appear automatically in the Word document.

In 1991, Microsoft introduced the Visual Basic Extension (VBX) technology with Visual Basic 1.0. A VBX is a packaged extension in the form of a dynamic-link library (DLL) that allows objects to be graphically placed in a form and manipulated by properties and methods. These were later adapted for use by other languages such as Visual C++.

In 1992, with Windows 3.1, Microsoft released OLE 2 with its new underlying object model, COM. The COM application binary interface (ABI) was the same as the MAPI ABI (released in 1992), and like it was based on MSRPC and ultimately on the Open Group's DCE/RPC. COM was created to replace DDE since its text-based conversation and Windows messaging design was not flexible enough to allow sharing application features in a robust and extensible way.

In 1994, the OLE custom control (OCX) technology, based on COM, was introduced as the successor to VBX. At the same time, Microsoft stated that OLE 2 would be known simply as "OLE".

In early 1996, Microsoft found a new use for OCX – extending their web browser's capability. Microsoft renamed some parts of OLE relating to the Internet as ActiveX, and gradually renamed all OLE technologies to ActiveX, except the compound document technology that was used in Microsoft Office.

Later in 1996, Microsoft extended COM to work across the network with DCOM.[6]

MSRPC

The COM IDL is based on the feature-rich DCE/RPC IDL, with object-oriented extensions. Microsoft's implementation of DCE/RPC, MSRPC, is used as the primary inter-process communication mechanism for Windows NT services and internal components, making it an obvious choice of foundation.

DCOM

DCOM extends COM from merely supporting a single user with separate applications communicating on the Windows desktop, to activating objects running under different security contexts, and on different machines across the network. With this were added necessary features for configuring which users have authority to create, activate and call objects, for identifying the calling user, as well as specifying required encryption for security of calls.

COM+

Microsoft introduced Microsoft Transaction Server (MTS) in Windows NT 4 in order to provide developers with support for distributed transactions, resource pooling, disconnected applications, event publication and subscription, better memory and processor (thread) management, as well as to position Windows as an alternative to other enterprise-level operating systems.

Renamed to COM+ in Windows 2000, the feature set was incorporated into the operating system as opposed to the series of external tools provided by MTS. At the same time, Microsoft de-emphasized DCOM as a separate entity. Components that used COM+ were handled more directly by the added layer of COM+; in particular by operating system support for interception. In the first release of MTS, interception was tacked on – installing an MTS component would modify the Windows Registry to call the MTS software, and not the component directly.

Windows 2000 included Component Services control panel updates for configuring COM+ components.

An advantage of COM+ was that it could be run in "component farms". Instances of a component, if coded properly, could be pooled and reused by new calls to its initializing routine without unloading it from memory. Components could also be distributed (called from another machine). COM+ and Microsoft Visual Studio provided tools to make it easy to generate client-side proxies, so although DCOM was used to make the remote call, it was easy to do for developers. COM+ also introduced a subscriber/publisher event mechanism called COM+ Events, and provided a new way of leveraging MSMQ (a technology that provides inter-application asynchronous messaging) with components called Queued Components. COM+ events extend the COM+ programming model to support late-bound (see Late binding) events or method calls between the publisher or subscriber and the event system.

.NET

.NET is Microsoft's component technology that supersedes COM. .NET hides many details of component creation and therefore eases development.

.NET provides wrappers to commonly used COM controls.

.NET can leverage COM+ via the System.EnterpriseServices namespace, and several of the services that COM+ provides have been duplicated in .NET. For example, the System.Transactions namespace provides the TransactionScope class, which provides transaction management without resorting to COM+. Similarly, queued components can be replaced by Windows Communication Foundation (WCF) with an MSMQ transport.

There is limited support for backward compatibility. A COM object may be used in .NET by implementing a Runtime Callable Wrapper (RCW).[7] NET objects that conform to certain interface restrictions may be used in COM objects by calling a COM callable wrapper (CCW).[8] From both the COM and .NET sides, objects using the other technology appear as native objects. See COM Interop.

WCF eases a number of COM's remote execution challenges. For instance, it allows objects to be transparently marshalled by value across process or machine boundaries more easily.

Windows Runtime

Windows Runtime (WinRT) is a COM-based API, albeit an enhanced COM variant. Because of its COM-like basis, WinRT supports interfacing from multiple programming contexts, but it is an unmanaged, native API. The API definitions are stored in ".winmd" files, which are encoded in ECMA 335 metadata format; the same CLI metadata format that .NET uses with a few modifications. This metadata format allows for significantly lower overhead than P/Invoke when WinRT is invoked from .NET applications.

Nano-COM

Nano-COM is a subset of COM focused on the application binary interface (ABI) aspects of COM that enable function and method calls across independently compiled modules/components. Nano-COM can be expressed in a portable C++ header file. Nano-COM extends the native ABI of the underlying instruction architecture and OS to support typed object references – whereas a typical ABI focuses on atomic types, structures, arrays and function calling conventions.

A Nano-COM header file defines or names at least three types:

  • GUID – identifies an interface type
  • HRESULT – method result codes such as S_OK, E_FAIL, E_OUTOFMEMORY
  • IUnknown – base type for object references; abstract virtual functions to support dynamic_cast<T>-style acquisition of new interface types and ref counting a la shared_ptr<T>

Many uses of Nano-COM define two functions to address callee-allocated memory buffers as results:

  • <NanoCom>Alloc – called by method implementations to allocate raw buffers (not objects) that are returned to the caller
  • <NanoCom>Free – called by method callers to free callee-allocated buffers when no longer in use

Some implementations of Nano-COM such as Direct3D eschew the allocator functions and restrict themselves to only use caller-allocated buffers.

Nano-COM has no notion of classes, apartments, marshaling, registration, etc. Rather, object references are simply passed across function boundaries and allocated via standard language constructs (e.g., C++ new operator).

The basis of Nano-COM was used by Mozilla to bootstrap Firefox (called XPCOM), and is currently in use as the base ABI technology for DirectX/Direct3D/DirectML.

Security

In Internet Explorer

Since an ActiveX control (any COM component) runs as native code, with no sandboxing protection, there are few restrictions on what it can do. Using ActiveX components, as Internet Explorer supported, in a web page lead to problems with malware infections. Microsoft recognized the problem as far back as 1996 when Charles Fitzgerald said, "We never made the claim up front that ActiveX is intrinsically secure".[9] Later versions of Internet Explorer prompt the user before installing an ActiveX control, allowing them to block installation.

As a level of protection, an ActiveX control is signed with a digital signature to guarantee authenticity.

It is also possible to disable ActiveX controls altogether, or to allow only a selected few.

Process corruption

The transparent support for out-of-process COM servers 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.

Binding

COM is supported via bindings in several languages, such as C, C++, Visual Basic, Delphi, Python[10][11] and several of the Windows scripting contexts. Component access is via interface methods. This allows for direct calling in-process and via the COM/DCOM sub-system access between processes and computers.

Type system

Coclass

A coclass, a COM class, implements one or more interfaces. It is identified by a class ID, called CLSID which is GUID, and by a human-readable programmatic identifier, called ProgID. A coclass is created via one of these identifiers.

Interface

Each COM interface extends the IUnknown interface, which exposes methods for reference counting and for accessing the other interfaces of the object – similar to type conversion, a.k.a. type casting.

An interface is identified by an interface ID (IID), a GUID.

A custom interface, anything derived from IUnknown, provides early bound access via a pointer to a virtual method table that contains a list of pointers to the functions that implement the functions declared in the interface, in the order they are declared. An in-process invocation overhead is, therefore, comparable to a C++ virtual method call.

Dispatching, a.k.a. late bound access, is provided by implementing IDispatch. Dispatching allows access from a wider range of programming contexts than a custom interface.

Like many object-oriented languages, COM provides a separation of interface from implementation. This distinction is especially strong in COM where an object has no default interface. A client must request an interface to have any access. COM supports multiple implementations of the same interface, so that clients can choose which implementation of an interface to use.

Type library

A COM type library defines COM metadata, such as coclasses and interfaces. A library can be defined as Interface definition language (IDL); a programming language independent syntax. IDL is similar to C++ with additional syntax for defining interfaces and coclasses. IDL also supports bracketed attributes before declarations to define metadata such as identifiers and relationships between parameters.

An IDL file is compiled via the MIDL compiler. For use with C/C++, the MIDL compiler generates a header file with struct definitions to match the vtbls of the declared interfaces and a C file containing declarations of the interface GUIDs. C++ source code for a proxy module can also be generated by the MIDL compiler. This proxy contains method stubs for converting COM calls into remote procedure calls to enable DCOM for out-of-process communication.

MIDL can generate a binary type library (TLB) that can be used by other tools to support access from other context.

Examples

The following IDL code declares a coclass named SomeClass which implements an interface named ISomeInterface.

coclass SomeClass {
  [default] interface ISomeInterface;
};

This is conceptually equivalent to the following C++ code where ISomeInterface is a pure virtual class, a.k.a. abstract base class.

class ISomeInterface {};
class SomeClass : public ISomeInterface {
};

In C++, COM objects are instantiated via the COM subsystem CoCreateInstance function that takes the CLSID and IID. SomeClass can be created as follows:

ISomeInterface* interface_ptr = NULL;
HRESULT hr = CoCreateInstance(CLSID_SomeClass, NULL, CLSCTX_ALL, IID_ISomeInterface, (void**)&interface_ptr);

Reference counting

A COM object uses reference counting to manage object lifetime. An object's reference count is controlled by the clients through the IUnknown AddRef and Release methods. COM objects are responsible for freeing their own memory when the reference count drops to zero. Some programming contexts (e.g. Visual Basic) provide automatic reference counting to simplify object use. In C++, a smart pointer can be used to automate reference count management.

The following are guidelines for when to AddRef and Release should called:

  • A functions that returns an interface reference (via return value or via "out" parameter) increments the count of the returned object
  • Release is called before the interface pointer is overwritten or goes out of scope
  • If a copy is made on an interface reference pointer, AddRef is called
  • AddRef and Release are called on the interface which is being referenced (not a different interface of the same object) since an object may implement per-interface reference counts in order to allocate internal resources only for the interfaces which are being referenced

For remote objects, not all reference count calls are sent over the wire. A a proxy keeps only one reference on the remote object and maintains its own local reference count.

To simplify COM development for C++ developers, Microsoft introduced ATL (Active Template Library). ATL provides a relatively high-level COM development paradigm. It also shields COM client application developers from the need to directly maintain reference counting, by providing smart pointer types. Other libraries and languages that are COM-aware include the Microsoft Foundation Classes, the VC Compiler COM Support,[12] VBScript, Visual Basic, ECMAScript (JavaScript) and Borland Delphi.

Programming context

COM is a language agnostic binary standard that allows objects to be used in any programming context able to access its binary interfaces.

COM client software is responsible for enabling the COM sub-system, instantiating and reference-counting COM objects and querying objects for supported interfaces.

The Microsoft Visual C++ compiler supports extensions to the C++ language, referred to as C++ Attributes, [13] that are designed to simplify COM development and minimize boilerplate code required to implement COM servers in C++.[14]

Type metadata storage

Originally, type library metadata was required to be stored in the system registry. A COM client would use the registry information for object creation.

Registration-free (RegFree) COM was introduced with Windows XP to allow storing type library metadata as an assembly manifest either as a resource in the executable file or in a separate file installed with the component.[15] This allows multiple versions of the same component to be installed on the same computer, in different directories. And it allows for XCOPY deployment.[16] This technology has limited support for EXE COM servers[17] and cannot be used for system-wide components such as MDAC, MSXML, DirectX or Internet Explorer.

During application loading, the Windows loader searches for the manifest.[18] If it is present, the loader adds information from it to the activation context.[16] When the COM class factory tries to instantiate a class, the activation context is first checked to see if an implementation for the CLSID can be found. Only if the lookup fails, the registry is scanned.[16]

A COM object can be created without type library information; with only a path to the DLL file and CLSID. A client can use the COM DLL function DllGetClassObject with the CLSID and IID_IClassFactory to create an instance of a factory object. The client can then use the factory object's CreateInstance to create an instance.[19] This is the same process the COM sub-system uses.[20] If an object created this way creates another object, it will do so in the usual way (using the registry or manifest). But it can create internal objects (which may not be registered at all), and hand out references to interfaces to them, using its own private knowledge.

Marshalling

A COM object can be transparently be created and used from within the same process (in-process), across process boundaries (out-of-process), or remotely over the network (DCOM). Out-of-process and remote objects use marshalling to serialize method calls and return values over process or network boundaries. This marshalling is invisible to the client, which accesses the object as if it were a local in-process object.

Threading

In COM, threading is addressed through a concept known as apartments.[21] An individual COM object lives in exactly one apartment, which might either be single-threaded or multi-threaded. There are three types of apartments in COM: Single-Threaded Apartment (STA), Multi-Threaded Apartment (MTA), and Thread Neutral Apartment (NA). Each apartment represents one mechanism whereby an object's internal state may be synchronized across multiple threads. A process can consist of multiple COM objects, some of which may use STA and others of which may use MTA. All threads accessing COM objects similarly live in one apartment. The choice of apartment for COM objects and threads are determined at run-time, and cannot be changed.

Apartment type Threading model Description
Single-Threaded Apartment[22] (STA)

Apartment

A single thread is dedicated to execute the methods of the object. Method calls from threads outside of the apartment are marshalled and automatically queued by the system (via Windows messaging). Thus, the COM run-time provides synchronization to ensure that each method call to the object is executed to completion before another is invoked.

Multi-Threaded Apartment[23] (MTA)

Free

The COM run-time provides no synchronization, and multiple threads are allowed to call object methods simultaneously. The object need to handle synchronization to prevent simultaneous access from multiple threads from problems. Calls to an MTA object from a thread in an STA are also marshalled.

Dynamically determined apartment

Both

The server auto-selects STA or MTA at object creation to match the apartment type of the calling thread.[24] This can be useful to avoid marshalling overhead when MTA servers are accessed by a STA thread.

Thread Neutral Apartment (NA)

Neutral

A special apartment without any assigned threads. When an STA or MTA thread calls an NA object in the same process, then the calling thread temporarily leaves its apartment and executes code directly in the NA without any thread switching.[25] Therefore, one can think of NA as an optimization for efficient interapartment method calls.

Threads and objects which belong to the same apartment follow the same thread access rules. Method calls which are made inside the same apartment are therefore performed directly without any assistance from COM. Method calls made across apartments are achieved via marshalling. This requires the use of proxies and stubs.

Criticisms

Complexity

COM is relatively complex especially compared to more modern component technologies such as .NET.

Message pumping

When an STA is initialized it creates a hidden window that is used for inter-apartment and inter-process message routing. This window must have its message queue regularly "pumped". This construct is known as a "message pump". On earlier versions of Windows, failure to do so could cause system-wide deadlocks. This problem is complicated by some Windows APIs that initialize COM as part of their implementation, which causes a "leak" of implementation details.

Reference counting

Reference counting within COM may cause problems if two or more objects are circularly referenced. The design of an application must take this into account so that objects are not left orphaned. Objects may also be left with active reference counts if the COM "event sink" model is used. Since the object that fires the event needs a reference to the object reacting to the event, the latter's reference count will never reach zero. Reference cycles are typically broken using either out-of-band termination or split identities. In the out-of-band termination technique, an object exposes a method which, when called, forces it to drop its references to other objects, thereby breaking the cycle. In the split identity technique, a single implementation exposes two separate COM objects (also known as identities). This creates a weak reference between the COM objects, preventing a reference cycle.

DLL Hell

Because in-process COM components are implemented in DLL files and registration only allows for a single version per CLSID, they might in some situations be subject to the "DLL Hell" effect. Registration-free COM capability eliminates this problem for in-process components; registration-free COM is not available for out-of-process servers.

See also

Notes

  1. ^ "Documentation Archive". developer.apple.com.
  2. ^ "Plug-ins and Microsoft's COM". Apple Inc. Retrieved October 5, 2010.
  3. ^ Microsoft forum: Binary compatibility across Visual C++ versions
  4. ^ "About Network DDE - Windows applications". Microsoft.com. May 30, 2018.
  5. ^ "Code Execution Technique Takes Advantage of Dynamic Data Exchange". McAfee.com. October 27, 2017.
  6. ^ Brown, Nina; Kindel, Charlie (March 11, 1998). "draft-brown-dcom-v1-spec-03 - Distributed Component Object Model Protocol -- DCOM/1.0". Ietf Datatracker. Retrieved August 29, 2019.
  7. ^ rpetrusha. "Runtime Callable Wrapper". msdn.microsoft.com.
  8. ^ rpetrusha. "COM Callable Wrapper". msdn.microsoft.com.
  9. ^ Steinberg, Jill (March 1, 1997). "Competing components make for prickly panelists". JavaWorld. Retrieved 2020-07-16.
  10. ^ "win32com Documentation Index". docs.activestate.com.
  11. ^ "Python and COM". www.boddie.org.uk.
  12. ^ "Compiler COM Support". MSDN. Microsoft.
  13. ^ Microsoft MSDN: C++ Attributes Reference
  14. ^ MSDN Magazine: C++ Attributes: Make COM Programming a Breeze with New Feature in Visual Studio .NET
  15. ^ "Assembly Manifests". MSDN. Retrieved November 5, 2009.
  16. ^ a b c Dave Templin. "Simplify App Deployment with ClickOnce and Registration-Free COM". MSDN Magazine. Retrieved April 22, 2008.
  17. ^ "How to use an out-of-process COM server without its tlb file". Retrieved April 16, 2011.
  18. ^ "Concepts of Isolated Applications and Side-by-side Assemblies". MSDN. Retrieved February 5, 2016.
  19. ^ Arkhipov, Mikhail (April 1, 2005). "Registration-free COM". MSDN Blogs. Retrieved April 29, 2016.
  20. ^ "DllGetClassObject entry point (COM)". MSDN. If a call to the CoGetClassObject function finds the class object that is to be loaded in a DLL, CoGetClassObject uses the DLL's exported DllGetClassObject function.
  21. ^ Microsoft MSDN: Processes, Threads, and Apartments
  22. ^ Microsoft MSDN: Single-Threaded Apartments
  23. ^ Microsoft MSDN: Multithreaded Apartments
  24. ^ Microsoft MSDN: Understanding and Using COM Threading Models
  25. ^ Codeguru: Understanding COM Apartments

References