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