17

In a multi-threaded environment with ADO database connections, I would like to know if CoInitialize has been called or not. How would I go about checking this?

Jerry Dodge
  • 26,858
  • 31
  • 155
  • 327
  • 2
    @KenWhite - don't forget that a thread's constructor is called in a different thread's context, destructor usually too. So these calls will be called in a wrong context. – kludg Jan 27 '13 at 00:21
  • 1
    @Serg: Yep, you're right. Should be called in `Execute` and `OnTerminate` of the thread itself instead, or a `try..finally` block in `Execute`. – Ken White Jan 27 '13 at 00:24
  • Yes this check will be inside the thread in which I need to check. – Jerry Dodge Jan 27 '13 at 00:43
  • Why can't you keep track of whether or not you initialized com? Surely you ought to be able to manage those details. – David Heffernan Jan 27 '13 at 00:47
  • Actually I already am, this is more for debugging purposes. – Jerry Dodge Jan 27 '13 at 00:53
  • 1
    Note: New continued question asking how to identify how many levels in `CoInitialize` has been called: http://stackoverflow.com/questions/14543496/how-to-identify-how-many-levels-of-coinitialize-have-been-called – Jerry Dodge Jan 27 '13 at 01:26

1 Answers1

15

Normally you should not do this check and just call CoInitialize/CoUnInitialize pair. Still you can do it like this:

function IsCoInitialized: Boolean;
var
  HR: HResult;

begin
  HR:= CoInitialize(nil);
  Result:= (HR and $80000000 = 0) and (HR <> S_OK);
  if (HR and $80000000 = 0) then CoUnInitialize;
end;

There is no problem if you call CoInitialize more than once in a thread. The first call should return S_OK, all subsequent calls should return S_FALSE. All these calls are considered successful and should be paired by CoUnInitialize calls. If you called CoInitialize n times in a thread, only the last n-th CoUnInitialize call closes COM.

kludg
  • 27,213
  • 5
  • 67
  • 118
  • 2
    @Serg, now I'm looking at the `CO_E_ALREADYINITIALIZED = HRESULT($800401F1)` constant defined in my Delphi 2009 `Windows.pas` unit with comment `CoInitialize has already been called.` and wondering what is that constant for. Have you seen or met this before ? Isn't that what returns the subsequent `CoInitialize` function call (can't verify this now) ? – TLama Jan 27 '13 at 01:04
  • 3
    @TLama - I guess `CO_E_ALREADYINITIALIZED` is never returned by `CoInitialize`, it is specific to other COM functions. – kludg Jan 27 '13 at 01:15
  • 1
    So you mean if I called `CoInitialize()` `n` times, and called `CoUninitialize()` `n-1` times, then COM will still be open for that thread? – kakyo Nov 22 '19 at 07:30