11

Let's say my application calls CoInitialize when it starts and CoUninitialize before it exists.

Assuming I have a 3rd party component that's used by my application and does a similar thing, will this cause some kind of failure?

is it okay to call CoInitialize when that call has already been submitted? will the second call fail? or will it just "let it pass" as it's already called.

JasonGenX
  • 4,952
  • 27
  • 106
  • 198
  • possible duplicate of [How does one call into COM from worker thread created with NT's QueueUserWorkItem?](http://stackoverflow.com/questions/7811118/how-does-one-call-into-com-from-worker-thread-created-with-nts-queueuserworkite) – i_am_jorf Oct 20 '11 at 15:52

2 Answers2

10

CoInitialize will return S_FALSE if it has already been initialized in the calling thread. However, for both invocations that return S_OK and S_FALSE there needs to be a CoUninitialize call. The number of calls to this functions get counted, and only when the number of CoUninitialize equals that of CoInitialize it will actually uninitialize things.

So in conclusion, a second call is harmless, and there are no problems with calling this pair of functions more than once.

K-ballo
  • 80,396
  • 20
  • 159
  • 169
  • 7
    Provided that the two calls are compatible. If the two calls are incompatible (e.g., the first call initialized in STA mode and the second call initializes in MTA mode), then you will get the error `RPC_E_CHANGED_MODE`. This is all spelled out in the documentation. http://msdn.microsoft.com/library/ms678543.aspx – Raymond Chen Oct 19 '11 at 16:12
  • 1
    Some applications will check the result of the CoInitialize and will "not continue" if S_FALSE is returned. You suggest to ignore it (for that second call?) – JasonGenX Oct 19 '11 at 16:15
  • 2
    @Ron M: Why would an application not continue after a successfull call to `CoInitialize`? Note the `S` in `S_FALSE` means success. – K-ballo Oct 19 '11 at 16:17
  • 1
    Excuse me- I haven't had enough caffeine this morning. Of course, S_FALSE is covered by the SUCCEEDED(result) evaluation.... – JasonGenX Oct 19 '11 at 16:26
  • Actually I had serious problems with the described logic - http://stackoverflow.com/q/2154151/57428 – sharptooth Oct 21 '11 at 07:26
7

It is pretty fundamentally wrong, CoInitialize() must be called by the code that owns the thread. Which is never the 3rd party component if it acts like an in-process server and doesn't start its own threads.

And sure, this can and will go wrong when it doesn't agree about the apartment type. Which is something it cannot guarantee, an STA is the usual choice and that requires pumping a message loop. The component won't do that, it's the host's job. And if the apartment type is a mismatch then it needs to marshal the interface pointer. Which it won't do when it relies on its apartment type of choice.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • makes sense. We have some leverage there and will work to change that. – JasonGenX Oct 19 '11 at 21:33
  • 5
    It is perfectly fine for a third-party component to call `CoInitialize()` if it needs to access a COM object and has no guarantee that the calling thread has already called `CoInitialize()` outside of the component. Just be careful if the component is calling `CoInitialize()` for the first time in the calling thread, as that will establish the threading model for the rest of the thread's lifetime, which might cause problems if the thread decides later on that is wants to to use a different threading model. – Remy Lebeau Oct 21 '11 at 01:05