471,327 Members | 2,682 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,327 software developers and data experts.

Problem with threading/marshalling COM within .NET (?)

Hello,

First of all, this is a .NET 1.1 component I'm creating.

SUMMARY
-----------------------

This component that I'm creating is, for all intents and purposes, a
document parser (I'm actually deserializing a SOAP document into an
object and parsing out the fields, but that's fairly immaterial to this
issue).

This component is instantiated by a VB 6.0 "manager" object, and is
passed by reference a C++ COM data object which, in a separate thread
within the parser, I populate with a bunch of child objects that are
instantiated as necessary. This C++ COM object is basically a very
robust data object, which contains individual children which are record
nodes.

I should mention that I can't change the signature of the method that
receives the parameters, as the interface has been defined and locked
down already.

When I'm done with all my parsing, I invoke my callback method (as I
stated before, the parsing occurs on a separate thread), which then
notifies the manager that the parsing is complete, and that it can save
the contents of the data object (which it already has a handle to).

I've checked the active state of the child thread prior to notifying
the manager object, and it says it's no longer alive. I'm also in the
correct thread (I checked the names I assigned the threads) when I
notify the manager that parsing is complete. Finally, I explicitly set
both my main thread and child threads to have an apartment state of STA
(by decorating the appropriate methods in the main thread).

PROBLEM
---------------------------

My problem is that I get an error within the data object (after it has
been passed back into the VB manager, and my parsing has completed)
having to do with it being unable to write to the system security log.
**This does not appear to be the fault of the application, but rather,
my code's fault, because if I run all my code synchronously, the data
object is able to save everything fine, and is able to write to the
system security log.**

I'm passing in the data object to my child thread within the thread's
constructor (by reference), and, within that separate thread, it's able
to access and manipulate all the properties and methods necessary to
add/delete/modify threats.

QUESTION
--------------------

My question is, do I need to do something special (e.g. some esoteric
marshalling command) to ensure that the COM data object is not going to
get corrupted or become invalid for some reason within the child
thread? What typically is done to COM objects (wrapped in the RCW)
prior to them being passed into separate threads? Am I completely
missing something?

Anything you guys can suggest would be extremely helpful, as this is
pretty much the only issue holding me up now. I could post certain
sub-sections of the code, but it's pretty dense, so I wanted to try a
description of the issue first.

Ideally, someone can tell me exactly what I'm doing wrong because
they've experienced the problem before. Feel free to mock me if I've
done something extraordinarily stupid, as well!

Thanks in advance for any help you can give.

Regards,

Bryce

Feb 4 '06 #1
10 2368
Bryce,

I'm a little concerned about you passing the COM object reference to
another thread (and possibly, another apartment).

How are you marshaling the COM interface pointer? You can't just pass
COM interface pointers across threads (depending on the apartments). It
will cause problems if you are not careful here, to say the least. You have
to be aware of the apartment that the thread is in, as well as the apartment
that the component demands.

Also, the callback methods, are they COM interface pointers as well?
These have to be marshaled correctly to the thread making the callbacks.

You also state:

Finally, I explicitly set both my main thread and child threads to have an
apartment state of STA (by decorating the appropriate methods in the main
thread).

The attributes to set the apartment state for the main thread of an
application (like STAThread) only work for the entry point of the
application. From the documentation of STAThread:

Apply this attribute to the entry point method (the Main() method in C# and
Visual Basic). It has no effect on other methods. To set the apartment state
of threads you start in your code, use the Thread.SetApartmentState method
before starting the thread.

Looking at the problem statement, it appears that you have to marshal
the interface pointer correctly. You need to register on the global
interface table and pass the cookie, or you can marhsal to a stream and then
unmarshal it.

I'm a little vague on the details on how much of this is .NET code, and
how much is VB/C++ code. Needless to say, the mechanism will be the same in
all of them. What it comes down to is that you have to marshal COM
interface pointers across apartment boundaries correctly, and it looks like
you might not be defining those boundaries, or passing them correctly.

Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Bryce Calhoun" <bc******@gmail.com> wrote in message
news:11**********************@g47g2000cwa.googlegr oups.com...
Hello,

First of all, this is a .NET 1.1 component I'm creating.

SUMMARY
-----------------------

This component that I'm creating is, for all intents and purposes, a
document parser (I'm actually deserializing a SOAP document into an
object and parsing out the fields, but that's fairly immaterial to this
issue).

This component is instantiated by a VB 6.0 "manager" object, and is
passed by reference a C++ COM data object which, in a separate thread
within the parser, I populate with a bunch of child objects that are
instantiated as necessary. This C++ COM object is basically a very
robust data object, which contains individual children which are record
nodes.

I should mention that I can't change the signature of the method that
receives the parameters, as the interface has been defined and locked
down already.

When I'm done with all my parsing, I invoke my callback method (as I
stated before, the parsing occurs on a separate thread), which then
notifies the manager that the parsing is complete, and that it can save
the contents of the data object (which it already has a handle to).

I've checked the active state of the child thread prior to notifying
the manager object, and it says it's no longer alive. I'm also in the
correct thread (I checked the names I assigned the threads) when I
notify the manager that parsing is complete. Finally, I explicitly set
both my main thread and child threads to have an apartment state of STA
(by decorating the appropriate methods in the main thread).

PROBLEM
---------------------------

My problem is that I get an error within the data object (after it has
been passed back into the VB manager, and my parsing has completed)
having to do with it being unable to write to the system security log.
**This does not appear to be the fault of the application, but rather,
my code's fault, because if I run all my code synchronously, the data
object is able to save everything fine, and is able to write to the
system security log.**

I'm passing in the data object to my child thread within the thread's
constructor (by reference), and, within that separate thread, it's able
to access and manipulate all the properties and methods necessary to
add/delete/modify threats.

QUESTION
--------------------

My question is, do I need to do something special (e.g. some esoteric
marshalling command) to ensure that the COM data object is not going to
get corrupted or become invalid for some reason within the child
thread? What typically is done to COM objects (wrapped in the RCW)
prior to them being passed into separate threads? Am I completely
missing something?

Anything you guys can suggest would be extremely helpful, as this is
pretty much the only issue holding me up now. I could post certain
sub-sections of the code, but it's pretty dense, so I wanted to try a
description of the issue first.

Ideally, someone can tell me exactly what I'm doing wrong because
they've experienced the problem before. Feel free to mock me if I've
done something extraordinarily stupid, as well!

Thanks in advance for any help you can give.

Regards,

Bryce

Feb 5 '06 #2
Nicolas,

Let me see if I understand what you're saying:

1. For any COM object that I will be using within my child thread, I
need to explicitly marshal it across the thread boundary. Correct?

2. If this is the case, then I need to do a DLLImport of
CoMarshalInterThreadInterfaceInStream and
CoGetInterfaceAndReleaseStream and stick references to the COM objects
in my parameters class that I use as a means of passing parameters to
my child thread. Correct?

3. Any COM objects I create in my second thread and then add to my
Data Object (which would have been marshalled), I do not need to
explictly marshal, as the container object would have been marshalled
already?

4. When I invoke my callback from the child thread, the Data Object
and Error Handler objects which would have been marshaled and passed in
-- do I need to re-marshal them back to the primary thread, or can I
use the objects that I initially had a reference to?

5. Finally, would it be better/easier to use the GIT to marshal these
objects? If so, do you have some specific recommendation as to how I
should use it? That is, are there any code samples? As far as I
understand, I would need to do something like create an interface and a
wrapper class to implement it, and it's not very clear how I would do
so.

6. Doesn't .NET take care of marshalling native .NET objects across
threads automatically? Why doesn't it handle marshalling COM objects
(which, in my case, have already been wrapped in a RCW)? Just a simple
explanation would suffice, I'm mildly curious.

Nicholas, thank you very much for your suggestions and help thus far.
I truly appreciate any further help you can provide.

Kind regards,

Bryce

Feb 5 '06 #3
You don't have to marshal interface pointers yourself, The CLR takes care
of this for you by calling ole32!CoMarshalInterface whenever an ITF pointer
changes context.

Willy.


"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard.caspershouse.com> wrote in
message news:ei*************@TK2MSFTNGP14.phx.gbl...
| Bryce,
|
| I'm a little concerned about you passing the COM object reference to
| another thread (and possibly, another apartment).
|
| How are you marshaling the COM interface pointer? You can't just pass
| COM interface pointers across threads (depending on the apartments). It
| will cause problems if you are not careful here, to say the least. You
have
| to be aware of the apartment that the thread is in, as well as the
apartment
| that the component demands.
|
| Also, the callback methods, are they COM interface pointers as well?
| These have to be marshaled correctly to the thread making the callbacks.
|
| You also state:
|
| Finally, I explicitly set both my main thread and child threads to have an
| apartment state of STA (by decorating the appropriate methods in the main
| thread).
|
| The attributes to set the apartment state for the main thread of an
| application (like STAThread) only work for the entry point of the
| application. From the documentation of STAThread:
|
| Apply this attribute to the entry point method (the Main() method in C#
and
| Visual Basic). It has no effect on other methods. To set the apartment
state
| of threads you start in your code, use the Thread.SetApartmentState method
| before starting the thread.
|
| Looking at the problem statement, it appears that you have to marshal
| the interface pointer correctly. You need to register on the global
| interface table and pass the cookie, or you can marhsal to a stream and
then
| unmarshal it.
|
| I'm a little vague on the details on how much of this is .NET code, and
| how much is VB/C++ code. Needless to say, the mechanism will be the same
in
| all of them. What it comes down to is that you have to marshal COM
| interface pointers across apartment boundaries correctly, and it looks
like
| you might not be defining those boundaries, or passing them correctly.
|
| Hope this helps.
|
|
| --
| - Nicholas Paldino [.NET/C# MVP]
| - mv*@spam.guard.caspershouse.com
|
| "Bryce Calhoun" <bc******@gmail.com> wrote in message
| news:11**********************@g47g2000cwa.googlegr oups.com...
| > Hello,
| >
| > First of all, this is a .NET 1.1 component I'm creating.
| >
| > SUMMARY
| > -----------------------
| >
| > This component that I'm creating is, for all intents and purposes, a
| > document parser (I'm actually deserializing a SOAP document into an
| > object and parsing out the fields, but that's fairly immaterial to this
| > issue).
| >
| > This component is instantiated by a VB 6.0 "manager" object, and is
| > passed by reference a C++ COM data object which, in a separate thread
| > within the parser, I populate with a bunch of child objects that are
| > instantiated as necessary. This C++ COM object is basically a very
| > robust data object, which contains individual children which are record
| > nodes.
| >
| > I should mention that I can't change the signature of the method that
| > receives the parameters, as the interface has been defined and locked
| > down already.
| >
| > When I'm done with all my parsing, I invoke my callback method (as I
| > stated before, the parsing occurs on a separate thread), which then
| > notifies the manager that the parsing is complete, and that it can save
| > the contents of the data object (which it already has a handle to).
| >
| > I've checked the active state of the child thread prior to notifying
| > the manager object, and it says it's no longer alive. I'm also in the
| > correct thread (I checked the names I assigned the threads) when I
| > notify the manager that parsing is complete. Finally, I explicitly set
| > both my main thread and child threads to have an apartment state of STA
| > (by decorating the appropriate methods in the main thread).
| >
| > PROBLEM
| > ---------------------------
| >
| > My problem is that I get an error within the data object (after it has
| > been passed back into the VB manager, and my parsing has completed)
| > having to do with it being unable to write to the system security log.
| >
| >
| > **This does not appear to be the fault of the application, but rather,
| > my code's fault, because if I run all my code synchronously, the data
| > object is able to save everything fine, and is able to write to the
| > system security log.**
| >
| > I'm passing in the data object to my child thread within the thread's
| > constructor (by reference), and, within that separate thread, it's able
| > to access and manipulate all the properties and methods necessary to
| > add/delete/modify threats.
| >
| > QUESTION
| > --------------------
| >
| > My question is, do I need to do something special (e.g. some esoteric
| > marshalling command) to ensure that the COM data object is not going to
| > get corrupted or become invalid for some reason within the child
| > thread? What typically is done to COM objects (wrapped in the RCW)
| > prior to them being passed into separate threads? Am I completely
| > missing something?
| >
| > Anything you guys can suggest would be extremely helpful, as this is
| > pretty much the only issue holding me up now. I could post certain
| > sub-sections of the code, but it's pretty dense, so I wanted to try a
| > description of the issue first.
| >
| > Ideally, someone can tell me exactly what I'm doing wrong because
| > they've experienced the problem before. Feel free to mock me if I've
| > done something extraordinarily stupid, as well!
| >
| > Thanks in advance for any help you can give.
| >
| > Regards,
| >
| > Bryce
| >
|
|
Feb 6 '06 #4
So, Willy, you're saying I don't need to explictly marshal the
interface pointers? That was what I had understood -- do you have any
ideas why I might be experiencing the problem with the COM object
failing to write to the security log after it runs in another thread?

Thanks,

Bryce

Willy Denoyette [MVP] wrote:
You don't have to marshal interface pointers yourself, The CLR takes care
of this for you by calling ole32!CoMarshalInterface whenever an ITF pointer
changes context.

Willy.


"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard.caspershouse.com> wrote in
message news:ei*************@TK2MSFTNGP14.phx.gbl...
| Bryce,
|
| I'm a little concerned about you passing the COM object reference to
| another thread (and possibly, another apartment).
|
| How are you marshaling the COM interface pointer? You can't just pass
| COM interface pointers across threads (depending on the apartments). It
| will cause problems if you are not careful here, to say the least. You
have
| to be aware of the apartment that the thread is in, as well as the
apartment
| that the component demands.
|
| Also, the callback methods, are they COM interface pointers as well?
| These have to be marshaled correctly to the thread making the callbacks.
|
| You also state:
|
| Finally, I explicitly set both my main thread and child threads to have an
| apartment state of STA (by decorating the appropriate methods in the main
| thread).
|
| The attributes to set the apartment state for the main thread of an
| application (like STAThread) only work for the entry point of the
| application. From the documentation of STAThread:
|
| Apply this attribute to the entry point method (the Main() method in C#
and
| Visual Basic). It has no effect on other methods. To set the apartment
state
| of threads you start in your code, use the Thread.SetApartmentState method
| before starting the thread.
|
| Looking at the problem statement, it appears that you have to marshal
| the interface pointer correctly. You need to register on the global
| interface table and pass the cookie, or you can marhsal to a stream and
then
| unmarshal it.
|
| I'm a little vague on the details on how much of this is .NET code, and
| how much is VB/C++ code. Needless to say, the mechanism will be the same
in
| all of them. What it comes down to is that you have to marshal COM
| interface pointers across apartment boundaries correctly, and it looks
like
| you might not be defining those boundaries, or passing them correctly.
|
| Hope this helps.
|
|
| --
| - Nicholas Paldino [.NET/C# MVP]
| - mv*@spam.guard.caspershouse.com
|
| "Bryce Calhoun" <bc******@gmail.com> wrote in message
| news:11**********************@g47g2000cwa.googlegr oups.com...
| > Hello,
| >
| > First of all, this is a .NET 1.1 component I'm creating.
| >
| > SUMMARY
| > -----------------------
| >
| > This component that I'm creating is, for all intents and purposes, a
| > document parser (I'm actually deserializing a SOAP document into an
| > object and parsing out the fields, but that's fairly immaterial to this
| > issue).
| >
| > This component is instantiated by a VB 6.0 "manager" object, and is
| > passed by reference a C++ COM data object which, in a separate thread
| > within the parser, I populate with a bunch of child objects that are
| > instantiated as necessary. This C++ COM object is basically a very
| > robust data object, which contains individual children which are record
| > nodes.
| >
| > I should mention that I can't change the signature of the method that
| > receives the parameters, as the interface has been defined and locked
| > down already.
| >
| > When I'm done with all my parsing, I invoke my callback method (as I
| > stated before, the parsing occurs on a separate thread), which then
| > notifies the manager that the parsing is complete, and that it can save
| > the contents of the data object (which it already has a handle to).
| >
| > I've checked the active state of the child thread prior to notifying
| > the manager object, and it says it's no longer alive. I'm also in the
| > correct thread (I checked the names I assigned the threads) when I
| > notify the manager that parsing is complete. Finally, I explicitly set
| > both my main thread and child threads to have an apartment state of STA
| > (by decorating the appropriate methods in the main thread).
| >
| > PROBLEM
| > ---------------------------
| >
| > My problem is that I get an error within the data object (after it has
| > been passed back into the VB manager, and my parsing has completed)
| > having to do with it being unable to write to the system security log.
| >
| >
| > **This does not appear to be the fault of the application, but rather,
| > my code's fault, because if I run all my code synchronously, the data
| > object is able to save everything fine, and is able to write to the
| > system security log.**
| >
| > I'm passing in the data object to my child thread within the thread's
| > constructor (by reference), and, within that separate thread, it's able
| > to access and manipulate all the properties and methods necessary to
| > add/delete/modify threats.
| >
| > QUESTION
| > --------------------
| >
| > My question is, do I need to do something special (e.g. some esoteric
| > marshalling command) to ensure that the COM data object is not going to
| > get corrupted or become invalid for some reason within the child
| > thread? What typically is done to COM objects (wrapped in the RCW)
| > prior to them being passed into separate threads? Am I completely
| > missing something?
| >
| > Anything you guys can suggest would be extremely helpful, as this is
| > pretty much the only issue holding me up now. I could post certain
| > sub-sections of the code, but it's pretty dense, so I wanted to try a
| > description of the issue first.
| >
| > Ideally, someone can tell me exactly what I'm doing wrong because
| > they've experienced the problem before. Feel free to mock me if I've
| > done something extraordinarily stupid, as well!
| >
| > Thanks in advance for any help you can give.
| >
| > Regards,
| >
| > Bryce
| >
|
|


Feb 6 '06 #5
Bryce,

Well, just like Nicholas, I wonder what you mean with decoration your
methods with the STA attribute, only Main can be marked as such, as I
suppose you know this too, I'm affraid to be missing something.

Anyway, the "access denied error" (supposed this is the error you see) when
accessing the security log is not related with interface marshaling. My
questions are, which thread handles the writing into the security log, what
is it's apartment state and what't the thread identity? What's the thread
APT. state and it's identiy when it scceeds (in "synchronous" mode).
Normally only the security system is allowed to write into the security log,
that means you run with elevated privileges, question is at which level, the
process or thread level?

Willy.

"Bryce Calhoun" <bc******@gmail.com> wrote in message
news:11**********************@z14g2000cwz.googlegr oups.com...
| So, Willy, you're saying I don't need to explictly marshal the
| interface pointers? That was what I had understood -- do you have any
| ideas why I might be experiencing the problem with the COM object
| failing to write to the security log after it runs in another thread?
|
| Thanks,
|
| Bryce
|
| Willy Denoyette [MVP] wrote:
| > You don't have to marshal interface pointers yourself, The CLR takes
care
| > of this for you by calling ole32!CoMarshalInterface whenever an ITF
pointer
| > changes context.
| >
| > Willy.
| >
| >
| >
| >
| > "Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard.caspershouse.com> wrote
in
| > message news:ei*************@TK2MSFTNGP14.phx.gbl...
| > | Bryce,
| > |
| > | I'm a little concerned about you passing the COM object reference
to
| > | another thread (and possibly, another apartment).
| > |
| > | How are you marshaling the COM interface pointer? You can't just
pass
| > | COM interface pointers across threads (depending on the apartments).
It
| > | will cause problems if you are not careful here, to say the least.
You
| > have
| > | to be aware of the apartment that the thread is in, as well as the
| > apartment
| > | that the component demands.
| > |
| > | Also, the callback methods, are they COM interface pointers as
well?
| > | These have to be marshaled correctly to the thread making the
callbacks.
| > |
| > | You also state:
| > |
| > | Finally, I explicitly set both my main thread and child threads to
have an
| > | apartment state of STA (by decorating the appropriate methods in the
main
| > | thread).
| > |
| > | The attributes to set the apartment state for the main thread of an
| > | application (like STAThread) only work for the entry point of the
| > | application. From the documentation of STAThread:
| > |
| > | Apply this attribute to the entry point method (the Main() method in
C#
| > and
| > | Visual Basic). It has no effect on other methods. To set the apartment
| > state
| > | of threads you start in your code, use the Thread.SetApartmentState
method
| > | before starting the thread.
| > |
| > | Looking at the problem statement, it appears that you have to
marshal
| > | the interface pointer correctly. You need to register on the global
| > | interface table and pass the cookie, or you can marhsal to a stream
and
| > then
| > | unmarshal it.
| > |
| > | I'm a little vague on the details on how much of this is .NET code,
and
| > | how much is VB/C++ code. Needless to say, the mechanism will be the
same
| > in
| > | all of them. What it comes down to is that you have to marshal COM
| > | interface pointers across apartment boundaries correctly, and it looks
| > like
| > | you might not be defining those boundaries, or passing them correctly.
| > |
| > | Hope this helps.
| > |
| > |
| > | --
| > | - Nicholas Paldino [.NET/C# MVP]
| > | - mv*@spam.guard.caspershouse.com
| > |
| > | "Bryce Calhoun" <bc******@gmail.com> wrote in message
| > | news:11**********************@g47g2000cwa.googlegr oups.com...
| > | > Hello,
| > | >
| > | > First of all, this is a .NET 1.1 component I'm creating.
| > | >
| > | > SUMMARY
| > | > -----------------------
| > | >
| > | > This component that I'm creating is, for all intents and purposes, a
| > | > document parser (I'm actually deserializing a SOAP document into an
| > | > object and parsing out the fields, but that's fairly immaterial to
this
| > | > issue).
| > | >
| > | > This component is instantiated by a VB 6.0 "manager" object, and is
| > | > passed by reference a C++ COM data object which, in a separate
thread
| > | > within the parser, I populate with a bunch of child objects that are
| > | > instantiated as necessary. This C++ COM object is basically a very
| > | > robust data object, which contains individual children which are
record
| > | > nodes.
| > | >
| > | > I should mention that I can't change the signature of the method
that
| > | > receives the parameters, as the interface has been defined and
locked
| > | > down already.
| > | >
| > | > When I'm done with all my parsing, I invoke my callback method (as I
| > | > stated before, the parsing occurs on a separate thread), which then
| > | > notifies the manager that the parsing is complete, and that it can
save
| > | > the contents of the data object (which it already has a handle to).
| > | >
| > | > I've checked the active state of the child thread prior to notifying
| > | > the manager object, and it says it's no longer alive. I'm also in
the
| > | > correct thread (I checked the names I assigned the threads) when I
| > | > notify the manager that parsing is complete. Finally, I explicitly
set
| > | > both my main thread and child threads to have an apartment state of
STA
| > | > (by decorating the appropriate methods in the main thread).
| > | >
| > | > PROBLEM
| > | > ---------------------------
| > | >
| > | > My problem is that I get an error within the data object (after it
has
| > | > been passed back into the VB manager, and my parsing has completed)
| > | > having to do with it being unable to write to the system security
log.
| > | >
| > | >
| > | > **This does not appear to be the fault of the application, but
rather,
| > | > my code's fault, because if I run all my code synchronously, the
data
| > | > object is able to save everything fine, and is able to write to the
| > | > system security log.**
| > | >
| > | > I'm passing in the data object to my child thread within the
thread's
| > | > constructor (by reference), and, within that separate thread, it's
able
| > | > to access and manipulate all the properties and methods necessary to
| > | > add/delete/modify threats.
| > | >
| > | > QUESTION
| > | > --------------------
| > | >
| > | > My question is, do I need to do something special (e.g. some
esoteric
| > | > marshalling command) to ensure that the COM data object is not going
to
| > | > get corrupted or become invalid for some reason within the child
| > | > thread? What typically is done to COM objects (wrapped in the RCW)
| > | > prior to them being passed into separate threads? Am I completely
| > | > missing something?
| > | >
| > | > Anything you guys can suggest would be extremely helpful, as this is
| > | > pretty much the only issue holding me up now. I could post certain
| > | > sub-sections of the code, but it's pretty dense, so I wanted to try
a
| > | > description of the issue first.
| > | >
| > | > Ideally, someone can tell me exactly what I'm doing wrong because
| > | > they've experienced the problem before. Feel free to mock me if
I've
| > | > done something extraordinarily stupid, as well!
| > | >
| > | > Thanks in advance for any help you can give.
| > | >
| > | > Regards,
| > | >
| > | > Bryce
| > | >
| > |
| > |
|
Feb 6 '06 #6
Ah-hah!

I figured out what I was doing. In the method that sends a response
back to the VB manager application, I was executing a SendMessage call
(which, duh, is synchronous) as opposed to a PostMessage (which doesn't
bother waiting for a response).

So, my second thread was still active while the SendMessage was being
processed, thus the failure writing to the security log, because that
was happening on the child thread as well!

Thank you both for your incredible help -- it definitely led me down
the correct path!

Regards,

Bryce

Willy Denoyette [MVP] wrote:
Bryce,

Well, just like Nicholas, I wonder what you mean with decoration your
methods with the STA attribute, only Main can be marked as such, as I
suppose you know this too, I'm affraid to be missing something.

Anyway, the "access denied error" (supposed this is the error you see) when
accessing the security log is not related with interface marshaling. My
questions are, which thread handles the writing into the security log, what
is it's apartment state and what't the thread identity? What's the thread
APT. state and it's identiy when it scceeds (in "synchronous" mode).
Normally only the security system is allowed to write into the security log,
that means you run with elevated privileges, question is at which level, the
process or thread level?

Willy.

"Bryce Calhoun" <bc******@gmail.com> wrote in message
news:11**********************@z14g2000cwz.googlegr oups.com...
| So, Willy, you're saying I don't need to explictly marshal the
| interface pointers? That was what I had understood -- do you have any
| ideas why I might be experiencing the problem with the COM object
| failing to write to the security log after it runs in another thread?
|
| Thanks,
|
| Bryce
|
| Willy Denoyette [MVP] wrote:
| > You don't have to marshal interface pointers yourself, The CLR takes
care
| > of this for you by calling ole32!CoMarshalInterface whenever an ITF
pointer
| > changes context.
| >
| > Willy.
| >
| >
| >
| >
| > "Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard.caspershouse.com> wrote
in
| > message news:ei*************@TK2MSFTNGP14.phx.gbl...
| > | Bryce,
| > |
| > | I'm a little concerned about you passing the COM object reference
to
| > | another thread (and possibly, another apartment).
| > |
| > | How are you marshaling the COM interface pointer? You can't just
pass
| > | COM interface pointers across threads (depending on the apartments).
It
| > | will cause problems if you are not careful here, to say the least.
You
| > have
| > | to be aware of the apartment that the thread is in, as well as the
| > apartment
| > | that the component demands.
| > |
| > | Also, the callback methods, are they COM interface pointers as
well?
| > | These have to be marshaled correctly to the thread making the
callbacks.
| > |
| > | You also state:
| > |
| > | Finally, I explicitly set both my main thread and child threads to
have an
| > | apartment state of STA (by decorating the appropriate methods in the
main
| > | thread).
| > |
| > | The attributes to set the apartment state for the main thread of an
| > | application (like STAThread) only work for the entry point of the
| > | application. From the documentation of STAThread:
| > |
| > | Apply this attribute to the entry point method (the Main() method in
C#
| > and
| > | Visual Basic). It has no effect on other methods. To set the apartment
| > state
| > | of threads you start in your code, use the Thread.SetApartmentState
method
| > | before starting the thread.
| > |
| > | Looking at the problem statement, it appears that you have to
marshal
| > | the interface pointer correctly. You need to register on the global
| > | interface table and pass the cookie, or you can marhsal to a stream
and
| > then
| > | unmarshal it.
| > |
| > | I'm a little vague on the details on how much of this is .NET code,
and
| > | how much is VB/C++ code. Needless to say, the mechanism will be the
same
| > in
| > | all of them. What it comes down to is that you have to marshal COM
| > | interface pointers across apartment boundaries correctly, and it looks
| > like
| > | you might not be defining those boundaries, or passing them correctly.
| > |
| > | Hope this helps.
| > |
| > |
| > | --
| > | - Nicholas Paldino [.NET/C# MVP]
| > | - mv*@spam.guard.caspershouse.com
| > |
| > | "Bryce Calhoun" <bc******@gmail.com> wrote in message
| > | news:11**********************@g47g2000cwa.googlegr oups.com...
| > | > Hello,
| > | >
| > | > First of all, this is a .NET 1.1 component I'm creating.
| > | >
| > | > SUMMARY
| > | > -----------------------
| > | >
| > | > This component that I'm creating is, for all intents and purposes, a
| > | > document parser (I'm actually deserializing a SOAP document into an
| > | > object and parsing out the fields, but that's fairly immaterial to
this
| > | > issue).
| > | >
| > | > This component is instantiated by a VB 6.0 "manager" object, and is
| > | > passed by reference a C++ COM data object which, in a separate
thread
| > | > within the parser, I populate with a bunch of child objects that are
| > | > instantiated as necessary. This C++ COM object is basically a very
| > | > robust data object, which contains individual children which are
record
| > | > nodes.
| > | >
| > | > I should mention that I can't change the signature of the method
that
| > | > receives the parameters, as the interface has been defined and
locked
| > | > down already.
| > | >
| > | > When I'm done with all my parsing, I invoke my callback method (as I
| > | > stated before, the parsing occurs on a separate thread), which then
| > | > notifies the manager that the parsing is complete, and that it can
save
| > | > the contents of the data object (which it already has a handle to).
| > | >
| > | > I've checked the active state of the child thread prior to notifying
| > | > the manager object, and it says it's no longer alive. I'm also in
the
| > | > correct thread (I checked the names I assigned the threads) when I
| > | > notify the manager that parsing is complete. Finally, I explicitly
set
| > | > both my main thread and child threads to have an apartment state of
STA
| > | > (by decorating the appropriate methods in the main thread).
| > | >
| > | > PROBLEM
| > | > ---------------------------
| > | >
| > | > My problem is that I get an error within the data object (after it
has
| > | > been passed back into the VB manager, and my parsing has completed)
| > | > having to do with it being unable to write to the system security
log.
| > | >
| > | >
| > | > **This does not appear to be the fault of the application, but
rather,
| > | > my code's fault, because if I run all my code synchronously, the
data
| > | > object is able to save everything fine, and is able to write to the
| > | > system security log.**
| > | >
| > | > I'm passing in the data object to my child thread within the
thread's
| > | > constructor (by reference), and, within that separate thread, it's
able
| > | > to access and manipulate all the properties and methods necessary to
| > | > add/delete/modify threats.
| > | >
| > | > QUESTION
| > | > --------------------
| > | >
| > | > My question is, do I need to do something special (e.g. some
esoteric
| > | > marshalling command) to ensure that the COM data object is not going
to
| > | > get corrupted or become invalid for some reason within the child
| > | > thread? What typically is done to COM objects (wrapped in the RCW)
| > | > prior to them being passed into separate threads? Am I completely
| > | > missing something?
| > | >
| > | > Anything you guys can suggest would be extremely helpful, as this is
| > | > pretty much the only issue holding me up now. I could post certain
| > | > sub-sections of the code, but it's pretty dense, so I wanted to try
a
| > | > description of the issue first.
| > | >
| > | > Ideally, someone can tell me exactly what I'm doing wrong because
| > | > they've experienced the problem before. Feel free to mock me if
I've
| > | > done something extraordinarily stupid, as well!
| > | >
| > | > Thanks in advance for any help you can give.
| > | >
| > | > Regards,
| > | >
| > | > Bryce
| > | >
| > |
| > |
|


Feb 7 '06 #7
Sorry, but I don't get this. How did you manage to write to the "security
log", this is not a privilege you hold normaly, more on anything else than
W2K3 just impossible, mind to explain?

Willy.

"Bryce Calhoun" <bc******@gmail.com> wrote in message
news:11**********************@g43g2000cwa.googlegr oups.com...
| Ah-hah!
|
| I figured out what I was doing. In the method that sends a response
| back to the VB manager application, I was executing a SendMessage call
| (which, duh, is synchronous) as opposed to a PostMessage (which doesn't
| bother waiting for a response).
|
| So, my second thread was still active while the SendMessage was being
| processed, thus the failure writing to the security log, because that
| was happening on the child thread as well!
|
| Thank you both for your incredible help -- it definitely led me down
| the correct path!
|
| Regards,
|
| Bryce
|
| Willy Denoyette [MVP] wrote:
| > Bryce,
| >
| > Well, just like Nicholas, I wonder what you mean with decoration your
| > methods with the STA attribute, only Main can be marked as such, as I
| > suppose you know this too, I'm affraid to be missing something.
| >
| > Anyway, the "access denied error" (supposed this is the error you see)
when
| > accessing the security log is not related with interface marshaling. My
| > questions are, which thread handles the writing into the security log,
what
| > is it's apartment state and what't the thread identity? What's the
thread
| > APT. state and it's identiy when it scceeds (in "synchronous" mode).
| > Normally only the security system is allowed to write into the security
log,
| > that means you run with elevated privileges, question is at which level,
the
| > process or thread level?
| >
| > Willy.
| >
| >
| >
| >
| >
| > "Bryce Calhoun" <bc******@gmail.com> wrote in message
| > news:11**********************@z14g2000cwz.googlegr oups.com...
| > | So, Willy, you're saying I don't need to explictly marshal the
| > | interface pointers? That was what I had understood -- do you have any
| > | ideas why I might be experiencing the problem with the COM object
| > | failing to write to the security log after it runs in another thread?
| > |
| > | Thanks,
| > |
| > | Bryce
| > |
| > | Willy Denoyette [MVP] wrote:
| > | > You don't have to marshal interface pointers yourself, The CLR takes
| > care
| > | > of this for you by calling ole32!CoMarshalInterface whenever an ITF
| > pointer
| > | > changes context.
| > | >
| > | > Willy.
| > | >
| > | >
| > | >
| > | >
| > | > "Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard.caspershouse.com>
wrote
| > in
| > | > message news:ei*************@TK2MSFTNGP14.phx.gbl...
| > | > | Bryce,
| > | > |
| > | > | I'm a little concerned about you passing the COM object
reference
| > to
| > | > | another thread (and possibly, another apartment).
| > | > |
| > | > | How are you marshaling the COM interface pointer? You can't
just
| > pass
| > | > | COM interface pointers across threads (depending on the
apartments).
| > It
| > | > | will cause problems if you are not careful here, to say the least.
| > You
| > | > have
| > | > | to be aware of the apartment that the thread is in, as well as the
| > | > apartment
| > | > | that the component demands.
| > | > |
| > | > | Also, the callback methods, are they COM interface pointers as
| > well?
| > | > | These have to be marshaled correctly to the thread making the
| > callbacks.
| > | > |
| > | > | You also state:
| > | > |
| > | > | Finally, I explicitly set both my main thread and child threads to
| > have an
| > | > | apartment state of STA (by decorating the appropriate methods in
the
| > main
| > | > | thread).
| > | > |
| > | > | The attributes to set the apartment state for the main thread
of an
| > | > | application (like STAThread) only work for the entry point of the
| > | > | application. From the documentation of STAThread:
| > | > |
| > | > | Apply this attribute to the entry point method (the Main() method
in
| > C#
| > | > and
| > | > | Visual Basic). It has no effect on other methods. To set the
apartment
| > | > state
| > | > | of threads you start in your code, use the
Thread.SetApartmentState
| > method
| > | > | before starting the thread.
| > | > |
| > | > | Looking at the problem statement, it appears that you have to
| > marshal
| > | > | the interface pointer correctly. You need to register on the
global
| > | > | interface table and pass the cookie, or you can marhsal to a
stream
| > and
| > | > then
| > | > | unmarshal it.
| > | > |
| > | > | I'm a little vague on the details on how much of this is .NET
code,
| > and
| > | > | how much is VB/C++ code. Needless to say, the mechanism will be
the
| > same
| > | > in
| > | > | all of them. What it comes down to is that you have to marshal
COM
| > | > | interface pointers across apartment boundaries correctly, and it
looks
| > | > like
| > | > | you might not be defining those boundaries, or passing them
correctly.
| > | > |
| > | > | Hope this helps.
| > | > |
| > | > |
| > | > | --
| > | > | - Nicholas Paldino [.NET/C# MVP]
| > | > | - mv*@spam.guard.caspershouse.com
| > | > |
| > | > | "Bryce Calhoun" <bc******@gmail.com> wrote in message
| > | > | news:11**********************@g47g2000cwa.googlegr oups.com...
| > | > | > Hello,
| > | > | >
| > | > | > First of all, this is a .NET 1.1 component I'm creating.
| > | > | >
| > | > | > SUMMARY
| > | > | > -----------------------
| > | > | >
| > | > | > This component that I'm creating is, for all intents and
purposes, a
| > | > | > document parser (I'm actually deserializing a SOAP document into
an
| > | > | > object and parsing out the fields, but that's fairly immaterial
to
| > this
| > | > | > issue).
| > | > | >
| > | > | > This component is instantiated by a VB 6.0 "manager" object, and
is
| > | > | > passed by reference a C++ COM data object which, in a separate
| > thread
| > | > | > within the parser, I populate with a bunch of child objects that
are
| > | > | > instantiated as necessary. This C++ COM object is basically a
very
| > | > | > robust data object, which contains individual children which are
| > record
| > | > | > nodes.
| > | > | >
| > | > | > I should mention that I can't change the signature of the method
| > that
| > | > | > receives the parameters, as the interface has been defined and
| > locked
| > | > | > down already.
| > | > | >
| > | > | > When I'm done with all my parsing, I invoke my callback method
(as I
| > | > | > stated before, the parsing occurs on a separate thread), which
then
| > | > | > notifies the manager that the parsing is complete, and that it
can
| > save
| > | > | > the contents of the data object (which it already has a handle
to).
| > | > | >
| > | > | > I've checked the active state of the child thread prior to
notifying
| > | > | > the manager object, and it says it's no longer alive. I'm also
in
| > the
| > | > | > correct thread (I checked the names I assigned the threads) when
I
| > | > | > notify the manager that parsing is complete. Finally, I
explicitly
| > set
| > | > | > both my main thread and child threads to have an apartment state
of
| > STA
| > | > | > (by decorating the appropriate methods in the main thread).
| > | > | >
| > | > | > PROBLEM
| > | > | > ---------------------------
| > | > | >
| > | > | > My problem is that I get an error within the data object (after
it
| > has
| > | > | > been passed back into the VB manager, and my parsing has
completed)
| > | > | > having to do with it being unable to write to the system
security
| > log.
| > | > | >
| > | > | >
| > | > | > **This does not appear to be the fault of the application, but
| > rather,
| > | > | > my code's fault, because if I run all my code synchronously, the
| > data
| > | > | > object is able to save everything fine, and is able to write to
the
| > | > | > system security log.**
| > | > | >
| > | > | > I'm passing in the data object to my child thread within the
| > thread's
| > | > | > constructor (by reference), and, within that separate thread,
it's
| > able
| > | > | > to access and manipulate all the properties and methods
necessary to
| > | > | > add/delete/modify threats.
| > | > | >
| > | > | > QUESTION
| > | > | > --------------------
| > | > | >
| > | > | > My question is, do I need to do something special (e.g. some
| > esoteric
| > | > | > marshalling command) to ensure that the COM data object is not
going
| > to
| > | > | > get corrupted or become invalid for some reason within the child
| > | > | > thread? What typically is done to COM objects (wrapped in the
RCW)
| > | > | > prior to them being passed into separate threads? Am I
completely
| > | > | > missing something?
| > | > | >
| > | > | > Anything you guys can suggest would be extremely helpful, as
this is
| > | > | > pretty much the only issue holding me up now. I could post
certain
| > | > | > sub-sections of the code, but it's pretty dense, so I wanted to
try
| > a
| > | > | > description of the issue first.
| > | > | >
| > | > | > Ideally, someone can tell me exactly what I'm doing wrong
because
| > | > | > they've experienced the problem before. Feel free to mock me if
| > I've
| > | > | > done something extraordinarily stupid, as well!
| > | > | >
| > | > | > Thanks in advance for any help you can give.
| > | > | >
| > | > | > Regards,
| > | > | >
| > | > | > Bryce
| > | > | >
| > | > |
| > | > |
| > |
|
Feb 7 '06 #8
Willy,

A separate COM object within the calling component (the Manager code)
writes to the security log. I didn't write this component, so I'm not
sure how it's being done...but it obviously needs to happen on the main
thread.

Bryce

Feb 7 '06 #9

"Bryce Calhoun" <bc******@gmail.com> wrote in message
news:11**********************@g44g2000cwa.googlegr oups.com...
| Willy,
|
| A separate COM object within the calling component (the Manager code)
| writes to the security log. I didn't write this component, so I'm not
| sure how it's being done...but it obviously needs to happen on the main
| thread.
|
| Bryce
|

Bryce,
Whatever, COM or not, there is only one single "piece of code" in the OS
(even on W2K3) that can write into the "security log", it's the LSA (the
local security authority) which is an integral part of the "security
system". If you happen to have a COM component that can write to this
security eventlog, I wonder what else it can do. Did you ever try yourself
to write something to the security log from a simple console application? No
matter which identity you run with (even SYSTEM), you won't be able to do
it. Honestly, if you are sure about this and if you care about security I
would be scared, all I can say is that the security of your system is
broken.

Willy.

Feb 7 '06 #10
Willy,

I'll look into this. Thank you (again) for the heads-up.

Bryce

Willy Denoyette [MVP] wrote:
"Bryce Calhoun" <bc******@gmail.com> wrote in message
news:11**********************@g44g2000cwa.googlegr oups.com...
| Willy,
|
| A separate COM object within the calling component (the Manager code)
| writes to the security log. I didn't write this component, so I'm not
| sure how it's being done...but it obviously needs to happen on the main
| thread.
|
| Bryce
|

Bryce,
Whatever, COM or not, there is only one single "piece of code" in the OS
(even on W2K3) that can write into the "security log", it's the LSA (the
local security authority) which is an integral part of the "security
system". If you happen to have a COM component that can write to this
security eventlog, I wonder what else it can do. Did you ever try yourself
to write something to the security log from a simple console application? No
matter which identity you run with (even SYSTEM), you won't be able to do
it. Honestly, if you are sure about this and if you care about security I
would be scared, all I can say is that the security of your system is
broken.

Willy.


Feb 7 '06 #11

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

9 posts views Thread by John Lull | last post: by
6 posts views Thread by Patty O'Dors | last post: by
reply views Thread by Paul Cotgrove | last post: by
4 posts views Thread by Bob | last post: by
14 posts views Thread by Christian Kaiser | last post: by
18 posts views Thread by Chubbly Geezer | last post: by
reply views Thread by Robin Becker | last post: by
reply views Thread by rosydwin | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.