On Wed, 2003-07-23 at 17:50, Gregory M. Turner wrote:
Mike, somehow in this thread, I have lost track of the basic parameters of your situation... could you remind us of the precise context in which your code is being compiled and run?
The story is like so: I have an app. Said app is written in Java, yet has many Win32 dependencies. Some of them are simple, for instance on a tray icon. Some are not. As such, I run the Sun JVM with this app under Wine. Rather ugly solution, but unfortunately there weren't really any alternatives given the context of this job.
One dependency that isn't simple is that it embeds Internet Explorer and uses it as an HTML enabled word processor. The app uses a Java<->COM bridge to do that, and as such gives OLE quite a work out. Originally, not having much time, I just used microsofts OLE, which worked pretty well but unfortunately there was a problem with it deadlocking on thread detach, which blocked the loader section and so everything died. After trying to divine what was going wrong there for about a week, I decided that it was fruitless and I'd be better bringing Wines DCOM/OLE up to scratch.
Because this app does many horrid things, like marshalling IDispatch between threads in order to make calls from Java to IE (C++), I needed Oves patch to add these features, which he kindly sent. I've been hacking on that ever since, trying to make it able to do all the things said app needs. Cue wild learning spree as I try to cram the entirety of COM into my head in a few days :)
The place I'm at now, is that IDispatch and its methods aren't always being marshalled correctly.
While IDispatch itself is now properly marshalled using the MIDL generated proxy/stub sets, one of the things this app does is manipulate the DOM from other threads, and it all goes via late bound IDispatch (because it's called from java via a generic bridge).
When IDispatch::Invoke is called with a property get request, said request is dealt with succesfully by Internet Explorer, but the output (an IDispatch for the HTML DOM object) doesn't make it back to the program, which prompty throws an exception and isn't very happy.
The issue that plagued me before (which i've now hacked around) was that the call was segfaulting inside IE, because riid == NULL, not IID_NULL. Clearly this field is used, even though it's marked as reserved by Microsoft, as if it's wrong IE dereferences it and dies. The reason NULL was being passed in instead of IID_NULL was because in the MIDL generated stubs, the Ndr call which demarshalls the iid was passed a pointer to a local variable (&riid), initialized on the stack as "RIID riid = NULL", it set *ppMemory = demarshaled iid, and trace statements confirmed that just before it returned *ppMemory was indeed pointing at the right thing. Unfortunately, for some reason riid stayed at NULL.
Changing the way riid was declared fixed that. I don't know why, and although I'm curious to find out, I'm running out of time before my year at QinetiQ is up and I drop the project and go back home, so I'm not that curious :(
The problem I face now is that the property get request returns the HTML DOM IDispatch in a variant of type VT_DISPATCH, which the Ndr variant marshalling code doesn't seem able to handle.
I poked about, saw that it couldn't handle that, and thought "I have a cunning plan - why not use NdrInterfacePointerMarshall to implement this code?", but unfortunately that function needs information that has been lost (ie not passed through the function calls) by the time we find out that the variant is a VT_DISPATCH.
Now I'm stuck :( I don't know how to get the information NdrInterfacePointerMarshall needs, namely the MIDL_STUB_BUFFER and format string, and I can't extend the function prototypes to contain it because they are invoked from some kind of table. Obviously hacks like global variables are wrong. That's where I left off todays adventures....
any insights welcome -mike