Hi,
Well, I've made pretty good progress, but am a bit stuck with this problem. Basically:
003d:trace:ole:TL_Marshal parameter 1 003d:trace:ole:TL_Marshal name : L"rgszNames" 003d:trace:ole:TL_Marshal type : 26 003d:trace:ole:TL_Marshal flags : 01 003d:trace:ole:TL_MarshalType dereferencing PTR 0x52edf7d0 => 0x54331260 003d:trace:ole:TL_MarshalType dereferencing PTR 0x54331260 => 0x54331270 003d:trace:ole:TL_MarshalType marshaling byte 100
As you can see, it's marshalling IDispatch across apartment boundaries, but it gets this parameter wrong. The double dereference seems correct, but marshalling a byte is not - I think it should be a BSTR.
rgszNames is a parameter of IDispatch::GetIDsFromNames, which is defined as an OLECHAR FAR* FAR*
I can't figure out where the typeinfo data for IDispatch is coming from though, hence my stuckness. BTW, is this line really correct:
TL_Unmarshal(pStm, pInfo, pDesc, PARAMFLAG_FIN, args, &argc, pChannel, &is_iid);
shouldn't it be:
TL_Unmarshal(pStm, pInfo, pDesc, PARAMFLAG_FIN, (DWORD*)&args[0], &argc, pChannel, &is_iid);
as args[] is a local array declared on the stack which is then passed to the function to be invoked - otherwise how does TL_Unmarshal set the arguments? Well I tried changing it, and it made no obvious difference to my bug, but I thought I'd ask anyway.
thanks -mike
Hi,
Well, I've made pretty good progress, but am a bit stuck with this problem. Basically:
003d:trace:ole:TL_Marshal parameter 1 003d:trace:ole:TL_Marshal name : L"rgszNames" 003d:trace:ole:TL_Marshal type : 26 003d:trace:ole:TL_Marshal flags : 01 003d:trace:ole:TL_MarshalType dereferencing PTR 0x52edf7d0 => 0x54331260 003d:trace:ole:TL_MarshalType dereferencing PTR 0x54331260 => 0x54331270 003d:trace:ole:TL_MarshalType marshaling byte 100
weird. are the "type" and "flags" correct?
As you can see, it's marshalling IDispatch across apartment boundaries, but it gets this parameter wrong. The double dereference seems correct, but marshalling a byte is not - I think it should be a BSTR.
rgszNames is a parameter of IDispatch::GetIDsFromNames, which is defined as an OLECHAR FAR* FAR*
bstr isn't right, since it's an array of bstr (or more precisely array of OLECHAR FAR* - which may also be causing problems) - though I may be wrong if it marshals them one by one. Shouldn't there be some special attributes in the IDL for this stuff, like size_of() or something like that (I'm a bit rusty)?
I can't figure out where the typeinfo data for IDispatch is coming from though, hence my stuckness. BTW, is this line really correct:
TL_Unmarshal(pStm, pInfo, pDesc, PARAMFLAG_FIN, args, &argc, pChannel, &is_iid);
shouldn't it be:
TL_Unmarshal(pStm, pInfo, pDesc, PARAMFLAG_FIN, (DWORD*)&args[0], &argc, pChannel, &is_iid);
these should be identical in terms of the code that gets compiles, though the second form may eliminate some warnings by using the typecast. Incidentally, you could just use (DWORD*)args to have the same effect.
Kelly
On Fri, 2003-07-18 at 17:08, Kelly Leahy wrote:
weird. are the "type" and "flags" correct?
They appear to be. Type 26 is VT_PTR, flags 1 == in param
bstr isn't right, since it's an array of bstr (or more precisely array of OLECHAR FAR* - which may also be causing problems) - though I may be wrong if it marshals them one by one.
Yeah, I had a thinko. It's supposed to be an array of bstr, but even simply marshalling the first element correctly would be good :)
Shouldn't there be some special attributes in the IDL for this stuff, like size_of() or something like that (I'm a bit rusty)?
HRESULT GetIDsOfNames( [in] REFIID riid, [in, size_is(cNames)] LPOLESTR *rgszNames, [in] UINT cNames, [in] LCID lcid, [out, size_is(cNames)] DISPID *rgDispId);
Maybe the size_is() field should be noticed somewhere in the marshalling code. I don't know where such information would surface though, it's not in the flags, there is no PARAMFLAG constant for it.
these should be identical in terms of the code that gets compiles, though the second form may eliminate some warnings by using the typecast. Incidentally, you could just use (DWORD*)args to have the same effect.
Hm, so if you declare an array like so:
DWORD args[32];
and then pass args as a parameter of type "DWORD *args", it automatically gets the address of it? I thought passing variables directly like that would normally cause a copy by value, but I don't know C well enough I suppose.
Hm, so if you declare an array like so:
DWORD args[32];
and then pass args as a parameter of type "DWORD *args", it automatically gets the address of it? I thought passing variables directly like that would normally cause a copy by value, but I don't know C well enough I suppose.
yes. As far as parameter passing goes, xxx *bob is the same as xxx bob[].
this is always true in C and C++, as far as I can remember.
Kelly
On 18 Jul 2003, Mike Hearn wrote:
Hm, so if you declare an array like so:
DWORD args[32];
and then pass args as a parameter of type "DWORD *args", it automatically gets the address of it? I thought passing variables directly like that would normally cause a copy by value, but I don't know C well enough I suppose.
Yes, in C everything is passed by value, but args is a pointer to 32 consecutive DWORDs, so in this case the value of args is the address, and it's the address that gets copied.
fre, 18.07.2003 kl. 17.53 skrev Mike Hearn:
Well, I've made pretty good progress, but am a bit stuck with this problem. Basically:
003d:trace:ole:TL_Marshal parameter 1 003d:trace:ole:TL_Marshal name : L"rgszNames" 003d:trace:ole:TL_Marshal type : 26 003d:trace:ole:TL_Marshal flags : 01 003d:trace:ole:TL_MarshalType dereferencing PTR 0x52edf7d0 => 0x54331260 003d:trace:ole:TL_MarshalType dereferencing PTR 0x54331260 => 0x54331270 003d:trace:ole:TL_MarshalType marshaling byte 100
As you can see, it's marshalling IDispatch across apartment boundaries, but it gets this parameter wrong. The double dereference seems correct, but marshalling a byte is not - I think it should be a BSTR.
rgszNames is a parameter of IDispatch::GetIDsFromNames, which is defined as an OLECHAR FAR* FAR*
Sorry for the late answer, I've been busy attending debconf3...
IDispatch should not be marshalled by the typelib marshaller, the method arguments it use cannot be represented by a typelib, as you've seen. The MIDL code in oaidl_p.c must be used instead. You need to change the registry to use the right marshaller, I think the necessary winedefault.reg changes were included in my patch, but I'm not sure.
I can't figure out where the typeinfo data for IDispatch is coming from though, hence my stuckness.
stdole32.tlb
BTW, is this line really correct:
TL_Unmarshal(pStm, pInfo, pDesc, PARAMFLAG_FIN, args, &argc, pChannel, &is_iid);
shouldn't it be:
TL_Unmarshal(pStm, pInfo, pDesc, PARAMFLAG_FIN, (DWORD*)&args[0], &argc, pChannel, &is_iid);
That should be the same thing. In expressions, the compiler will treat an array variable as a pointer to its first element. This feature has always been in C (and have been useful for no ends of code obfuscation tricks, as well as numerous novice-programmer bugs). In my opinion, &args[0] is more unredable than just using args, so the latter is my preferred style. But I'm not sure what you thought it meant?
Sorry for the late answer, I've been busy attending debconf3...
Ah, no problem, I hope it was good :)
IDispatch should not be marshalled by the typelib marshaller, the method arguments it use cannot be represented by a typelib, as you've seen. The MIDL code in oaidl_p.c must be used instead. You need to change the registry to use the right marshaller, I think the necessary winedefault.reg changes were included in my patch, but I'm not sure.
There were some changes yes, it seems for some reason they are not being used. I will double check. I probably simply forgot to remerge the default registry, thinking about it. My mind wasn't very clear on anything by friday :)
That should be the same thing. In expressions, the compiler will treat an array variable as a pointer to its first element. This feature has always been in C (and have been useful for no ends of code obfuscation tricks, as well as numerous novice-programmer bugs). In my opinion, &args[0] is more unredable than just using args, so the latter is my preferred style. But I'm not sure what you thought it meant?
In Delphi/Object Pascal passing an array like that would perform a copy by value, not pass the address. I (wrongly) assumed C would have similar rules. This is what I get for learning it as I go :)
thanks -mike
s?, 20.07.2003 kl. 13.38 skrev Mike Hearn:
Sorry for the late answer, I've been busy attending debconf3...
Ah, no problem, I hope it was good :)
Not bad.
IDispatch should not be marshalled by the typelib marshaller, the method arguments it use cannot be represented by a typelib, as you've seen. The MIDL code in oaidl_p.c must be used instead. You need to change the registry to use the right marshaller, I think the necessary winedefault.reg changes were included in my patch, but I'm not sure.
There were some changes yes, it seems for some reason they are not being used. I will double check. I probably simply forgot to remerge the default registry, thinking about it. My mind wasn't very clear on anything by friday :)
I've mentioned before the InstallShield hack in typelib.c (the "if (1 || ...)"), right? I suspect that you *must* disable it. or it'll probably keep reinstalling the wrong marshaller into the registry every time you run it.
In Delphi/Object Pascal passing an array like that would perform a copy by value, not pass the address. I (wrongly) assumed C would have similar rules. This is what I get for learning it as I go :)
Hmm, OK.
On Sun, 2003-07-20 at 12:29, Ove Kaaven wrote:
IDispatch should not be marshalled by the typelib marshaller, the method arguments it use cannot be represented by a typelib, as you've seen. The MIDL code in oaidl_p.c must be used instead. You need to change the registry to use the right marshaller, I think the necessary winedefault.reg changes were included in my patch, but I'm not sure.
I'd just like to double check that it *is* actually possible to marshal IDispatch, right? I've got it using the marshallers in oaidl_p.c, but I get fixmes from the RPC runtime like so:
fixme:ole:NdrConvert (pStubMsg == ^0x4d7a27a4, pFormat == ^0x53bc5f84): stub.
fixme:ole:PointerUnmarshall unhandled ptr type=12
and so on. Eventually it crashes inside native code (i think) just after returning from the proxy (well, i can see the last call to NdrComplexArrayUnmarshall) and calling VariantInit.
Are those fixmes actually critical? The NdrConvert stub at least suggests that it might be, and that it should throw an exception.
any insights welcome, thanks -mike