mirror of
https://github.com/reactos/reactos.git
synced 2024-12-31 19:42:51 +00:00
[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. svn path=/trunk/; revision=75898
This commit is contained in:
parent
c615faa665
commit
0ee2ebaf78
8 changed files with 160 additions and 93 deletions
|
@ -2929,7 +2929,7 @@ static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg,
|
|||
{
|
||||
/* 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 @@ static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
|
|||
{
|
||||
/* 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 @@ static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
|
|||
{
|
||||
/* 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 @@ static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg,
|
|||
{
|
||||
/* 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);
|
||||
|
|
|
@ -581,8 +581,8 @@ PFORMAT_STRING convert_old_args( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFo
|
|||
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 @@ struct async_call_data
|
|||
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;
|
||||
|
|
|
@ -279,14 +279,13 @@ RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection)
|
|||
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)
|
||||
|
|
|
@ -59,6 +59,7 @@ typedef struct _RpcConnection
|
|||
{
|
||||
LONG ref;
|
||||
BOOL server;
|
||||
HANDLE wait_release;
|
||||
LPSTR NetworkAddr;
|
||||
LPSTR Endpoint;
|
||||
LPWSTR NetworkOptions;
|
||||
|
@ -158,7 +159,7 @@ RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server, LPCS
|
|||
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 @@ RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding, RpcConnection** Connection,
|
|||
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;
|
||||
|
|
|
@ -647,21 +647,44 @@ static DWORD CALLBACK RPCRT4_server_thread(LPVOID the_arg)
|
|||
{
|
||||
/* 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 void RPCRT4_sync_with_server_thread(RpcServerProtseq *ps)
|
|||
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 @@ static RPC_STATUS RPCRT4_stop_listen(BOOL auto_listen)
|
|||
|
||||
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 RpcServerListen( UINT MinimumCallThreads, UINT MaxCalls, UINT
|
|||
*/
|
||||
RPC_STATUS WINAPI RpcMgmtWaitServerListen( void )
|
||||
{
|
||||
HANDLE event;
|
||||
RpcServerProtseq *protseq;
|
||||
HANDLE event, wait_thread;
|
||||
|
||||
TRACE("()\n");
|
||||
|
||||
|
@ -1519,6 +1539,28 @@ RPC_STATUS WINAPI RpcMgmtWaitServerListen( void )
|
|||
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;
|
||||
|
|
|
@ -36,8 +36,8 @@ typedef struct _RpcServerProtseq
|
|||
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 */
|
||||
|
|
|
@ -65,6 +65,7 @@ typedef struct _RpcConnection_np
|
|||
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 @@ static void release_np_event(RpcConnection_np *connection, HANDLE event)
|
|||
CloseHandle(event);
|
||||
}
|
||||
|
||||
static RPC_STATUS rpcrt4_conn_create_pipe(RpcConnection *Connection, LPCSTR pname)
|
||||
static RPC_STATUS rpcrt4_conn_create_pipe(RpcConnection *conn)
|
||||
{
|
||||
RpcConnection_np *npc = (RpcConnection_np *) Connection;
|
||||
TRACE("listening on %s\n", pname);
|
||||
RpcConnection_np *connection = (RpcConnection_np *) conn;
|
||||
|
||||
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;
|
||||
}
|
||||
TRACE("listening on %s\n", connection->listen_pipe);
|
||||
|
||||
/* 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;
|
||||
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_ncalrpc_open(RpcConnection* Connection)
|
|||
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 @@ static RPC_STATUS rpcrt4_protseq_ncalrpc_open_endpoint(RpcServerProtseq* protseq
|
|||
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_ncacn_np_open(RpcConnection* Connection)
|
|||
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 @@ static RPC_STATUS rpcrt4_protseq_ncacn_np_open_endpoint(RpcServerProtseq *protse
|
|||
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 @@ static RPC_STATUS rpcrt4_ncacn_np_handoff(RpcConnection *old_conn, RpcConnection
|
|||
{
|
||||
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 @@ static RPC_STATUS rpcrt4_ncalrpc_handoff(RpcConnection *old_conn, RpcConnection
|
|||
{
|
||||
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 @@ static void *rpcrt4_protseq_np_get_wait_array(RpcServerProtseq *protseq, void *p
|
|||
*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 @@ static RpcConnection *rpcrt4_spawn_connection(RpcConnection *old_connection)
|
|||
return connection;
|
||||
}
|
||||
|
||||
RpcConnection *RPCRT4_GrabConnection( RpcConnection *conn )
|
||||
void rpcrt4_conn_release_and_wait(RpcConnection *connection)
|
||||
{
|
||||
InterlockedIncrement( &conn->ref );
|
||||
return conn;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
RPC_STATUS RPCRT4_ReleaseConnection(RpcConnection* Connection)
|
||||
RpcConnection *RPCRT4_GrabConnection(RpcConnection *connection)
|
||||
{
|
||||
if (InterlockedDecrement( &Connection->ref ) > 0) return RPC_S_OK;
|
||||
LONG ref = InterlockedIncrement(&connection->ref);
|
||||
TRACE("%p ref=%u\n", connection, ref);
|
||||
return connection;
|
||||
}
|
||||
|
||||
TRACE("destroying connection %p\n", Connection);
|
||||
void RPCRT4_ReleaseConnection(RpcConnection *connection)
|
||||
{
|
||||
LONG 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);
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* server-only */
|
||||
if (Connection->server_binding) RPCRT4_ReleaseBinding(Connection->server_binding);
|
||||
TRACE("%p ref=%u\n", connection, ref);
|
||||
|
||||
if (Connection->protseq)
|
||||
{
|
||||
EnterCriticalSection(&Connection->protseq->cs);
|
||||
list_remove(&Connection->protseq_entry);
|
||||
LeaveCriticalSection(&Connection->protseq->cs);
|
||||
}
|
||||
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);
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, Connection);
|
||||
return RPC_S_OK;
|
||||
/* 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)
|
||||
|
|
|
@ -160,7 +160,7 @@ reactos/dll/win32/rasapi32 # Synced to WineStaging-2.9
|
|||
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
|
||||
|
|
Loading…
Reference in a new issue