Sync to Wine-20050310:
Alexandre Julliard <julliard(a)winehq.org>
- Avoid spaces before preprocessor directives, that's not portable.
Robert Shearman <rob(a)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(a)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