On Sunday 13 October 2002 03:06 pm, Greg Turner wrote:
A few small things.
Changelog:
- dlls/rpcrt4: rpcrt4.spec, ndr_stubless.c, rpc_binding.c, rpc_server.c; include/rpcdce.h: Greg Turner gmturner007@ameritech.net
- (try to) implement RpcMgmtWaitServerListen
- remove duplicate RpcServerListen declaration in rpcdce.h
- some TRACEs
LICENSE: X11
There's something wrong with the stuff I did in ndr_stubless.c (RpcMgmtWaitServerListen is kinda screwy too but that was intentional). I seem to have scrambled my brain, perhaps somebody with an unscrabled brain can help me...?
I submitted RPCRT4_NdrClientCall2 as:
LONG_PTR RPCRT4_NdrClientCall2(PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat, va_list args) {
FIXME("(pStubDec == ^%p,pFormat = "%s",...): stub\n", pStubDesc, pFormat);
PRPC_CLIENT_INTERFACE rpc_cli_if = (PRPC_CLIENT_INTERFACE) pStubDesc;
TRACE("rpc_cli_if: Length == %d; InterfaceID == <%s,<%d.%d>>; TransferSyntax == <%s,<%d.%d>>; DispatchTable == ^%p; RpcProtseqEndpoi ntCount == %d; RpcProtseqEndpoint == ^%p; Flags == %d\n", rpc_cli_if->Length, debugstr_guid(&rpc_cli_if->InterfaceId.SyntaxGUID), rpc_cli_if->InterfaceId.SyntaxVersion.MajorVersion, rpc_cli_if->InterfaceId.Syn taxVersion.MinorVersion, debugstr_guid(&rpc_cli_if->TransferSyntax.SyntaxGUID), rpc_cli_if->TransferSyntax.SyntaxVersion.MajorVersion, rpc_cli_if->TransferS yntax.SyntaxVersion.MinorVersion, rpc_cli_if->DispatchTable, rpc_cli_if->RpcProtseqEndpointCount, rpc_cli_if->RpcProtseqEndpoint, rpc_cli_if->Flags);
return 0; }
That's just wrong. pStubDesc is /not/ a PRPC_CLIENT_INTERFACE. Instead, it is what it says it is, a PMIDL_STUB_DESC. The first element of the PMIDL_STUB_DESC, RpcInterfaceInformation /is/ a PRPC_CLIENT_INTERFACE, however---the one I want (right?). So now I do this:
LONG_PTR RPCRT4_NdrClientCall2(PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat, va_list args) {
FIXME("(pStubDec == ^%p,pFormat = "%s",...): stub\n", pStubDesc, pFormat);
PRPC_CLIENT_INTERFACE rpc_cli_if = (PRPC_CLIENT_INTERFACE)(pStubDesc->RpcInterfaceInformation); TRACE("rpc_cli_if == ^%p\n", rpc_cli_if);
TRACE("rpc_cli_if: Length == %d; InterfaceID == <%s,<%d.%d>>; TransferSyntax == <%s,<%d.%d>>; DispatchTable == ^%p; RpcProtseqEndpointCount == %d; RpcProtseqEndpoint == ^%p; Flags == %d\n", rpc_cli_if->Length, debugstr_guid(&rpc_cli_if->InterfaceId.SyntaxGUID), rpc_cli_if->InterfaceId.SyntaxVersion.MajorVersion, rpc_cli_if->InterfaceId.SyntaxVersion.MinorVersion, debugstr_guid(&rpc_cli_if->TransferSyntax.SyntaxGUID), rpc_cli_if->TransferSyntax.SyntaxVersion.MajorVersion, rpc_cli_if->TransferSyntax.SyntaxVersion.MinorVersion, rpc_cli_if->DispatchTable, rpc_cli_if->RpcProtseqEndpointCount, rpc_cli_if->RpcProtseqEndpoint, rpc_cli_if->Flags);
return 0; }
but that doesn't work out. It blows up:
greg@yodull midled $ wine --dll rpcrt4,msvcrt=b --debugmsg +ole helloc trace:ole:RpcStringBindingComposeA ((null),"ncacn_np",(null),"\pipe\hello",(null),0x406d2ddc) RpcStringBindingCompose returned 0x0 pszStringBinding = ncacn_np:[\pipe\hello] trace:ole:RpcBindingFromStringBindingA ("ncacn_np:[\pipe\hello]",0x403224) trace:ole:RpcStringBindingParseA ("ncacn_np:[\pipe\hello]",0x406d2d68,0x406d2d6c,0x406d2d70,0x406d2d74,0x406d2d78) trace:ole:RPCRT4_CreateBindingA binding: 0x403b4970 trace:ole:RPCRT4_SetBindingObject (*RpcBinding == ^0x403b4970, UUID == {00000000-0000-0000-0000-000000000000}) trace:ole:RPCRT4_CompleteBindingA (RpcBinding == ^0x403b4970, NetworkAddr == "", EndPoint == "\pipe\hello", NetworkOptions == "(null)") RpcBindingFromStringBinding returned 0x0 Calling the remote procedure 'HelloProc' Print the string 'hello, world' on the server trace:ole:NdrClientCall2 (0x4020c2,0x406d2da4,...) fixme:ole:RPCRT4_NdrClientCall2 (pStubDec == ^0x4020c2,pFormat = "0@",...): stub trace:ole:RPCRT4_NdrClientCall2 rpc_cli_if = ^0x4832 Runtime reported exception 0xc0000005 = -1073741819
Obviously, it never succesfully displays the big trace stmt, probably crashing deferincing the suspicious-looking "0x4832" pointer...
Surely I'm doing something really dumb and obvious; perhaps I just need more coffee...
Anyhow, for now, I'm in a muddle, D_PL1 should stay out until I fix it with a D_PL2. Any help would be appreciated, I'm sure the problem is squarely between the chair and the keyboard...
On Sun, 13 Oct 2002, Greg Turner wrote:
LONG_PTR RPCRT4_NdrClientCall2(PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat, va_list args) {
FIXME("(pStubDec == ^%p,pFormat = "%s",...): stub\n", pStubDesc, pFormat);
PRPC_CLIENT_INTERFACE rpc_cli_if = (PRPC_CLIENT_INTERFACE)(pStubDesc->RpcInterfaceInformation);
(hmm, does this even compile? I didn't think C allowed variable declarations after statements)
TRACE("rpc_cli_if == ^%p\n", rpc_cli_if);
TRACE("rpc_cli_if: Length == %d; InterfaceID == <%s,<%d.%d>>; TransferSyntax == <%s,<%d.%d>>; DispatchTable == ^%p; RpcProtseqEndpointCount == %d; RpcProtseqEndpoint == ^%p; Flags == %d\n", rpc_cli_if->Length, debugstr_guid(&rpc_cli_if->InterfaceId.SyntaxGUID), rpc_cli_if->InterfaceId.SyntaxVersion.MajorVersion, rpc_cli_if->InterfaceId.SyntaxVersion.MinorVersion, debugstr_guid(&rpc_cli_if->TransferSyntax.SyntaxGUID), rpc_cli_if->TransferSyntax.SyntaxVersion.MajorVersion, rpc_cli_if->TransferSyntax.SyntaxVersion.MinorVersion, rpc_cli_if->DispatchTable, rpc_cli_if->RpcProtseqEndpointCount, rpc_cli_if->RpcProtseqEndpoint, rpc_cli_if->Flags);
return 0; }
but that doesn't work out. It blows up:
greg@yodull midled $ wine --dll rpcrt4,msvcrt=b --debugmsg +ole helloc trace:ole:RpcStringBindingComposeA ((null),"ncacn_np",(null),"\pipe\hello",(null),0x406d2ddc) RpcStringBindingCompose returned 0x0 pszStringBinding = ncacn_np:[\pipe\hello] trace:ole:RpcBindingFromStringBindingA ("ncacn_np:[\pipe\hello]",0x403224) trace:ole:RpcStringBindingParseA ("ncacn_np:[\pipe\hello]",0x406d2d68,0x406d2d6c,0x406d2d70,0x406d2d74,0x406d2d78) trace:ole:RPCRT4_CreateBindingA binding: 0x403b4970 trace:ole:RPCRT4_SetBindingObject (*RpcBinding == ^0x403b4970, UUID == {00000000-0000-0000-0000-000000000000}) trace:ole:RPCRT4_CompleteBindingA (RpcBinding == ^0x403b4970, NetworkAddr == "", EndPoint == "\pipe\hello", NetworkOptions == "(null)") RpcBindingFromStringBinding returned 0x0 Calling the remote procedure 'HelloProc' Print the string 'hello, world' on the server trace:ole:NdrClientCall2 (0x4020c2,0x406d2da4,...) fixme:ole:RPCRT4_NdrClientCall2 (pStubDec == ^0x4020c2,pFormat = "0@",...): stub trace:ole:RPCRT4_NdrClientCall2 rpc_cli_if = ^0x4832 Runtime reported exception 0xc0000005 = -1073741819
Obviously, it never succesfully displays the big trace stmt, probably crashing deferincing the suspicious-looking "0x4832" pointer...
The pStubDesc structure should have been initialized (including setting that pointer, I think) by the NdrClientInitialize or NdrClientInitializeNew (or for DCOM, NdrProxyInitialize, but perhaps NdrProxyInitialize should call down to NdrClientInitialize/New anyway) functions. My patches didn't implement those functions, since I was mostly concerned with DCOM. Is this a real RPC app that works on Windows you're working on?
On Sunday 13 October 2002 06:41 pm, Ove Kaaven wrote:
On Sun, 13 Oct 2002, Greg Turner wrote:
LONG_PTR RPCRT4_NdrClientCall2(PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat, va_list args) {
FIXME("(pStubDec == ^%p,pFormat = "%s",...): stub\n", pStubDesc, pFormat);
PRPC_CLIENT_INTERFACE rpc_cli_if = (PRPC_CLIENT_INTERFACE)(pStubDesc->RpcInterfaceInformation);
(hmm, does this even compile? I didn't think C allowed variable declarations after statements)
This is a c++ism that gcc allows; it already is used quite a bit in wine, although in this case there is no good reason for it and it should probably go.
The pStubDesc structure should have been initialized (including setting that pointer, I think) by the NdrClientInitialize or NdrClientInitializeNew (or for DCOM, NdrProxyInitialize, but perhaps NdrProxyInitialize should call down to NdrClientInitialize/New anyway) functions. My patches didn't implement those functions, since I was mostly concerned with DCOM. Is this a real RPC app that works on Windows you're working on?
It's "Samples\netds\rpc\Hello" from the latest platform SDK, compiled native. It does seem to work in real Windows. Binaries are enclosed. I will look into some of the functions you mention after Sopranos :)
Thanks, Ove,
On Sunday 13 October 2002 08:20 pm, Greg Turner wrote:
On Sunday 13 October 2002 06:41 pm, Ove Kaaven wrote:
On Sun, 13 Oct 2002, Greg Turner wrote:
LONG_PTR RPCRT4_NdrClientCall2(PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat, va_list args) {
FIXME("(pStubDec == ^%p,pFormat = "%s",...): stub\n", pStubDesc, pFormat);
PRPC_CLIENT_INTERFACE rpc_cli_if = (PRPC_CLIENT_INTERFACE)(pStubDesc->RpcInterfaceInformation);
(hmm, does this even compile? I didn't think C allowed variable declarations after statements)
This is a c++ism that gcc allows; it already is used quite a bit in wine, although in this case there is no good reason for it and it should probably go.
The pStubDesc structure should have been initialized (including setting that pointer, I think) by the NdrClientInitialize or NdrClientInitializeNew (or for DCOM, NdrProxyInitialize, but perhaps NdrProxyInitialize should call down to NdrClientInitialize/New anyway) functions. My patches didn't implement those functions, since I was mostly concerned with DCOM. Is this a real RPC app that works on Windows you're working on?
It's "Samples\netds\rpc\Hello" from the latest platform SDK, compiled native. It does seem to work in real Windows. Binaries are enclosed. I will look into some of the functions you mention after Sopranos :)
Thanks, Ove,
did these come through for everybody? I got a message from an Exchange bot about virus blocking. Here they are again in a format that an MS bot is unlikely to censor.
On Sunday 13 October 2002 06:41 pm, Ove Kaaven wrote:
The pStubDesc structure should have been initialized (including setting that pointer, I think) by the NdrClientInitialize or NdrClientInitializeNew (or for DCOM, NdrProxyInitialize, but perhaps NdrProxyInitialize should call down to NdrClientInitialize/New anyway) functions. My patches didn't implement those functions, since I was mostly concerned with DCOM. Is this a real RPC app that works on Windows you're working on?
Apparently this isn't how /Oicf works in this case... the MIDL-generated source looks to me like I am recieving constant structures that should already have been initialized statically.
To "prove" it here's the the client stub source (abridged and annotated):
====================== /* * GMT: I hope this doesn't matter.... I think it only * affects the wire representation, not yet my concern (soon!) */ #if !(TARGET_IS_NT50_OR_LATER) #error You need a Windows 2000 or later to run this stub because it uses these features: #error /robust command line switch. #error However, your C/C++ compilation flags indicate you intend to run this app on earlier systems. #error This app will die there with the RPC_X_WRONG_STUB_VERSION error. #endif
static const RPC_CLIENT_INTERFACE hello___RpcClientInterface = { sizeof(RPC_CLIENT_INTERFACE), {{0x906B0CE0,0xC70B,0x1067,{0xB3,0x17,0x00,0xDD,0x01,0x06,0x62,0xDA}},{1,0}}, {{0x8A885D04,0x1CEB,0x11C9,{0x9F,0xE8,0x08,0x00,0x2B,0x10,0x48,0x60}},{2,0}}, 0, 0, 0, 0, 0, 0x00000000 };
/* * GMT: Interesting, I just noticed that there are two def's for hello_StubDesc; * Could this be the one I'm getting instead of the one below? Doesn't the * "extern" mean they will be one and the same? What a mess... */ extern const MIDL_STUB_DESC hello_StubDesc;
void HelloProc( /* [string][in] */ unsigned char *pszString) {
NdrClientCall2( ( PMIDL_STUB_DESC )&hello_StubDesc, (PFORMAT_STRING) &__MIDL_ProcFormatString.Format[0], pszString);
}
/* * GMT: here is what I thought I was going to get: */ static const MIDL_STUB_DESC hello_StubDesc = { (void *)& hello___RpcClientInterface, MIDL_user_allocate, MIDL_user_free, &hello_IfHandle, 0, 0, 0, 0, __MIDL_TypeFormatString.Format, 1, /* -error bounds_check flag */ 0x50002, /* Ndr library version */ 0, 0x6000169, /* MIDL Version 6.0.361 */ 0, 0, 0, /* notify & notify_flag routine table */ 0x1, /* MIDL flag */ 0, /* cs routines */ 0, /* proxy/server info */ 0 /* Reserved5 */ }; ======================
Anyhow, if it was calling the functions you mention, it should be crashing with unimplmented function, since there are no stubs, right? So, to me, it seems that it's supposed to be giving me the above static const struct... and yet, as far as I can tell, it ain't :(
Here's the main source, also abridged:
====================== void __cdecl main(int argc, char **argv) { RPC_STATUS status; unsigned char * pszUuid = NULL; unsigned char * pszProtocolSequence = "ncacn_np"; unsigned char * pszNetworkAddress = NULL; unsigned char * pszEndpoint = "\pipe\hello"; unsigned char * pszOptions = NULL; unsigned char * pszStringBinding = NULL; unsigned char * pszString = "hello, world"; unsigned long ulCode;
status = RpcStringBindingCompose(pszUuid, pszProtocolSequence, pszNetworkAddress, pszEndpoint, pszOptions, &pszStringBinding);
status = RpcBindingFromStringBinding(pszStringBinding, &hello_IfHandle);
printf("Calling the remote procedure 'HelloProc'\n");
RpcTryExcept { HelloProc(pszString); // make call with user message printf("Calling the remote procedure 'Shutdown'\n"); Shutdown(); // shut down the server side } RpcExcept(1) { ulCode = RpcExceptionCode(); printf("Runtime reported exception 0x%lx = %ld\n", ulCode, ulCode); } RpcEndExcept
status = RpcStringFree(&pszStringBinding); // remote calls done; unbind status = RpcBindingFree(&hello_IfHandle); // remote calls done; unbind exit(0); } ======================
Hrmm... well, I'm stumped for tonight, time to play video games. Thanks for your help.
On Sun, 13 Oct 2002, Greg Turner wrote:
On Sunday 13 October 2002 06:41 pm, Ove Kaaven wrote:
The pStubDesc structure should have been initialized (including setting that pointer, I think) by the NdrClientInitialize or NdrClientInitializeNew (or for DCOM, NdrProxyInitialize, but perhaps NdrProxyInitialize should call down to NdrClientInitialize/New anyway) functions. My patches didn't implement those functions, since I was mostly concerned with DCOM. Is this a real RPC app that works on Windows you're working on?
Apparently this isn't how /Oicf works in this case... the MIDL-generated source looks to me like I am recieving constant structures that should already have been initialized statically.
Oh yeah sorry, I confused MIDL_STUB_DESC with MIDL_STUB_MESSAGE, must have been too long since I looked at this. Hmm... perhaps there's a memory corruption somewhere, then?
On Monday 14 October 2002 10:23 am, Ove Kaaven wrote:
On Sun, 13 Oct 2002, Greg Turner wrote:
On Sunday 13 October 2002 06:41 pm, Ove Kaaven wrote:
The pStubDesc structure should have been initialized (including setting that pointer, I think) by the NdrClientInitialize or NdrClientInitializeNew (or for DCOM, NdrProxyInitialize, but perhaps NdrProxyInitialize should call down to NdrClientInitialize/New anyway) functions. My patches didn't implement those functions, since I was mostly concerned with DCOM. Is this a real RPC app that works on Windows you're working on?
Apparently this isn't how /Oicf works in this case... the MIDL-generated source looks to me like I am recieving constant structures that should already have been initialized statically.
Oh yeah sorry, I confused MIDL_STUB_DESC with MIDL_STUB_MESSAGE, must have been too long since I looked at this. Hmm... perhaps there's a memory corruption somewhere, then?
well, that sounds about right, but how to detect such a thing...? I guess I need to learn how to create 'on change some ram' breakpoints, not to mention track down these datastructures in memory (or perhaps learn how to get debug symbols for w32-native-compiled stuff generated).
Here's what's really wierd. I just compiled this as a winelib app (this takes some doing, but basically seems to work). And the corruption goes away! I'll present a couple of theories on this below, but first, allow me to dump gobs of debugmsg output.
Here's what I get from the winelib version: ==================== trace:loaddll:MODULE_LoadLibraryExA Loaded module 'C:\WINDOWS\SYSTEM\kernel32.dll' : builtin trace:loaddll:MODULE_LoadLibraryExA Loaded module 'C:\windows\system\ADVAPI32.DLL' : builtin trace:loaddll:MODULE_LoadLibraryExA Loaded module 'C:\WINDOWS\SYSTEM\gdi32.dll' : builtin trace:loaddll:MODULE_LoadLibraryExA Loaded module 'C:\WINDOWS\SYSTEM\user32.dll' : builtin trace:loaddll:MODULE_LoadLibraryExA Loaded module 'C:\windows\system\rpcrt4.dll' : builtin trace:loaddll:MODULE_LoadLibraryExA Loaded module 'C:\windows\system\ole32.dll' : builtin trace:loaddll:MODULE_LoadLibraryExA Loaded module 'C:\windows\system\SHLWAPI.DLL' : builtin trace:loaddll:MODULE_LoadLibraryExA Loaded module 'C:\windows\system\COMCTL32.DLL' : builtin trace:loaddll:MODULE_LoadLibraryExA Loaded module 'C:\windows\system\shell32.dll' : builtin trace:loaddll:MODULE_LoadLibraryExA Loaded module 'C:\WINDOWS\SYSTEM\winspool.drv' : builtin trace:loaddll:MODULE_LoadLibraryExA Loaded module 'C:\windows\system\comdlg32.dll' : builtin trace:loaddll:MODULE_LoadLibraryExA Loaded module 'C:\windows\system\odbc32.dll' : builtin trace:loaddll:MODULE_LoadLibraryExA Loaded module 'C:\windows\system\OLEAUT32.DLL' : builtin trace:loaddll:MODULE_LoadModule16 Loaded module 'krnl386.exe' : builtin trace:loaddll:MODULE_LoadModule16 Loaded module 'system' : builtin trace:loaddll:MODULE_LoadModule16 Loaded module 'wprocs' : builtin trace:loaddll:MODULE_LoadModule16 Loaded module 'GDI.EXE' : builtin trace:loaddll:MODULE_LoadModule16 Loaded module 'USER.EXE' : builtin trace:loaddll:MODULE_LoadLibraryExA Loaded module 'C:\WINDOWS\SYSTEM\x11drv.dll' : builtin trace:loaddll:MODULE_LoadModule16 Loaded module 'display' : builtin trace:ole:OLE32_DllEntryPoint 0x40900000 0x1 0x1 trace:ole:CoRegisterMallocSpy trace:ole:IMallocSpy_fnQueryInterface ({0000001d-0000-0000-c000-000000000046},0x406d2cec) trace:ole:IMalloc_fnAlloc (20) trace:ole:IMallocSpy_fnPreAlloc (0x40957378)->(20) trace:ole:IMallocSpy_fnPostAlloc (0x40957378)->(0x403dba70) trace:ole:IMalloc_fnAlloc --(0x403dba70) trace:ole:IMalloc_fnAlloc (20) <<snip: about 100 lines like this>> trace:ole:IMallocSpy_fnPreAlloc (0x40957378)->(20) trace:ole:IMallocSpy_fnPostAlloc (0x40957378)->(0x403e3ba8) trace:ole:IMalloc_fnAlloc --(0x403e3ba8) trace:ole:IMalloc_fnAlloc (20) trace:ole:IMallocSpy_fnPreAlloc (0x40957378)->(20) trace:ole:IMallocSpy_fnPostAlloc (0x40957378)->(0x403e3be8) trace:ole:IMalloc_fnAlloc --(0x403e3be8) trace:loaddll:MODULE_LoadLibraryExA Loaded module 'C:\WINDOWS\SYSTEM\WINEPS.dll' : builtin trace:loaddll:MODULE_FlushModrefs Unloaded module 'C:\WINDOWS\SYSTEM\wineps.dll' : builtin trace:loaddll:MODULE_LoadLibraryExA Loaded module 'C:\WINDOWS\SYSTEM\WINEPS.dll' : builtin trace:loaddll:MODULE_FlushModrefs Unloaded module 'C:\WINDOWS\SYSTEM\wineps.dll' : builtin trace:loaddll:MODULE_LoadLibraryExA Loaded module 'C:\WINDOWS\SYSTEM\WINEPS.dll' : builtin trace:loaddll:MODULE_FlushModrefs Unloaded module 'C:\WINDOWS\SYSTEM\wineps.dll' : builtin trace:loaddll:MODULE_LoadModule16 Loaded module 'commdlg.dll' : builtin trace:ole:RpcStringBindingComposeA ((null),"ncacn_np",(null),"\pipe\hello",(null),0x406d2e3c) RpcStringBindingCompose returned 0x0 pszStringBinding = ncacn_np:[\pipe\hello] trace:ole:RpcBindingFromStringBindingA ("ncacn_np:[\pipe\hello]",0x4002a9e0) trace:ole:RpcStringBindingParseA ("ncacn_np:[\pipe\hello]",0x406d2dc8,0x406d2dcc,0x406d2dd0,0x406d2dd4,0x406d2dd8) trace:ole:RPCRT4_CreateBindingA binding: 0x403e3e50 trace:ole:RPCRT4_SetBindingObject (*RpcBinding == ^0x403e3e50, UUID == {00000000-0000-0000-0000-000000000000}) trace:ole:RPCRT4_CompleteBindingA (RpcBinding == ^0x403e3e50, NetworkAddr == "", EndPoint == "\pipe\hello", NetworkOptions == "(null)") RpcBindingFromStringBinding returned 0x0 Calling the remote procedure 'HelloProc' Print the string 'hello, world' on the server trace:ole:NdrClientCall2 (0x4002a5c0,0x40029442,...) fixme:ole:RPCRT4_NdrClientCall2 (pStubDec == ^0x4002a5c0,pFormat = "2H",...): stub trace:ole:RPCRT4_NdrClientCall2 rpc_cli_if == ^0x400293e0 trace:ole:RPCRT4_NdrClientCall2 rpc_cli_if: Length == 68; InterfaceID == <{906b0ce0-c70b-1067-b317-00dd010662da},<1.0>>; TransferSyntax == <{8a885d04-1ceb-11c9-9fe8-08002b104860},<2.0>>; DispatchTable == ^(nil); RpcProtseqEndpointCount == 0; RpcProtseqEndpoint == ^(nil); Flags == 0 Calling the remote procedure 'Shutdown' trace:ole:NdrClientCall2 (0x4002a5c0,0x40029460,...) fixme:ole:RPCRT4_NdrClientCall2 (pStubDec == ^0x4002a5c0,pFormat = "2H",...): stub trace:ole:RPCRT4_NdrClientCall2 rpc_cli_if == ^0x400293e0 trace:ole:RPCRT4_NdrClientCall2 rpc_cli_if: Length == 68; InterfaceID == <{906b0ce0-c70b-1067-b317-00dd010662da},<1.0>>; TransferSyntax == <{8a885d04-1ceb-11c9-9fe8-08002b104860},<2.0>>; DispatchTable == ^(nil); RpcProtseqEndpointCount == 0; RpcProtseqEndpoint == ^(nil); Flags == 0 RpcStringFree returned 0x0 trace:ole:RpcBindingFree (0x4002a9e0) = 0x403e3e50 trace:ole:RPCRT4_DestroyBinding binding: 0x403e3e50 trace:ole:RPCRT4_CloseBinding (Binding == ^0x403e3e50) RpcBindingFree returned 0x0 ================================
looks great! The interfaceID is the right one, the same one I get on the server side.
now here's the native version:
================================ trace:loaddll:MODULE_LoadLibraryExA Loaded module 'C:\WINDOWS\SYSTEM\kernel32.dll' : builtin trace:loaddll:MODULE_LoadLibraryExA Loaded module 'C:\windows\system\ADVAPI32.DLL' : builtin trace:loaddll:MODULE_LoadLibraryExA Loaded module 'C:\windows\system\rpcrt4.dll' : builtin trace:loaddll:MODULE_LoadLibraryExA Loaded module 'C:\windows\system\msvcrt.dll' : builtin trace:loaddll:MODULE_LoadModule16 Loaded module 'krnl386.exe' : builtin trace:loaddll:MODULE_LoadModule16 Loaded module 'system' : builtin trace:loaddll:MODULE_LoadModule16 Loaded module 'wprocs' : builtin trace:ole:RpcStringBindingComposeA ((null),"ncacn_np",(null),"\pipe\hello",(null),0x406d2ddc) RpcStringBindingCompose returned 0x0 pszStringBinding = ncacn_np:[\pipe\hello] trace:ole:RpcBindingFromStringBindingA ("ncacn_np:[\pipe\hello]",0x403224) trace:ole:RpcStringBindingParseA ("ncacn_np:[\pipe\hello]",0x406d2d68,0x406d2d6c,0x406d2d70,0x406d2d74,0x406d2d78) trace:ole:RPCRT4_CreateBindingA binding: 0x403b4a08 trace:ole:RPCRT4_SetBindingObject (*RpcBinding == ^0x403b4a08, UUID == {00000000-0000-0000-0000-000000000000}) trace:ole:RPCRT4_CompleteBindingA (RpcBinding == ^0x403b4a08, NetworkAddr == "", EndPoint == "\pipe\hello", NetworkOptions == "(null)") RpcBindingFromStringBinding returned 0x0 Calling the remote procedure 'HelloProc' Print the string 'hello, world' on the server trace:ole:NdrClientCall2 (0x4020c2,0x406d2da4,...) fixme:ole:RPCRT4_NdrClientCall2 (pStubDec == ^0x4020c2,pFormat = "0@",...): stub trace:ole:RPCRT4_NdrClientCall2 rpc_cli_if == ^0x4832 Runtime reported exception 0xc0000005 = -1073741819 RpcStringFree returned 0x0 trace:ole:RpcBindingFree (0x403224) = 0x403b4a08 trace:ole:RPCRT4_DestroyBinding binding: 0x403b4a08 trace:ole:RPCRT4_CloseBinding (Binding == ^0x403b4a08) RpcBindingFree returned 0x0 ==================================
Serveral differences worth noting:
o Many more dlls loaded in the winelib version (why?) o lots of IMallocSpy activity in the winelib version (perhaps just part of the ole32 initialization?) o pFormat argument to RPCRT4_NdrClientCall2 is different in the winelib version (!?)
Things I had to change to get the winelib working
o remove RpcTryExcept macros from the source o change MIDL_user_allocate/MIDL_user_free to midl_user_allocate/midl_user_free (MS rpcndr.h does the opposite, but that shouldn't matter)
There were other changes but they were probably irrelevant to the matter at hand.
My theories:
o it's the try/except macros; they're causing stack corruption or something (they occur right before the NdrClientCall2) o it's MIDL_user_allocate somehow (nah) o it's a problem with dll loading (lets hope not)
Right now I will test the first theory by taking the try/except stuff out and recompiling the sample. Then, when it doesn't solve the problem, I'll be stumped again :(
any thoughts? thanks,
On Monday 14 October 2002 11:39 pm, Greg Turner wrote:
My theories:
o it's the try/except macros; they're causing stack corruption or something (they occur right before the NdrClientCall2)
nope. removing the RpcTryExcept results in the same behavior (except, of course, that winedbg instead of the client code catches the segfault).
As predicted, I am now stumped :(
This is not a recomendation, but Alexandre, feel free to apply D_PL1, just as long as you apply D_PL2 on top of it.
Whatever this problem is, it doesn't appear to be the "D_PLn" series of patches causing the problem (except infosar as they expose an already-existing memory corruption problem).
On Mon, 14 Oct 2002, Greg Turner wrote:
well, that sounds about right, but how to detect such a thing...? I guess I need to learn how to create 'on change some ram' breakpoints,
That's called "watchpoints". In gdb, you can set such a watchpoint with: watch *(int*)0xaddress
not to mention track down these datastructures in memory (or perhaps learn how to get debug symbols for w32-native-compiled stuff generated).
Well you can just use the pointer given to NdrClientCall2, right?
Serveral differences worth noting:
o Many more dlls loaded in the winelib version (why?)
Perhaps you have lots of unneeded import statements in your Winelib app's .spec file.
o lots of IMallocSpy activity in the winelib version (perhaps just part of the ole32 initialization?)
I suppose.
o pFormat argument to RPCRT4_NdrClientCall2 is different in the winelib version (!?)
Hmm, not good.
My theories:
o it's the try/except macros; they're causing stack corruption or something (they occur right before the NdrClientCall2) o it's MIDL_user_allocate somehow (nah) o it's a problem with dll loading (lets hope not)
o it's a calling convention problem (stdcall/cdecl, argument count, return value). This theory is substantiated by the difference in the pFormat argument. Perhaps gcc wants to return the CLIENT_CALL_RETURN structure in a way that isn't compatible with what Microsoft compilers expect (wants stack space reserved for it by the caller or something?)... I think we've had issues with gcc and returning structures before. If this is it, rpcrt4 probably need to return it as just LONG_PTR in the code, not CLIENT_CALL_RETURN?
On Tuesday 15 October 2002 10:53 am, Ove Kaaven wrote:
On Mon, 14 Oct 2002, Greg Turner wrote:
well, that sounds about right, but how to detect such a thing...? I guess I need to learn how to create 'on change some ram' breakpoints,
That's called "watchpoints". In gdb, you can set such a watchpoint with: watch *(int*)0xaddress
not to mention track down these datastructures in memory (or perhaps learn how to get debug symbols for w32-native-compiled stuff generated).
Well you can just use the pointer given to NdrClientCall2, right?
yes, but by then it's too late; besides, by the time we're in NdrClientCall2, I no longer trust anything I see. To pursue this, I need to snag it as early as possible. I was able to produce a .pdb file using the compiler. Winedbg loads it but still no dice. I'd almost rather just get to the raw data than worry about debug symbols in this case. I can put some magic numbers in there and grep the various allocated memory places, to generate some nice re-usable offsets. Anyhow, if it's a calling convention problem as discussed below, then presumably I would find no memory corruption, so I will look into that first.
Serveral differences worth noting:
o Many more dlls loaded in the winelib version (why?)
Perhaps you have lots of unneeded import statements in your Winelib app's .spec file.
that sounds right. winemaker seemed to generate a lot of superflous deps (and failed to generate the rpcrt4 one).
My theories:
o it's the try/except macros; they're causing stack corruption or something (they occur right before the NdrClientCall2) o it's MIDL_user_allocate somehow (nah) o it's a problem with dll loading (lets hope not)
o it's a calling convention problem (stdcall/cdecl, argument count, return value). This theory is substantiated by the difference in the pFormat argument. Perhaps gcc wants to return the CLIENT_CALL_RETURN structure in a way that isn't compatible with what Microsoft compilers expect (wants stack space reserved for it by the caller or something?)... I think we've had issues with gcc and returning structures before. If this is it, rpcrt4 probably need to return it as just LONG_PTR in the code, not CLIENT_CALL_RETURN?
I like this theory, it has recently occured to me too. I will try compiling the sample using stdcall and see if that has an effect, after work. Also, in the winelib version, I changed main() to stdcall from cdecl (!) which I took to mean that winelib framework didn't want that calling convention.
As for fixing it... this may be a bit beyond me; but I'll look into what you reccomend. If gcc and msvc use incompatible cdecl conventions then that's a pretty serious problem, right, not just for rpcrt4? Looks like to fix I will need to read some machine code.
If there's a fundamental problem here, I guess this would mean we'd have to install gcc<->msvc cdecl thunks somewhere to properly fix the problem? Well, perhaps not, just thinking out loud. I'll look into this tonight; I bet you are on to something here.
Greg Turner gmturner007@ameritech.net writes:
I like this theory, it has recently occured to me too. I will try compiling the sample using stdcall and see if that has an effect, after work. Also, in the winelib version, I changed main() to stdcall from cdecl (!) which I took to mean that winelib framework didn't want that calling convention.
It's not an stdcall/cdecl issue, Ove is right that it's a problem with returning a structure, gcc doesn't do it the same way as msvc. Just change NdrClientCall2 to return a LONG_PTR (it won't be 100% source compatible then, but we have no choice I'm afraid).
On 15 Oct 2002, Alexandre Julliard wrote:
Greg Turner gmturner007@ameritech.net writes:
I like this theory, it has recently occured to me too. I will try compiling the sample using stdcall and see if that has an effect, after work. Also, in the winelib version, I changed main() to stdcall from cdecl (!) which I took to mean that winelib framework didn't want that calling convention.
It's not an stdcall/cdecl issue, Ove is right that it's a problem with returning a structure, gcc doesn't do it the same way as msvc. Just change NdrClientCall2 to return a LONG_PTR (it won't be 100% source compatible then, but we have no choice I'm afraid).
Hmm. Maybe it's possible to do something in the fashion of
LONG_PTR RPC_VAR_ENTRY NdrClientCall2( PMIDL_STUB_DESC pStubDescriptor, PFORMAT_STRING pFormat, ... ); #ifndef __WINE__ #define NdrClientCall2 (CLIENT_CALL_RETURN)NdrClientCall2 #endif
to gain source compatibility.
On Tuesday 15 October 2002 12:07 pm, Ove Kaaven wrote:
On 15 Oct 2002, Alexandre Julliard wrote:
Greg Turner gmturner007@ameritech.net writes:
I like this theory, it has recently occured to me too. I will try compiling the sample using stdcall and see if that has an effect, after work. Also, in the winelib version, I changed main() to stdcall from cdecl (!) which I took to mean that winelib framework didn't want that calling convention.
It's not an stdcall/cdecl issue, Ove is right that it's a problem with returning a structure, gcc doesn't do it the same way as msvc. Just change NdrClientCall2 to return a LONG_PTR (it won't be 100% source compatible then, but we have no choice I'm afraid).
Hmm. Maybe it's possible to do something in the fashion of
LONG_PTR RPC_VAR_ENTRY NdrClientCall2( PMIDL_STUB_DESC pStubDescriptor, PFORMAT_STRING pFormat, ... ); #ifndef __WINE__ #define NdrClientCall2 (CLIENT_CALL_RETURN)NdrClientCall2 #endif
to gain source compatibility.
something like that should work... presumably we want to discriminate against msvc/gcc not wine/no-wine, right? Should I do something like this?
./include/commctrl.h-438-#if defined(__GNUC__) ./include/commctrl.h-439-# define PROGRESS_CLASSW (const WCHAR []){ 'm','s','c','t','l','s','_', \ ./include/commctrl.h-440- 'p','r','o','g','r','e','s','s','3','2',0 } ./include/commctrl.h:441:#elif defined(_MSC_VER) ./include/commctrl.h-442-# define PROGRESS_CLASSW L"msctls_progress32" ./include/commctrl.h-443-#else ./include/commctrl.h-444-static const WCHAR PROGRESS_CLASSW[] = { 'm','s','c','t','l','s','_', ./include/commctrl.h-445- 'p','r','o','g','r','e','s','s','3','2',0 }; ./include/commctrl.h-446-#endif
what is The Right Thing To Do if neither __GNUC__ nor _MSC_VER are defined in this case?
Ove Kaaven ovek@arcticnet.no writes:
Hmm. Maybe it's possible to do something in the fashion of
LONG_PTR RPC_VAR_ENTRY NdrClientCall2( PMIDL_STUB_DESC pStubDescriptor, PFORMAT_STRING pFormat, ... ); #ifndef __WINE__ #define NdrClientCall2 (CLIENT_CALL_RETURN)NdrClientCall2 #endif
to gain source compatibility.
Well, that's not 100% compatible either, and depending on how the app uses it could even fail to compile. I'd say we leave it as LONG_PTR and worry about it once we find a case where it matters in practice.
On 15 Oct 2002, Alexandre Julliard wrote:
Ove Kaaven ovek@arcticnet.no writes:
Hmm. Maybe it's possible to do something in the fashion of
LONG_PTR RPC_VAR_ENTRY NdrClientCall2( PMIDL_STUB_DESC pStubDescriptor, PFORMAT_STRING pFormat, ... ); #ifndef __WINE__ #define NdrClientCall2 (CLIENT_CALL_RETURN)NdrClientCall2 #endif
to gain source compatibility.
Well, that's not 100% compatible either, and depending on how the app uses it could even fail to compile.
Only MIDL-generated RPC client code is likely to use NdrClientCall2 directly. MIDL-generated code is 1) predictable, 2) plenty of. And if I remember right, the CLIENT_CALL_RETURN is going to be used by client code for remote procedure calls that has a return value. So I'd say this is both good enough and desirable (Greg can probably easily come up with an example?)... of course, we'd eventually have to finish widl and then we could generate RPC client code with it instead, but still...
On Tuesday 15 October 2002 12:34 pm, Alexandre Julliard wrote:
Ove Kaaven ovek@arcticnet.no writes:
Hmm. Maybe it's possible to do something in the fashion of
LONG_PTR RPC_VAR_ENTRY NdrClientCall2( PMIDL_STUB_DESC pStubDescriptor, PFORMAT_STRING pFormat, ... ); #ifndef __WINE__ #define NdrClientCall2 (CLIENT_CALL_RETURN)NdrClientCall2 #endif
to gain source compatibility.
Well, that's not 100% compatible either, and depending on how the app uses it could even fail to compile. I'd say we leave it as LONG_PTR and worry about it once we find a case where it matters in practice.
Well, if this were a democracy, I'd vote with Ove on this; his off-the-cuff implementation might not be the right one, but /something/ ought to be doable to preserve source-compatibility...
What, exactly, is the source-compatibility scenario we are trying to protect, here? Compiling wine under msvc to run the test suite? Seems like people do, indeed, do this, and I plan to add some kind of test of this code once I get a usable subset of marshalling & client stub invocation up and working; which means it'd become an issue at that time, I guess.
Since I don't think wine is (or should be) a democracy, I will go with Alexandre's advice ATM, and worry about it once I get around to testing. Hopefully, this will be sooner than later :) But I think I can come up with a reasonable solution at that time.
BTW, for now, WIDL should officially stand for "Wetware IDL" compiler :P
Greg Turner gmturner007@ameritech.net writes:
Well, if this were a democracy, I'd vote with Ove on this; his off-the-cuff implementation might not be the right one, but /something/ ought to be doable to preserve source-compatibility...
There's no point in doing anything until we know what compatibility problem we need to solve. But if the MIDL generated code requires something like Ove's fix, then that's of course a very good reason for including it.
On Tuesday 15 October 2002 01:50 pm, Alexandre Julliard wrote:
Greg Turner gmturner007@ameritech.net writes:
Well, if this were a democracy, I'd vote with Ove on this; his off-the-cuff implementation might not be the right one, but /something/ ought to be doable to preserve source-compatibility...
There's no point in doing anything until we know what compatibility problem we need to solve. But if the MIDL generated code requires something like Ove's fix, then that's of course a very good reason for including it.
hey, I just looked through the gcc info pages and found -fpcc-struct-return, which seems to adress this problem. does this exist in older gcc's? If so, wouldn't it solve this problem universally?