Sometimes people (my customers) have a problem with COM Initialization in an ISAPI application. It seems sometimes they do not have to call CoInitializeEx and sometimes they do. Since CoInitializeEx "must" be called prior to using COM and sometimes the isapi works without calling this function, it seems IIS or something else has already called this function.
Can someone tell me, what is IIS's behavior in regard to COM initialization?
IIS's behavior in regards to COM initialization is clean - it simply does nothing.
Thus, the behavior you describe sounds like a common bug with some ISAPI DLL running on IIS - calling CoInitializeEx() on threads not owned by the ISAPI. Since IIS reuses threads from its thread pool to call into ISAPI, the following sequence can occur and cause what you observe:
- IIS does not call CoInitializeEx() on any of the threads in its thread pool.
- IIS uses thread 1 from its thread pool to call the ISAPI entrypoint.
- In the entrypoint, ISAPI calls CoInitializeEx() on thread 1 but does not call CoUninitialize() prior to exiting the entrypoint and returning control to IIS.
thread 1 has now called CoInitializeEx() once.
- IIS later uses thread 2 from its thread pool to call the ISAPI entrypoint. Since this thread has never called CoInitializeEx(), thread 2 has called CoInitializeEx() once.
- IIS later re-uses thread 1 from its thread pool to call the ISAPI entrypoint.
thread 1 has now called CoInitializeEx() twice.
At this point, this ISAPI has seriously confused things. There is no way for it to call the correct number of CoUninitialize() on all the IIS threads (suppose the ISAPI entrypoint is never invoked again by IIS - no chance for it to call CoUninitialize() correct number of times, and no way for new user of the same thread to know how many times to call CoUninitialize()). It has tainted the thread pool shared by all other ISAPIs. All sorts of badness can commence at this point.
The simple rule of thumb: do not call CoInitialize()/CoUninitialize() on a thread which you do not own.