Now RpcMgmtStopServerListen /almost/ does the right thing, except a w-thread is left hanging (the unix process is in "suspended" state, haven't even looked into this yet), and //all other running wine processes freak out (hang) for some reason//. Maybe I just need to implement RpcServerUnregisterIf; but if that's the problem, there's a robustness deficiency (no surprise there, considering the largely untested status of the code). Needless to say, be careful if you want to experiment with this patchlevel's RPC capabilities, you /will/ loose your other wine processes permanently (until you kill them off). LICENSE: X11 CHANGELOG: * dlls/rpcrt4: ndr_marshall.c, rpc_binding.c, rpc_server.c, rpcrt4.spec; include: rpcdce.h: Greg Turner <gmturner007@ameritech.net> - fix offset bug in the conformant string unmarshall routine - fix discrepancy between headers and implementation of I_RpcBindingSetAsync when compiling under WINNT - eliminate race conditions in the relationship between "listen_count" and "std_listen" in rpc_server.h - code-stubs for RpcServerUnregisterIf, RpcServerUnregisterIfEx - attempt to implement RpcMgmtStopServerListening (definitely not happy just yet). - RpcServerUnregisterIfEx wasn't xp-sepcific after all; this leads me to suspect there are more such mistakes in the spec-file comments, but I haven't looked into it or fixed them yet (coming soon). - cleanups, trace-enhancements, etc. -- gmt "The purpose of government is to rein in the rights of the people" --President Bill Clinton, MTV interview, 1993
diff -ur -x CVS -x 'bigdif*' ../wine.test/dlls/rpcrt4/ndr_marshall.c ./dlls/rpcrt4/ndr_marshall.c --- ../wine.test/dlls/rpcrt4/ndr_marshall.c 2002-10-29 12:59:02.000000000 -0600 +++ ./dlls/rpcrt4/ndr_marshall.c 2002-10-29 13:28:39.000000000 -0600 @@ -199,7 +199,7 @@ len = LITTLE_ENDIAN_32_READ(pStubMsg->Buffer); pStubMsg->Buffer += 4; - pStubMsg->Buffer += ofs; + c += ofs; /* presumably this will always be zero, otherwise the string is no good */ while ((*c++ = *(pStubMsg->Buffer++)) != '\0') ; diff -ur -x CVS -x 'bigdif*' ../wine.test/dlls/rpcrt4/rpc_binding.c ./dlls/rpcrt4/rpc_binding.c --- ../wine.test/dlls/rpcrt4/rpc_binding.c 2002-10-29 12:59:02.000000000 -0600 +++ ./dlls/rpcrt4/rpc_binding.c 2002-10-29 13:28:39.000000000 -0600 @@ -865,14 +865,21 @@ * Exists in win9x and winNT, but with different number of arguments * (9x version has 3 arguments, NT has 2). */ +#ifdef WINNT +RPC_STATUS WINAPI I_RpcBindingSetAsync( RPC_BINDING_HANDLE Binding, RPC_BLOCKING_FN BlockingFn) +#else RPC_STATUS WINAPI I_RpcBindingSetAsync( RPC_BINDING_HANDLE Binding, RPC_BLOCKING_FN BlockingFn, unsigned long ServerTid ) +#endif { RpcBinding* bind = (RpcBinding*)Binding; TRACE( "(%p,%p,%ld): stub\n", Binding, BlockingFn, ServerTid ); bind->BlockingFn = BlockingFn; + + #ifndef WINNT bind->ServerTid = ServerTid; + #endif return RPC_S_OK; } diff -ur -x CVS -x 'bigdif*' ../wine.test/dlls/rpcrt4/rpc_server.c ./dlls/rpcrt4/rpc_server.c --- ../wine.test/dlls/rpcrt4/rpc_server.c 2002-10-29 12:59:02.000000000 -0600 +++ ./dlls/rpcrt4/rpc_server.c 2002-10-29 13:28:51.000000000 -0600 @@ -23,6 +23,7 @@ #include <stdio.h> #include <string.h> +#include <assert.h> #include "windef.h" #include "winbase.h" @@ -42,6 +43,7 @@ static RpcServerInterface* ifs; static CRITICAL_SECTION server_cs = CRITICAL_SECTION_INIT("RpcServer"); +static CRITICAL_SECTION listen_cs = CRITICAL_SECTION_INIT("RpcListen"); static BOOL std_listen; static LONG listen_count = -1; static HANDLE mgr_event, server_thread; @@ -95,7 +97,7 @@ } #endif if (dwRead != sizeof(hdr)) { - TRACE("protocol error\n"); + if (dwRead) TRACE("protocol error: <hdrsz == %d, dwRead == %lu>\n", sizeof(hdr), dwRead); break; } @@ -118,7 +120,7 @@ } #endif if (dwRead != hdr.len) { - TRACE("protocol error\n"); + TRACE("protocol error: <bodylen == %d, dwRead == %lu>\n", hdr.len, dwRead); break; } @@ -231,7 +233,7 @@ /* start waiting */ res = WaitForMultipleObjects(count, objs, FALSE, INFINITE); if (res == WAIT_OBJECT_0) { - if (listen_count == -1) break; + if (!std_listen) break; } else if (res == WAIT_FAILED) { ERR("wait failed\n"); @@ -279,24 +281,33 @@ static void RPCRT4_start_listen(void) { TRACE("\n"); - if (!InterlockedIncrement(&listen_count)) { - mgr_event = CreateEventA(NULL, FALSE, FALSE, NULL); + + EnterCriticalSection(&listen_cs); + if (! ++listen_count) { + if (!mgr_event) mgr_event = CreateEventA(NULL, FALSE, FALSE, NULL); + std_listen = TRUE; server_thread = CreateThread(NULL, 0, RPCRT4_server_thread, NULL, 0, NULL); + LeaveCriticalSection(&listen_cs); + } else { + LeaveCriticalSection(&listen_cs); + SetEvent(mgr_event); } - else SetEvent(mgr_event); } -/* not used (WTF?) --------------------------- - static void RPCRT4_stop_listen(void) { - HANDLE m_event = mgr_event; - if (InterlockedDecrement(&listen_count) < 0) - SetEvent(m_event); + EnterCriticalSection(&listen_cs); + if (listen_count == -1) + LeaveCriticalSection(&listen_cs); + else if (--listen_count == -1) { + std_listen = FALSE; + LeaveCriticalSection(&listen_cs); + SetEvent(mgr_event); + } else + LeaveCriticalSection(&listen_cs); + assert(listen_count > -2); } ---------------------- */ - static RPC_STATUS RPCRT4_use_protseq(RpcServerProtseq* ps) { RPCRT4_CreateBindingA(&ps->bind, TRUE, ps->Protseq); @@ -307,7 +318,7 @@ protseqs = ps; LeaveCriticalSection(&server_cs); - if (listen_count >= 0) SetEvent(mgr_event); + if (std_listen) SetEvent(mgr_event); return RPC_S_OK; } @@ -535,6 +546,28 @@ } /*********************************************************************** + * RpcServerUnregisterIf (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcServerUnregisterIf( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, UINT WaitForCallsToComplete ) +{ + FIXME("(IfSpec == (RPC_IF_HANDLE)^%p, MgrTypeUuid == %s, WaitForCallsToComplete == %u): stub\n", + IfSpec, debugstr_guid(MgrTypeUuid), WaitForCallsToComplete); + + return RPC_S_OK; +} + +/*********************************************************************** + * RpcServerUnregisterIfEx (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcServerUnregisterIfEx( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, int RundownContextHandles ) +{ + FIXME("(IfSpec == (RPC_IF_HANDLE)^%p, MgrTypeUuid == %s, RundownContextHandles == %d): stub\n", + IfSpec, debugstr_guid(MgrTypeUuid), RundownContextHandles); + + return RPC_S_OK; +} + +/*********************************************************************** * RpcServerRegisterAuthInfoA (RPCRT4.@) */ RPC_STATUS WINAPI RpcServerRegisterAuthInfoA( LPSTR ServerPrincName, ULONG AuthnSvc, RPC_AUTH_KEY_RETRIEVAL_FN GetKeyFn, @@ -563,15 +596,20 @@ { TRACE("(%u,%u,%u)\n", MinimumCallThreads, MaxCalls, DontWait); - if (std_listen) - return RPC_S_ALREADY_LISTENING; - if (!protseqs) return RPC_S_NO_PROTSEQS_REGISTERED; - std_listen = TRUE; + EnterCriticalSection(&listen_cs); + + if (std_listen) { + LeaveCriticalSection(&listen_cs); + return RPC_S_ALREADY_LISTENING; + } + RPCRT4_start_listen(); + LeaveCriticalSection(&listen_cs); + if (DontWait) return RPC_S_OK; return RpcMgmtWaitServerListen(); @@ -585,18 +623,46 @@ RPC_STATUS rslt = RPC_S_OK; TRACE("\n"); + + EnterCriticalSection(&listen_cs); + if (!std_listen) - if ( (rslt = RpcServerListen(1, 0, TRUE)) != RPC_S_OK ) + if ( (rslt = RpcServerListen(1, 0, TRUE)) != RPC_S_OK ) { + LeaveCriticalSection(&listen_cs); return rslt; + } + LeaveCriticalSection(&listen_cs); + while (std_listen) { - WaitForSingleObject(mgr_event, 1000); + WaitForSingleObject(mgr_event, INFINITE); } return rslt; } /*********************************************************************** + * RpcMgmtStopServerListening (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcMgmtStopServerListening ( RPC_BINDING_HANDLE Binding ) +{ + TRACE("(Binding == (RPC_BINDING_HANDLE)^%p)\n", Binding); + + if (Binding) { + FIXME("client-side invocation not implemented.\n"); + return RPC_S_WRONG_KIND_OF_BINDING; + } + + /* hmm... */ + EnterCriticalSection(&listen_cs); + while (std_listen) + RPCRT4_stop_listen(); + LeaveCriticalSection(&listen_cs); + + return RPC_S_OK; +} + +/*********************************************************************** * I_RpcServerStartListening (RPCRT4.@) */ RPC_STATUS WINAPI I_RpcServerStartListening( void* hWnd ) diff -ur -x CVS -x 'bigdif*' ../wine.test/dlls/rpcrt4/rpcrt4.spec ./dlls/rpcrt4/rpcrt4.spec --- ../wine.test/dlls/rpcrt4/rpcrt4.spec 2002-10-29 14:09:58.000000000 -0600 +++ ./dlls/rpcrt4/rpcrt4.spec 2002-10-29 13:48:08.000000000 -0600 @@ -98,7 +98,7 @@ @ stub RpcMgmtSetParameter # win9x @ stub RpcMgmtSetServerStackSize @ stub RpcMgmtStatsVectorFree -@ stub RpcMgmtStopServerListening +@ stdcall RpcMgmtStopServerListening(ptr) RpcMgmtStopServerListening @ stdcall RpcMgmtWaitServerListen() RpcMgmtWaitServerListen @ stub RpcNetworkInqProtseqsA @ stub RpcNetworkInqProtseqsW @@ -128,8 +128,8 @@ @ stdcall RpcServerRegisterIfEx(ptr ptr ptr long long ptr) RpcServerRegisterIfEx @ stdcall RpcServerRegisterIf2(ptr ptr ptr long long long ptr) RpcServerRegisterIf2 @ stub RpcServerTestCancel -@ stub RpcServerUnregisterIf -@ stub RpcServerUnregisterIfEx # wxp +@ stdcall RpcServerUnregisterIf(ptr ptr long) RpcServerUnregisterIf +@ stdcall RpcServerUnregisterIfEx(ptr ptr long) RpcServerUnregisterIfEx @ stub RpcServerUseAllProtseqs @ stub RpcServerUseAllProtseqsEx @ stub RpcServerUseAllProtseqsIf diff -ur -x CVS -x 'bigdif*' ../wine.test/include/rpcdce.h ./include/rpcdce.h --- ../wine.test/include/rpcdce.h 2002-10-29 12:42:46.000000000 -0600 +++ ./include/rpcdce.h 2002-10-29 13:28:51.000000000 -0600 @@ -173,6 +173,9 @@ RpcMgmtWaitServerListen( void ); RPCRTAPI RPC_STATUS RPC_ENTRY + RpcMgmtStopServerListening( RPC_BINDING_HANDLE Binding ); + +RPCRTAPI RPC_STATUS RPC_ENTRY RpcServerRegisterIf( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, RPC_MGR_EPV* MgrEpv ); RPCRTAPI RPC_STATUS RPC_ENTRY @@ -183,6 +186,12 @@ RpcServerRegisterIf2( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, RPC_MGR_EPV* MgrEpv, UINT Flags, UINT MaxCalls, UINT MaxRpcSize, RPC_IF_CALLBACK_FN* IfCallbackFn ); +RPCRTAPI RPC_STATUS RPC_ENTRY + RpcServerUnregisterIf( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, UINT WaitForCallsToComplete ); + +RPCRTAPI RPC_STATUS RPC_ENTRY + RpcServerUnregisterIfEx( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, int RundownContextHandles ); + RPCRTAPI RPC_STATUS RPC_ENTRY RpcServerUseProtseqA(LPSTR Protseq, unsigned int MaxCalls, void *SecurityDescriptor); @@ -190,7 +199,6 @@ RpcServerUseProtseqW(LPWSTR Protseq, unsigned int MaxCalls, void *SecurityDescriptor); #define RpcServerUseProtseq WINELIB_NAME_AW(RpcServerUseProtseq) - RPCRTAPI RPC_STATUS RPC_ENTRY RpcServerUseProtseqEpA( LPSTR Protseq, UINT MaxCalls, LPSTR Endpoint, LPVOID SecurityDescriptor ); RPCRTAPI RPC_STATUS RPC_ENTRY