https://bugs.winehq.org/show_bug.cgi?id=49162
Bug ID: 49162 Summary: widl generates incorrect marshaller for pointer sized output parameter for 32-bit client and 64-bit server Product: Wine Version: 5.8 Hardware: x86-64 OS: Linux Status: NEW Severity: normal Priority: P2 Component: rpc Assignee: wine-bugs@winehq.org Reporter: dmitry@baikal.ru Distribution: ---
Consider the following .idl:
import "objidl.idl";
cpp_quote("#if 0") typedef ULONG_PTR HDATA; cpp_quote("#endif")
[ uuid(00000000-1111-2222-3333-444444444444), implicit_handle(handle_t rpc_handle), version(1.0) ] interface IServer { DWORD rpc_GetData([out] HDATA *data); }
Makefile snippet:
server_s.c: Makefile server.idl $(WIDL) $(WIDL) -s -h -o $@ server.idl -m64 -I. -I$(WINEINCLUDE)
server_c.c: Makefile server.idl $(WIDL) $(WIDL) -c -h -o $@ server.idl -m32 -I. -I$(WINEINCLUDE)
generated server_s.c snippet: void __RPC_STUB IServer_rpc_GetData( PRPC_MESSAGE _pRpcMessage ) { ... *(HDATA *)__frame->_StubMsg.Buffer = *__frame->data; ... *(DWORD *)__frame->_StubMsg.Buffer = __frame->_RetVal; }
generated server_c.c snippet: DWORD __cdecl rpc_GetData( HDATA *data) { ... *data = *(HDATA *)__frame->_StubMsg.Buffer; ... _RetVal = *(DWORD *)__frame->_StubMsg.Buffer; }
As a result a being marshalled buffer looks like this: [8 bytes HDATA][4 bytes _RetVal] and on the client side _Retval gets value of upper 32-bits of the 64-bit HDATA.
https://bugs.winehq.org/show_bug.cgi?id=49162
Zebediah Figura z.figura12@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |z.figura12@gmail.com
--- Comment #1 from Zebediah Figura z.figura12@gmail.com --- IIRC MIDL screws this up too, but I'll have to test.
https://bugs.winehq.org/show_bug.cgi?id=49162
--- Comment #2 from Zebediah Figura z.figura12@gmail.com --- Yep, MIDL screws this up too (or rpcrt4 does). It doesn't screw it up in the same way as Wine (it actually seems to return the right value for the return value and the wrong value for the out parameter), but suffice it to say, you can't depend on pointer-size types working across different bitnesses. We could probably fix it to work on Wine regardless, but I'm inclined to believe it isn't worthwhile...
https://bugs.winehq.org/show_bug.cgi?id=49162
--- Comment #3 from Dmitry Timoshkov dmitry@baikal.ru --- (In reply to Zebediah Figura from comment #2)
Yep, MIDL screws this up too (or rpcrt4 does). It doesn't screw it up in the same way as Wine (it actually seems to return the right value for the return value and the wrong value for the out parameter), but suffice it to say, you can't depend on pointer-size types working across different bitnesses. We could probably fix it to work on Wine regardless, but I'm inclined to believe it isn't worthwhile...
Thanks for looking at this! It's perfectly acceptable that the pointer gets truncated, that's unavoidable, the source that I have here uses pointer mapper (the idea is similar to remote handle manager that msi uses), so that's not a problem. I've created this bug report mostly for the bug with return value being wrong, and if it's not very much effort I'd like to see it fixed.
https://bugs.winehq.org/show_bug.cgi?id=49162
--- Comment #4 from Zebediah Figura z.figura12@gmail.com --- Unfortunately it's not just a matter of truncation; the out value is filled with what's essentially garbage (it looks like a pointer value).
https://bugs.winehq.org/show_bug.cgi?id=49162
--- Comment #5 from Zebediah Figura z.figura12@gmail.com --- Actually, on further reflection I'm not even sure there is a good way to fix this while retaining compatibility. The problem is, unless I've made a mistake while testing, the wire format for 32-bit and 64-bit values is different. If we change the behaviour of widl or rpcrt4, we break programs (assuming there are any) depending on those working within one bitness.
https://bugs.winehq.org/show_bug.cgi?id=49162
--- Comment #6 from Dmitry Timoshkov dmitry@baikal.ru --- (In reply to Zebediah Figura from comment #5)
Actually, on further reflection I'm not even sure there is a good way to fix this while retaining compatibility. The problem is, unless I've made a mistake while testing, the wire format for 32-bit and 64-bit values is different. If we change the behaviour of widl or rpcrt4, we break programs (assuming there are any) depending on those working within one bitness.
Apparently this works in some way under Windows.
https://bugs.winehq.org/show_bug.cgi?id=49162
--- Comment #7 from Zebediah Figura z.figura12@gmail.com --- (In reply to Dmitry Timoshkov from comment #6)
Apparently this works in some way under Windows.
Can you please provide a complete test case? I can't get anything but garbage in the out parameter.
https://bugs.winehq.org/show_bug.cgi?id=49162
--- Comment #8 from Zebediah Figura z.figura12@gmail.com --- Incidentally, it works perfectly in stubless mode, on both Wine and Windows. If you were testing with MIDL and default options, that may be why.
https://bugs.winehq.org/show_bug.cgi?id=49162
--- Comment #9 from Dmitry Timoshkov dmitry@baikal.ru --- (In reply to Zebediah Figura from comment #8)
Incidentally, it works perfectly in stubless mode, on both Wine and Windows. If you were testing with MIDL and default options, that may be why.
I started working with widl and later switched to midl for testing purposes, and for midl I decided to reproduce widl behaviour as much as possible, as a result I used 'midl /Os' since it's the default (and looks like preferable) setting for widl.