From def211c4c9b6f0e7d970614664e7a127ca80c0ce Mon Sep 17 00:00:00 2001 From: Ove Kaaven Date: Wed, 19 Feb 2003 03:44:35 +0000 Subject: [PATCH] For better concurrency, separate the connections from the bindings. --- dlls/rpcrt4/rpc_binding.c | 392 ++++++++++++++++++++++---------------- dlls/rpcrt4/rpc_binding.h | 30 ++- dlls/rpcrt4/rpc_message.c | 141 ++++++++++---- dlls/rpcrt4/rpc_server.c | 346 ++++++++++++++++++++++----------- dlls/rpcrt4/rpc_server.h | 2 +- 5 files changed, 581 insertions(+), 330 deletions(-) diff --git a/dlls/rpcrt4/rpc_binding.c b/dlls/rpcrt4/rpc_binding.c index 895299f04d7..d10e7179b8c 100644 --- a/dlls/rpcrt4/rpc_binding.c +++ b/dlls/rpcrt4/rpc_binding.c @@ -93,13 +93,209 @@ void RPCRT4_strfree(LPSTR src) if (src) HeapFree(GetProcessHeap(), 0, src); } -RPC_STATUS RPCRT4_CreateBindingA(RpcBinding** Binding, BOOL server, LPSTR Protseq) +RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server, LPSTR Protseq, LPSTR NetworkAddr, LPSTR Endpoint, LPSTR NetworkOptions) +{ + RpcConnection* NewConnection; + + NewConnection = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcConnection)); + NewConnection->server = server; + NewConnection->Protseq = RPCRT4_strdupA(Protseq); + NewConnection->NetworkAddr = RPCRT4_strdupA(NetworkAddr); + NewConnection->Endpoint = RPCRT4_strdupA(Endpoint); + + TRACE("connection: %p\n", NewConnection); + *Connection = NewConnection; + + return RPC_S_OK; +} + +RPC_STATUS RPCRT4_DestroyConnection(RpcConnection* Connection) +{ + TRACE("connection: %p\n", Connection); + if (Connection->Used) ERR("connection is still in use\n"); + RPCRT4_CloseConnection(Connection); + RPCRT4_strfree(Connection->Endpoint); + RPCRT4_strfree(Connection->NetworkAddr); + RPCRT4_strfree(Connection->Protseq); + HeapFree(GetProcessHeap(), 0, Connection); + return RPC_S_OK; +} + +RPC_STATUS RPCRT4_OpenConnection(RpcConnection* Connection) +{ + TRACE("(Connection == ^%p)\n", Connection); + if (!Connection->conn) { + if (Connection->server) { /* server */ + /* protseq=ncalrpc: supposed to use NT LPC ports, + * but we'll implement it with named pipes for now */ + if (strcmp(Connection->Protseq, "ncalrpc") == 0) { + static LPSTR prefix = "\\\\.\\pipe\\lrpc\\"; + LPSTR pname; + pname = HeapAlloc(GetProcessHeap(), 0, strlen(prefix) + strlen(Connection->Endpoint) + 1); + strcat(strcpy(pname, prefix), Connection->Endpoint); + TRACE("listening on %s\n", pname); + Connection->conn = CreateNamedPipeA(pname, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, + 0, PIPE_UNLIMITED_INSTANCES, 0, 0, 5000, NULL); + HeapFree(GetProcessHeap(), 0, pname); + memset(&Connection->ovl, 0, sizeof(Connection->ovl)); + Connection->ovl.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL); + if (!ConnectNamedPipe(Connection->conn, &Connection->ovl)) { + DWORD err = GetLastError(); + if (err == ERROR_PIPE_CONNECTED) { + SetEvent(Connection->ovl.hEvent); + return RPC_S_OK; + } + return err; + } + } + /* protseq=ncacn_np: named pipes */ + else if (strcmp(Connection->Protseq, "ncacn_np") == 0) { + static LPSTR prefix = "\\\\."; + LPSTR pname; + pname = HeapAlloc(GetProcessHeap(), 0, strlen(prefix) + strlen(Connection->Endpoint) + 1); + strcat(strcpy(pname, prefix), Connection->Endpoint); + TRACE("listening on %s\n", pname); + Connection->conn = CreateNamedPipeA(pname, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, + 0, PIPE_UNLIMITED_INSTANCES, 0, 0, 5000, NULL); + HeapFree(GetProcessHeap(), 0, pname); + memset(&Connection->ovl, 0, sizeof(Connection->ovl)); + Connection->ovl.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL); + if (!ConnectNamedPipe(Connection->conn, &Connection->ovl)) { + DWORD err = GetLastError(); + if (err == ERROR_PIPE_CONNECTED) { + SetEvent(Connection->ovl.hEvent); + return RPC_S_OK; + } + return err; + } + } + else { + ERR("protseq %s not supported\n", Connection->Protseq); + return RPC_S_PROTSEQ_NOT_SUPPORTED; + } + } + else { /* client */ + /* protseq=ncalrpc: supposed to use NT LPC ports, + * but we'll implement it with named pipes for now */ + if (strcmp(Connection->Protseq, "ncalrpc") == 0) { + static LPSTR prefix = "\\\\.\\pipe\\lrpc\\"; + LPSTR pname; + HANDLE conn; + DWORD err; + + pname = HeapAlloc(GetProcessHeap(), 0, strlen(prefix) + strlen(Connection->Endpoint) + 1); + strcat(strcpy(pname, prefix), Connection->Endpoint); + TRACE("connecting to %s\n", pname); + while (TRUE) { + if (WaitNamedPipeA(pname, NMPWAIT_WAIT_FOREVER)) { + conn = CreateFileA(pname, GENERIC_READ|GENERIC_WRITE, 0, NULL, + OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); + if (conn != INVALID_HANDLE_VALUE) break; + err = GetLastError(); + if (err == ERROR_PIPE_BUSY) continue; + TRACE("connection failed, error=%lx\n", err); + HeapFree(GetProcessHeap(), 0, pname); + return err; + } else { + err = GetLastError(); + TRACE("connection failed, error=%lx\n", err); + HeapFree(GetProcessHeap(), 0, pname); + return err; + } + } + + /* success */ + HeapFree(GetProcessHeap(), 0, pname); + memset(&Connection->ovl, 0, sizeof(Connection->ovl)); + Connection->ovl.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL); + Connection->conn = conn; + } + /* protseq=ncacn_np: named pipes */ + else if (strcmp(Connection->Protseq, "ncacn_np") == 0) { + static LPSTR prefix = "\\\\."; + LPSTR pname; + HANDLE conn; + DWORD err; + + pname = HeapAlloc(GetProcessHeap(), 0, strlen(prefix) + strlen(Connection->Endpoint) + 1); + strcat(strcpy(pname, prefix), Connection->Endpoint); + TRACE("connecting to %s\n", pname); + conn = CreateFileA(pname, GENERIC_READ|GENERIC_WRITE, 0, NULL, + OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); + if (conn == INVALID_HANDLE_VALUE) { + err = GetLastError(); + /* we don't need to handle ERROR_PIPE_BUSY here, + * the doc says that it is returned to the app */ + TRACE("connection failed, error=%lx\n", err); + HeapFree(GetProcessHeap(), 0, pname); + return err; + } + + /* success */ + HeapFree(GetProcessHeap(), 0, pname); + memset(&Connection->ovl, 0, sizeof(Connection->ovl)); + Connection->ovl.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL); + Connection->conn = conn; + } else { + ERR("protseq %s not supported\n", Connection->Protseq); + return RPC_S_PROTSEQ_NOT_SUPPORTED; + } + } + } + return RPC_S_OK; +} + +RPC_STATUS RPCRT4_CloseConnection(RpcConnection* Connection) +{ + TRACE("(Connection == ^%p)\n", Connection); + if (Connection->conn) { + CancelIo(Connection->conn); + CloseHandle(Connection->conn); + Connection->conn = 0; + } + if (Connection->ovl.hEvent) { + CloseHandle(Connection->ovl.hEvent); + Connection->ovl.hEvent = 0; + } + return RPC_S_OK; +} + +RPC_STATUS RPCRT4_SpawnConnection(RpcConnection** Connection, RpcConnection* OldConnection) +{ + RpcConnection* NewConnection; + RPC_STATUS err = RPCRT4_CreateConnection(&NewConnection, OldConnection->server, OldConnection->Protseq, + OldConnection->NetworkAddr, OldConnection->Endpoint, NULL); + if (err == RPC_S_OK) { + /* because of the way named pipes work, we'll transfer the connected pipe + * to the child, then reopen the server binding to continue listening */ + NewConnection->conn = OldConnection->conn; + NewConnection->ovl = OldConnection->ovl; + OldConnection->conn = 0; + memset(&OldConnection->ovl, 0, sizeof(OldConnection->ovl)); + *Connection = NewConnection; + RPCRT4_OpenConnection(OldConnection); + } + return err; +} + +RPC_STATUS RPCRT4_AllocBinding(RpcBinding** Binding, BOOL server) { RpcBinding* NewBinding; NewBinding = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcBinding)); NewBinding->refs = 1; NewBinding->server = server; + + *Binding = NewBinding; + + return RPC_S_OK; +} + +RPC_STATUS RPCRT4_CreateBindingA(RpcBinding** Binding, BOOL server, LPSTR Protseq) +{ + RpcBinding* NewBinding; + + RPCRT4_AllocBinding(&NewBinding, server); NewBinding->Protseq = RPCRT4_strdupA(Protseq); TRACE("binding: %p\n", NewBinding); @@ -111,16 +307,8 @@ RPC_STATUS RPCRT4_CreateBindingA(RpcBinding** Binding, BOOL server, LPSTR Protse RPC_STATUS RPCRT4_CreateBindingW(RpcBinding** Binding, BOOL server, LPWSTR Protseq) { RpcBinding* NewBinding; - if (Binding) - TRACE("(*Binding == ^%p, server == %s, Protseq == \"%s\")\n", *Binding, server ? "Yes" : "No", debugstr_w(Protseq)); - else { - ERR("!RpcBinding?\n"); - assert(FALSE); /* we will crash below anyhow... */ - } - NewBinding = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcBinding)); - NewBinding->refs = 1; - NewBinding->server = server; + RPCRT4_AllocBinding(&NewBinding, server); NewBinding->Protseq = RPCRT4_strdupWtoA(Protseq); TRACE("binding: %p\n", NewBinding); @@ -131,8 +319,8 @@ RPC_STATUS RPCRT4_CreateBindingW(RpcBinding** Binding, BOOL server, LPWSTR Prots RPC_STATUS RPCRT4_CompleteBindingA(RpcBinding* Binding, LPSTR NetworkAddr, LPSTR Endpoint, LPSTR NetworkOptions) { - - TRACE("(RpcBinding == ^%p, NetworkAddr == \"%s\", EndPoint == \"%s\", NetworkOptions == \"%s\")\n", Binding, NetworkAddr, Endpoint, NetworkOptions); + TRACE("(RpcBinding == ^%p, NetworkAddr == \"%s\", EndPoint == \"%s\", NetworkOptions == \"%s\")\n", Binding, + debugstr_a(NetworkAddr), debugstr_a(Endpoint), debugstr_a(NetworkOptions)); RPCRT4_strfree(Binding->NetworkAddr); Binding->NetworkAddr = RPCRT4_strdupA(NetworkAddr); @@ -183,31 +371,19 @@ RPC_STATUS RPCRT4_SetBindingObject(RpcBinding* Binding, UUID* ObjectUuid) return RPC_S_OK; } -RPC_STATUS RPCRT4_SpawnBinding(RpcBinding** Binding, RpcBinding* OldBinding) +RPC_STATUS RPCRT4_MakeBinding(RpcBinding** Binding, RpcConnection* Connection) { RpcBinding* NewBinding; - if (Binding) - TRACE("(*RpcBinding == ^%p, OldBinding == ^%p)\n", *Binding, OldBinding); - else { - ERR("!RpcBinding?"); - /* we will crash below anyhow... */ - *((char *)0) = 0; - } + TRACE("(*RpcBinding == ^%p, Connection == ^%p)\n", *Binding, Connection); - NewBinding = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcBinding)); - NewBinding->refs = 1; - NewBinding->server = OldBinding->server; - NewBinding->Protseq = RPCRT4_strdupA(OldBinding->Protseq); - NewBinding->NetworkAddr = RPCRT4_strdupA(OldBinding->NetworkAddr); - NewBinding->Endpoint = RPCRT4_strdupA(OldBinding->Endpoint); - /* because of the way named pipes work, we'll transfer the connected pipe - * to the child, then reopen the server binding to continue listening */ - NewBinding->conn = OldBinding->conn; - NewBinding->ovl = OldBinding->ovl; - OldBinding->conn = 0; - memset(&OldBinding->ovl, 0, sizeof(OldBinding->ovl)); + RPCRT4_AllocBinding(&NewBinding, Connection->server); + NewBinding->Protseq = RPCRT4_strdupA(Connection->Protseq); + NewBinding->NetworkAddr = RPCRT4_strdupA(Connection->NetworkAddr); + NewBinding->Endpoint = RPCRT4_strdupA(Connection->Endpoint); + NewBinding->FromConn = Connection; + + TRACE("binding: %p\n", NewBinding); *Binding = NewBinding; - RPCRT4_OpenBinding(OldBinding); return RPC_S_OK; } @@ -225,7 +401,7 @@ RPC_STATUS RPCRT4_DestroyBinding(RpcBinding* Binding) return RPC_S_OK; TRACE("binding: %p\n", Binding); - RPCRT4_CloseBinding(Binding); + /* FIXME: release connections */ RPCRT4_strfree(Binding->Endpoint); RPCRT4_strfree(Binding->NetworkAddr); RPCRT4_strfree(Binding->Protseq); @@ -233,143 +409,29 @@ RPC_STATUS RPCRT4_DestroyBinding(RpcBinding* Binding) return RPC_S_OK; } -RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding) +RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding, RpcConnection** Connection) { + RpcConnection* NewConnection; TRACE("(Binding == ^%p)\n", Binding); - if (!Binding->conn) { - if (Binding->server) { /* server */ - /* protseq=ncalrpc: supposed to use NT LPC ports, - * but we'll implement it with named pipes for now */ - if (strcmp(Binding->Protseq, "ncalrpc") == 0) { - static LPSTR prefix = "\\\\.\\pipe\\lrpc\\"; - LPSTR pname; - pname = HeapAlloc(GetProcessHeap(), 0, strlen(prefix) + strlen(Binding->Endpoint) + 1); - strcat(strcpy(pname, prefix), Binding->Endpoint); - TRACE("listening on %s\n", pname); - Binding->conn = CreateNamedPipeA(pname, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, - 0, PIPE_UNLIMITED_INSTANCES, 0, 0, 5000, NULL); - HeapFree(GetProcessHeap(), 0, pname); - memset(&Binding->ovl, 0, sizeof(Binding->ovl)); - Binding->ovl.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL); - if (!ConnectNamedPipe(Binding->conn, &Binding->ovl)) { - DWORD err = GetLastError(); - if (err == ERROR_PIPE_CONNECTED) { - SetEvent(Binding->ovl.hEvent); - return RPC_S_OK; - } - return err; - } - } - /* protseq=ncacn_np: named pipes */ - else if (strcmp(Binding->Protseq, "ncacn_np") == 0) { - static LPSTR prefix = "\\\\."; - LPSTR pname; - pname = HeapAlloc(GetProcessHeap(), 0, strlen(prefix) + strlen(Binding->Endpoint) + 1); - strcat(strcpy(pname, prefix), Binding->Endpoint); - TRACE("listening on %s\n", pname); - Binding->conn = CreateNamedPipeA(pname, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, - 0, PIPE_UNLIMITED_INSTANCES, 0, 0, 5000, NULL); - HeapFree(GetProcessHeap(), 0, pname); - memset(&Binding->ovl, 0, sizeof(Binding->ovl)); - Binding->ovl.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL); - if (!ConnectNamedPipe(Binding->conn, &Binding->ovl)) { - DWORD err = GetLastError(); - if (err == ERROR_PIPE_CONNECTED) { - SetEvent(Binding->ovl.hEvent); - return RPC_S_OK; - } - return err; - } - } - else { - ERR("protseq %s not supported\n", Binding->Protseq); - return RPC_S_PROTSEQ_NOT_SUPPORTED; - } - } - else { /* client */ - /* protseq=ncalrpc: supposed to use NT LPC ports, - * but we'll implement it with named pipes for now */ - if (strcmp(Binding->Protseq, "ncalrpc") == 0) { - static LPSTR prefix = "\\\\.\\pipe\\lrpc\\"; - LPSTR pname; - HANDLE conn; - DWORD err; - - pname = HeapAlloc(GetProcessHeap(), 0, strlen(prefix) + strlen(Binding->Endpoint) + 1); - strcat(strcpy(pname, prefix), Binding->Endpoint); - TRACE("connecting to %s\n", pname); - while (TRUE) { - if (WaitNamedPipeA(pname, NMPWAIT_WAIT_FOREVER)) { - conn = CreateFileA(pname, GENERIC_READ|GENERIC_WRITE, 0, NULL, - OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); - if (conn != INVALID_HANDLE_VALUE) break; - err = GetLastError(); - if (err == ERROR_PIPE_BUSY) continue; - TRACE("connection failed, error=%lx\n", err); - HeapFree(GetProcessHeap(), 0, pname); - return err; - } else { - err = GetLastError(); - TRACE("connection failed, error=%lx\n", err); - HeapFree(GetProcessHeap(), 0, pname); - return err; - } - } - - /* success */ - HeapFree(GetProcessHeap(), 0, pname); - memset(&Binding->ovl, 0, sizeof(Binding->ovl)); - Binding->ovl.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL); - Binding->conn = conn; - } - /* protseq=ncacn_np: named pipes */ - else if (strcmp(Binding->Protseq, "ncacn_np") == 0) { - static LPSTR prefix = "\\\\."; - LPSTR pname; - HANDLE conn; - DWORD err; - - pname = HeapAlloc(GetProcessHeap(), 0, strlen(prefix) + strlen(Binding->Endpoint) + 1); - strcat(strcpy(pname, prefix), Binding->Endpoint); - TRACE("connecting to %s\n", pname); - conn = CreateFileA(pname, GENERIC_READ|GENERIC_WRITE, 0, NULL, - OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); - if (conn == INVALID_HANDLE_VALUE) { - err = GetLastError(); - /* we don't need to handle ERROR_PIPE_BUSY here, - * the doc says that it is returned to the app */ - TRACE("connection failed, error=%lx\n", err); - HeapFree(GetProcessHeap(), 0, pname); - return err; - } - - /* success */ - HeapFree(GetProcessHeap(), 0, pname); - memset(&Binding->ovl, 0, sizeof(Binding->ovl)); - Binding->ovl.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL); - Binding->conn = conn; - } else { - ERR("protseq %s not supported\n", Binding->Protseq); - return RPC_S_PROTSEQ_NOT_SUPPORTED; - } - } + if (Binding->FromConn) { + *Connection = Binding->FromConn; + return RPC_S_OK; } - return RPC_S_OK; + + /* FIXME: cache connections */ + RPCRT4_CreateConnection(&NewConnection, Binding->server, Binding->Protseq, Binding->NetworkAddr, Binding->Endpoint, NULL); + NewConnection->Used = Binding; + *Connection = NewConnection; + return RPCRT4_OpenConnection(NewConnection); } -RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding) +RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection) { TRACE("(Binding == ^%p)\n", Binding); - if (Binding->conn) { - CancelIo(Binding->conn); - CloseHandle(Binding->conn); - Binding->conn = 0; - } - if (Binding->ovl.hEvent) { - CloseHandle(Binding->ovl.hEvent); - Binding->ovl.hEvent = 0; - } - return RPC_S_OK; + if (!Connection) return RPC_S_OK; + if (Binding->FromConn == Connection) return RPC_S_OK; + Connection->Used = NULL; + return RPCRT4_DestroyConnection(Connection); } /* utility functions for string composing and parsing */ @@ -862,7 +924,7 @@ RPC_STATUS WINAPI RpcBindingToStringBindingW( RPC_BINDING_HANDLE Binding, LPWSTR RpcStringFreeA((unsigned char**)&str); return ret; } - + /*********************************************************************** * I_RpcBindingSetAsync (RPCRT4.@) * NOTES diff --git a/dlls/rpcrt4/rpc_binding.h b/dlls/rpcrt4/rpc_binding.h index cd3da91eaa9..7259abe4668 100644 --- a/dlls/rpcrt4/rpc_binding.h +++ b/dlls/rpcrt4/rpc_binding.h @@ -23,20 +23,32 @@ #include "wine/rpcss_shared.h" +typedef struct _RpcConnection +{ + struct _RpcConnection* Next; + struct _RpcBinding* Used; + BOOL server; + LPSTR Protseq; + LPSTR NetworkAddr; + LPSTR Endpoint; + HANDLE conn, thread; + OVERLAPPED ovl; +} RpcConnection; + /* don't know what MS's structure looks like */ typedef struct _RpcBinding { DWORD refs; - struct _RpcBinding* Next; /* for rpc server */ + struct _RpcBinding* Next; BOOL server; UUID ObjectUuid; + UUID ActiveUuid; LPSTR Protseq; LPSTR NetworkAddr; LPSTR Endpoint; RPC_BLOCKING_FN BlockingFn; ULONG ServerTid; - HANDLE conn, thread; - OVERLAPPED ovl; + RpcConnection* FromConn; } RpcBinding; LPSTR RPCRT4_strndupA(LPSTR src, INT len); @@ -48,17 +60,23 @@ void RPCRT4_strfree(LPSTR src); #define RPCRT4_strdupA(x) RPCRT4_strndupA((x),-1) #define RPCRT4_strdupW(x) RPCRT4_strndupW((x),-1) +RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server, LPSTR Protseq, LPSTR NetworkAddr, LPSTR Endpoint, LPSTR NetworkOptions); +RPC_STATUS RPCRT4_DestroyConnection(RpcConnection* Connection); +RPC_STATUS RPCRT4_OpenConnection(RpcConnection* Connection); +RPC_STATUS RPCRT4_CloseConnection(RpcConnection* Connection); +RPC_STATUS RPCRT4_SpawnConnection(RpcConnection** Connection, RpcConnection* OldConnection); + RPC_STATUS RPCRT4_CreateBindingA(RpcBinding** Binding, BOOL server, LPSTR Protseq); RPC_STATUS RPCRT4_CreateBindingW(RpcBinding** Binding, BOOL server, LPWSTR Protseq); RPC_STATUS RPCRT4_CompleteBindingA(RpcBinding* Binding, LPSTR NetworkAddr, LPSTR Endpoint, LPSTR NetworkOptions); RPC_STATUS RPCRT4_CompleteBindingW(RpcBinding* Binding, LPWSTR NetworkAddr, LPWSTR Endpoint, LPWSTR NetworkOptions); RPC_STATUS RPCRT4_ResolveBinding(RpcBinding* Binding, LPSTR Endpoint); RPC_STATUS RPCRT4_SetBindingObject(RpcBinding* Binding, UUID* ObjectUuid); -RPC_STATUS RPCRT4_SpawnBinding(RpcBinding** Binding, RpcBinding* OldBinding); +RPC_STATUS RPCRT4_MakeBinding(RpcBinding** Binding, RpcConnection* Connection); RPC_STATUS RPCRT4_ExportBinding(RpcBinding** Binding, RpcBinding* OldBinding); RPC_STATUS RPCRT4_DestroyBinding(RpcBinding* Binding); -RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding); -RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding); +RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding, RpcConnection** Connection); +RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection); BOOL RPCRT4_RPCSSOnDemandCall(PRPCSS_NP_MESSAGE msg, char *vardata_payload, PRPCSS_NP_REPLY reply); HANDLE RPCRT4_GetMasterMutex(void); HANDLE RPCRT4_RpcssNPConnect(void); diff --git a/dlls/rpcrt4/rpc_message.c b/dlls/rpcrt4/rpc_message.c index b35b1143eb8..8ba3996ecb9 100644 --- a/dlls/rpcrt4/rpc_message.c +++ b/dlls/rpcrt4/rpc_message.c @@ -48,9 +48,10 @@ RPC_STATUS WINAPI I_RpcGetBuffer(PRPC_MESSAGE pMsg) { void* buf; - TRACE("(%p)\n", pMsg); + TRACE("(%p): BufferLength=%d\n", pMsg, pMsg->BufferLength); /* FIXME: pfnAllocate? */ buf = HeapReAlloc(GetProcessHeap(), 0, pMsg->Buffer, pMsg->BufferLength); + TRACE("Buffer=%p\n", buf); if (buf) pMsg->Buffer = buf; /* FIXME: which errors to return? */ return buf ? S_OK : E_OUTOFMEMORY; @@ -74,14 +75,23 @@ RPC_STATUS WINAPI I_RpcFreeBuffer(PRPC_MESSAGE pMsg) RPC_STATUS WINAPI I_RpcSend(PRPC_MESSAGE pMsg) { RpcBinding* bind = (RpcBinding*)pMsg->Handle; + RpcConnection* conn; RPC_CLIENT_INTERFACE* cif = NULL; RPC_SERVER_INTERFACE* sif = NULL; + UUID* obj; + UUID* act; RPC_STATUS status; RpcPktHdr hdr; TRACE("(%p)\n", pMsg); if (!bind) return RPC_S_INVALID_BINDING; + status = RPCRT4_OpenBinding(bind, &conn); + if (status != RPC_S_OK) return status; + + obj = &bind->ObjectUuid; + act = &bind->ActiveUuid; + if (bind->server) { sif = pMsg->RpcInterfaceInformation; if (!sif) return RPC_S_INTERFACE_NOT_FOUND; /* ? */ @@ -90,19 +100,17 @@ RPC_STATUS WINAPI I_RpcSend(PRPC_MESSAGE pMsg) if (!cif) return RPC_S_INTERFACE_NOT_FOUND; /* ? */ } - status = RPCRT4_OpenBinding(bind); - if (status != RPC_S_OK) return status; - /* initialize packet header */ memset(&hdr, 0, sizeof(hdr)); hdr.rpc_ver = 4; - hdr.ptype = PKT_REQUEST; - hdr.object = bind->ObjectUuid; /* FIXME: IIRC iff no object, the header structure excludes this elt */ + hdr.ptype = bind->server ? PKT_RESPONSE : PKT_REQUEST; + hdr.object = *obj; /* FIXME: IIRC iff no object, the header structure excludes this elt */ hdr.if_id = (bind->server) ? sif->InterfaceId.SyntaxGUID : cif->InterfaceId.SyntaxGUID; hdr.if_vers = (bind->server) ? MAKELONG(sif->InterfaceId.SyntaxVersion.MinorVersion, sif->InterfaceId.SyntaxVersion.MajorVersion) : MAKELONG(cif->InterfaceId.SyntaxVersion.MinorVersion, cif->InterfaceId.SyntaxVersion.MajorVersion); + hdr.act_id = *act; hdr.opnum = pMsg->ProcNum; /* only the low-order 3 octets of the DataRepresentation go in the header */ hdr.drep[0] = LOBYTE(LOWORD(pMsg->DataRepresentation)); @@ -111,13 +119,26 @@ RPC_STATUS WINAPI I_RpcSend(PRPC_MESSAGE pMsg) hdr.len = pMsg->BufferLength; /* transmit packet */ - if (!WriteFile(bind->conn, &hdr, sizeof(hdr), NULL, NULL)) - return GetLastError(); - if (!WriteFile(bind->conn, pMsg->Buffer, pMsg->BufferLength, NULL, NULL)) - return GetLastError(); + if (!WriteFile(conn->conn, &hdr, sizeof(hdr), NULL, NULL)) { + status = GetLastError(); + goto fail; + } + if (pMsg->BufferLength && !WriteFile(conn->conn, pMsg->Buffer, pMsg->BufferLength, NULL, NULL)) { + status = GetLastError(); + goto fail; + } /* success */ - return RPC_S_OK; + if (!bind->server) { + /* save the connection, so the response can be read from it */ + pMsg->ReservedForRuntime = conn; + return RPC_S_OK; + } + RPCRT4_CloseBinding(bind, conn); + status = RPC_S_OK; +fail: + + return status; } /*********************************************************************** @@ -126,6 +147,8 @@ RPC_STATUS WINAPI I_RpcSend(PRPC_MESSAGE pMsg) RPC_STATUS WINAPI I_RpcReceive(PRPC_MESSAGE pMsg) { RpcBinding* bind = (RpcBinding*)pMsg->Handle; + RpcConnection* conn; + UUID* act; RPC_STATUS status; RpcPktHdr hdr; DWORD dwRead; @@ -133,44 +156,78 @@ RPC_STATUS WINAPI I_RpcReceive(PRPC_MESSAGE pMsg) TRACE("(%p)\n", pMsg); if (!bind) return RPC_S_INVALID_BINDING; - status = RPCRT4_OpenBinding(bind); - if (status != RPC_S_OK) return status; - - /* read packet header */ -#ifdef OVERLAPPED_WORKS - if (!ReadFile(bind->conn, &hdr, sizeof(hdr), &dwRead, &bind->ovl)) { - DWORD err = GetLastError(); - if (err != ERROR_IO_PENDING) { - return err; - } - if (!GetOverlappedResult(bind->conn, &bind->ovl, &dwRead, TRUE)) return GetLastError(); + if (pMsg->ReservedForRuntime) { + conn = pMsg->ReservedForRuntime; + pMsg->ReservedForRuntime = NULL; + } else { + status = RPCRT4_OpenBinding(bind, &conn); + if (status != RPC_S_OK) return status; } -#else - if (!ReadFile(bind->conn, &hdr, sizeof(hdr), &dwRead, NULL)) - return GetLastError(); -#endif - if (dwRead != sizeof(hdr)) return RPC_S_PROTOCOL_ERROR; - /* read packet body */ - pMsg->BufferLength = hdr.len; - status = I_RpcGetBuffer(pMsg); - if (status != RPC_S_OK) return status; + act = &bind->ActiveUuid; + + for (;;) { + /* read packet header */ #ifdef OVERLAPPED_WORKS - if (!ReadFile(bind->conn, pMsg->Buffer, hdr.len, &dwRead, &bind->ovl)) { - DWORD err = GetLastError(); - if (err != ERROR_IO_PENDING) { - return err; + if (!ReadFile(conn->conn, &hdr, sizeof(hdr), &dwRead, &conn->ovl)) { + DWORD err = GetLastError(); + if (err != ERROR_IO_PENDING) { + status = err; + goto fail; + } + if (!GetOverlappedResult(conn->conn, &conn->ovl, &dwRead, TRUE)) { + status = GetLastError(); + goto fail; + } } - if (!GetOverlappedResult(bind->conn, &bind->ovl, &dwRead, TRUE)) return GetLastError(); - } #else - if (!ReadFile(bind->conn, pMsg->Buffer, hdr.len, &dwRead, NULL)) - return GetLastError(); + if (!ReadFile(conn->conn, &hdr, sizeof(hdr), &dwRead, NULL)) { + status = GetLastError(); + goto fail; + } #endif - if (dwRead != hdr.len) return RPC_S_PROTOCOL_ERROR; + if (dwRead != sizeof(hdr)) { + status = RPC_S_PROTOCOL_ERROR; + goto fail; + } - /* success */ - return RPC_S_OK; + /* read packet body */ + pMsg->BufferLength = hdr.len; + status = I_RpcGetBuffer(pMsg); + if (status != RPC_S_OK) goto fail; + if (!pMsg->BufferLength) dwRead = 0; else +#ifdef OVERLAPPED_WORKS + if (!ReadFile(conn->conn, pMsg->Buffer, hdr.len, &dwRead, &conn->ovl)) { + DWORD err = GetLastError(); + if (err != ERROR_IO_PENDING) { + status = err; + goto fail; + } + if (!GetOverlappedResult(conn->conn, &conn->ovl, &dwRead, TRUE)) { + status = GetLastError(); + goto fail; + } + } +#else + if (!ReadFile(conn->conn, pMsg->Buffer, hdr.len, &dwRead, NULL)) { + status = GetLastError(); + goto fail; + } +#endif + if (dwRead != hdr.len) { + status = RPC_S_PROTOCOL_ERROR; + goto fail; + } + + /* success */ + status = RPC_S_OK; + + /* FIXME: check packet type, destination, etc? */ + break; + } +fail: + RPCRT4_CloseBinding(bind, conn); + return status; } /*********************************************************************** diff --git a/dlls/rpcrt4/rpc_server.c b/dlls/rpcrt4/rpc_server.c index 158545c1800..4de7c092564 100644 --- a/dlls/rpcrt4/rpc_server.c +++ b/dlls/rpcrt4/rpc_server.c @@ -37,8 +37,18 @@ #include "rpc_server.h" #include "rpc_defs.h" +#define MAX_THREADS 128 + WINE_DEFAULT_DEBUG_CHANNEL(ole); +typedef struct _RpcPacket +{ + struct _RpcPacket* next; + struct _RpcConnection* conn; + RpcPktHdr hdr; + void* buf; +} RpcPacket; + static RpcServerProtseq* protseqs; static RpcServerInterface* ifs; @@ -48,6 +58,13 @@ static BOOL std_listen; static LONG listen_count = -1; static HANDLE mgr_event, server_thread; +static CRITICAL_SECTION spacket_cs = CRITICAL_SECTION_INIT("RpcServerPacket"); +static RpcPacket* spacket_head; +static RpcPacket* spacket_tail; +static HANDLE server_sem; + +static DWORD worker_count, worker_free; + static RpcServerInterface* RPCRT4_find_interface(UUID* object, UUID* if_id) { UUID* MgrType = NULL; @@ -67,31 +84,168 @@ static RpcServerInterface* RPCRT4_find_interface(UUID* object, UUID* if_id) return cif; } -static DWORD CALLBACK RPCRT4_io_thread(LPVOID the_arg) +static void RPCRT4_push_packet(RpcPacket* packet) { - RpcBinding* bind = (RpcBinding*)the_arg; - RpcPktHdr hdr; - DWORD dwRead; + packet->next = NULL; + EnterCriticalSection(&spacket_cs); + if (spacket_tail) spacket_tail->next = packet; + else { + spacket_head = packet; + spacket_tail = packet; + } + LeaveCriticalSection(&spacket_cs); +} + +static RpcPacket* RPCRT4_pop_packet(void) +{ + RpcPacket* packet; + EnterCriticalSection(&spacket_cs); + packet = spacket_head; + if (packet) { + spacket_head = packet->next; + if (!spacket_head) spacket_tail = NULL; + } + LeaveCriticalSection(&spacket_cs); + if (packet) packet->next = NULL; + return packet; +} + +static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr, void* buf) +{ + RpcBinding* pbind; RPC_MESSAGE msg; RpcServerInterface* sif; RPC_DISPATCH_FUNCTION func; memset(&msg, 0, sizeof(msg)); - msg.Handle = (RPC_BINDING_HANDLE)bind; + msg.BufferLength = hdr->len; + msg.Buffer = buf; + sif = RPCRT4_find_interface(&hdr->object, &hdr->if_id); + if (sif) { + TRACE("packet received for interface %s\n", debugstr_guid(&hdr->if_id)); + msg.RpcInterfaceInformation = sif->If; + /* create temporary binding for dispatch */ + RPCRT4_MakeBinding(&pbind, conn); + RPCRT4_SetBindingObject(pbind, &hdr->object); + msg.Handle = (RPC_BINDING_HANDLE)pbind; + /* process packet */ + switch (hdr->ptype) { + case PKT_REQUEST: + /* find dispatch function */ + msg.ProcNum = hdr->opnum; + if (sif->Flags & RPC_IF_OLE) { + /* native ole32 always gives us a dispatch table with a single entry + * (I assume that's a wrapper for IRpcStubBuffer::Invoke) */ + func = *sif->If->DispatchTable->DispatchTable; + } else { + if (msg.ProcNum >= sif->If->DispatchTable->DispatchTableCount) { + ERR("invalid procnum\n"); + func = NULL; + } + func = sif->If->DispatchTable->DispatchTable[msg.ProcNum]; + } + + /* put in the drep. FIXME: is this more universally applicable? + perhaps we should move this outward... */ + msg.DataRepresentation = + MAKELONG( MAKEWORD(hdr->drep[0], hdr->drep[1]), + MAKEWORD(hdr->drep[2], 0)); + + /* dispatch */ + if (func) func(&msg); + + /* send response packet */ + I_RpcSend(&msg); + break; + default: + ERR("unknown packet type\n"); + break; + } + + RPCRT4_DestroyBinding(pbind); + msg.Handle = 0; + msg.RpcInterfaceInformation = NULL; + } + else { + ERR("got RPC packet to unregistered interface %s\n", debugstr_guid(&hdr->if_id)); + } + + /* clean up */ + HeapFree(GetProcessHeap(), 0, msg.Buffer); + msg.Buffer = NULL; +} + +static DWORD CALLBACK RPCRT4_worker_thread(LPVOID the_arg) +{ + DWORD obj; + RpcPacket* pkt; + + for (;;) { + /* idle timeout after 5s */ + obj = WaitForSingleObject(server_sem, 5000); + if (obj == WAIT_TIMEOUT) { + /* if another idle thread exist, self-destruct */ + if (worker_free > 1) break; + continue; + } + pkt = RPCRT4_pop_packet(); + if (!pkt) continue; + InterlockedDecrement(&worker_free); + for (;;) { + RPCRT4_process_packet(pkt->conn, &pkt->hdr, pkt->buf); + HeapFree(GetProcessHeap(), 0, pkt); + /* try to grab another packet here without waiting + * on the semaphore, in case it hits max */ + pkt = RPCRT4_pop_packet(); + if (!pkt) break; + /* decrement semaphore */ + WaitForSingleObject(server_sem, 0); + } + InterlockedIncrement(&worker_free); + } + InterlockedDecrement(&worker_free); + InterlockedDecrement(&worker_count); + return 0; +} + +static void RPCRT4_create_worker_if_needed(void) +{ + if (!worker_free && worker_count < MAX_THREADS) { + HANDLE thread; + InterlockedIncrement(&worker_count); + InterlockedIncrement(&worker_free); + thread = CreateThread(NULL, 0, RPCRT4_worker_thread, NULL, 0, NULL); + if (thread) CloseHandle(thread); + else { + InterlockedDecrement(&worker_free); + InterlockedDecrement(&worker_count); + } + } +} + +static DWORD CALLBACK RPCRT4_io_thread(LPVOID the_arg) +{ + RpcConnection* conn = (RpcConnection*)the_arg; + RpcPktHdr hdr; + DWORD dwRead; + void* buf = NULL; + RpcPacket* packet; + + TRACE("(%p)\n", conn); for (;;) { /* read packet header */ #ifdef OVERLAPPED_WORKS - if (!ReadFile(bind->conn, &hdr, sizeof(hdr), &dwRead, &bind->ovl)) { + if (!ReadFile(conn->conn, &hdr, sizeof(hdr), &dwRead, &conn->ovl)) { DWORD err = GetLastError(); if (err != ERROR_IO_PENDING) { TRACE("connection lost, error=%08lx\n", err); break; } - if (!GetOverlappedResult(bind->conn, &bind->ovl, &dwRead, TRUE)) break; + if (!GetOverlappedResult(conn->conn, &conn->ovl, &dwRead, TRUE)) break; } #else - if (!ReadFile(bind->conn, &hdr, sizeof(hdr), &dwRead, NULL)) { + if (!ReadFile(conn->conn, &hdr, sizeof(hdr), &dwRead, NULL)) { TRACE("connection lost, error=%08lx\n", GetLastError()); break; } @@ -102,19 +256,20 @@ static DWORD CALLBACK RPCRT4_io_thread(LPVOID the_arg) } /* read packet body */ - msg.BufferLength = hdr.len; - msg.Buffer = HeapAlloc(GetProcessHeap(), 0, msg.BufferLength); + buf = HeapAlloc(GetProcessHeap(), 0, hdr.len); + TRACE("receiving payload=%d\n", hdr.len); + if (!hdr.len) dwRead = 0; else #ifdef OVERLAPPED_WORKS - if (!ReadFile(bind->conn, msg.Buffer, msg.BufferLength, &dwRead, &bind->ovl)) { + if (!ReadFile(conn->conn, buf, hdr.len, &dwRead, &conn->ovl)) { DWORD err = GetLastError(); if (err != ERROR_IO_PENDING) { TRACE("connection lost, error=%08lx\n", err); break; } - if (!GetOverlappedResult(bind->conn, &bind->ovl, &dwRead, TRUE)) break; + if (!GetOverlappedResult(conn->conn, &conn->ovl, &dwRead, TRUE)) break; } #else - if (!ReadFile(bind->conn, msg.Buffer, msg.BufferLength, &dwRead, NULL)) { + if (!ReadFile(conn->conn, buf, hdr.len, &dwRead, NULL)) { TRACE("connection lost, error=%08lx\n", GetLastError()); break; } @@ -124,72 +279,31 @@ static DWORD CALLBACK RPCRT4_io_thread(LPVOID the_arg) break; } - sif = RPCRT4_find_interface(&hdr.object, &hdr.if_id); - if (sif) { - msg.RpcInterfaceInformation = sif->If; - /* associate object with binding (this is a bit of a hack... - * a new binding should probably be created for each object) */ - RPCRT4_SetBindingObject(bind, &hdr.object); - /* process packet*/ - switch (hdr.ptype) { - case PKT_REQUEST: - /* find dispatch function */ - msg.ProcNum = hdr.opnum; - if (sif->Flags & RPC_IF_OLE) { - /* native ole32 always gives us a dispatch table with a single entry - * (I assume that's a wrapper for IRpcStubBuffer::Invoke) */ - func = *sif->If->DispatchTable->DispatchTable; - } else { - if (msg.ProcNum >= sif->If->DispatchTable->DispatchTableCount) { - ERR("invalid procnum\n"); - func = NULL; - } - func = sif->If->DispatchTable->DispatchTable[msg.ProcNum]; - } - - /* put in the drep. FIXME: is this more universally applicable? - perhaps we should move this outward... */ - msg.DataRepresentation = - MAKELONG( MAKEWORD(hdr.drep[0], hdr.drep[1]), - MAKEWORD(hdr.drep[2], 0)); - - /* dispatch */ - if (func) func(&msg); - - /* prepare response packet */ - hdr.ptype = PKT_RESPONSE; - break; - default: - ERR("unknown packet type\n"); - goto no_reply; - } - - /* write reply packet */ - hdr.len = msg.BufferLength; - WriteFile(bind->conn, &hdr, sizeof(hdr), NULL, NULL); - WriteFile(bind->conn, msg.Buffer, msg.BufferLength, NULL, NULL); - - no_reply: - /* un-associate object */ - RPCRT4_SetBindingObject(bind, NULL); - msg.RpcInterfaceInformation = NULL; - } - else { - ERR("got RPC packet to unregistered interface %s\n", debugstr_guid(&hdr.if_id)); - } - - /* clean up */ - HeapFree(GetProcessHeap(), 0, msg.Buffer); - msg.Buffer = NULL; +#if 0 + RPCRT4_process_packet(conn, &hdr, buf); +#else + packet = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcPacket)); + packet->conn = conn; + packet->hdr = hdr; + packet->buf = buf; + RPCRT4_create_worker_if_needed(); + RPCRT4_push_packet(packet); + ReleaseSemaphore(server_sem, 1, NULL); +#endif + buf = NULL; } - if (msg.Buffer) HeapFree(GetProcessHeap(), 0, msg.Buffer); - RPCRT4_DestroyBinding(bind); + if (buf) HeapFree(GetProcessHeap(), 0, buf); + RPCRT4_DestroyConnection(conn); return 0; } -static void RPCRT4_new_client(RpcBinding* bind) +static void RPCRT4_new_client(RpcConnection* conn) { - bind->thread = CreateThread(NULL, 0, RPCRT4_io_thread, bind, 0, NULL); + conn->thread = CreateThread(NULL, 0, RPCRT4_io_thread, conn, 0, NULL); + if (!conn->thread) { + DWORD err = GetLastError(); + ERR("failed to create thread, error=%08lx\n", err); + } } static DWORD CALLBACK RPCRT4_server_thread(LPVOID the_arg) @@ -198,33 +312,33 @@ static DWORD CALLBACK RPCRT4_server_thread(LPVOID the_arg) HANDLE *objs = NULL; DWORD count, res; RpcServerProtseq* cps; - RpcBinding* bind; - RpcBinding* cbind; + RpcConnection* conn; + RpcConnection* cconn; for (;;) { EnterCriticalSection(&server_cs); - /* open and count bindings */ + /* open and count connections */ count = 1; cps = protseqs; while (cps) { - bind = cps->bind; - while (bind) { - RPCRT4_OpenBinding(bind); - if (bind->ovl.hEvent) count++; - bind = bind->Next; + conn = cps->conn; + while (conn) { + RPCRT4_OpenConnection(conn); + if (conn->ovl.hEvent) count++; + conn = conn->Next; } cps = cps->Next; } - /* make array of bindings */ + /* make array of connings */ objs = HeapReAlloc(GetProcessHeap(), 0, objs, count*sizeof(HANDLE)); objs[0] = m_event; count = 1; cps = protseqs; while (cps) { - bind = cps->bind; - while (bind) { - if (bind->ovl.hEvent) objs[count++] = bind->ovl.hEvent; - bind = bind->Next; + conn = cps->conn; + while (conn) { + if (conn->ovl.hEvent) objs[count++] = conn->ovl.hEvent; + conn = conn->Next; } cps = cps->Next; } @@ -241,37 +355,37 @@ static DWORD CALLBACK RPCRT4_server_thread(LPVOID the_arg) } else { b_handle = objs[res - WAIT_OBJECT_0]; - /* find which binding got a RPC */ + /* find which connection got a RPC */ EnterCriticalSection(&server_cs); - bind = NULL; + conn = NULL; cps = protseqs; while (cps) { - bind = cps->bind; - while (bind) { - if (bind->ovl.hEvent == b_handle) break; - bind = bind->Next; + conn = cps->conn; + while (conn) { + if (conn->ovl.hEvent == b_handle) break; + conn = conn->Next; } - if (bind) break; + if (conn) break; cps = cps->Next; } - cbind = NULL; - if (bind) RPCRT4_SpawnBinding(&cbind, bind); + cconn = NULL; + if (conn) RPCRT4_SpawnConnection(&cconn, conn); LeaveCriticalSection(&server_cs); - if (!bind) { - ERR("failed to locate binding for handle %p\n", b_handle); + if (!conn) { + ERR("failed to locate connection for handle %p\n", b_handle); } - if (cbind) RPCRT4_new_client(cbind); + if (cconn) RPCRT4_new_client(cconn); } } HeapFree(GetProcessHeap(), 0, objs); EnterCriticalSection(&server_cs); - /* close bindings */ + /* close connections */ cps = protseqs; while (cps) { - bind = cps->bind; - while (bind) { - RPCRT4_CloseBinding(bind); - bind = bind->Next; + conn = cps->conn; + while (conn) { + RPCRT4_CloseConnection(conn); + conn = conn->Next; } cps = cps->Next; } @@ -286,6 +400,7 @@ static void RPCRT4_start_listen(void) EnterCriticalSection(&listen_cs); if (! ++listen_count) { if (!mgr_event) mgr_event = CreateEventA(NULL, TRUE, FALSE, NULL); + if (!server_sem) server_sem = CreateSemaphoreA(NULL, 0, MAX_THREADS, NULL); std_listen = TRUE; server_thread = CreateThread(NULL, 0, RPCRT4_server_thread, NULL, 0, NULL); LeaveCriticalSection(&listen_cs); @@ -311,8 +426,7 @@ static void RPCRT4_stop_listen(void) static RPC_STATUS RPCRT4_use_protseq(RpcServerProtseq* ps) { - RPCRT4_CreateBindingA(&ps->bind, TRUE, ps->Protseq); - RPCRT4_CompleteBindingA(ps->bind, NULL, ps->Endpoint, NULL); + RPCRT4_CreateConnection(&ps->conn, TRUE, ps->Protseq, NULL, ps->Endpoint, NULL); EnterCriticalSection(&server_cs); ps->Next = protseqs; @@ -332,7 +446,7 @@ RPC_STATUS WINAPI RpcServerInqBindings( RPC_BINDING_VECTOR** BindingVector ) RPC_STATUS status; DWORD count; RpcServerProtseq* ps; - RpcBinding* bind; + RpcConnection* conn; if (BindingVector) TRACE("(*BindingVector == ^%p)\n", *BindingVector); @@ -340,14 +454,14 @@ RPC_STATUS WINAPI RpcServerInqBindings( RPC_BINDING_VECTOR** BindingVector ) ERR("(BindingVector == ^null!!?)\n"); EnterCriticalSection(&server_cs); - /* count bindings */ + /* count connections */ count = 0; ps = protseqs; while (ps) { - bind = ps->bind; - while (bind) { + conn = ps->conn; + while (conn) { count++; - bind = bind->Next; + conn = conn->Next; } ps = ps->Next; } @@ -360,12 +474,12 @@ RPC_STATUS WINAPI RpcServerInqBindings( RPC_BINDING_VECTOR** BindingVector ) count = 0; ps = protseqs; while (ps) { - bind = ps->bind; - while (bind) { - RPCRT4_ExportBinding((RpcBinding**)&(*BindingVector)->BindingH[count], - bind); + conn = ps->conn; + while (conn) { + RPCRT4_MakeBinding((RpcBinding**)&(*BindingVector)->BindingH[count], + conn); count++; - bind = bind->Next; + conn = conn->Next; } ps = ps->Next; } diff --git a/dlls/rpcrt4/rpc_server.h b/dlls/rpcrt4/rpc_server.h index da15d84b474..1f43de8d024 100644 --- a/dlls/rpcrt4/rpc_server.h +++ b/dlls/rpcrt4/rpc_server.h @@ -29,7 +29,7 @@ typedef struct _RpcServerProtseq LPSTR Protseq; LPSTR Endpoint; UINT MaxCalls; - RpcBinding* bind; + RpcConnection* conn; } RpcServerProtseq; typedef struct _RpcServerInterface