OleInitialize CoInitialize CoInitializeEx

When you intitialize a COM object do you need to call one of these functions? (otherwise I'm way off the mark)

Which function do you use? What's the difference? MSDN doesn't seem particularily clear on that.

Where do you call it? At the beginning of your code? Inside a function that uses the COM object?

Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

These functions should be called in each thread which works with COM, for example, creates and uses some COM components.

CoInitialize - initializes COM in the current thread using STA model. Remains for backward compatibility; use CoInitializeEx instead of it.

CoInitializeEx - initializes COM in the current thread. Allows to select STA amd MTA models.

OleInitialize - initializes COM in the current thread using STA model and activates additional functionality.

When to call: in the start of each thread. If application is single-threaded, in the main thread initialization code. In MFC application this may be, for example, InitInstance.

What function should be called:
CoInitialize - should not be used.
OleInitialize - if you need Clipboard, drag-and-drop, OLE or in-place-activation support.
CoInitializeEx - in other cases.

See details in this article:

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
>>These functions should be called in each thread which works with COM

Multithreading and COM requires special care, as passing IF pointers between threads is inherently dangerous.

>>MSDN doesn't seem particularily clear on that

The article at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnesscom/html/c5interfaceimplementationrevisited.asp ("Interface and Implementation Revisited") is pretty on point about the differences :o)

You also might want to read an article by *the* COM guru at http://www.microsoft.com/msj/0798/com0798.aspx ("House of COM")
Introduction to R

R is considered the predominant language for data scientist and statisticians. Learn how to use R for your own data science projects.

Sorry, my fault :o)
Sandra-24Author Commented:
lol @ Alex & jkr

So if I have several threads that will use this COM object (possibly concurrently) do I use CoInitializeEx(NULL,COINIT_MULTITHREADED) before I started the threads or do I use CoInitializeEx(NULL,COINIT_APARTMENTTHREADED) in the beginning of each thread?

You should use CoInitializeEx in the beginning of each thread. But which one of them - I am not sure. I would try CoInitializeEx(NULL,COINIT_MULTITHREADED).
And, you will need to marshal the interface pointers between the threads:

See see http://support.microsoft.com/default.aspx?scid=kb;en-us;150777 ("INFO: Descriptions and Workings of OLE Threading Models")

See also http://support.microsoft.com/default.aspx?scid=kb;en-us;206076 ("206076 - MARSHAL.EXE: How To Marshal Interfaces Across Apartments")

To elaborate (http://msdn.microsoft.com/msdnmag/issues/1100/wicked/default.aspx):

"Always Call CoInitialize(Ex)
A few months ago, I received an e-mail message from a friend at a prominent hardware company. His company had written a fairly sophisticated COM-based application that employed a number of in-proc and local (out-of-process) COM components. At startup, the application created COM objects to serve various client threads running in multithreaded apartments (MTAs). The objects were also consigned to MTAs, which meant that interface pointers could be freely exchanged among client threads. In testing, my friend discovered that everything worked fine until the application was ready to shut down. Then, for no apparent reason, calls to Release (calls that had to be made in order to properly free the interface pointers that the clients were holding) were locking up. His question: "What on earth is going wrong?"
The answer, as it turned out, was quite simple. The application's developers had done everything right with one very important exception: they weren't calling CoInitialize or CoInitializeEx in all of their client threads. One of the fundamental rules of modern-day COM is that every thread that uses COM should first initialize COM by calling either CoInitialize or CoInitializeEx. There are no exemptions to this rule. Among other things, CoInitialize(Ex) places a thread inside an apartment and initializes important per-thread state information that is required for COM to operate properly. Failure to call CoInitialize(Ex) typically manifests itself early in the application's lifetime in the form of failed COM API functions, most commonly activation requests. But sometimes the problems are more insidious and don't manifest themselves until it's too late, as in the case of calls to Release that disappear and never return. Once the dev team added CoInitialize(Ex) calls to all the threads that touched COM, their problems went away.
Ironically, Microsoft is one of the reasons that COM programmers sometimes don't call CoInitialize(Ex). The Microsoft® Knowledge Base contains documents stating that calls to CoInitialize(Ex) aren't strictly necessary for MTA-based threads (see article Q150777 for an example). Yes, there are cases in which you can get away with skipping CoInitialize(Ex). No, you shouldn't do it unless you know what you're doing and can be absolutely sure that you'll suffer no debilitating effects. It's never harmful to call CoInitialize(Ex), so my advice to COM programmers is to always call it from any thread that does anything whatsoever with COM.

Don't Pass Raw Interface Pointers Between Threads
One of the first COM projects I ever consulted on involved a distributed application comprising about 100,000 lines of code, written by a large software company on the West Coast. The application created dozens of COM objects on various machines and called into those objects from background threads launched by client processes. The development team was stymied by calls that would disappear into never-never land or simply fail for no obvious reason. One of the most egregious symptoms that they demonstrated for me was that following a call that failed to return, starting other COM-enabled applications (including Microsoft Paint, of all things) on the same machine would frequently induce those applications to lock up too.
An examination of their code revealed that they had broken one of the fundamental laws of COM concurrency, which says that if one thread wants to share an interface pointer with another thread, it should first marshal the interface pointer. Marshaling an interface pointer enables COM to create a new proxy if necessary (and a new channel object, pairing the proxy with a stub) to permit callouts from another apartment. Passing a raw interface pointer (a 32-bit address in memory) to another thread without marshaling it bypasses COM's concurrency mechanism, and can produce all sorts of undesirable behavior if the sending and receiving threads reside in different apartments. (In Windows® 2000, because two objects can share an apartment but reside in different contexts, it can even get you in trouble if the threads are in the same apartment.) A typical symptom involves calls that fail and return RPC_E_WRONG_THREAD_ERROR.
Windows NT® 4.0 and higher make it easy to marshal interface pointers between threads with a pair of API functions named CoMarshalInterThreadInterfaceInStream and CoGetInterfaceAndReleaseStream. Let's say one thread in your application (thread A) has created a COM object and received an IFoo interface pointer in return, and that another thread in the same process (thread B) wants to place calls to that object. In preparation for passing the interface pointer to thread B, thread A should marshal the interface pointer like this:

CoMarshalInterThreadInterfaceInStream (IID_IFoo, pFoo, &pStream);

Once CoMarshalInterThreadInterfaceInStream has returned, thread B can safely unmarshal the interface pointer:

IFoo* pFoo;
CoGetInterfaceAndReleaseStream (pStream, IID_IFoo, (void**) &pFoo);"

If you want to avoid all the marshalling hassle, take a look at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/com/htm/cmi_d2l_5omd.asp ("IGlobalInterfaceTable"), which provides aninterface is an efficient way for a process to store an interface pointer in a memory location that can be accessed from multiple apartments within the process, such as processwide variables and agile (free-threaded marshaled) objects containing interface pointers to other objects (last half of the sentence shamelessly stolen from that page :o)

On the last issue, see also

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/com/htm/aptnthrd_4ew5.asp ("Creating the Global Interface Table")

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/com/htm/aptnthrd_6uat.asp ("When to Use the Global Interface Table")

http://www.microsoft.com/msj/0997/activex0997.aspx ("ActiveX Q&A, MSJ September, 1997 - Apartment Neutrality: The Free Threaded Marshaler and the Global Interface Table")
Sandra-24Author Commented:
This is odd. I'm compiling on a Win XP machine but it seems CoInitializeEx is not availiable to me.

I looked in objbase header and it's defined like so:

#if (_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM) // DCOM
WINOLEAPI  CoInitializeEx(IN LPVOID pvReserved, IN DWORD dwCoInit);

the constant COINIT_MULTITHREADED is also defined like that. It is also unavailible.

So i changed my code to this:

#if (_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM) // DCOM

It will now compile, which means it'll use CoInitialize.

I'll look into this behaviour in the morning but it strikes me that XP is > NT 4 and is defined (as far as I can tell) on my machine to be 0x0501.


Requirements for CoInitializeEx:

Windows NT/2000: Requires Windows NT 4.0 or later.
Windows 95/98: Requires Windows 98 (or Windows 95 with DCOM).

You need to add line
#define _WIN32_WINNT 0x0400

to compile CoInitializeEx. To compile it in Win98 add line
#define _WIN32_WINDOWS 0x0410    // or more

Add this definition in stdafx.h, before all #include lines.
Sandra-24Author Commented:
I added _WIN32_WINNT 0x0501 to the preprocessor definitions in the project properties. It worked, thanks.

Always so much more to learn it seems! Thanks again guys.

It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today

From novice to tech pro — start learning today.