Ok, I admit it. I'm a geek.
I'm actually one of those people who rants over the loss of the printed version of the platform SDK documentation (I still have some of the original Win32 Platform SDK documents in my office and use them regularly).
One of the things I used to LOVE doing is to take the old platform SDK documents, there was all SORTS of stuff that you could find in them. It was just FUN to read through and look at all the cool APIs people had come up with.
If you look through the COM documentation, you'll find a bunch of rather fascinating entries (I started this article with the comment that I'm a geek, right?).
COM describes a bunch of memory allocation routines - there's CoTaskMemAlloc, CoTaskMemFree, CoTaskMemRealloc. There are even APIs to allow you to spy on allocations (CoRegisterMallocSpy and the IMallocSpy interface). This makes sense - as a part of the contract for any interface, the allocation strategy associated with that interface needs to be documented, COM encapsulates the allocation strategy in the CoTaskMem* APIs.
There's also this rather odd duck of an API called CoGetMalloc. CoGetMalloc returns a pointer to an object that implements the IMalloc interface. And it turns out that the CoTaskMemAlloc, CoTaskMemFree and CoTaskMemRealloc routines are really just procedural wrappers around the IMalloc interface. If you think about it, this is just wierd. Why on earth would there be a function that allows you to retrieve a pointer to an interface that duplicates other functionality? It's not likely it's for efficiency.
It turns out that way back when - so far back that it's almost in prehistoric times (we're talking Win3.1 here), the COM memory allocator operated on a per-apartment basis. It was possible to replace the default allocator for a particular apartment, and that allocator would be used for all subsequent COM calls. Obviously you can't perform such a substitution on-the-fly, so you had to establish the allocator when you created the apartment in the first place. And that's what the first (now reserved) parameter to the CoInitialize and CoInitializeEx API used to do - it was a pointer to an IMalloc object which would subsequently be associated with the apartment. In Win3.1, that first parameter was a pointer to an IMalloc object.
At some point after this, it was determined that having the ability to provide an application specific allocator was a bad idea and the functionality was removed - I'm not sure why, but it was.
After the ability to set an allocator was removed, there was no need for an API to retrieve the allocator (after all, since there's only one allocator, you're always going to get the same answer). But of course, since it's been a documented API since COM was first created, it lives on. It's the COM version of the human appendix - a sad remainder of a time long gone that has outlived its original purpose.