Discussion:
CoInitialize/CoUninitialize
(too old to reply)
George
2008-06-24 12:14:02 UTC
Permalink
Hello everyone,


I want to develop an automatic tool or manually using existing tool (e.g.
WinDbg) to watch when CoInitialize/CoUninitialize is called. I suspect
CoUninitialize is not called the same times as CoInitialize, and I want to
get the call stack.

Any ideas or reference documents about how to do this?

(I do not have the full source codes, but I have symbol files. My current
ideas is either to add to system level COM Runtime hook to monitor when the
two functions are called and get stack trace if possible, or using WinDbg to
monitor the two specific function calls -- but I do not know the command in
WinDbg. :-) )


thanks in advance,
George
Cholo Lennon
2008-06-24 12:53:19 UTC
Permalink
Post by George
Hello everyone,
I want to develop an automatic tool or manually using existing tool
(e.g. WinDbg) to watch when CoInitialize/CoUninitialize is called. I
suspect CoUninitialize is not called the same times as CoInitialize,
and I want to get the call stack.
Any ideas or reference documents about how to do this?
(I do not have the full source codes, but I have symbol files. My
current ideas is either to add to system level COM Runtime hook to
monitor when the two functions are called and get stack trace if
possible, or using WinDbg to monitor the two specific function calls
-- but I do not know the command in WinDbg. :-) )
One option is to use Detour library:

http://research.microsoft.com/sn/detours/

Be warned, Detour is not perfect:

http://jpassing.wordpress.com/2008/01/16/dangerous-detours-part-1-introduction/


Regards

--
Cholo Lennon
Bs.As.
ARG
George
2008-06-24 13:04:03 UTC
Permalink
Thanks Cholo,


I have a new idea. Is it possible to set breakpoint to function
CoInitialize/CoUninitialize in Visual Studio or WinDbg? I doubt since it is
COM Runtime code, not my code.

If we can, how?


regards,
George
Alex Blekhman
2008-06-24 17:29:23 UTC
Permalink
Post by George
Is it possible to set breakpoint to function
CoInitialize/CoUninitialize in Visual Studio or WinDbg? I doubt
since it is COM Runtime code, not my code.
It is very simple. Go to Debug menu, then select "New
breakpoint..." item (or press Ctrl+B). In breakpoint location
write:

{,,ole32.dll} ***@8

it will stop on each entry into `CoInitializeEx' (`CoInitialize'
calls `CoInitializeEx' internally').

HTH
Alex
George
2008-06-25 07:47:00 UTC
Permalink
Thanks Alex,
Post by Alex Blekhman
It is very simple. Go to Debug menu, then select "New
breakpoint..." item (or press Ctrl+B). In breakpoint location
I have tried both WinDbg and Visual Studio, and I think the above operation
you mean Visual Studio, correct?

If yes, to tell the truth, I have never set any breakpoint in the system API
code, other than in my code, could you tell me what does the grammar mean
please -- "{,,ole32.dll} ***@8"?


regards,
George
Alex Blekhman
2008-06-25 10:05:02 UTC
Permalink
Post by George
I have tried both WinDbg and Visual Studio, and I think the
above operation you mean Visual Studio, correct?
Yes, I mean Visual C++.
Post by George
If yes, to tell the truth, I have never set any breakpoint in
the system API code, other than in my code, could you tell me
what does the grammar mean please -- "{,,ole32.dll}
This is, so called context operator:

"Context Operator (C/C++ Language Expressions)"
http://msdn.microsoft.com/en-us/library/wztycb7f.aspx

"ole32.dll" - is the module that contains `CoInitialize' and
`CoInitializeEx'. The "***@8" expression is the true
name of `CoInitializeEx' function as it appears inside the DLL.

HTH
Alex
George
2008-06-25 11:52:01 UTC
Permalink
Thanks Alex,


How do you know,

1. CoInitializeEx belongs to ole32.dll?

2. The "***@8" expression is the true name of `CoInitializeEx'
function? 8 means the 8th exported function of ole32.dll?


regards,
George
Alex Blekhman
2008-06-25 13:13:11 UTC
Permalink
Post by George
How do you know,
1. CoInitializeEx belongs to ole32.dll?
Read "Requirements" section in the MSDN page dedicated to
`CoInitializeEx'. Although it is not stated that the function is
implemented in ole32.dll, but the library you should use is
ole32.lib. So, assuming ole32.dll is a good guess.
Post by George
`CoInitializeEx' function? 8 means the 8th exported function of
ole32.dll?
No, this is mangled (or decorated) name of a function. Here's the
description of the format of decorated names:

"Format of a C Decorated Name"
http://msdn.microsoft.com/en-us/library/x7kb4e2f.aspx

HTH
Alex
George
2008-06-25 13:55:01 UTC
Permalink
Thanks Alex,


1.
Post by Alex Blekhman
Read "Requirements" section in the MSDN page dedicated to
`CoInitializeEx'. Although it is not stated that the function is
implemented in ole32.dll, but the library you should use is
ole32.lib. So, assuming ole32.dll is a good guess.
Smart!

2.
Post by Alex Blekhman
No, this is mangled (or decorated) name of a function. Here's the
"Format of a C Decorated Name"
http://msdn.microsoft.com/en-us/library/x7kb4e2f.aspx
I am using dumpbin /exports ole32.dll, There is results like below, how to
transfer such results or using some other tool to transfer results into
***@8?

--------------------
58 35 000EC1A0 CoGetObject
59 36 0001CD40 CoGetObjectContext
60 37 000321A0 CoGetPSClsid
61 38 00102510 CoGetProcessIdentifier
62 39 000967B0 CoGetStandardMarshal
63 3A 000FD490 CoGetState
64 3B 00101EA0 CoGetStdMarshalEx
65 3C 00102550 CoGetSystemSecurityPermissions
66 3D 000397F0 CoGetTreatAsClass
67 3E 00049530 CoImpersonateClient
68 3F 0004F3D0 CoInitialize
--------------------


regards,
George
Alex Blekhman
2008-06-25 14:25:35 UTC
Permalink
Post by George
I am using dumpbin /exports ole32.dll, There is results like
below, how to transfer such results or using some other tool to
I don't use any tool. I just apply naming mangling rules to get
the resulting name. `CoInitializeEx' is __stdcall (see declaration
on ObjBase.h), hence the leading underscore. Also, the function
takes two parameters, each one is 4 bytes, so total 8 bytes.
Finaly you get the mangled name: "***@8".

Alex
George
2008-06-25 14:44:02 UTC
Permalink
Thanks for sharing experience, Alex!


Two more comments,

1.

I think using WinDbg is much clear to set a breakpoint. I just use bm
CoInitialize, I think I can achieve the same effect. Right?

2.

Using Visual Studio, are there any easier way to set break point in system
API? e.g. like what we did in WinDbg, just type the API name is ok, no need
to calculate size of parameters and DLL name.

BTW: there are a couple of call conventions, how do you know it is stdcall?
Not fastcall or something else?


regards,
George
Alex Blekhman
2008-06-25 15:06:23 UTC
Permalink
Post by George
1.
I think using WinDbg is much clear to set a breakpoint. I just
use bm
CoInitialize, I think I can achieve the same effect. Right?
So WinDbg does the mangling for you, that's all.
Post by George
2.
Using Visual Studio, are there any easier way to set break point
in system API? e.g. like what we did in WinDbg, just type the
API name is ok, no need to calculate size of parameters and DLL
name.
There is no such thing as "just API name". API name is mangled. I
tried to use undecorated names with VC++, but it have never
worked. It is not difficult to calculate the mangled name, though.
Post by George
BTW: there are a couple of call conventions, how do you know it
is stdcall? Not fastcall or something else?
I looked it up in ObjBase.h file. `CoInitializeEx' is declared as
WINOLEAPI. So you stand on the token with a carret and press F12
until you get to the bottom. WINOLEAPI is expanded to
STDAPICALLTYPE among other things, which in its turn is expanded
to __stdcall.

Alex
George
2008-06-30 03:58:00 UTC
Permalink
Hi Alex!


Great reply! I debugged for 2 days, and find something more interesting.
When set a breakpoint in WinDbg, using "bp CoInitialize", WinDbg will show
CoInitialize is in Kernerl32.dll. But it is incorrect. Actually, as you said,
it is in ole32.dll.

Any ideas about what is wrong?

(I solve this issue by using bu command to set breakpoint until ole32.dll is
loaded.)


regards,
George
Alex Blekhman
2008-06-30 07:14:37 UTC
Permalink
Post by George
When set a breakpoint in WinDbg, using "bp CoInitialize", WinDbg
will show CoInitialize is in Kernerl32.dll. But it is incorrect.
Actually, as you said, it is in ole32.dll.
Any ideas about what is wrong?
I have no idea. Probably WinDbg assumes "kernel32.dll" by default
when it doesn't have enough information and resolves it later.

Alex
George
2008-06-30 08:35:00 UTC
Permalink
Thanks Alex,


I have to set manually ole32!CoInitialize, or else if I only type
CoInitialize, WinDbg will think the function resides in Kernel32.dll, and
will never stop on the breakpoint, even if it is called.

1.

Do you think it is a bug of WinDbg?

2.

Could you reproduce it?


regards,
George
Alex Blekhman
2008-06-30 09:47:06 UTC
Permalink
Post by George
I have to set manually ole32!CoInitialize, or else if I only
type CoInitialize, WinDbg will think the function resides in
Kernel32.dll, and will never stop on the breakpoint, even if it
is called.
Do you think it is a bug of WinDbg?
No, I don't think it's a bug. After all, WinDbg cannot guess for
you about location of a function. I don't see any problem in
specifying module name in addition to function name.

Alex
George
2008-06-30 11:17:00 UTC
Permalink
Thanks Alex,


I totally agree with you. But suppose when we use CoInitialize other than
ole32!CoInitialize in WinDbg, there is no error and displays
kernerl32!CoInitialize. It will mislead people to think CoInitialize is in
kernerl32.dll other than ole32.dll.

So, I think reporting unfound symbol should be the most convenient solution.
:-)


regards,
George
George
2008-06-24 13:04:04 UTC
Permalink
Thanks Cholo,


I have a new idea. Is it possible to set breakpoint to function
CoInitialize/CoUninitialize in Visual Studio or WinDbg? I doubt since it is
COM Runtime code, not my code.

If we can, how?


regards,
George
Cholo Lennon
2008-06-24 19:36:06 UTC
Permalink
Post by George
Thanks Cholo,
I have a new idea. Is it possible to set breakpoint to function
CoInitialize/CoUninitialize in Visual Studio or WinDbg? I doubt since
it is COM Runtime code, not my code.
If we can, how?
In WinDbg, load the executable, open the disassembly window, type CoInitialize
in offset
textbox and press enter. Then press F9 to set up the breakpoint in the selected
line.

--
Cholo Lennon
Bs.As.
ARG
George
2008-06-25 07:50:02 UTC
Permalink
Thanks Cholo,


Two more comments,

1.

What harm will be if an application calls CoInitialize multiple times, and
CoUninitialize only one time? Any leak?

2.

I think your method will only find the code in my own code which calls
CoInitialize, not all the code (including system SDK) which calls
CoInitialize, correct?

For example, if my code calls some API in some system32 DLL, and the API
calls CoInitialize, your method will not set breakpoint in this situation?


regards,
George
Brian Muth
2008-06-24 16:16:32 UTC
Permalink
I would write a DLL with entry points CoInitialize and CoUninitialize that would call the Win32 API's on behalf of the application,
probably necessitating a call to LoadLibrary on ole32.dll.

Would that work for you? It would require that the targeted program would have to be relinked.
George
2008-06-25 07:53:00 UTC
Permalink
Thanks Brian,


I do not quite understand your solution. How could your code in DLL monitor
the call in other part of my code which calls CoInitialize and
CoUninitialize? Could you clarify please?

(other part of my own code, and some system API may not call through your
DLL as s proxy to call CoInitialize and CoUninitialize.)


regards,
George
Alf P. Steinbach
2008-06-30 07:33:46 UTC
Permalink
Post by George
Hello everyone,
I want to develop an automatic tool or manually using existing tool (e.g.
WinDbg) to watch when CoInitialize/CoUninitialize is called. I suspect
CoUninitialize is not called the same times as CoInitialize, and I want to
get the call stack.
No you don't.

You don't want to call CoInitialize/CoUninitialize locally anywhere, because
that doesn't work with e.g. Internet Explorer machinery.

And if you do, you want to simply check the return values.
Post by George
Any ideas or reference documents about how to do this?
Don't.
Post by George
(I do not have the full source codes, but I have symbol files. My current
ideas is either to add to system level COM Runtime hook to monitor when the
two functions are called and get stack trace if possible, or using WinDbg to
monitor the two specific function calls -- but I do not know the command in
WinDbg. :-) )
Since it isn't your own source code there's not much you can do about it if you
do find a mismatch in number of calls, is there?

What you should do is to make sure that your driver code calls CoInitialize and
CoUninitialize, at top level.

Don't rely on any local calls.


Cheers, & hth.,

- Alf
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
George
2008-06-30 08:40:01 UTC
Permalink
Thanks Alf,


1.

I have to set manually ole32!CoInitialize, or else if I only type
CoInitialize, WinDbg will think the function resides in Kernel32.dll, and
will never stop on the breakpoint, even if it is called.

Do you think it is a bug of WinDbg?

2.

"You don't want to call CoInitialize/CoUninitialize locally anywhere, because
that doesn't work with e.g. Internet Explorer machinery." and "Don't rely on
any local calls." -- could you say the comments in some other words please?
Sorry, my English is not good.


regards,
George
Alf P. Steinbach
2008-06-30 11:13:33 UTC
Permalink
Post by George
Thanks Alf,
1.
I have to set manually ole32!CoInitialize, or else if I only type
CoInitialize, WinDbg will think the function resides in Kernel32.dll, and
will never stop on the breakpoint, even if it is called.
Do you think it is a bug of WinDbg?
I think you're concentrating on entirely the wrong thing.
Post by George
2.
"You don't want to call CoInitialize/CoUninitialize locally anywhere, because
that doesn't work with e.g. Internet Explorer machinery." and "Don't rely on
any local calls." -- could you say the comments in some other words please?
Sorry, my English is not good.
Here is bad code, relying on local COM initialization:

void doAnHTMLDialog()
{
if( !SUCCEEDED( CoInitialize() ) )
{
throwX( "Unable to initalize COM" );
}

// Do HTML dialog using COM-based IE machinery, then

CoUninitialize();
// Dontcha know, there might still be some thread using COM! Splat!
}

int main()
{
doAnHTMLDialog();
// Perhaps do other things here, then:
return EXIT_SUCCESS;
}

Here is less bad code, which might even be counted as good if one ignores
exception safety aspects and lack of abstraction and reusability:

void doAnHTMLDialog()
{
HRESULT const initResult = CoInitialize();
if( FAILED( initResult ) )
{
throwX( "Unable to initalize COM" );
}
else if( initResult != S_OK )
{
CoUninitialize();
throwX( "COM was not initialized before calling doAnHTMLDialog." );
}
CoUninitialize(); // "Undo" the checking call of CoInitialize.

// Do HTML dialog using COM-based IE machinery.
}

int main()
{
if( !SUCCEEDED( CoInitialize ) ) { return EXIT_FAILURE; }
doAnHTMLDialog();
// Perhaps do other things here, then:
CoUninitialize();

return EXIT_SUCCESS;
// It's unclear exactly why terminating the process never invokes fatal
// errors and undefined behavior for still running COM things, but, in
// practice it's always worked. It's about the best one /can/ do with
// ugly bug-ridden MS library software that gives no means of waiting
// for finished cleanup, or of forcing cleanup.
}


Cheers, & hth.,

- Alf
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Alf P. Steinbach
2008-06-30 11:15:49 UTC
Permalink
Post by Alf P. Steinbach
Post by George
Thanks Alf,
1.
I have to set manually ole32!CoInitialize, or else if I only type
CoInitialize, WinDbg will think the function resides in Kernel32.dll,
and will never stop on the breakpoint, even if it is called.
Do you think it is a bug of WinDbg?
I think you're concentrating on entirely the wrong thing.
Post by George
2.
"You don't want to call CoInitialize/CoUninitialize locally anywhere,
because that doesn't work with e.g. Internet Explorer machinery." and
"Don't rely on any local calls." -- could you say the comments in some
other words please? Sorry, my English is not good.
void doAnHTMLDialog()
{
if( !SUCCEEDED( CoInitialize() ) )
{
throwX( "Unable to initalize COM" );
}
// Do HTML dialog using COM-based IE machinery, then
CoUninitialize();
// Dontcha know, there might still be some thread using COM! Splat!
}
int main()
{
doAnHTMLDialog();
return EXIT_SUCCESS;
}
Here is less bad code, which might even be counted as good if one
void doAnHTMLDialog()
{
HRESULT const initResult = CoInitialize();
if( FAILED( initResult ) )
{
throwX( "Unable to initalize COM" );
}
else if( initResult != S_OK )
Uh, "==".
Post by Alf P. Steinbach
{
CoUninitialize();
throwX( "COM was not initialized before calling
doAnHTMLDialog." );
}
CoUninitialize(); // "Undo" the checking call of CoInitialize.
// Do HTML dialog using COM-based IE machinery.
}
int main()
{
if( !SUCCEEDED( CoInitialize ) ) { return EXIT_FAILURE; }
doAnHTMLDialog();
CoUninitialize();
return EXIT_SUCCESS;
// It's unclear exactly why terminating the process never invokes fatal
// errors and undefined behavior for still running COM things, but, in
// practice it's always worked. It's about the best one /can/ do with
// ugly bug-ridden MS library software that gives no means of waiting
// for finished cleanup, or of forcing cleanup.
}
Cheers, & hth.,
- Alf
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
George
2008-06-30 12:06:00 UTC
Permalink
Thanks Alf,


1.

Your first sample is bad because, if CoInitialize fails, you will throw
throwX( "Unable to initalize COM" ) and no chance to call CoUninitialize?

2.

"It's unclear exactly why terminating the process never invokes fatal errors
and undefined behavior for still running COM things" -- do you mean when
terminate a process without making the same amount of calls to CoUninitialize
(compared with the amount of calls to CoInitialize), it is surprising COM
library still works without error for unbalanced call pairs?

If yes, I am confused. Suppose your process loads an DLL (in-process COM
server) and the process terminates, the DLL will be unloaded when the process
terminates, why do you think there may be fatal errors?

3.

If we do not call less CoUninitialize than the amount of CoInitialize, what
will happen? Leak or?


regards,
George
Igor Tandetnik
2008-06-30 12:16:29 UTC
Permalink
Post by Alf P. Steinbach
void doAnHTMLDialog()
{
if( !SUCCEEDED( CoInitialize() ) )
{
throwX( "Unable to initalize COM" );
}
// Do HTML dialog using COM-based IE machinery, then
CoUninitialize();
// Dontcha know, there might still be some thread using COM!
Splat! }
CoInitialize/CoUninitialize are per thread. Calling CoUninitialize in
one thread cannot affect other threads.

While I agree it's not the best idea, I don't see the horrible problems
in the code above you seem to ascribe to it. The code should work as
written.
Post by Alf P. Steinbach
Here is less bad code, which might even be counted as good if one
ignores exception safety aspects and lack of abstraction and
void doAnHTMLDialog()
{
HRESULT const initResult = CoInitialize();
if( FAILED( initResult ) )
{
throwX( "Unable to initalize COM" );
}
else if( initResult != S_OK )
{
CoUninitialize();
throwX( "COM was not initialized before calling
doAnHTMLDialog." ); }
CoUninitialize(); // "Undo" the checking call of
CoInitialize.
// Do HTML dialog using COM-based IE machinery.
}
If you are willing to do the complete CoInitialize / CoUninitialize
dance just for checking, why not do it for real as in the first example,
and actually use the freshly initialized apartment (since you have
already invoked the overhead anyway)?
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
Alf P. Steinbach
2008-06-30 12:43:23 UTC
Permalink
Post by Igor Tandetnik
Post by Alf P. Steinbach
void doAnHTMLDialog()
{
if( !SUCCEEDED( CoInitialize() ) )
{
throwX( "Unable to initalize COM" );
}
// Do HTML dialog using COM-based IE machinery, then
CoUninitialize();
// Dontcha know, there might still be some thread using COM!
Splat! }
CoInitialize/CoUninitialize are per thread. Calling CoUninitialize in
one thread cannot affect other threads.
You'd think so, wouldn't you? :-)

But reality is a bit different.

In particular, there's much messaging between threads, and just to make the
point, the above is an actual case, not some hypothetical silly-example.
Post by Igor Tandetnik
While I agree it's not the best idea, I don't see the horrible problems
in the code above you seem to ascribe to it. The code should work as
written.
I totally agree, it should. Ideally. Reality is that it doesn't. Or didn't.
Perhaps Microsoft has now fixed all their libraries (I doubt it, however).
Post by Igor Tandetnik
Post by Alf P. Steinbach
Here is less bad code, which might even be counted as good if one
ignores exception safety aspects and lack of abstraction and
void doAnHTMLDialog()
{
HRESULT const initResult = CoInitialize();
if( FAILED( initResult ) )
{
throwX( "Unable to initalize COM" );
}
else if( initResult != S_OK )
{
CoUninitialize();
throwX( "COM was not initialized before calling
doAnHTMLDialog." ); }
CoUninitialize(); // "Undo" the checking call of
CoInitialize.
// Do HTML dialog using COM-based IE machinery.
}
If you are willing to do the complete CoInitialize / CoUninitialize
dance just for checking, why not do it for real as in the first example,
and actually use the freshly initialized apartment
Because that doesn't work in general, but might work in particular cases (it's
like C++ Undefined Behavior), thus leading someone -- e.g. you! :-) -- to
use it, and sometime in the future get some very difficult-to-find bug.
Post by Igor Tandetnik
(since you have
already invoked the overhead anyway)?
I think the overhead is there only in the unreliable case where CoInitialize
actually initializes. For a secondary or third call I imagine the overhead is
miniscule, irrelevant. But anyway this is about correctness, not speed: first
make your code correct, then, if needed, faster or whatever.


Cheers, & hth.,

- Alf
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Igor Tandetnik
2008-06-30 13:18:25 UTC
Permalink
Post by Alf P. Steinbach
Post by Igor Tandetnik
CoInitialize/CoUninitialize are per thread. Calling CoUninitialize in
one thread cannot affect other threads.
You'd think so, wouldn't you? :-)
But reality is a bit different.
In particular, there's much messaging between threads, and just to
make the point, the above is an actual case, not some hypothetical
silly-example.
You seem to be hinting at some dark secret only you know about. Do you
have any evidence to back up the claim? Perhaps a working sample where a
code similar to what you show causes problems?
Post by Alf P. Steinbach
I totally agree, it should. Ideally. Reality is that it doesn't. Or
didn't. Perhaps Microsoft has now fixed all their libraries (I doubt
it, however).
Again, can you show an example that would demonstrate the bug you
allege?
Post by Alf P. Steinbach
Post by Igor Tandetnik
If you are willing to do the complete CoInitialize / CoUninitialize
dance just for checking, why not do it for real as in the first
example, and actually use the freshly initialized apartment
Because that doesn't work in general, but might work in particular
cases (it's like C++ Undefined Behavior), thus leading someone --
e.g. you! :-) -- to use it, and sometime in the future get some
very difficult-to-find bug.
The behavior of this code looks well defined and documented to me.
Again, what specifically do you believe is a problem with it?
Post by Alf P. Steinbach
I think the overhead is there only in the unreliable case where
CoInitialize actually initializes.
So you think calling CoInitialize and then immediately CoUninitialize
(when COM was not initialized before on this thread) is well defined,
but calling CoInitialize, then doing some COM work, and then calling
CoUninitialize is somehow different. What exactly do you believe is the
difference between these two cases?

Under your theory, when is it ever safe to call CoInitialize and
CoUninitialize? You say that calling CoInitialize for the first time in
a thread is "unreliable" - wouldn't that mean there's no reliable way to
use COM at all?
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
Alf P. Steinbach
2008-06-30 13:54:24 UTC
Permalink
Post by Igor Tandetnik
Post by Alf P. Steinbach
Post by Igor Tandetnik
CoInitialize/CoUninitialize are per thread. Calling CoUninitialize in
one thread cannot affect other threads.
You'd think so, wouldn't you? :-)
But reality is a bit different.
In particular, there's much messaging between threads, and just to
make the point, the above is an actual case, not some hypothetical
silly-example.
You seem to be hinting at some dark secret only you know about. Do you
have any evidence to back up the claim? Perhaps a working sample where a
code similar to what you show causes problems?
Post by Alf P. Steinbach
I totally agree, it should. Ideally. Reality is that it doesn't. Or
didn't. Perhaps Microsoft has now fixed all their libraries (I doubt
it, however).
Again, can you show an example that would demonstrate the bug you
allege?
I don't like being called a liar.

And I'm not about to waste time (which could be hours) creating /more detailed/
example code for the badmouthed one.

Bye, best,


- Alf
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
George
2008-07-01 02:29:01 UTC
Permalink
Thanks Igor,
Post by Igor Tandetnik
So you think calling CoInitialize and then immediately CoUninitialize
(when COM was not initialized before on this thread) is well defined,
but calling CoInitialize, then doing some COM work, and then calling
CoUninitialize is somehow different. What exactly do you believe is the
difference between these two cases?
Under your theory, when is it ever safe to call CoInitialize and
CoUninitialize? You say that calling CoInitialize for the first time in
a thread is "unreliable" - wouldn't that mean there's no reliable way to
use COM at all?
I totally agree with you CoInitialize and CoInitializeEx are thread based,
not process based. How could you call CoUninitialize before call
CoInitialize? Could you show me the pseudo code please?


regards,
George
George
2008-07-01 02:19:02 UTC
Permalink
Thanks Alf,


I am confused about what do you mean the real issue in the 1st sample. In my
previous understanding, I think the issue is, if CoInitialize fails, you will
throw
throwX( "Unable to initalize COM" ) and no chance to call CoUninitialize?

Is that what you mean the issue? If not, could you clarify what is the issue
of the first sample do you mean please? :-)


regards,
George
Alf P. Steinbach
2008-07-01 06:20:56 UTC
Permalink
Post by George
Thanks Alf,
I am confused about what do you mean the real issue in the 1st sample. In my
previous understanding, I think the issue is, if CoInitialize fails, you will
throw
throwX( "Unable to initalize COM" ) and no chance to call CoUninitialize?
Is that what you mean the issue? If not, could you clarify what is the issue
of the first sample do you mean please? :-)
Quoting myself, "What you should do is to make sure that your driver code calls
CoInitialize and CoUninitialize, at top level.".

For whichever thread.

In a single-threaded program that means in 'main'.


Cheers, & hth.,

- Alf
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
George
2008-07-01 06:51:00 UTC
Permalink
Thanks Alf,


Actually I always initialize things in main to make things simple and clear.
But what are the harm if I put the initialization code like CoInitialize not
in main, but in the first MTA thread entry point (suppose main thread may not
be the part of the MTA thread)?
Could you show some samples of harm to make your points more impressive
please? :-)


regards,
George
Alf P. Steinbach
2008-07-01 07:03:28 UTC
Permalink
Post by George
Thanks Alf,
Actually I always initialize things in main to make things simple and clear.
Good.
Post by George
But what are the harm if I put the initialization code like CoInitialize not
in main, but in the first MTA thread entry point (suppose main thread may not
be the part of the MTA thread)?
I think that's OK.
Post by George
Could you show some samples of harm to make your points more impressive
please? :-)
No, because that's too much work. In some earlier time I'd do it. But I don't
have that drive anymore, sorry. You either grok my points, or not. Or if you
don't grok them, just follow the advice anyway.


Cheers, & hth.,

- Alf
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
George
2008-07-01 07:52:01 UTC
Permalink
Thanks Alf,


I feel it is always good to learn what other people doing and thinking
because oneself is too narrow minded. So, it is always good to learn from
code review or peer review. So, even if some code is bad, we can know why it
is bad in order to better understand why a practice is good.

Anyway, if it is convenient, could you let me know what are the issue of
your first sample if my analysis is wrong?


regards,
George

George
2008-07-01 02:15:00 UTC
Permalink
Thanks Igor,


1.
Post by Igor Tandetnik
If you are willing to do the complete CoInitialize / CoUninitialize
dance just for checking, why not do it for real as in the first example,
and actually use the freshly initialized apartment (since you have
already invoked the overhead anyway)?
The "freshly initialized apartment" you mean? Could you show the code you
refer to please? (sorry my English is not good.)

2.

BTW: when type bp CoInitialize in WinDbg, there will be a breakpoint set in
kernerl32!CoInitialize, do you think it is a bug? Since CoInitialize is
actually in ole32.dll.


regards,
George
Loading...