diff --git a/dlls/rpcrt4/rpc_assoc.c b/dlls/rpcrt4/rpc_assoc.c index bcaa1c2579e..8cf294798a2 100644 --- a/dlls/rpcrt4/rpc_assoc.c +++ b/dlls/rpcrt4/rpc_assoc.c @@ -203,7 +203,7 @@ ULONG RpcAssoc_Release(RpcAssoc *assoc) LIST_FOR_EACH_ENTRY_SAFE(Connection, cursor2, &assoc->free_connection_pool, RpcConnection, conn_pool_entry) { list_remove(&Connection->conn_pool_entry); - RPCRT4_DestroyConnection(Connection); + RPCRT4_ReleaseConnection(Connection); } LIST_FOR_EACH_ENTRY_SAFE(context_handle, context_handle_cursor, &assoc->context_handle_list, RpcContextHandle, entry) @@ -410,14 +410,14 @@ RPC_STATUS RpcAssoc_GetClientConnection(RpcAssoc *assoc, status = RPCRT4_OpenClientConnection(NewConnection); if (status != RPC_S_OK) { - RPCRT4_DestroyConnection(NewConnection); + RPCRT4_ReleaseConnection(NewConnection); return status; } status = RpcAssoc_BindConnection(assoc, NewConnection, InterfaceId, TransferSyntax); if (status != RPC_S_OK) { - RPCRT4_DestroyConnection(NewConnection); + RPCRT4_ReleaseConnection(NewConnection); return status; } diff --git a/dlls/rpcrt4/rpc_binding.c b/dlls/rpcrt4/rpc_binding.c index 685b569835e..11956e3d6f9 100644 --- a/dlls/rpcrt4/rpc_binding.c +++ b/dlls/rpcrt4/rpc_binding.c @@ -298,7 +298,7 @@ RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection) /* don't destroy a connection that is cached in the binding */ if (Binding->FromConn == Connection) return RPC_S_OK; - return RPCRT4_DestroyConnection(Connection); + return RPCRT4_ReleaseConnection(Connection); } else { RpcAssoc_ReleaseIdleConnection(Binding->Assoc, Connection); diff --git a/dlls/rpcrt4/rpc_binding.h b/dlls/rpcrt4/rpc_binding.h index 7d49074fc5e..21c962d91fa 100644 --- a/dlls/rpcrt4/rpc_binding.h +++ b/dlls/rpcrt4/rpc_binding.h @@ -61,6 +61,7 @@ struct connection_ops; typedef struct _RpcConnection { + LONG ref; BOOL server; LPSTR NetworkAddr; LPSTR Endpoint; @@ -153,7 +154,8 @@ ULONG RpcQualityOfService_Release(RpcQualityOfService *qos) DECLSPEC_HIDDEN; BOOL RpcQualityOfService_IsEqual(const RpcQualityOfService *qos1, const RpcQualityOfService *qos2) DECLSPEC_HIDDEN; RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server, LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, LPCWSTR NetworkOptions, RpcAuthInfo* AuthInfo, RpcQualityOfService *QOS) DECLSPEC_HIDDEN; -RPC_STATUS RPCRT4_DestroyConnection(RpcConnection* Connection) DECLSPEC_HIDDEN; +RpcConnection *RPCRT4_GrabConnection( RpcConnection *conn ) DECLSPEC_HIDDEN; +RPC_STATUS RPCRT4_ReleaseConnection(RpcConnection* Connection) DECLSPEC_HIDDEN; RPC_STATUS RPCRT4_OpenClientConnection(RpcConnection* Connection) DECLSPEC_HIDDEN; RPC_STATUS RPCRT4_CloseConnection(RpcConnection* Connection) DECLSPEC_HIDDEN; diff --git a/dlls/rpcrt4/rpc_message.c b/dlls/rpcrt4/rpc_message.c index 1d18627c339..189f6c40f67 100644 --- a/dlls/rpcrt4/rpc_message.c +++ b/dlls/rpcrt4/rpc_message.c @@ -1875,7 +1875,7 @@ RPC_STATUS WINAPI I_RpcReceive(PRPC_MESSAGE pMsg) fail: RPCRT4_FreeHeader(hdr); - RPCRT4_DestroyConnection(conn); + RPCRT4_ReleaseConnection(conn); pMsg->ReservedForRuntime = NULL; return status; } diff --git a/dlls/rpcrt4/rpc_server.c b/dlls/rpcrt4/rpc_server.c index 9121280a5f3..6fd1a7b5962 100644 --- a/dlls/rpcrt4/rpc_server.c +++ b/dlls/rpcrt4/rpc_server.c @@ -539,6 +539,7 @@ static DWORD CALLBACK RPCRT4_worker_thread(LPVOID the_arg) RpcPacket *pkt = the_arg; RPCRT4_process_packet(pkt->conn, pkt->hdr, pkt->msg, pkt->auth_data, pkt->auth_length); + RPCRT4_ReleaseConnection(pkt->conn); HeapFree(GetProcessHeap(), 0, pkt); return 0; } @@ -585,7 +586,7 @@ static DWORD CALLBACK RPCRT4_io_thread(LPVOID the_arg) HeapFree(GetProcessHeap(), 0, auth_data); goto exit; } - packet->conn = conn; + packet->conn = RPCRT4_GrabConnection( conn ); packet->hdr = hdr; packet->msg = msg; packet->auth_data = auth_data; @@ -621,7 +622,7 @@ static DWORD CALLBACK RPCRT4_io_thread(LPVOID the_arg) } } exit: - RPCRT4_DestroyConnection(conn); + RPCRT4_ReleaseConnection(conn); return 0; } @@ -631,7 +632,7 @@ void RPCRT4_new_client(RpcConnection* conn) if (!thread) { DWORD err = GetLastError(); ERR("failed to create thread, error=%08x\n", err); - RPCRT4_DestroyConnection(conn); + RPCRT4_ReleaseConnection(conn); } /* we could set conn->thread, but then we'd have to make the io_thread wait * for that, otherwise the thread might finish, destroy the connection, and diff --git a/dlls/rpcrt4/rpc_transport.c b/dlls/rpcrt4/rpc_transport.c index 6568683f7da..f873f710024 100644 --- a/dlls/rpcrt4/rpc_transport.c +++ b/dlls/rpcrt4/rpc_transport.c @@ -1374,7 +1374,7 @@ static RPC_STATUS rpcrt4_protseq_ncacn_ip_tcp_open_endpoint(RpcServerProtseq *pr if (ret < 0) { WARN("listen failed: %s\n", strerror(errno)); - RPCRT4_DestroyConnection(&tcpc->common); + RPCRT4_ReleaseConnection(&tcpc->common); status = RPC_S_OUT_OF_RESOURCES; continue; } @@ -1387,7 +1387,7 @@ static RPC_STATUS rpcrt4_protseq_ncacn_ip_tcp_open_endpoint(RpcServerProtseq *pr if (ret < 0) { WARN("couldn't make socket non-blocking, error %d\n", ret); - RPCRT4_DestroyConnection(&tcpc->common); + RPCRT4_ReleaseConnection(&tcpc->common); status = RPC_S_OUT_OF_RESOURCES; continue; } @@ -2946,6 +2946,7 @@ RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server, } NewConnection = ops->alloc(); + NewConnection->ref = 1; NewConnection->Next = NULL; NewConnection->server_binding = NULL; NewConnection->server = server; @@ -2991,9 +2992,17 @@ static RPC_STATUS RPCRT4_SpawnConnection(RpcConnection** Connection, RpcConnecti return err; } -RPC_STATUS RPCRT4_DestroyConnection(RpcConnection* Connection) +RpcConnection *RPCRT4_GrabConnection( RpcConnection *conn ) { - TRACE("connection: %p\n", Connection); + 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);