the basics
CoInitialize(Ex) needs to be called for every thread that uses COM.
If these are "your" threads - i.e. you control their lifetime, it's customary to CoInitialize / Uninitialize at the beginning and end of the thread function.
it's not your thread
It's a bit trickier if the thread is created by someone else, and you don't know whether COM is initialized or not (e.g. when your DLL is loaded as a plugin and called via a "normal" exported function.)
There are two ways to go here:
(a) Try CoInitialize(Ex), and mark the return code.
- S_OK means you initialized the com libraries and you need to call CoUninitialize
- S_FALSE means COM libraries already are initialized with a compatible threading model, but you still need to call CoUninitialize (to "counter") your CoInitialue
- An error code
(FAILED(hr) == true), which usually means COM linraries were already initialized, but with a threading model that's not compatible with the one you requested. Do not call CoUninitialize if an error is returned
(b) Create your own thread
... and do all your COM work there (this might not be possible with all plugin API's)
OleInitialize vs. CoInitializeEx
Some Windows APIs may require OleInitialize which is "CoInitialize plus more".
It is not well documented which services require OleInitialize,but I've ran into problems with some Shell APIs.
(Even if the main thread does OleInitialize, worker threads still use CoInitializeEx)