Author: akhaldi Date: Sun Sep 17 22:57:32 2017 New Revision: 75898
URL: http://svn.reactos.org/svn/reactos?rev=75898&view=rev Log: [RPCRT4] Sync with Wine Staging 2.16. CORE-13762
2d9e894 rpcrt4: Always protect ref access for connections associated with protseq in RPCRT4_ReleaseConnection. aea6d23 rpcrt4: Mark function that are only called from assembly as hidden. bea5c0c rpcrt4: Spelling fixes in comments. 2cb32b2 rpcrt4: Change RPCRT4_ReleaseConnection return type to void. e889b02 rpcrt4: Fix a race when server grabs a connection from the list of active connections. 09e98be rpcrt4: Wait for server threads to finish in RpcMgmtWaitServerListen. e98c7a5 rpcrt4: Wait for all active connections to be released before quiting server thread. 10a6b33 rpcrt4: Recreate listening pipe in rpcrt4_protseq_np_get_wait_array if needed. 5c2083f rpcrt4: Store listening pipe name in RpcConnection_np. 5c81f82 rpcrt4: Store server thread handle in RpcServerProtseq.
Modified: trunk/reactos/dll/win32/rpcrt4/ndr_marshall.c trunk/reactos/dll/win32/rpcrt4/ndr_stubless.c trunk/reactos/dll/win32/rpcrt4/rpc_binding.c trunk/reactos/dll/win32/rpcrt4/rpc_binding.h trunk/reactos/dll/win32/rpcrt4/rpc_server.c trunk/reactos/dll/win32/rpcrt4/rpc_server.h trunk/reactos/dll/win32/rpcrt4/rpc_transport.c trunk/reactos/media/doc/README.WINE
Modified: trunk/reactos/dll/win32/rpcrt4/ndr_marshall.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/rpcrt4/ndr_marsha... ============================================================================== --- trunk/reactos/dll/win32/rpcrt4/ndr_marshall.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/rpcrt4/ndr_marshall.c [iso-8859-1] Sun Sep 17 22:57:32 2017 @@ -2929,7 +2929,7 @@ { /* for some reason interface pointers aren't generated as * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet - * they still need the derefencing treatment that pointers are + * they still need the dereferencing treatment that pointers are * given */ if (*desc == RPC_FC_IP) m(pStubMsg, *(unsigned char **)pMemory, desc); @@ -3105,7 +3105,7 @@ { /* for some reason interface pointers aren't generated as * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet - * they still need the derefencing treatment that pointers are + * they still need the dereferencing treatment that pointers are * given */ if (*desc == RPC_FC_IP) m(pStubMsg, (unsigned char **)pMemory, desc, FALSE); @@ -3229,7 +3229,7 @@ { /* for some reason interface pointers aren't generated as * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet - * they still need the derefencing treatment that pointers are + * they still need the dereferencing treatment that pointers are * given */ if (*desc == RPC_FC_IP) m(pStubMsg, *(unsigned char **)pMemory, desc); @@ -3330,7 +3330,7 @@ { /* for some reason interface pointers aren't generated as * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet - * they still need the derefencing treatment that pointers are + * they still need the dereferencing treatment that pointers are * given */ if (*desc == RPC_FC_IP) m(pStubMsg, *(unsigned char **)pMemory, desc);
Modified: trunk/reactos/dll/win32/rpcrt4/ndr_stubless.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/rpcrt4/ndr_stuble... ============================================================================== --- trunk/reactos/dll/win32/rpcrt4/ndr_stubless.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/rpcrt4/ndr_stubless.c [iso-8859-1] Sun Sep 17 22:57:32 2017 @@ -581,8 +581,8 @@ return (PFORMAT_STRING)args; }
-LONG_PTR CDECL ndr_client_call( PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat, - void **stack_top, void **fpu_stack ) +LONG_PTR CDECL DECLSPEC_HIDDEN ndr_client_call( PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat, + void **stack_top, void **fpu_stack ) { /* pointer to start of stack where arguments start */ RPC_MESSAGE rpcMsg; @@ -1511,7 +1511,8 @@ ULONG_PTR NdrCorrCache[256]; };
-LONG_PTR CDECL ndr_async_client_call( PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat, void **stack_top ) +LONG_PTR CDECL DECLSPEC_HIDDEN ndr_async_client_call( PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat, + void **stack_top ) { /* pointer to start of stack where arguments start */ PRPC_MESSAGE pRpcMsg;
Modified: trunk/reactos/dll/win32/rpcrt4/rpc_binding.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/rpcrt4/rpc_bindin... ============================================================================== --- trunk/reactos/dll/win32/rpcrt4/rpc_binding.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/rpcrt4/rpc_binding.c [iso-8859-1] Sun Sep 17 22:57:32 2017 @@ -279,14 +279,13 @@ if (!Connection) return RPC_S_OK; if (Binding->server) { /* don't destroy a connection that is cached in the binding */ - if (Binding->FromConn == Connection) - return RPC_S_OK; - return RPCRT4_ReleaseConnection(Connection); + if (Binding->FromConn != Connection) + RPCRT4_ReleaseConnection(Connection); } else { RpcAssoc_ReleaseIdleConnection(Binding->Assoc, Connection); - return RPC_S_OK; - } + } + return RPC_S_OK; }
static LPSTR RPCRT4_strconcatA(LPSTR dst, LPCSTR src)
Modified: trunk/reactos/dll/win32/rpcrt4/rpc_binding.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/rpcrt4/rpc_bindin... ============================================================================== --- trunk/reactos/dll/win32/rpcrt4/rpc_binding.h [iso-8859-1] (original) +++ trunk/reactos/dll/win32/rpcrt4/rpc_binding.h [iso-8859-1] Sun Sep 17 22:57:32 2017 @@ -59,6 +59,7 @@ { LONG ref; BOOL server; + HANDLE wait_release; LPSTR NetworkAddr; LPSTR Endpoint; LPWSTR NetworkOptions; @@ -158,7 +159,7 @@ LPCSTR NetworkAddr, LPCSTR Endpoint, LPCWSTR NetworkOptions, RpcAuthInfo* AuthInfo, RpcQualityOfService *QOS, LPCWSTR CookieAuth) DECLSPEC_HIDDEN; RpcConnection *RPCRT4_GrabConnection( RpcConnection *conn ) DECLSPEC_HIDDEN; -RPC_STATUS RPCRT4_ReleaseConnection(RpcConnection* Connection) DECLSPEC_HIDDEN; +void RPCRT4_ReleaseConnection(RpcConnection* Connection) DECLSPEC_HIDDEN; RPC_STATUS RPCRT4_OpenClientConnection(RpcConnection* Connection) DECLSPEC_HIDDEN; RPC_STATUS RPCRT4_CloseConnection(RpcConnection* Connection) DECLSPEC_HIDDEN; RPC_STATUS RPCRT4_IsServerListening(const char *protseq, const char *endpoint) DECLSPEC_HIDDEN; @@ -172,6 +173,8 @@ const RPC_SYNTAX_IDENTIFIER *TransferSyntax, const RPC_SYNTAX_IDENTIFIER *InterfaceId) DECLSPEC_HIDDEN; RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection) DECLSPEC_HIDDEN;
+void rpcrt4_conn_release_and_wait(RpcConnection *connection) DECLSPEC_HIDDEN; + static inline const char *rpcrt4_conn_get_name(const RpcConnection *Connection) { return Connection->ops->name;
Modified: trunk/reactos/dll/win32/rpcrt4/rpc_server.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/rpcrt4/rpc_server... ============================================================================== --- trunk/reactos/dll/win32/rpcrt4/rpc_server.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/rpcrt4/rpc_server.c [iso-8859-1] Sun Sep 17 22:57:32 2017 @@ -647,21 +647,44 @@ { /* cleanup */ cps->ops->free_wait_array(cps, objs); - - EnterCriticalSection(&cps->cs); - LIST_FOR_EACH_ENTRY(conn, &cps->listeners, RpcConnection, protseq_entry) - RPCRT4_CloseConnection(conn); - LIST_FOR_EACH_ENTRY(conn, &cps->connections, RpcConnection, protseq_entry) - rpcrt4_conn_close_read(conn); - LeaveCriticalSection(&cps->cs); - - if (res == 0 && !std_listen) - SetEvent(cps->server_ready_event); break; } else if (res == 0) set_ready_event = TRUE; } + + TRACE("closing connections\n"); + + EnterCriticalSection(&cps->cs); + LIST_FOR_EACH_ENTRY(conn, &cps->listeners, RpcConnection, protseq_entry) + RPCRT4_CloseConnection(conn); + LIST_FOR_EACH_ENTRY(conn, &cps->connections, RpcConnection, protseq_entry) + { + RPCRT4_GrabConnection(conn); + rpcrt4_conn_close_read(conn); + } + LeaveCriticalSection(&cps->cs); + + if (res == 0 && !std_listen) + SetEvent(cps->server_ready_event); + + TRACE("waiting for active connections to close\n"); + + EnterCriticalSection(&cps->cs); + while (!list_empty(&cps->connections)) + { + conn = LIST_ENTRY(list_head(&cps->connections), RpcConnection, protseq_entry); + LeaveCriticalSection(&cps->cs); + rpcrt4_conn_release_and_wait(conn); + EnterCriticalSection(&cps->cs); + } + LeaveCriticalSection(&cps->cs); + + EnterCriticalSection(&listen_cs); + CloseHandle(cps->server_thread); + cps->server_thread = NULL; + LeaveCriticalSection(&listen_cs); + TRACE("done\n"); return 0; }
@@ -685,21 +708,15 @@ static RPC_STATUS RPCRT4_start_listen_protseq(RpcServerProtseq *ps, BOOL auto_listen) { RPC_STATUS status = RPC_S_OK; - HANDLE server_thread;
EnterCriticalSection(&listen_cs); - if (ps->is_listening) goto done; + if (ps->server_thread) goto done;
if (!ps->mgr_mutex) ps->mgr_mutex = CreateMutexW(NULL, FALSE, NULL); if (!ps->server_ready_event) ps->server_ready_event = CreateEventW(NULL, FALSE, FALSE, NULL); - server_thread = CreateThread(NULL, 0, RPCRT4_server_thread, ps, 0, NULL); - if (!server_thread) - { + ps->server_thread = CreateThread(NULL, 0, RPCRT4_server_thread, ps, 0, NULL); + if (!ps->server_thread) status = RPC_S_OUT_OF_RESOURCES; - goto done; - } - ps->is_listening = TRUE; - CloseHandle(server_thread);
done: LeaveCriticalSection(&listen_cs); @@ -767,8 +784,10 @@
if (stop_listen) { RpcServerProtseq *cps; + EnterCriticalSection(&server_cs); LIST_FOR_EACH_ENTRY(cps, &protseqs, RpcServerProtseq, entry) RPCRT4_sync_with_server_thread(cps); + LeaveCriticalSection(&server_cs); }
if (!auto_listen) @@ -1503,7 +1522,8 @@ */ RPC_STATUS WINAPI RpcMgmtWaitServerListen( void ) { - HANDLE event; + RpcServerProtseq *protseq; + HANDLE event, wait_thread;
TRACE("()\n");
@@ -1519,6 +1539,28 @@ TRACE( "done waiting\n" );
EnterCriticalSection(&listen_cs); + /* wait for server threads to finish */ + while(1) + { + if (listen_count) + break; + + wait_thread = NULL; + EnterCriticalSection(&server_cs); + LIST_FOR_EACH_ENTRY(protseq, &protseqs, RpcServerProtseq, entry) + { + if ((wait_thread = protseq->server_thread)) + break; + } + LeaveCriticalSection(&server_cs); + if (!wait_thread) + break; + + TRACE("waiting for thread %u\n", GetThreadId(wait_thread)); + LeaveCriticalSection(&listen_cs); + WaitForSingleObject(wait_thread, INFINITE); + EnterCriticalSection(&listen_cs); + } if (listen_done_event == event) { listen_done_event = NULL;
Modified: trunk/reactos/dll/win32/rpcrt4/rpc_server.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/rpcrt4/rpc_server... ============================================================================== --- trunk/reactos/dll/win32/rpcrt4/rpc_server.h [iso-8859-1] (original) +++ trunk/reactos/dll/win32/rpcrt4/rpc_server.h [iso-8859-1] Sun Sep 17 22:57:32 2017 @@ -36,8 +36,8 @@ struct list connections; /* CS cs */ CRITICAL_SECTION cs;
- /* is the server currently listening? */ - BOOL is_listening; /* CS ::listen_cs */ + /* handle to listening thread */ + HANDLE server_thread; /* CS ::listen_cs */ /* mutex for ensuring only one thread can change state at a time */ HANDLE mgr_mutex; /* set when server thread has finished opening connections */
Modified: trunk/reactos/dll/win32/rpcrt4/rpc_transport.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/rpcrt4/rpc_transp... ============================================================================== --- trunk/reactos/dll/win32/rpcrt4/rpc_transport.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/rpcrt4/rpc_transport.c [iso-8859-1] Sun Sep 17 22:57:32 2017 @@ -65,6 +65,7 @@ RpcConnection common; HANDLE pipe; HANDLE listen_event; + char *listen_pipe; IO_STATUS_BLOCK io_status; HANDLE event_cache; BOOL read_closed; @@ -89,26 +90,26 @@ CloseHandle(event); }
-static RPC_STATUS rpcrt4_conn_create_pipe(RpcConnection *Connection, LPCSTR pname) -{ - RpcConnection_np *npc = (RpcConnection_np *) Connection; - TRACE("listening on %s\n", pname); - - npc->pipe = CreateNamedPipeA(pname, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, - PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, - PIPE_UNLIMITED_INSTANCES, - RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE, 5000, NULL); - if (npc->pipe == INVALID_HANDLE_VALUE) { - WARN("CreateNamedPipe failed with error %d\n", GetLastError()); - if (GetLastError() == ERROR_FILE_EXISTS) - return RPC_S_DUPLICATE_ENDPOINT; - else - return RPC_S_CANT_CREATE_ENDPOINT; - } - - /* Note: we don't call ConnectNamedPipe here because it must be done in the - * server thread as the thread must be alertable */ - return RPC_S_OK; +static RPC_STATUS rpcrt4_conn_create_pipe(RpcConnection *conn) +{ + RpcConnection_np *connection = (RpcConnection_np *) conn; + + TRACE("listening on %s\n", connection->listen_pipe); + + connection->pipe = CreateNamedPipeA(connection->listen_pipe, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, + PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, + PIPE_UNLIMITED_INSTANCES, + RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE, 5000, NULL); + if (connection->pipe == INVALID_HANDLE_VALUE) + { + WARN("CreateNamedPipe failed with error %d\n", GetLastError()); + if (GetLastError() == ERROR_FILE_EXISTS) + return RPC_S_DUPLICATE_ENDPOINT; + else + return RPC_S_CANT_CREATE_ENDPOINT; + } + + return RPC_S_OK; }
static RPC_STATUS rpcrt4_conn_open_pipe(RpcConnection *Connection, LPCSTR pname, BOOL wait) @@ -201,7 +202,6 @@ static RPC_STATUS rpcrt4_protseq_ncalrpc_open_endpoint(RpcServerProtseq* protseq, const char *endpoint) { RPC_STATUS r; - LPSTR pname; RpcConnection *Connection; char generated_endpoint[22];
@@ -220,9 +220,8 @@ if (r != RPC_S_OK) return r;
- pname = ncalrpc_pipe_name(Connection->Endpoint); - r = rpcrt4_conn_create_pipe(Connection, pname); - I_RpcFree(pname); + ((RpcConnection_np*)Connection)->listen_pipe = ncalrpc_pipe_name(Connection->Endpoint); + r = rpcrt4_conn_create_pipe(Connection);
EnterCriticalSection(&protseq->cs); list_add_head(&protseq->listeners, &Connection->protseq_entry); @@ -263,7 +262,6 @@ static RPC_STATUS rpcrt4_protseq_ncacn_np_open_endpoint(RpcServerProtseq *protseq, const char *endpoint) { RPC_STATUS r; - LPSTR pname; RpcConnection *Connection; char generated_endpoint[26];
@@ -282,9 +280,8 @@ if (r != RPC_S_OK) return r;
- pname = ncacn_pipe_name(Connection->Endpoint); - r = rpcrt4_conn_create_pipe(Connection, pname); - I_RpcFree(pname); + ((RpcConnection_np*)Connection)->listen_pipe = ncacn_pipe_name(Connection->Endpoint); + r = rpcrt4_conn_create_pipe(Connection);
EnterCriticalSection(&protseq->cs); list_add_head(&protseq->listeners, &Connection->protseq_entry); @@ -308,13 +305,9 @@ { DWORD len = MAX_COMPUTERNAME_LENGTH + 1; RPC_STATUS status; - LPSTR pname;
rpcrt4_conn_np_handoff((RpcConnection_np *)old_conn, (RpcConnection_np *)new_conn); - - pname = ncacn_pipe_name(old_conn->Endpoint); - status = rpcrt4_conn_create_pipe(old_conn, pname); - I_RpcFree(pname); + status = rpcrt4_conn_create_pipe(old_conn);
/* Store the local computer name as the NetworkAddr for ncacn_np as long as * we don't support named pipes over the network. */ @@ -359,15 +352,11 @@ { DWORD len = MAX_COMPUTERNAME_LENGTH + 1; RPC_STATUS status; - LPSTR pname;
TRACE("%s\n", old_conn->Endpoint);
rpcrt4_conn_np_handoff((RpcConnection_np *)old_conn, (RpcConnection_np *)new_conn); - - pname = ncalrpc_pipe_name(old_conn->Endpoint); - status = rpcrt4_conn_create_pipe(old_conn, pname); - I_RpcFree(pname); + status = rpcrt4_conn_create_pipe(old_conn);
/* Store the local computer name as the NetworkAddr for ncalrpc. */ new_conn->NetworkAddr = HeapAlloc(GetProcessHeap(), 0, len); @@ -672,6 +661,8 @@ *count = 1; LIST_FOR_EACH_ENTRY(conn, &protseq->listeners, RpcConnection_np, common.protseq_entry) { + if (!conn->pipe && rpcrt4_conn_create_pipe(&conn->common) != RPC_S_OK) + continue; if (!conn->listen_event) { NTSTATUS status; @@ -3372,38 +3363,69 @@ return connection; }
-RpcConnection *RPCRT4_GrabConnection( RpcConnection *conn ) -{ - InterlockedIncrement( &conn->ref ); - return conn; -} - -RPC_STATUS RPCRT4_ReleaseConnection(RpcConnection* Connection) -{ - if (InterlockedDecrement( &Connection->ref ) > 0) return RPC_S_OK; - - TRACE("destroying connection %p\n", Connection); - - RPCRT4_CloseConnection(Connection); - RPCRT4_strfree(Connection->Endpoint); - RPCRT4_strfree(Connection->NetworkAddr); - HeapFree(GetProcessHeap(), 0, Connection->NetworkOptions); - HeapFree(GetProcessHeap(), 0, Connection->CookieAuth); - if (Connection->AuthInfo) RpcAuthInfo_Release(Connection->AuthInfo); - if (Connection->QOS) RpcQualityOfService_Release(Connection->QOS); - - /* server-only */ - if (Connection->server_binding) RPCRT4_ReleaseBinding(Connection->server_binding); - - if (Connection->protseq) - { - EnterCriticalSection(&Connection->protseq->cs); - list_remove(&Connection->protseq_entry); - LeaveCriticalSection(&Connection->protseq->cs); - } - - HeapFree(GetProcessHeap(), 0, Connection); - return RPC_S_OK; +void rpcrt4_conn_release_and_wait(RpcConnection *connection) +{ + HANDLE event = NULL; + + if (connection->ref > 1) + event = connection->wait_release = CreateEventW(NULL, TRUE, FALSE, NULL); + + RPCRT4_ReleaseConnection(connection); + + if(event) + { + WaitForSingleObject(event, INFINITE); + CloseHandle(event); + } +} + +RpcConnection *RPCRT4_GrabConnection(RpcConnection *connection) +{ + LONG ref = InterlockedIncrement(&connection->ref); + TRACE("%p ref=%u\n", connection, ref); + return connection; +} + +void RPCRT4_ReleaseConnection(RpcConnection *connection) +{ + LONG ref; + + /* protseq stores a list of active connections, but does not own references to them. + * It may need to grab a connection from the list, which could lead to a race if + * connection is being released, but not yet removed from the list. We handle that + * by synchronizing on CS here. */ + if (connection->protseq) + { + EnterCriticalSection(&connection->protseq->cs); + ref = InterlockedDecrement(&connection->ref); + if (!ref) + list_remove(&connection->protseq_entry); + LeaveCriticalSection(&connection->protseq->cs); + } + else + { + ref = InterlockedDecrement(&connection->ref); + } + + TRACE("%p ref=%u\n", connection, ref); + + if (!ref) + { + RPCRT4_CloseConnection(connection); + RPCRT4_strfree(connection->Endpoint); + RPCRT4_strfree(connection->NetworkAddr); + HeapFree(GetProcessHeap(), 0, connection->NetworkOptions); + HeapFree(GetProcessHeap(), 0, connection->CookieAuth); + if (connection->AuthInfo) RpcAuthInfo_Release(connection->AuthInfo); + if (connection->QOS) RpcQualityOfService_Release(connection->QOS); + + /* server-only */ + if (connection->server_binding) RPCRT4_ReleaseBinding(connection->server_binding); + + if (connection->wait_release) SetEvent(connection->wait_release); + + HeapFree(GetProcessHeap(), 0, connection); + } }
RPC_STATUS RPCRT4_IsServerListening(const char *protseq, const char *endpoint)
Modified: trunk/reactos/media/doc/README.WINE URL: http://svn.reactos.org/svn/reactos/trunk/reactos/media/doc/README.WINE?rev=7... ============================================================================== --- trunk/reactos/media/doc/README.WINE [iso-8859-1] (original) +++ trunk/reactos/media/doc/README.WINE [iso-8859-1] Sun Sep 17 22:57:32 2017 @@ -160,7 +160,7 @@ reactos/dll/win32/resutils # Synced to WineStaging-2.9 reactos/dll/win32/riched20 # Synced to WineStaging-2.16 reactos/dll/win32/riched32 # Synced to WineStaging-2.9 -reactos/dll/win32/rpcrt4 # Synced to WineStaging-2.9 +reactos/dll/win32/rpcrt4 # Synced to WineStaging-2.16 reactos/dll/win32/rsabase # Synced to WineStaging-2.9 reactos/dll/win32/rsaenh # Synced to WineStaging-2.9 reactos/dll/win32/sccbase # Synced to WineStaging-2.9