Staring into the COM Abyss
cmpct.info
cmpct.info
I know MS technology was never popular in SV, but people never even looked at it, which to me is weird when developers spend a lot of time investigating other languages and frameworks.
Anyway its mostly dead now I guess, except for these random archaeological digs.
WinRT/UWP is just COM improved to support generics and .NET types.
It is pretty much alive despite not being popular in SV, and it is also how iDevices drivers work actually.
I know where you're coming from, given Longhorn's original history as an effort to implement part of Windows on .Net, but it's still interesting to see it cast this way.
Without getting too deep into the gory details, COM was originally the implementation technology for OLE 2.0, with the CLR being a combination of efforts to replace COM and compete with Java/JVM. (At least partially in response to the Sun lawsuit over Microsoft's attempts to extend Java directly.)
Hence why many .NET configuration flags still have COM prefix to this day.
Also check the C++/COM Hilo project released for Vista, and updated for Windows 7 release
> Anyway its mostly dead now I guess, except for these random archaeological digs.
Far from dead. All new windows stuff is built on top of extended COM.
DCOM was a couple of orders of magnitude more fiddly to get working. But amazing once it worked. Create an object on another server, call its methods, side effects happen on that server, results are returned to your process.
When I was learning Go the similarity between COM interfaces and Go interfaces really helped me grok them quicker.
So in the infamous Windows XP SP2 (not a major release of the operating system, but a mere service pack), DCOM got locked down hard. If you have a legitimate use for DCOM (like an OPC-DA server), you have to toggle several obscure settings to make it work again (see https://www-bd.fnal.gov/controls/opc/Using_OPC_via_DCOM_with... for a fourteen-page tutorial).
DCOM was deeply misguided as a model for distributed programming. When you look at an actually functioning system, you realize that network transparency at the programming level is possibly the worst thing you can do. Can you imagine how web pages would work under a DCOM model?
Aargh. For a while I maintained an app which embedded IE (technically "IHTMLDocument2") on Windows CE, which meant dealing with a lot of this madness. It spawned all kinds of background threads and didn't take kindly to being interrupted, and control over it was limited - ended up drawing a window over its control bar and passing clicks through ourselves.
He mentions "the cultural defeat of Microsoft", which is absolutely right; developers no longer choose the Windows platform, they are only ever forced to by circumstance, and have developed tools like Electron which allow them to ignore the platform entirely.
For whatever reason, the "developer community" of Microsoft was very weak, at least post-dotcom era. You couldn't find many people talking about it openly to learn from. And only recently have they responded to that, especially with Roslyn and the buyout of Github.
I was thinking along the same lines. WSL looks like a half-hearted and late attempt to put some POSIX lipstick on the Windows pig, but for me at least it doesn't really stick. The implementation is as messy and intransparent as usual in Windows. When I have to use Windows, Cygwin is still my tool of choice to make the system usable at all.
There's a third wart, the path length limit of 260 characters. Work on that seems to already be in progress: https://docs.microsoft.com/pt-br/archive/blogs/jeremykuhne/n... (though I see no mention of a related and more annoying wart, which is not allowing some simple file names like "aux.c").
Don't expect AUX, COM1, etc to be fixed any time soon, because that is a huge backwards compatibility issue.
I think that this is also possible to fix. Always require the colon ('CON:' instead of 'CON'), and make this opt-in per process, like "longPathAware".
Sure, old apps will choke if you now create a CON file. But 1) the file dialogs could show a warning when doing that, 2) you can already create filenames that make old apps choke and 3) they could transparently show them as CON~1 or something in those old apps.
Not sure about CR-only, but Notepad only recently-ish (a year ago, perhaps) gained the ability to work with LF-only text files. Mind you, that's probably not a fix in Notepad, but really in the decades-old Win32 edit control ... (which might give a hint as to why this was neither much of a priority, nor probably an easy fix while not breaking anything else).
Meanwhile a whole community of competing free alternatives appeared - students learnt Java and Python because C# was a paid product that was also not cross platform.
With .Net core you can get by with never touching VS. But that wasn’t always the case.
I also don’t believe MS had a free livense of Visual Studio like they do now.
Package never arrived, so I got him to re-send it. Got the discs a few weeks later.
Some time later I got a call from the RCMP -- Canadian version of the FBI. They wanted me to come to their detachment and answer some questions. When I showed up they took me into an interrogation room and told me they had seized the CD-Rs at the border, that software piracy was a big deal and he had been instructed by his superiors to "make an example out of someone."
They wanted to know who sent them, how I got in contact with him, how much I had paid him, and a lot of other questions. I was 19 and scared shitless. I had seen the warnings at the beginning of Hollywood movies, I should have asked for a lawyer but didn't.
I gave a statement and signed it. I told them that the guy had re-sent the discs and I received them, what should I do? They told me to bring the discs in, and I did.
Never heard from them again. No criminal record. I have no idea what happened behind the scenes, but I thank my lucky stars that I wasn't charged with copyright infringement.
I'm not trying to paint this as some kind of Les Miserables bread-loaf-stealing tragedy, but I am beyond ecstatic at the wealth of free software development tools available to anyone with a $400 laptop.
Also the Windows SDK was always available for free, just you needed to get a C compiler yourself.
Not quite _always_... For the first few versions of Windows, the SDK was a fairly expensive separate product you had to buy in addition to the compilers itself. I'm pretty sure it was MS C/C++ 7 that was first available bundled with the SDK. IIRC, the product was $700-800 (in 1990 money), took a couple feet of shelf space, and shipped with seven or eight thousand pages of documentation.
Visual C++ (really MS C/C++ _8_) democratized it a bunch by shipping with the libraries/tools needed to develop for Windows and offering a basic product at a <$200 price point. That was also the first version of Microsoft C that shipped with a Windows-based debugging UI.
The early 90's also saw the introduction of MSDN - the Microsoft Developer Network. At the time, this was a subscription CD based library of essentially all of Microsoft's developer documentation (as well as a few tools, etc.) It was essential... and to put the timeline in perspective, Microsoft sold a version of MSDN that was bundled with a CD-ROM drive, since they were as uncommon as they were at the time. They quickly added a premium version of MSDN that got you the full tooling also.
Ten or fifteen years after all that, the full version of Visual Studio was a $10k/seat proposition. Between that and all of the API churn, they lost sight of their original goal of staying developer friendly, and it was to their deteriment. (Particularly given the concurrent ascendence of the Web, OS X, Mobile, Linux, and the like.)
Back in the 90's I used to be the custodian and curator of our great big box of MSDN CD's ensuring that updates and replacements were properly seen to. Oh the memories :)
In fairness you didn't just get the development tools, you also got copies of just about every MS server and office product on what were fairly generous developer licenses. Many of these things didn't even require phoning home for "activation" and MS turned a blind eye to partners sharing one copy amongst 10-15 devs; after all the real money was where the fruit of our efforts would be deployed, stuff running in banks and other corporates paying serious coin for server licenses and direct support. Ultimately all this stuff was about capturing developers mindsets with a view to selling production licenses.
It didn't start out that way... they added a premium level later, and that was the version that included all the free tooling. I still have volumes 3 and 5 (April 1993 and Fall 1993), and it's a single CD product that was mostly focused on just the documentation. (This is actually how I got my first CD-ROM drive... IIRC, the whole package, a one year subscription and a proprietary interface CD-ROM was $400).
Have been developing for Windows and UNIX flavors ever since.
Windows has been always developer friendly from my point of view, more so than UNIX ever was, then again I guess we have different points of view what being developer friendly actually means.
> I guess we have different points of view what being developer friendly actually means.
We may be in more agreement than you suspect, for what it's worth - I think it's mainly a matter of timing. The development community, including Borland, pivoted from OS/2 to Windows right around the 1990 release of 3.0. That forced Microsoft to open up a lot of the tooling required to compile Windows binaries. (IIRC, the effort was something like Open Tools, and there was also ToolHelp, which was Microsoft's way of opening up Win16 debugger support that had been previously proprietary.) This was a big part of the reason that companies like Borland could ship products that let you code for Windows without an SDK.
Prior to that point... 1985-1989/90, the situation was a lot more closed and tools like the SDK were extra cost add ons.
As for Windows 1.0 - 2.0, which is the time frame you are talking about, Windows did not matter at all. We only cared about MS-DOS and compatibles.
And on MS-DOS, their Pascal and C offerings were quite lousy when compared with the competition, so we were gladly giving money to TMT, Borland, Nanuteck, Gardens Point, Watcom.
They were also ironically the last C compiler vendor for MS-DOS to add support for C++, the very last edition of their compiler for MS-DOS, Microsoft C/C++ v7.
And in what concerns freely available, MS-DOS did not had any SDK, so yeah we had to pay for a book with the BIOS and Int 21h documentation, like PC Systems Internals.
Doubly so if you are a newcomer to programming.
In theory, it's just price discrimination; put features that are only valuable to enterprise customers in the $6k/year version, and profit. But then they put key UX features which are useful to _everyone_, like Live Unit Testing, in the Enterprise version too.
The upshot is that they sell a few more Enterprise licenses, but the development experience is worse for 99% of .NET developers on Windows. It's such a weird contrast to their developer tooling strategy in every other area.
Most countries have Microsoft sponsored education programs and all big software shops have MSDN subscriptions anyway.
So it's really amazing to see giving step-by-step examples of how a namespace extension could be implemented.
I remember in particular that MS Outlook implemented their desktop icon as a namespace extension instead of an ordinary shortcut. I never understand why it was done this way, as the icon didn't behave particularly different than a normal shortcut: The only practical differences were that it did not allow you to look up the exe path and that you could not remove it from the desktop short of uninstalling Outlook.
I wonder if this was done purely for nerd cred in much the same manner as the author of the OP - or if some overzealous manager had an irrational fear of users deleting the "Outlook" icon and ordered their team to do anything in their power prevent that...
I’ve always been annoyed that all the major OSes have all this GUI-shell-level virtual folders and namespaces stuff, but none of them bother to “push it down” such that it’s accessible by the command-line, or better, by syscalls.
I feel it would have made a lot of sense to do this in Windows: just replace “shell” objects with NT kernel objects, and allow the writing of (userland) NT-kernel-object-namespace extensions. Like FUSE, but without the filesystem part.
COM was always the real api for interacting with the desktop environment/shell, even from cli applications. The problem is that COM is strictly object oriented (unlike the user32 api and co) but both C and C++ used the same bindings to interface with it, which were written at the lowest common denominator giving us C++ com wrappers were ugly as hell when they could have been so much nicer. Microsoft finally fixed that in the past couple of years with the new winrt api for C++ but the world would have been different if such COM bindings for C++ had existed twenty years ago.
C++/CX was the closer that they got to it, and it remains to be seen how much complains are they willing to keep taking until C++/WinRT matches C++/CX tooling.
And I fully agree with you, C++ Builder and also Delphi have proven that such bindings were already possible 20 years ago, but for whatever reason there are some key devs (or management) at Microsoft that keeps pushing back for such productivity and brings out stuff like ATL/WRL instead.
I like COM/UWP, but boy some of the decisions just don't make sense.
Decoupling is good; but this isn't just decoupling, it's encapsulation. The problem with graphical "shells" / userland object systems is that they treat the OS kernel as something to run on top of — to abstract away and mostly ignore — rather than something to implement themselves in terms of. The shell isn't described to the kernel in a way where shell objects are in any way "visible" or "accessible" to the kernel. Instead, in the major OSes, shell state (shell objects, namespaces, etc.) lives only in the shell; as far as the kernel is concerned, it doesn't exist.
Now, I have no opinion on whether shell state should actually "live" in the shell, vs. in the kernel (or in kernel-accessible subsystems, if we're talking microkernels.) It's probably better engineering-wise to keep shell-level state in userland.
But the kernel should still be able to interact with that userland shell state. The shell should be built such that it's easy for the kernel to enumerate and manipulate its objects. And the kernel should be built to know about the stable abstractions that make up the shell object runtime.
Where we are today, with shells opaque to kernel understanding:
• The Windows CLI sees my Windows network shares, and mounted drives from disk extensions, but not my Windows shell namespaces, nor my volume-ID-only mounts
• The macOS Finder can treat bundles as files (for e.g. copy/move operations, atomic backup, last-accessed versioning, etc.), but the BSD CLI just sees .bundle directories and needs special help to emulate the Finder approach
• Windows and macOS both treat directories containing only file-reified shell-level metadata (Desktop.ini/Thumbs.db, .DS_Store, AppleDouble files) as "empty" for purposes of preview / overwrite / merge / safe deletion – but their CLIs don't
• Both Windows and GNOME allow me to browse within compressed files, but only when going through the shell, not through the CLI, and not even when going through older APIs like Win16
• The Linux binfmt_misc driver needs shebang lines, despite the existence of file extensions, MIME-type xattrs, and shell file-association preferences tables
• Files marked as "quarantined" in macOS just look like regular files in the CLI, and no CLI program chokes on them, allowing scripted operations against such files to get quite deep in, until they hit some Cocoa-enabled subtask like codesign(8) that suddenly chokes on the quarantined input
I'm not totally sure on what a good solution to all this would look like, but I imagine it'd look like a replacement of all the custom kernel-to-userland callback APIs with a sort of "kernel-supported COM" where the kernel can talk to userland processes as if it were just another userland process making a COM request; and then the kernel can end up holding onto userland process COM object proxy-handles, passing them around, putting them into other kernel structs, etc.
Ideally, I think, the kernel would be responsible for declaring the contracts/interfaces that all shells running on that OS must implement themselves in terms of. Then "shell objects" would just be pure-userland kernel objects (i.e. defined by kernel base-classes, but with no kernel code in their codepath at runtime), sort of like Linux vDSOs are pure-userland kernel drivers.
Linux isn't really "ready" for this change—there are some gnarly legacy kernel-structs that need to retain their shapes and semantics, due to them being directly userland-visible without an intermediate view layer. But WinNt could totally do this, implemented almost entirely in terms of opaque kernel-object handles as it is. Nt-level structs don't matter one whit to userland, so they're free to be changed to retain opaque shell-level references. (I believe this was part of Midori's design?)
- reference counting
- string incompatibilities, exacerbated by the tendency of every man and his dog at Microsoft with an internet audience writing their own COM string class for C++ and publishing it; IIRC BSTR, _bstr_t, CCOMBStr but there were surely others, none of which really succeeded in bridging the very large gap that exists between what COM things a string should look like (length encoded at the front, two bytes per char) and the C / C++ view.
Oh, and there is Python scripting in there somewhere too.
Ungh.
Favorite “COM-ism”: IClassFactory, the basic interface to a class. Why not call it IClass? Or IFactory since a class is essentially a Factory pattern? IClassFactory makes it sound like a Factory for Classes, not objects.
With an interface like AddRef/Release, they all but guarantee memory leaks.
Developers that know what they are doing would use a C++ library with support for COM smart pointers, .NET or Delphi.
So I would end up wrapping the objects in IDisposable and calling Marshal.ReleaseComObject on Dispose. Then COM objects were usually wrapped in using() to remain idiomatic for manual cleanup in c#.
That was some years ago.
Nowadays we don't typically build desktop applications and even when we do we typically employ cross-platform technologies. So COM has pretty much fallen by the wayside - which isn't a bad thing! We've moved on.
Everything old is new again.
This is how we used to write code, back in the day. If you had a particularly hard time and experimentation wasn't working well, you traced through the disassembly in the debugger.
Has that changed by now?
[0] https://devblogs.microsoft.com/oldnewthing/20061218-01/?p=28...
The advice is still "don't use .NET managed code for your in-proc shell extension", but the given reasons are not necessarily specific to the .NET runtime:
1. The .NET framework CLR takes too long to load for an extension that could be loaded by any app that pops up shell UIs.
2. There are seams between .NET and COM even with interop. These seams open traps for you because the COM-era shell APIs (Windows 95 to Windows 7) were designed for people who write their shell extensions in C++ and so can deal with all the tricky details of COM.
https://docs.microsoft.com/en-us/archive/msdn-magazine/2009/...
Also note that Windows development team doesn't have that much .NET love (owned by DevTools).
Don't even get me started on the Java wrappers for ArcObjects... Thank god things have moved on.