After winning the war against the Longhorn team, the Windows team picked up their .NET ideas and reimplemented them in COM.
So since Windows Vista the large majority of new Windows APIs got implemented as COM.
With the Windows 8 release, an improved COM was released as WinRT, which basically picked up on the ideas of COM Runtime before it got redone as CLR.
After that we got UAP with 8.1 release, as the phone, tablet and desktop APIs got a bit closer.
Then with Windows 10, we UWP as the whole set of APIs (IoT, phone, tablet, desktop and XBox) got the same common base.
Every single Windows 10 release has been closing the distance between legacy Win32 and modern UWP, bringing the models together and merging the sandbox models (old style Win32 and UWP).
At BUILD 2019, Microsoft also announced that they will be rewriting React Native for Windows on top of UWP.
Meanwhile C++/CX was deprecated, and thanks to the work lead by Kenny Kerr, it got replaced by C++/WinRT, a C++17 compliant framework for doing UWP programming on Windows (aka Modern COM).
BUILD 2019: "Meet C++/WinRT 2.0: Faster and smarter in the open"
If you're looking for a gentle and free introduction to COM and a few other component and object models, you could do worse than my thesis from 2009 (licensed under a Creative Commons license):
When Ericsson's cell phone business split into Ericsson Mobile Platforms (EMP) and Sony Ericsson (SEMC) back in 2001, they created an object model named Ericsson Component Model (ECM/OPA), which was heavily inspired by COM. The intent was to create an API separating the lower-level Ericsson software from the user-facing software developed by Sony Ericsson.
Sony Ericsson then expanded upon ECM, calling it ECM Extended (or ECMX, though the technology was universally known as "IDL" internally). ECMX was supposed to enable their aging software stack to be modularized by providing an object model for code written in C.
For the future, though, they wanted to switch to writing application code in Java. Back in these feature phone days, Java games were written to Sun Microsystems's MIDlet specification. Sony Ericsson expanded upon that specification and created the SEMClet specification for their internally-developed applications. By writing software in Java and not C, Sony Ericsson not only wanted to use a modern, garbage-collected language, they also wanted to break free of their monolith. All native code was linked together statically as this monolith, and this process could take hours. MIDlets and by extension SEMClets could be installed dynamically, significantly streamlining development.
ECMX was the technology used to enable SEMClets to communicate with native code. If you're familiar with Mozilla and XPCOM, this may all sound very familiar -- and you'd be right.
All this was back in 2005, when I did my thesis work as part of Sony Ericsson's software architecture group. As part of that work, I had to figure out what COM was, what it really meant for COM to be a binary standard (and how that differed from the approach taken by CORBA) and how all that fit together with the Java component model OSGi, .NET assemblies and ECM/ECMX. I felt that I had to have a handle on all that history in order to write my thesis.
None of this is very fashionable today, but I still think that there's a lot we can learn from this era.
Reading about COM really takes me back to my VisualBasic (classic) days. I was an inexperienced teenager at the time, and I remember the excitement I'd get when browsing through the different COM controls I could add to my projects, picking some just to see what they did and trying to figure out how to use them (pre-Google and mostly didn't have internet at home at the time). Learning to make my own COM controls and distribute them was highly instructional, if also maddening at times when trying to get the right version of a .DLL registered and installed.
I was 11, but I managed to make a HTML page which played Shrek trailer from filesystem on loop (with audio of course) and mount that as wallpaper in Windows 98. Frontpage, IIRC.
> Object enabling technology consisting of an simple yet elegant object model and a lightweight runtime support system sufficient for implementing language-independent objects on virtually any platform that supports dynamic linking.
I don't know about elegant, but circa 2001, I ported some COM objects to Linux, including enough of the surrounding Win32 API's to make it work. I had a fake registry based on text files, with CoCreateClass and all that junk working. The shared libs continued to have a DllMain, and DllCanUnloadnow and so on.
Don Box wrote an excellent in-depth book about COM: "Essential COM": "Nobody explains COM better than Don Box" -Charlie Kindel, COM Guy, Microsoft Corporation.
Here's a synopsis of COM I wrote in response to "Can someone link to a synopsis describing what "COM" is? It's hard to search for. (e.g. microsoft com visual studio)":
Don't get me wrong: I'm not advocating everybody jump on the COM bandwagon! I just think it's interesting and useful to know where it came from, how it evolved, what different layers were built on top of it, and how it compared to the alternatives at the time it was designed. And it's still pretty widely used, and will probably never go away.
It certainly had a lot of problems and limitations, and OLE/ActiveX/DCOM/DirectX/etc took it way too far, then Mozilla XP/COM cloned it and also took it way too far (and then back again: see "decomification" and "decomtamination"), but it really was a pretty elegant and successful solution to the problems it was designed to address at the time.
There's also a (deliberately provocative) bit Rob Pike wrote - "There has been much talk about component architectures but only one true success: Unix pipes"
These symbolic devices enable arbitrary pairs of procedures to talk to each other as buffered input-output devices. Each file on any of these "core link" devices represents a 200 word area, most of which is buffer, which may be simultaneously open for reading, writing, both or neither. The files are identified by two regular file names and a system name [Sec 2.2, 2.2.3]. Only one procedure at a time may have a core link open to write or read on one channel. All standard modes are available.
The CLO (Core Link Open) device may be used to open any core link file and (whether reading or writing) will create one if none exists with the name used. The CLU (Core Link Use) device is identical except that an .OPEN on it will fail if the referenced file does not already exist.
Core link "files" have some peculiar properties. When writing a core link, a procedure will hang if the buffer is full and will write an end-of-file mark outside of the data stream when it closes the channel it has the file open on. However, opening and writing again the same file name essentially pushes a new block of data into the pipeline to be removed by a reading procedure. A procedure reading a core link can not read past an end-of-file and must close and reopen the file if it suspects that there is more to follow. If a reading procedure closes a core link before encountering an end-of-file, remaining information until the end-of-file is ignored. Core link "files" cease to exist only if empty and open for neither reading nor writing or not empty and not open for from two to four minutes. In the later case they are expunged by the system job [Sec 6.5] to unclutter the system.
The CLI (Core Link Interrupt) device may only be opened to write. The two file names specified should be the UNAME and JNAME [Sec 5.1] of a procedure in the system with the CLI interrupt [Sec 4.2] enabled. If ther is no existing core link with the file names and system name used, the .OPEN will succeed in creating a link and interrupting the specified procedure. In addition ITS inserts in the created link two words of information as the start of the first file. These are the UNAME and JNAME of the .OPEN'ing procedure.
The CLA (Core Link Answer) device is to be used in response to a CLI interrupt. It may only be opened for reading and scans through all existing links for one with file names the same as the UNAME and JNAME [Sec 5.1] of the procedure doing the CLA open. If one is found not already open for reading, the .OPEN succeeds.
The following is some sample code (complete with documentation) that I found in my notes and thought might be helpful:
;;; Notes about CLI interrupts:
;;;
;;; A CLI interrupt is what happens when another job sends to yours. It is
;;; normally the case that other jobs will send directly to a user's HACTRN.
;;; If, however, Lisp is interrupted by a CLI message, it can elect to handle
;;; handle the interrupt in an arbitrary way.
;;;
;;; To define a handler, two things must be done:
;;; [1] Place the name of the handler function (function of one arg)
;;; in the variable CLI-MESSAGE.
;;; [2] Enable CLI handling with (SSTATUS CLI T)
;;;
;;; The handler should take a single argument which it probably should ignore
;;; since I have no idea what it is likely to be.
;;;
;;; The handler should open the file "CLA:" in (CLA BLOCK) mode and immediately
;;; discard the first 8 characters which will be garbage.
;;;
;;; The remainder of the stream, until a control-C or an eof, will be the text
;;; of the message sent. It may be read with TYI, READ, etc. and handled
;;; however.
(eval-when (eval compile)
(cond ((not (get 'iota 'version))
(load "liblsp;iota"))))
(defun handle-cli-msg (ignore)
(iota ((stream '((cla)) '(cla block)))
(do ((i 0 (1+ i))) ((= i 8)) (tyi stream))
(do ((c (tyi stream -1) (tyi stream -1)))
((or (= c -1) (= c 3)))
(format t "~&~3,'0O ~@:C~%" c c)))) ;print out chars seen
(setq cli-message 'handle-cli-msg)
(sstatus cli t)
; --------
(defun eval-cli-msg (ignore) ;alternate handler
(iota ((stream '((cla)) '(block cla)))
(do ((i 0 (1+ i))) ((= i 8)) (tyi stream))
(do ((f (read stream nil) (read stream nil)))
((null f))
(errset (eval f) nil)))) ;Quietly evaluate forms...
;; Assumes the other lisp will have EVAL-CLI-MSG as value of CLI-MESSAGE
(defun eval-in-other-lisp (uname jname s-expression)
(iota ((stream `((cli) ,uname ,jname) '(out ascii block)))
(print s-expression stream)))
SYS-DEATH Value NIL
This is a silly framing, but I'll bite: All Chromium and Gecko browsers are based on Unix pipes (and Windows named pipes) for IPC. Chrome and Firefox together bring in billions of dollars of advertising revenue.
Right. Note that at the time Gecko was initially developed, it wasn't at all clear that JS would win. Having to support VBScript in addition to JS was a very real possibility. So COM made a certain amount of sense as a way to expose Web APIs to multiple languages simultaneously.
Thankfully, the Web avoided VBScript, and later Dart.
Given market share of Chrome, WebAssembly and Flutter, you should hold on to that "thankfully".
Also from BUILD React Native talks regarding React Native vs Electron performance on Windows, I wouldn't be surprised if VSCode eventually moves away from Electron into React Native.
"First there were VBXs. Then there were OCXs. Then, Microsoft wanted us to call them OLE Custom Controls, but we persisted in calling them OCXs. So they must have figured that we wouldn't accept any control technology that didn't have a name ending in X." -Curt Hagenlocher
COM is pretty much alive on the Windows world.
After winning the war against the Longhorn team, the Windows team picked up their .NET ideas and reimplemented them in COM.
So since Windows Vista the large majority of new Windows APIs got implemented as COM.
With the Windows 8 release, an improved COM was released as WinRT, which basically picked up on the ideas of COM Runtime before it got redone as CLR.
After that we got UAP with 8.1 release, as the phone, tablet and desktop APIs got a bit closer.
Then with Windows 10, we UWP as the whole set of APIs (IoT, phone, tablet, desktop and XBox) got the same common base.
Every single Windows 10 release has been closing the distance between legacy Win32 and modern UWP, bringing the models together and merging the sandbox models (old style Win32 and UWP).
At BUILD 2019, Microsoft also announced that they will be rewriting React Native for Windows on top of UWP.
Meanwhile C++/CX was deprecated, and thanks to the work lead by Kenny Kerr, it got replaced by C++/WinRT, a C++17 compliant framework for doing UWP programming on Windows (aka Modern COM).
BUILD 2019: "Meet C++/WinRT 2.0: Faster and smarter in the open"
https://www.youtube.com/watch?v=X41j_gzSwOY
If you're looking for a gentle and free introduction to COM and a few other component and object models, you could do worse than my thesis from 2009 (licensed under a Creative Commons license):
http://www.polberger.se/components/read/
When Ericsson's cell phone business split into Ericsson Mobile Platforms (EMP) and Sony Ericsson (SEMC) back in 2001, they created an object model named Ericsson Component Model (ECM/OPA), which was heavily inspired by COM. The intent was to create an API separating the lower-level Ericsson software from the user-facing software developed by Sony Ericsson.
Sony Ericsson then expanded upon ECM, calling it ECM Extended (or ECMX, though the technology was universally known as "IDL" internally). ECMX was supposed to enable their aging software stack to be modularized by providing an object model for code written in C.
For the future, though, they wanted to switch to writing application code in Java. Back in these feature phone days, Java games were written to Sun Microsystems's MIDlet specification. Sony Ericsson expanded upon that specification and created the SEMClet specification for their internally-developed applications. By writing software in Java and not C, Sony Ericsson not only wanted to use a modern, garbage-collected language, they also wanted to break free of their monolith. All native code was linked together statically as this monolith, and this process could take hours. MIDlets and by extension SEMClets could be installed dynamically, significantly streamlining development.
ECMX was the technology used to enable SEMClets to communicate with native code. If you're familiar with Mozilla and XPCOM, this may all sound very familiar -- and you'd be right.
All this was back in 2005, when I did my thesis work as part of Sony Ericsson's software architecture group. As part of that work, I had to figure out what COM was, what it really meant for COM to be a binary standard (and how that differed from the approach taken by CORBA) and how all that fit together with the Java component model OSGi, .NET assemblies and ECM/ECMX. I felt that I had to have a handle on all that history in order to write my thesis.
None of this is very fashionable today, but I still think that there's a lot we can learn from this era.
Reading about COM really takes me back to my VisualBasic (classic) days. I was an inexperienced teenager at the time, and I remember the excitement I'd get when browsing through the different COM controls I could add to my projects, picking some just to see what they did and trying to figure out how to use them (pre-Google and mostly didn't have internet at home at the time). Learning to make my own COM controls and distribute them was highly instructional, if also maddening at times when trying to get the right version of a .DLL registered and installed.
Was going to write exactly the same thing!
I was 11, but I managed to make a HTML page which played Shrek trailer from filesystem on loop (with audio of course) and mount that as wallpaper in Windows 98. Frontpage, IIRC.
> Object enabling technology consisting of an simple yet elegant object model and a lightweight runtime support system sufficient for implementing language-independent objects on virtually any platform that supports dynamic linking.
I don't know about elegant, but circa 2001, I ported some COM objects to Linux, including enough of the surrounding Win32 API's to make it work. I had a fake registry based on text files, with CoCreateClass and all that junk working. The shared libs continued to have a DllMain, and DllCanUnloadnow and so on.
One thing from SOM that made me envy was that SOM had metaclasses, just like Smalltalk, so it was possible to do some interesting designs.
COM Type libraries and now UWP metadata aren't really the same.
This article comparing SOM and COM was written by Don Box. (first archived in January 1999, but doesn't say when published):
The Component Object Model and Some Other Model: A comparison of technologies revisited yet again:
https://web.archive.org/web/19990127184653/http://www.develo...
https://en.wikipedia.org/wiki/Component_Object_Model
It was in response to IBM's somewhat misleading article comparing their SOM with Microsoft COM, last updated July 1994:
The System Object Model (SOM) and the Component Object Model (COM): A comparison of technologies summarized
https://web.archive.org/web/19990117055950/http://www.develo...
https://en.wikipedia.org/wiki/IBM_System_Object_Model
Don Box wrote an excellent in-depth book about COM: "Essential COM": "Nobody explains COM better than Don Box" -Charlie Kindel, COM Guy, Microsoft Corporation.
https://en.wikipedia.org/wiki/Don_Box
https://archive.org/details/essentialcom00boxd
Unfortunately COM had the most un-googlable name possible (even before there was a Google), so Microsoft renamed it ActiveX.
For more comtext, here are some notes I wrote about Win32, COM, OLE, OLE Controls, and ActiveX in 1996:
https://donhopkins.com/home/interval/pluggers/win32.html
https://donhopkins.com/home/interval/pluggers/com.html
https://donhopkins.com/home/interval/pluggers/ole.html
https://donhopkins.com/home/interval/pluggers/olecontrols.ht...
https://donhopkins.com/home/interval/pluggers/activex.html
Here's a synopsis of COM I wrote in response to "Can someone link to a synopsis describing what "COM" is? It's hard to search for. (e.g. microsoft com visual studio)":
https://news.ycombinator.com/item?id=12975257
Don't get me wrong: I'm not advocating everybody jump on the COM bandwagon! I just think it's interesting and useful to know where it came from, how it evolved, what different layers were built on top of it, and how it compared to the alternatives at the time it was designed. And it's still pretty widely used, and will probably never go away.
It certainly had a lot of problems and limitations, and OLE/ActiveX/DCOM/DirectX/etc took it way too far, then Mozilla XP/COM cloned it and also took it way too far (and then back again: see "decomification" and "decomtamination"), but it really was a pretty elegant and successful solution to the problems it was designed to address at the time.
https://wiki.mozilla.org/Gecko:DeCOMtamination
https://news.ycombinator.com/item?id=12968830
https://bugzilla.mozilla.org/buglist.cgi?query_format=specif...
It's always good to study history to avoid repeating the mistakes of the past!
WebAssembly is going through a similar evolution, and might benefit from some of the lessons of COM and SOM.
> Unfortunately COM had the most un-googlable name possible (even before there was a Google), so Microsoft renamed it ActiveX.
All ActiveX components are COM components, but the opposite is not true.
Don Box wrote an excellent in-depth book about COM: "Essential COM"
It's on my desk right now, I was relatively inexperienced when I first read it so I thought it might be worth another look 15 years later.
There's also a (deliberately provocative) bit Rob Pike wrote - "There has been much talk about component architectures but only one true success: Unix pipes"
ITS had "Core Link Interrupts" for sending messages between processes and implementing cool features like "EVAL-IN-OTHER-LISP":
https://web.archive.org/web/20110720170137/http://www.sigfs....
3.4.3 The CLA, CLI, CLO and CLU Devices
These symbolic devices enable arbitrary pairs of procedures to talk to each other as buffered input-output devices. Each file on any of these "core link" devices represents a 200 word area, most of which is buffer, which may be simultaneously open for reading, writing, both or neither. The files are identified by two regular file names and a system name [Sec 2.2, 2.2.3]. Only one procedure at a time may have a core link open to write or read on one channel. All standard modes are available.
The CLO (Core Link Open) device may be used to open any core link file and (whether reading or writing) will create one if none exists with the name used. The CLU (Core Link Use) device is identical except that an .OPEN on it will fail if the referenced file does not already exist.
Core link "files" have some peculiar properties. When writing a core link, a procedure will hang if the buffer is full and will write an end-of-file mark outside of the data stream when it closes the channel it has the file open on. However, opening and writing again the same file name essentially pushes a new block of data into the pipeline to be removed by a reading procedure. A procedure reading a core link can not read past an end-of-file and must close and reopen the file if it suspects that there is more to follow. If a reading procedure closes a core link before encountering an end-of-file, remaining information until the end-of-file is ignored. Core link "files" cease to exist only if empty and open for neither reading nor writing or not empty and not open for from two to four minutes. In the later case they are expunged by the system job [Sec 6.5] to unclutter the system.
The CLI (Core Link Interrupt) device may only be opened to write. The two file names specified should be the UNAME and JNAME [Sec 5.1] of a procedure in the system with the CLI interrupt [Sec 4.2] enabled. If ther is no existing core link with the file names and system name used, the .OPEN will succeed in creating a link and interrupting the specified procedure. In addition ITS inserts in the created link two words of information as the start of the first file. These are the UNAME and JNAME of the .OPEN'ing procedure.
The CLA (Core Link Answer) device is to be used in response to a CLI interrupt. It may only be opened for reading and scans through all existing links for one with file names the same as the UNAME and JNAME [Sec 5.1] of the procedure doing the CLA open. If one is found not already open for reading, the .OPEN succeeds.
https://www.reddit.com/r/programming/comments/t4rre/common_l...
http://www.maclisp.info/pitmanual/system.html
The following is some sample code (complete with documentation) that I found in my notes and thought might be helpful:
Hah. One could probably make a decent (with [in]conclusiveness to taste) Worse is Better case study out of this.
COM has been a success on Windows.
Plenty of companies live from selling ready made components to integrate into Windows applications.
How many are making a business from selling UNIX pipes?
This is a silly framing, but I'll bite: All Chromium and Gecko browsers are based on Unix pipes (and Windows named pipes) for IPC. Chrome and Firefox together bring in billions of dollars of advertising revenue.
Ironically, Firefox is also based on XP/COM (though less and less over time, thanks to deCOMification and deCOMtamination).
Right. Note that at the time Gecko was initially developed, it wasn't at all clear that JS would win. Having to support VBScript in addition to JS was a very real possibility. So COM made a certain amount of sense as a way to expose Web APIs to multiple languages simultaneously.
Thankfully, the Web avoided VBScript, and later Dart.
Given market share of Chrome, WebAssembly and Flutter, you should hold on to that "thankfully".
Also from BUILD React Native talks regarding React Native vs Electron performance on Windows, I wouldn't be surprised if VSCode eventually moves away from Electron into React Native.
> Given market share of Chrome, WebAssembly and Flutter, you should hold on to that "thankfully".
WebAssembly doesn't need COM because it's integrated into the JS engine and uses the same JS engine bindings.
I don't think anyone, even Googlers, seriously thinks that native Dart is going to make it onto the Web at this point.
Chrome never used COM as part of its implementation.
My reply had nothing to do with it.
Naturally from Mozilla's employee point of view it is easier to ignore what I actually meant.
Doesn't look like selling software components to me.
"First there were VBXs. Then there were OCXs. Then, Microsoft wanted us to call them OLE Custom Controls, but we persisted in calling them OCXs. So they must have figured that we wouldn't accept any control technology that didn't have a name ending in X." -Curt Hagenlocher