Sync to Wine-20050310:
Alexandre Julliard <julliard@winehq.org>
- Avoid spaces before preprocessor directives, that's not portable.
Robert Shearman <rob@codeweavers.com>
- Add a stub implementation of RpcImpersonateClient.
- More tracing, particularly on error paths.
- ERROR_IO_PENDING is expected, so don't return an error.
Mike Hearn <mh@codeweavers.com>
- Suppress some useless warnings in the RPC runtime, and make a few
  TRACEs that were reporting problems into WARNs.
Modified: trunk/reactos/lib/rpcrt4/ndr_marshall.c
Modified: trunk/reactos/lib/rpcrt4/rpc_binding.c
Modified: trunk/reactos/lib/rpcrt4/rpc_message.c
Modified: trunk/reactos/lib/rpcrt4/rpc_server.c
Modified: trunk/reactos/lib/rpcrt4/rpcrt4.spec

Modified: trunk/reactos/lib/rpcrt4/ndr_marshall.c
--- trunk/reactos/lib/rpcrt4/ndr_marshall.c	2005-03-15 09:08:16 UTC (rev 14092)
+++ trunk/reactos/lib/rpcrt4/ndr_marshall.c	2005-03-15 09:22:34 UTC (rev 14093)
@@ -45,21 +45,21 @@
 #define BUFFER_PARANOIA 20
 
 #if defined(__i386__)
-  #define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
+# define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
     (*((UINT32 *)(pchar)) = (uint32))
 
-  #define LITTLE_ENDIAN_UINT32_READ(pchar) \
+# define LITTLE_ENDIAN_UINT32_READ(pchar) \
     (*((UINT32 *)(pchar)))
 #else
   /* these would work for i386 too, but less efficient */
-  #define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
+# define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
     (*(pchar)     = LOBYTE(LOWORD(uint32)), \
      *((pchar)+1) = HIBYTE(LOWORD(uint32)), \
      *((pchar)+2) = LOBYTE(HIWORD(uint32)), \
      *((pchar)+3) = HIBYTE(HIWORD(uint32)), \
      (uint32)) /* allow as r-value */
 
-  #define LITTLE_ENDIAN_UINT32_READ(pchar) \
+# define LITTLE_ENDIAN_UINT32_READ(pchar) \
     (MAKELONG( \
       MAKEWORD(*(pchar), *((pchar)+1)), \
       MAKEWORD(*((pchar)+2), *((pchar)+3))))
@@ -78,14 +78,14 @@
     MAKEWORD(*((pchar)+1), *(pchar))))
 
 #ifdef NDR_LOCAL_IS_BIG_ENDIAN
-  #define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
+# define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
     BIG_ENDIAN_UINT32_WRITE(pchar, uint32)
-  #define NDR_LOCAL_UINT32_READ(pchar) \
+# define NDR_LOCAL_UINT32_READ(pchar) \
     BIG_ENDIAN_UINT32_READ(pchar)
 #else
-  #define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
+# define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
     LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32)
-  #define NDR_LOCAL_UINT32_READ(pchar) \
+# define NDR_LOCAL_UINT32_READ(pchar) \
     LITTLE_ENDIAN_UINT32_READ(pchar)
 #endif
 

Modified: trunk/reactos/lib/rpcrt4/rpc_binding.c
--- trunk/reactos/lib/rpcrt4/rpc_binding.c	2005-03-15 09:08:16 UTC (rev 14092)
+++ trunk/reactos/lib/rpcrt4/rpc_binding.c	2005-03-15 09:22:34 UTC (rev 14093)
@@ -173,11 +173,13 @@
         memset(&Connection->ovl, 0, sizeof(Connection->ovl));
         Connection->ovl.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
         if (!ConnectNamedPipe(Connection->conn, &Connection->ovl)) {
-          WARN("Couldn't ConnectNamedPipe (error was %ld)\n", GetLastError());
           if (GetLastError() == ERROR_PIPE_CONNECTED) {
             SetEvent(Connection->ovl.hEvent);
             return RPC_S_OK;
+          } else if (GetLastError() == ERROR_IO_PENDING) {
+            return RPC_S_OK;
           }
+          WARN("Couldn't ConnectNamedPipe (error was %ld)\n", GetLastError());
           return RPC_S_SERVER_UNAVAILABLE;
         }
       }
@@ -211,7 +213,7 @@
             return RPC_S_SERVER_TOO_BUSY;
           } else {
             err = GetLastError();
-            TRACE("connection failed, error=%lx\n", err);
+            WARN("connection failed, error=%lx\n", err);
             HeapFree(GetProcessHeap(), 0, pname);
             return RPC_S_SERVER_UNAVAILABLE;
           }
@@ -243,7 +245,7 @@
           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);
+          WARN("connection failed, error=%lx\n", err);
           HeapFree(GetProcessHeap(), 0, pname);
           if (err == ERROR_PIPE_BUSY)
             return RPC_S_SERVER_TOO_BUSY;
@@ -397,7 +399,7 @@
 RPC_STATUS RPCRT4_MakeBinding(RpcBinding** Binding, RpcConnection* Connection)
 {
   RpcBinding* NewBinding;
-  TRACE("(*RpcBinding == ^%p, Connection == ^%p)\n", *Binding, Connection);
+  TRACE("(RpcBinding == ^%p, Connection == ^%p)\n", Binding, Connection);
 
   RPCRT4_AllocBinding(&NewBinding, Connection->server);
   NewBinding->Protseq = RPCRT4_strdupA(Connection->Protseq);
@@ -1094,3 +1096,22 @@
   FIXME("Unknown protseq %s - we probably need to implement it one day\n", debugstr_w(protseq));
   return RPC_S_PROTSEQ_NOT_SUPPORTED;
 }
+
+/***********************************************************************
+ *             RpcImpersonateClient (RPCRT4.@)
+ *
+ * Impersonates the client connected via a binding handle so that security
+ * checks are done in the context of the client.
+ *
+ * PARAMS
+ *  BindingHandle [I] Handle to the binding to the client.
+ *
+ * RETURNS
+ *  Success: RPS_S_OK.
+ *  Failure: RPC_STATUS value.
+ */
+RPC_STATUS WINAPI RpcImpersonateClient(RPC_BINDING_HANDLE BindingHandle)
+{
+    FIXME("(%p): stub\n", BindingHandle);
+    return RPC_S_NO_CONTEXT_AVAILABLE;
+}

Modified: trunk/reactos/lib/rpcrt4/rpc_message.c
--- trunk/reactos/lib/rpcrt4/rpc_message.c	2005-03-15 09:08:16 UTC (rev 14092)
+++ trunk/reactos/lib/rpcrt4/rpc_message.c	2005-03-15 09:22:34 UTC (rev 14093)
@@ -330,6 +330,7 @@
     }
   }
   if (dwRead != sizeof(common_hdr)) {
+    WARN("Short read of header, %ld/%d bytes\n", dwRead, sizeof(common_hdr));
     status = RPC_S_PROTOCOL_ERROR;
     goto fail;
   }
@@ -344,6 +345,7 @@
 
   hdr_length = RPCRT4_GetHeaderSize((RpcPktHdr*)&common_hdr);
   if (hdr_length == 0) {
+    WARN("header length == 0\n");
     status = RPC_S_PROTOCOL_ERROR;
     goto fail;
   }
@@ -366,6 +368,7 @@
     }
   }
   if (dwRead != hdr_length - sizeof(common_hdr)) {
+    WARN("bad header length, %ld/%ld bytes\n", dwRead, hdr_length - sizeof(common_hdr));
     status = RPC_S_PROTOCOL_ERROR;
     goto fail;
   }
@@ -382,6 +385,9 @@
   default:
     pMsg->BufferLength = common_hdr.frag_len - hdr_length;
   }
+
+  TRACE("buffer length = %u\n", pMsg->BufferLength);
+
   status = I_RpcGetBuffer(pMsg);
   if (status != RPC_S_OK) goto fail;
 
@@ -413,12 +419,15 @@
       }
     }
     if (dwRead != data_length) {
+      WARN("bad data length, %ld/%ld\n", dwRead, data_length);
       status = RPC_S_PROTOCOL_ERROR;
       goto fail;
     }
 
+    /* when there is no more data left, it should be the last packet */
     if (buffer_length == pMsg->BufferLength &&
         ((*Header)->common.flags & RPC_FLG_LAST) == 0) {
+      WARN("no more data left, but not last packet\n");
       status = RPC_S_PROTOCOL_ERROR;
       goto fail;
     }
@@ -610,6 +619,7 @@
     status = RPC_S_CALL_FAILED; /* ? */
     goto fail;
   default:
+    WARN("bad packet type %d\n", hdr->common.ptype);
     goto fail;
   }
 

Modified: trunk/reactos/lib/rpcrt4/rpc_server.c
--- trunk/reactos/lib/rpcrt4/rpc_server.c	2005-03-15 09:08:16 UTC (rev 14092)
+++ trunk/reactos/lib/rpcrt4/rpc_server.c	2005-03-15 09:22:34 UTC (rev 14093)
@@ -93,7 +93,14 @@
 
 static BOOL std_listen;
 static LONG listen_count = -1;
-static HANDLE mgr_event, server_thread;
+/* set on change of configuration (e.g. listening on new protseq) */
+static HANDLE mgr_event;
+/* mutex for ensuring only one thread can change state at a time */
+static HANDLE mgr_mutex;
+/* set when server thread has finished opening connections */
+static HANDLE server_ready_event;
+/* thread that waits for connections */
+static HANDLE server_thread;
 
 static CRITICAL_SECTION spacket_cs;
 static CRITICAL_SECTION_DEBUG spacket_cs_debug =
@@ -463,6 +470,7 @@
   RpcServerProtseq* cps;
   RpcConnection* conn;
   RpcConnection* cconn;
+  BOOL set_ready_event = FALSE;
 
   TRACE("(the_arg == ^%p)\n", the_arg);
 
@@ -499,11 +507,22 @@
     }
     LeaveCriticalSection(&server_cs);
 
+    if (set_ready_event)
+    {
+        /* signal to function that changed state that we are now sync'ed */
+        SetEvent(server_ready_event);
+        set_ready_event = FALSE;
+    }
+
     /* start waiting */
     res = WaitForMultipleObjects(count, objs, FALSE, INFINITE);
     if (res == WAIT_OBJECT_0) {
-      ResetEvent(m_event);
-      if (!std_listen) break;
+      if (!std_listen)
+      {
+        SetEvent(server_ready_event);
+        break;
+      }
+      set_ready_event = TRUE;
     }
     else if (res == WAIT_FAILED) {
       ERR("wait failed\n");
@@ -548,13 +567,31 @@
   return 0;
 }
 
+/* tells the server thread that the state has changed and waits for it to
+ * make the changes */
+static void RPCRT4_sync_with_server_thread(void)
+{
+  /* make sure we are the only thread sync'ing the server state, otherwise
+   * there is a race with the server thread setting an older state and setting
+   * the server_ready_event when the new state hasn't yet been applied */
+  WaitForSingleObject(mgr_mutex, INFINITE);
+
+  SetEvent(mgr_event);
+  /* wait for server thread to make the requested changes before returning */
+  WaitForSingleObject(server_ready_event, INFINITE);
+
+  ReleaseMutex(mgr_mutex);
+}
+
 static void RPCRT4_start_listen(void)
 {
   TRACE("\n");
 
   EnterCriticalSection(&listen_cs);
   if (! ++listen_count) {
-    if (!mgr_event) mgr_event = CreateEventW(NULL, TRUE, FALSE, NULL);
+    if (!mgr_mutex) mgr_mutex = CreateMutexW(NULL, FALSE, NULL);
+    if (!mgr_event) mgr_event = CreateEventW(NULL, FALSE, FALSE, NULL);
+    if (!server_ready_event) server_ready_event = CreateEventW(NULL, FALSE, FALSE, NULL);
     if (!server_sem) server_sem = CreateSemaphoreW(NULL, 0, MAX_THREADS, NULL);
     if (!worker_tls) worker_tls = TlsAlloc();
     std_listen = TRUE;
@@ -562,7 +599,7 @@
     LeaveCriticalSection(&listen_cs);
   } else {
     LeaveCriticalSection(&listen_cs);
-    SetEvent(mgr_event);
+    RPCRT4_sync_with_server_thread();
   }
 }
 
@@ -574,7 +611,7 @@
   else if (--listen_count == -1) {
     std_listen = FALSE;
     LeaveCriticalSection(&listen_cs);
-    SetEvent(mgr_event);
+    RPCRT4_sync_with_server_thread();
   } else
     LeaveCriticalSection(&listen_cs);
   assert(listen_count > -2);
@@ -589,7 +626,7 @@
   protseqs = ps;
   LeaveCriticalSection(&server_cs);
 
-  if (std_listen) SetEvent(mgr_event);
+  if (std_listen) RPCRT4_sync_with_server_thread();
 
   return RPC_S_OK;
 }

Modified: trunk/reactos/lib/rpcrt4/rpcrt4.spec
--- trunk/reactos/lib/rpcrt4/rpcrt4.spec	2005-03-15 09:08:16 UTC (rev 14092)
+++ trunk/reactos/lib/rpcrt4/rpcrt4.spec	2005-03-15 09:22:34 UTC (rev 14093)
@@ -72,7 +72,7 @@
 @ stub RpcGetAsyncCallStatus
 @ stub RpcIfIdVectorFree
 @ stub RpcIfInqId
-@ stub RpcImpersonateClient
+@ stdcall RpcImpersonateClient(ptr)
 @ stub RpcInitializeAsyncHandle
 @ stub RpcMgmtBindingInqParameter # win9x
 @ stub RpcMgmtBindingSetParameter # win9x