Marshalling tutorial

Mike Hearn mh at codeweavers.com
Sun Jul 25 12:14:10 CDT 2004


On Sun, 2004-07-25 at 11:27 +0200, Ove Kaaven wrote:
> The answer is of course that COM doesn't assume that objects actually
> are thread-safe. Most real-world objects aren't, in fact, for various
> reasons. What these reasons are isn't too important here, though, it's
> just important to realize that the problem of thread-unsafe objects is
> what COM tries hard to solve with its apartment model. There are also
> ways to tell COM that your object is truly thread-safe (namely the
> free-threaded marshaller). In general, no object is truly thread-safe if
> it could potentially use another not so thread-safe object, though, so
> the free-threaded marshaller is less used than you'd think.

Right.

> Perhaps you should spell out "QueryInterface-d", instead of saying
> "QId".

Yeah, I suppose I should be as explicit as possible with this topic.

Actually I found out later that I was wrong anyway. You can't just take
a proxy and QueryInterface it to IRpcProxyBuffer as they have two
physically separate vtables. If you want to control the proxy you have
to use a separate vtable that is only ever returned by the CreateProxy
function and cannot be accessed any other way.

> It depends on the Windows version, I think. Windows 95 and Windows NT 4
> certainly had very different models when I looked. I'm pretty sure the
> Windows 98 version of RPCRT4 was able to dispatch messages directly to
> individual apartments. I'd be surprised if some similar functionality
> was not added to Windows 2000. After all, if an object on machine A
> wanted to use an object on machine B in an apartment C, wouldn't it be
> most efficient if the RPC system knew about apartments and could
> dispatch the message directly to it? And if RPC does know how to
> efficiently dispatch to apartments, why should COM duplicate this
> functionality? There were, however, no unified way to tell RPC about
> them across Windows versions, so in that old patch of mine, I let the
> COM/OLE dlls do the apartment dispatch, but even then, the RPC runtime
> was always involved. After all, it could be quite tricky to tell whether
> the call is merely interthread, without involving the RPC runtime...

Currently OXIDs are just ((PID << 32) | TID) so you could see if it was
inter-thread by examining that. In real DCOM though I don't know how
they do it - presumably by walking the proesses apartment list looking
for that OXID first.

> Yes, it's right, but as you mentioned, typelibs cannot encode all the
> information in the original IDL. InstallShield uses MIDL marshallers for
> the interfaces which cannot be represented perfectly by a type library.
> (You could of course ask why not use MIDL-generated marshallers all the
> way. I believe part of the reason for that is that on appropriate
> Windows versions, the marshallers generated from typelibs will be in a
> form that Microsoft claims will run faster than a big MIDL-generated
> marshaller, due to less RAM usage and CPU cache trashing.)

Right.

> And some related hacks in the typelib marshaller to cover up for the
> fact that the typelibs don't actually represent the IDL perfectly, by
> guessing at the extra information needed to successfully marshal the
> interfaces used by InstallShield.

To elaborate, the hack we're talking about is treating VT_VOID as an
interface pointer.

> All those hacks would no longer be needed after that old patch of mine,
> of course...

Yes but it's very large and none of us have been able to figure out how
to chop it up and submit it in a way that won't cause regressions:
really up until recently I didn't understand DCOM well enough to even
attempt this, I would just have made a big mess of it.

> I don't think you have covered the possibility of manually marshalling
> an interface from one single-threaded apartment to another, either
> (CoMarshalInterThreadInterfaceInStream). This is used to great effect in
> InstallShield to separate the worker thread and the UI thread; DCOM does
> all the hard work of letting the objects in the threads communicate
> easily and conveniently, even while the worker threads work and the UI
> thread remains responsive.

Yes, I did not cover this as I thought the email was long enough as is,
though the basic principles are still the same. Just the RPC transport
differs.

thanks for the review!
-mike




More information about the wine-devel mailing list