Hi, more questions (i'll master COM yet :)
HRESULT IWebBrowser2::get_Document(IDispatch **ppDisp);
invocation of this method/property fails, for some reason. I'm not sure why yet, but I don't understand how this is marshalled. Presumably, OLE Automation provides a ppDisp and then dereferences it back to IDispatch which is then marshalled. In ITypeInfo::Invoke, there is this code:
if (tdesc->vt == VT_PTR) tdesc = tdesc->u.lptdesc;
when looping over the arguments (?). So, it seems that this code is responsible for dereferencing the pointer, but it only does it once. Shouldn't this be a loop to dereference the arg as many times as needed? I feel that's wrong even as I write it, but I'm not sure how this part should work.
As it is, tdesc->vt ends up being (correctly) VT_DISPATCH but pVarResult doesn't seem to be changed....
ons, 23.07.2003 kl. 12.02 skrev Mike Hearn:
Hi, more questions (i'll master COM yet :)
HRESULT IWebBrowser2::get_Document(IDispatch **ppDisp);
Hmm. I assume this is an argument marked [out].
invocation of this method/property fails, for some reason. I'm not sure why yet, but I don't understand how this is marshalled. Presumably, OLE Automation provides a ppDisp and then dereferences it back to IDispatch which is then marshalled.
OLE Automation isn't going to provide a ppDisp. When it's [out], it's the IWebBrowser2 object implementation (not OLE Automation) that's supposed to write a valid interface pointer (or maybe NULL) to *ppDisp, after which the typelib marshaller will marshal the interface back to the caller. (And of course, when it's [in], it's the caller that's supposed to provide a valid interface pointer.)
In ITypeInfo::Invoke, there is this code:
if (tdesc->vt == VT_PTR)
tdesc = tdesc->u.lptdesc;
when looping over the arguments (?). So, it seems that this code is responsible for dereferencing the pointer, but it only does it once. Shouldn't this be a loop to dereference the arg as many times as needed?
VT_DISPATCH is equivalent to IDispatch*, and VT_UNKNOWN is equivalent to IUnknown*; that is, interface pointers, being interface *pointers*, already have one level of indirection built in to them (which obviously helps making the typelib marshaller as complex as it is), so this seems correct, only one dereference is needed on this level.
As it is, tdesc->vt ends up being (correctly) VT_DISPATCH but pVarResult doesn't seem to be changed....
If the IWebBrowser2 method that's invoked doesn't return an interface, it's either a bug in the IWebBrowser2 implementation, it failed for some reason, or perhaps the wrong method was invoked. Or something, I don't know the exact situation you have.
On Wed, 2003-07-23 at 12:11, Ove Kaaven wrote:
ons, 23.07.2003 kl. 12.02 skrev Mike Hearn:
Hi, more questions (i'll master COM yet :)
HRESULT IWebBrowser2::get_Document(IDispatch **ppDisp);
Hmm. I assume this is an argument marked [out].
I don't have the IDL unfortunately, but I think that must be correct. It's access via IDispatch as a property at any rate.
OLE Automation isn't going to provide a ppDisp. When it's [out], it's the IWebBrowser2 object implementation (not OLE Automation) that's supposed to write a valid interface pointer (or maybe NULL) to *ppDisp, after which the typelib marshaller will marshal the interface back to the caller. (And of course, when it's [in], it's the caller that's supposed to provide a valid interface pointer.)
Yes, I see now, that makes sense.
If the IWebBrowser2 method that's invoked doesn't return an interface, it's either a bug in the IWebBrowser2 implementation, it failed for some reason, or perhaps the wrong method was invoked. Or something, I don't know the exact situation you have.
This comment in the code concerns me:
/*FIXME: give pointers for the rest, so propertyget works*/
well, this is indeed a property get, so the result should be made available in pVarResult.
This code looked promising:
/* If pointer to variant, pass reference it. */ if ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_VARIANT) && pVarResult) { args[argspos] = (DWORD)pVarResult; }
so I copied it for the VT_DISPATCH case, but no cigar, it crashes later on in the marshalling code (in VariantClear). Am I at least on the right track? It seems not everything for property gets is implemented yet.
thanks -mike (i owe you about a million beers already :)
Mike Hearn wrote:
On Wed, 2003-07-23 at 12:11, Ove Kaaven wrote:
Hmm. I assume this is an argument marked [out].
I don't have the IDL unfortunately, but I think that must be correct. It's access via IDispatch as a property at any rate.
I don't have the IDL either, but from the header:
/* [helpcontext][helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *get_Document )( IWebBrowser2 __RPC_FAR * This, /* [retval][out] */ IDispatch __RPC_FAR *__RPC_FAR *ppDisp);
-- Jon Bright Lead Programmer, Silicon Circus Ltd. http://www.siliconcircus.com
ons, 23.07.2003 kl. 15.49 skrev Mike Hearn:
This comment in the code concerns me:
/*FIXME: give pointers for the rest, so propertyget works*/
I'm not sure what this comment refers to. It looks to me like "give pointers for the rest so propertyget works" is what it's already doing. Perhaps the fixme means "this should probably be done only when appropriate, not always", or perhaps someone added it without removing the fixme.
well, this is indeed a property get, so the result should be made available in pVarResult.
This code looked promising:
/* If pointer to variant, pass reference it. */ if ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_VARIANT) && pVarResult) { args[argspos] = (DWORD)pVarResult; }
This is just a fast-path, the other cases are handled below, in the "if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET)))" section.