The result of Microsoft developers in the 90s drunkenly making up an object model on top of C with the goal of it being cross-language and cross-platform (in theory). The idea being that you can define an interface and implement it in any language and consume it in any language. A good idea in theory. In practice, DLL hell often made the experience unpleasant. A big part of Windows's APIs are COM-based. For historical reasons it's also used at the core of a few macOS system components, hence the grandparent comment
COM is the main way Windows APIs are exposed since Windows Vista, as the .NET ideas for Longhorn were rebooted as COM.
While plain old bare bones Win32 APIs are still coming up in every release, they aren't the main ones.
Also COM as concept wasn't something designed by Microsoft, it rather build up on the ideas of what Sun, IBM and co were doing with distributed objects protocols.
It is no coincidence that COM IDL language is based on DCE RPC.
At the most basic level (IUnknown), COM doesn't care about DLL loading at all, so DLL hell is not in the picture. Many Windows libraries are actually like that - you call a single global exported function that gives you an "entrypoint" COM object, and from there you call methods on that and/or on other things that it returns. This is the extent of COM that you would usually see in cross-platform code (e.g. Mozilla's XPCOM, or COM Interop in Mono when running on Linux or Mac).
Beyond that, if we're talking about coclasses etc, one of the things about Win32 COM was kinda sorta solving DLL hell by using UUIDs as primary identifiers for those classes - CLSIDs - and mapping them to actual files on disk via the registry. Thus, you could have things installed wherever, including DLLs with identical names in different folders. A new version of the class would get the new CLSID, so multiple versions could be installed and correctly resolved at runtime.
Of course, that just made it a registry hell instead, where messing up those (global!) entries would break apps that depended on the affected classes. So Windows XP (IIRC) added the ability to register CLSIDs and map them to DLLs directly in the app manifest, allowing for a fully self-contained solution.
Yes, lower-level modern APIs are written in it, but you can write a modern windows GUI app without really needing to touch COM directly because there are other abstractions built on those APIs.
This was not as true of Windows programming 20 years ago.
Not sure how this disagrees with my statement that "you can write a modern windows GUI app without really needing to touch COM directly because there are other abstractions built on those APIs"
COM is several things. Although COM on its own always means Microsoft's version and they invented it, there have been quite a few reinventions over time. Mozilla uses/used their own version called XPCOM inside Firefox for example. It can be thought of as a standardized way to expose objects across languages, compilers, incompatible ABIs, processes and machines. It provides:
1. A standardization of vtables and how to obtain/query them from objects.
2. A standardized memory management protocol based on reference counting.
3. A standardized type description/reflection IDL and binary data format, so dynamic languages can reflect objects to learn what methods/properties/events they support.
4. A standardized protocol for dynamically invoking methods and properties by string and using variant types, for scripting languages again.
5. A whole lot of machinery for auto-generating implementations of dynamic method dispatch for objects written in C++/Pascal/C#/etc.
6. A way to load/dynamically link against objects by UUID instead of library name. In COM the actual location and name of a shared library is (in theory) unimportant.
7. A way to "activate" objects either in-process, which is basically a wrapper around dynamic library loading, or out-of-process, in which case Windows starts an EXE that then exposes objects as a server using RPC.
8. A way to do OOP RPC on objects over the network or a process boundary (DCOM).
9. A protocol for negotiating UI embeddings (OLE) so one component could contribute menus and toolbars that would get merged with the host program's UI.
And a lot more stuff that I've probably forgotten.
It's really a very feature complete and powerful framework for solving common problems you face when writing software made up on components written in different languages and by different teams. For example, an advanced use of COM is to run some objects at one privilege level and others at lower privilege levels. Installers/updaters often do this so the GUI runs as the user, and the engine runs as an administrator.
Most platforms (except the web) have something vaguely COM-like or COM inspired. Apple's stack uses MIG, Mach ports and Objective-C for similar purposes. Linux never really did but the closest equivalent is DBUS. Android has the Binder.
COM doesn't get much use these days outside a few stock use cases because other platforms never implemented it, so modern devs (web+mobile) aren't familiar with it and so we are now seeing a new generation 'rediscover' parts of it in the context of WASM, thinking it's new. However in its heydey COM was ubiquitous. There were large markets of components for sale, distributed in binary form and written in/for many different languages. COM stood in the middle making it all work. It was one reason that Windows was relatively language neutral and friendly to language innovation. In comparison other platforms are quite language and binding unfriendly.