[PATCH] rpcrt4: Implement RpcBindingServerFromClient and populate NetworkAddr for each transport. Add more thorough testing for this function.

Colin Finck mail at colinfinck.de
Wed Oct 12 10:14:11 CDT 2016


Fixes https://bugs.winehq.org/show_bug.cgi?id=38766

From: Christoph von Wittich <Christoph at ApiViewer.de>
Signed-off-by: Colin Finck <mail at colinfinck.de>
---
 dlls/rpcrt4/rpc_binding.c   | 22 ++++++++++++++++++----
 dlls/rpcrt4/rpc_transport.c | 34 ++++++++++++++++++++++++++++++++--
 dlls/rpcrt4/tests/server.c  | 33 ++++++++++++++++++++++-----------
 3 files changed, 72 insertions(+), 17 deletions(-)

diff --git a/dlls/rpcrt4/rpc_binding.c b/dlls/rpcrt4/rpc_binding.c
index 7212a18..07eddbe 100644
--- a/dlls/rpcrt4/rpc_binding.c
+++ b/dlls/rpcrt4/rpc_binding.c
@@ -1636,11 +1636,25 @@ RpcBindingInqAuthClientExW( RPC_BINDING_HANDLE ClientBinding, RPC_AUTHZ_HANDLE *
 /***********************************************************************
  *             RpcBindingServerFromClient (RPCRT4.@)
  */
-
-RPC_STATUS RPC_ENTRY RpcBindingServerFromClient(RPC_BINDING_HANDLE ClientBinding, RPC_BINDING_HANDLE *ServerBinding)
+RPCRTAPI RPC_STATUS RPC_ENTRY
+RpcBindingServerFromClient(RPC_BINDING_HANDLE ClientBinding, RPC_BINDING_HANDLE* ServerBinding)
 {
-    FIXME("%p %p: stub\n", ClientBinding, ServerBinding);
-    return RPC_S_INVALID_BINDING;
+    RpcBinding* bind = ClientBinding;
+    RpcBinding* NewBinding;
+
+    if (!bind)
+        bind = I_RpcGetCurrentCallHandle();
+
+    if (!bind->server)
+        return RPC_S_INVALID_BINDING;
+
+    RPCRT4_AllocBinding(&NewBinding, TRUE);
+    NewBinding->Protseq = RPCRT4_strdupA(bind->Protseq);
+    NewBinding->NetworkAddr = RPCRT4_strdupA(bind->NetworkAddr);
+
+    *ServerBinding = NewBinding;
+
+    return RPC_S_OK;
 }
 
 /***********************************************************************
diff --git a/dlls/rpcrt4/rpc_transport.c b/dlls/rpcrt4/rpc_transport.c
index b2fbf9b..cc9471d 100644
--- a/dlls/rpcrt4/rpc_transport.c
+++ b/dlls/rpcrt4/rpc_transport.c
@@ -388,6 +388,7 @@ static void rpcrt4_conn_np_handoff(RpcConnection_np *old_npc, RpcConnection_np *
 
 static RPC_STATUS rpcrt4_ncacn_np_handoff(RpcConnection *old_conn, RpcConnection *new_conn)
 {
+  DWORD cbComputerName = MAX_COMPUTERNAME_LENGTH + 1;
   RPC_STATUS status;
   LPSTR pname;
 
@@ -397,6 +398,16 @@ static RPC_STATUS rpcrt4_ncacn_np_handoff(RpcConnection *old_conn, RpcConnection
   status = rpcrt4_conn_create_pipe(old_conn, pname);
   I_RpcFree(pname);
 
+  /* Store the local computer name as the NetworkAddr for ncacn_np as long as
+   * we don't support named pipes over the network. */
+  FIXME("Using local computer name as NetworkAddr\n");
+  new_conn->NetworkAddr = HeapAlloc(GetProcessHeap(), 0, cbComputerName);
+  if (!GetComputerNameA(new_conn->NetworkAddr, &cbComputerName))
+  {
+    ERR("Failed to retrieve the computer name, error %u\n", GetLastError());
+    return RPC_S_OUT_OF_RESOURCES;
+  }
+
   return status;
 }
 
@@ -429,6 +440,7 @@ static RPC_STATUS rpcrt4_ncalrpc_np_is_server_listening(const char *endpoint)
 
 static RPC_STATUS rpcrt4_ncalrpc_handoff(RpcConnection *old_conn, RpcConnection *new_conn)
 {
+  DWORD cbComputerName = MAX_COMPUTERNAME_LENGTH + 1;
   RPC_STATUS status;
   LPSTR pname;
 
@@ -439,7 +451,15 @@ static RPC_STATUS rpcrt4_ncalrpc_handoff(RpcConnection *old_conn, RpcConnection
   pname = ncalrpc_pipe_name(old_conn->Endpoint);
   status = rpcrt4_conn_create_pipe(old_conn, pname);
   I_RpcFree(pname);
-    
+
+  /* Store the local computer name as the NetworkAddr for ncalrpc. */
+  new_conn->NetworkAddr = HeapAlloc(GetProcessHeap(), 0, cbComputerName);
+  if (!GetComputerNameA(new_conn->NetworkAddr, &cbComputerName))
+  {
+    ERR("Failed to retrieve the computer name, error %u\n", GetLastError());
+    return RPC_S_OUT_OF_RESOURCES;
+  }
+
   return status;
 }
 
@@ -1479,10 +1499,20 @@ static RPC_STATUS rpcrt4_conn_tcp_handoff(RpcConnection *old_conn, RpcConnection
     ERR("Failed to accept a TCP connection: error %d\n", ret);
     return RPC_S_OUT_OF_RESOURCES;
   }
+
   nonblocking = 1;
   ioctlsocket(ret, FIONBIO, &nonblocking);
   client->sock = ret;
-  TRACE("Accepted a new TCP connection\n");
+
+  client->common.NetworkAddr = HeapAlloc(GetProcessHeap(), 0, INET6_ADDRSTRLEN);
+  ret = getnameinfo((struct sockaddr*)&address, addrsize, client->common.NetworkAddr, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);
+  if (ret != 0)
+  {
+    ERR("Failed to retrieve the IP address, error %d\n", ret);
+    return RPC_S_OUT_OF_RESOURCES;
+  }
+
+  TRACE("Accepted a new TCP connection from %s\n", client->common.NetworkAddr);
   return RPC_S_OK;
 }
 
diff --git a/dlls/rpcrt4/tests/server.c b/dlls/rpcrt4/tests/server.c
index f9a5a96..ee28703 100644
--- a/dlls/rpcrt4/tests/server.c
+++ b/dlls/rpcrt4/tests/server.c
@@ -745,29 +745,40 @@ void __cdecl s_context_handle_test(void)
     binding = NULL;
     status = RpcBindingServerFromClient(NULL, &binding);
 
-    todo_wine
-    {
-        ok(status == RPC_S_OK, "expected RPC_S_OK got %u\n", status);
-        ok(binding != NULL, "binding is NULL\n");
-    }
+    ok(status == RPC_S_OK, "expected RPC_S_OK got %u\n", status);
+    ok(binding != NULL, "binding is NULL\n");
 
     if (status == RPC_S_OK && binding != NULL)
     {
         unsigned char* string_binding = NULL;
-        unsigned char* computer_name = NULL;
+        unsigned char* object_uuid = NULL;
+        unsigned char* protseq = NULL;
+        unsigned char* network_address = NULL;
+        unsigned char* endpoint = NULL;
+        unsigned char* network_options = NULL;
 
         status = RpcBindingToStringBindingA(binding, &string_binding);
-
         ok(status == RPC_S_OK, "expected RPC_S_OK got %u\n", status);
         ok(string_binding != NULL, "string_binding is NULL\n");
 
-        status = RpcStringBindingParseA(string_binding, NULL, NULL, &computer_name, NULL, NULL);
-
+        status = RpcStringBindingParseA(string_binding, &object_uuid, &protseq, &network_address, &endpoint, &network_options);
         ok(status == RPC_S_OK, "expected RPC_S_OK got %u\n", status);
-        ok(computer_name != NULL, "computer_name is NULL\n");
+        ok(protseq != NULL && *protseq != '\0', "protseq is %s\n", protseq);
+        ok(network_address != NULL && *network_address != '\0', "network_address is %s\n", network_address);
+
+        todo_wine
+        {
+            ok(object_uuid != NULL && *object_uuid == '\0', "object_uuid is %s\n", object_uuid);
+            ok(endpoint != NULL && *endpoint == '\0', "endpoint is %s\n", endpoint);
+            ok(network_options != NULL && *network_options == '\0', "network_options is %s\n", network_options);
+        }
 
         RpcStringFreeA(&string_binding);
-        RpcStringFreeA(&computer_name);
+        RpcStringFreeA(&object_uuid);
+        RpcStringFreeA(&protseq);
+        RpcStringFreeA(&network_address);
+        RpcStringFreeA(&endpoint);
+        RpcStringFreeA(&network_options);
         RpcBindingFree(&binding);
     }
 }
-- 
1.9.1




More information about the wine-patches mailing list