diff --git a/reactos/lib/rpcrt4/ndr_marshall.c b/reactos/lib/rpcrt4/ndr_marshall.c index 33ff8f59ddd..aeb42ca80d3 100644 --- a/reactos/lib/rpcrt4/ndr_marshall.c +++ b/reactos/lib/rpcrt4/ndr_marshall.c @@ -45,21 +45,21 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole); #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 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole); 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 diff --git a/reactos/lib/rpcrt4/rpc_binding.c b/reactos/lib/rpcrt4/rpc_binding.c index 82e1690ea5f..2cf2f54f99f 100644 --- a/reactos/lib/rpcrt4/rpc_binding.c +++ b/reactos/lib/rpcrt4/rpc_binding.c @@ -173,11 +173,13 @@ RPC_STATUS RPCRT4_OpenConnection(RpcConnection* Connection) 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 @@ RPC_STATUS RPCRT4_OpenConnection(RpcConnection* Connection) 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 @@ RPC_STATUS RPCRT4_OpenConnection(RpcConnection* Connection) 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_SetBindingObject(RpcBinding* Binding, UUID* ObjectUuid) 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 @@ RPC_STATUS WINAPI RpcNetworkIsProtseqValidW(LPWSTR protseq) { 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; +} diff --git a/reactos/lib/rpcrt4/rpc_message.c b/reactos/lib/rpcrt4/rpc_message.c index 0e48cb631ff..8a2e0e21a00 100644 --- a/reactos/lib/rpcrt4/rpc_message.c +++ b/reactos/lib/rpcrt4/rpc_message.c @@ -330,6 +330,7 @@ RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header, } } 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 @@ RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header, 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 @@ RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header, } } 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 @@ RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header, 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 @@ RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header, } } 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 @@ RPC_STATUS WINAPI I_RpcReceive(PRPC_MESSAGE pMsg) status = RPC_S_CALL_FAILED; /* ? */ goto fail; default: + WARN("bad packet type %d\n", hdr->common.ptype); goto fail; } diff --git a/reactos/lib/rpcrt4/rpc_server.c b/reactos/lib/rpcrt4/rpc_server.c index bb3cb95da82..c18bc7f8d5b 100644 --- a/reactos/lib/rpcrt4/rpc_server.c +++ b/reactos/lib/rpcrt4/rpc_server.c @@ -93,7 +93,14 @@ static CRITICAL_SECTION listen_cs = { &listen_cs_debug, -1, 0, 0, 0, 0 }; 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 @@ static DWORD CALLBACK RPCRT4_server_thread(LPVOID the_arg) RpcServerProtseq* cps; RpcConnection* conn; RpcConnection* cconn; + BOOL set_ready_event = FALSE; TRACE("(the_arg == ^%p)\n", the_arg); @@ -499,11 +507,22 @@ static DWORD CALLBACK RPCRT4_server_thread(LPVOID the_arg) } 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 @@ static DWORD CALLBACK RPCRT4_server_thread(LPVOID the_arg) 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 @@ static void RPCRT4_start_listen(void) LeaveCriticalSection(&listen_cs); } else { LeaveCriticalSection(&listen_cs); - SetEvent(mgr_event); + RPCRT4_sync_with_server_thread(); } } @@ -574,7 +611,7 @@ static void RPCRT4_stop_listen(void) 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 @@ static RPC_STATUS RPCRT4_use_protseq(RpcServerProtseq* ps) protseqs = ps; LeaveCriticalSection(&server_cs); - if (std_listen) SetEvent(mgr_event); + if (std_listen) RPCRT4_sync_with_server_thread(); return RPC_S_OK; } diff --git a/reactos/lib/rpcrt4/rpcrt4.spec b/reactos/lib/rpcrt4/rpcrt4.spec index c2250a8e1e4..b098786153e 100644 --- a/reactos/lib/rpcrt4/rpcrt4.spec +++ b/reactos/lib/rpcrt4/rpcrt4.spec @@ -72,7 +72,7 @@ @ stub RpcGetAsyncCallStatus @ stub RpcIfIdVectorFree @ stub RpcIfInqId -@ stub RpcImpersonateClient +@ stdcall RpcImpersonateClient(ptr) @ stub RpcInitializeAsyncHandle @ stub RpcMgmtBindingInqParameter # win9x @ stub RpcMgmtBindingSetParameter # win9x