4 * Copyright 2001 Ove Kåven, TransGaming Technologies
5 * Copyright 2003 Mike Hearn
6 * Copyright 2004 Filip Navara
7 * Copyright 2006 Mike McCormack
8 * Copyright 2006 Damjan Jovanovic
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
33 #include <sys/types.h>
35 #if defined(__MINGW32__) || defined (_MSC_VER)
36 # include <ws2tcpip.h>
38 # define EADDRINUSE WSAEADDRINUSE
41 # define EAGAIN WSAEWOULDBLOCK
44 # define errno WSAGetLastError()
51 # ifdef HAVE_SYS_SOCKET_H
52 # include <sys/socket.h>
54 # ifdef HAVE_NETINET_IN_H
55 # include <netinet/in.h>
57 # ifdef HAVE_NETINET_TCP_H
58 # include <netinet/tcp.h>
60 # ifdef HAVE_ARPA_INET_H
61 # include <arpa/inet.h>
66 # ifdef HAVE_SYS_POLL_H
67 # include <sys/poll.h>
69 # ifdef HAVE_SYS_FILIO_H
70 # include <sys/filio.h>
72 # ifdef HAVE_SYS_IOCTL_H
73 # include <sys/ioctl.h>
75 # define closesocket close
76 # define ioctlsocket ioctl
77 #endif /* defined(__MINGW32__) || defined (_MSC_VER) */
85 #include "wine/unicode.h"
90 #include "wine/debug.h"
92 #include "rpc_binding.h"
93 #include "rpc_assoc.h"
94 #include "rpc_message.h"
95 #include "rpc_server.h"
96 #include "epm_towers.h"
99 # define SOL_TCP IPPROTO_TCP
102 #define DEFAULT_NCACN_HTTP_TIMEOUT (60 * 1000)
104 WINE_DEFAULT_DEBUG_CHANNEL(rpc);
106 static RPC_STATUS RPCRT4_SpawnConnection(RpcConnection** Connection, RpcConnection* OldConnection);
108 /**** ncacn_np support ****/
110 typedef struct _RpcConnection_np
112 RpcConnection common;
118 static RpcConnection *rpcrt4_conn_np_alloc(void)
120 RpcConnection_np *npc = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcConnection_np));
124 memset(&npc->ovl, 0, sizeof(npc->ovl));
125 npc->listening = FALSE;
130 static RPC_STATUS rpcrt4_conn_listen_pipe(RpcConnection_np *npc)
135 npc->listening = TRUE;
138 if (ConnectNamedPipe(npc->pipe, &npc->ovl))
141 switch(GetLastError())
143 case ERROR_PIPE_CONNECTED:
144 SetEvent(npc->ovl.hEvent);
146 case ERROR_IO_PENDING:
147 /* will be completed in rpcrt4_protseq_np_wait_for_new_connection */
149 case ERROR_NO_DATA_DETECTED:
150 /* client has disconnected, retry */
151 DisconnectNamedPipe( npc->pipe );
154 npc->listening = FALSE;
155 WARN("Couldn't ConnectNamedPipe (error was %d)\n", GetLastError());
156 return RPC_S_OUT_OF_RESOURCES;
161 static RPC_STATUS rpcrt4_conn_create_pipe(RpcConnection *Connection, LPCSTR pname)
163 RpcConnection_np *npc = (RpcConnection_np *) Connection;
164 TRACE("listening on %s\n", pname);
166 npc->pipe = CreateNamedPipeA(pname, PIPE_ACCESS_DUPLEX,
167 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE,
168 PIPE_UNLIMITED_INSTANCES,
169 RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE, 5000, NULL);
170 if (npc->pipe == INVALID_HANDLE_VALUE) {
171 WARN("CreateNamedPipe failed with error %d\n", GetLastError());
172 if (GetLastError() == ERROR_FILE_EXISTS)
173 return RPC_S_DUPLICATE_ENDPOINT;
175 return RPC_S_CANT_CREATE_ENDPOINT;
178 memset(&npc->ovl, 0, sizeof(npc->ovl));
179 npc->ovl.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
181 /* Note: we don't call ConnectNamedPipe here because it must be done in the
182 * server thread as the thread must be alertable */
186 static RPC_STATUS rpcrt4_conn_open_pipe(RpcConnection *Connection, LPCSTR pname, BOOL wait)
188 RpcConnection_np *npc = (RpcConnection_np *) Connection;
192 TRACE("connecting to %s\n", pname);
198 dwFlags = SECURITY_SQOS_PRESENT;
199 switch (Connection->QOS->qos->ImpersonationType)
201 case RPC_C_IMP_LEVEL_DEFAULT:
202 /* FIXME: what to do here? */
204 case RPC_C_IMP_LEVEL_ANONYMOUS:
205 dwFlags |= SECURITY_ANONYMOUS;
207 case RPC_C_IMP_LEVEL_IDENTIFY:
208 dwFlags |= SECURITY_IDENTIFICATION;
210 case RPC_C_IMP_LEVEL_IMPERSONATE:
211 dwFlags |= SECURITY_IMPERSONATION;
213 case RPC_C_IMP_LEVEL_DELEGATE:
214 dwFlags |= SECURITY_DELEGATION;
217 if (Connection->QOS->qos->IdentityTracking == RPC_C_QOS_IDENTITY_DYNAMIC)
218 dwFlags |= SECURITY_CONTEXT_TRACKING;
220 pipe = CreateFileA(pname, GENERIC_READ|GENERIC_WRITE, 0, NULL,
221 OPEN_EXISTING, dwFlags, 0);
222 if (pipe != INVALID_HANDLE_VALUE) break;
223 err = GetLastError();
224 if (err == ERROR_PIPE_BUSY) {
225 TRACE("connection failed, error=%x\n", err);
226 return RPC_S_SERVER_TOO_BUSY;
228 if (!wait || !WaitNamedPipeA(pname, NMPWAIT_WAIT_FOREVER)) {
229 err = GetLastError();
230 WARN("connection failed, error=%x\n", err);
231 return RPC_S_SERVER_UNAVAILABLE;
236 memset(&npc->ovl, 0, sizeof(npc->ovl));
237 /* pipe is connected; change to message-read mode. */
238 dwMode = PIPE_READMODE_MESSAGE;
239 SetNamedPipeHandleState(pipe, &dwMode, NULL, NULL);
240 npc->ovl.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
246 static RPC_STATUS rpcrt4_ncalrpc_open(RpcConnection* Connection)
248 RpcConnection_np *npc = (RpcConnection_np *) Connection;
249 static const char prefix[] = "\\\\.\\pipe\\lrpc\\";
253 /* already connected? */
257 /* protseq=ncalrpc: supposed to use NT LPC ports,
258 * but we'll implement it with named pipes for now */
259 pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1);
260 strcat(strcpy(pname, prefix), Connection->Endpoint);
261 r = rpcrt4_conn_open_pipe(Connection, pname, TRUE);
267 static RPC_STATUS rpcrt4_protseq_ncalrpc_open_endpoint(RpcServerProtseq* protseq, const char *endpoint)
269 static const char prefix[] = "\\\\.\\pipe\\lrpc\\";
272 RpcConnection *Connection;
273 char generated_endpoint[22];
277 static LONG lrpc_nameless_id;
278 DWORD process_id = GetCurrentProcessId();
279 ULONG id = InterlockedIncrement(&lrpc_nameless_id);
280 snprintf(generated_endpoint, sizeof(generated_endpoint),
281 "LRPC%08x.%08x", process_id, id);
282 endpoint = generated_endpoint;
285 r = RPCRT4_CreateConnection(&Connection, TRUE, protseq->Protseq, NULL,
286 endpoint, NULL, NULL, NULL);
290 /* protseq=ncalrpc: supposed to use NT LPC ports,
291 * but we'll implement it with named pipes for now */
292 pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1);
293 strcat(strcpy(pname, prefix), Connection->Endpoint);
294 r = rpcrt4_conn_create_pipe(Connection, pname);
297 EnterCriticalSection(&protseq->cs);
298 Connection->Next = protseq->conn;
299 protseq->conn = Connection;
300 LeaveCriticalSection(&protseq->cs);
305 static RPC_STATUS rpcrt4_ncacn_np_open(RpcConnection* Connection)
307 RpcConnection_np *npc = (RpcConnection_np *) Connection;
308 static const char prefix[] = "\\\\.";
312 /* already connected? */
316 /* protseq=ncacn_np: named pipes */
317 pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1);
318 strcat(strcpy(pname, prefix), Connection->Endpoint);
319 r = rpcrt4_conn_open_pipe(Connection, pname, FALSE);
325 static RPC_STATUS rpcrt4_protseq_ncacn_np_open_endpoint(RpcServerProtseq *protseq, const char *endpoint)
327 static const char prefix[] = "\\\\.";
330 RpcConnection *Connection;
331 char generated_endpoint[21];
335 static LONG np_nameless_id;
336 DWORD process_id = GetCurrentProcessId();
337 ULONG id = InterlockedExchangeAdd(&np_nameless_id, 1 );
338 snprintf(generated_endpoint, sizeof(generated_endpoint),
339 "\\\\pipe\\\\%08x.%03x", process_id, id);
340 endpoint = generated_endpoint;
343 r = RPCRT4_CreateConnection(&Connection, TRUE, protseq->Protseq, NULL,
344 endpoint, NULL, NULL, NULL);
348 /* protseq=ncacn_np: named pipes */
349 pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1);
350 strcat(strcpy(pname, prefix), Connection->Endpoint);
351 r = rpcrt4_conn_create_pipe(Connection, pname);
354 EnterCriticalSection(&protseq->cs);
355 Connection->Next = protseq->conn;
356 protseq->conn = Connection;
357 LeaveCriticalSection(&protseq->cs);
362 static void rpcrt4_conn_np_handoff(RpcConnection_np *old_npc, RpcConnection_np *new_npc)
364 /* because of the way named pipes work, we'll transfer the connected pipe
365 * to the child, then reopen the server binding to continue listening */
367 new_npc->pipe = old_npc->pipe;
368 new_npc->ovl = old_npc->ovl;
370 memset(&old_npc->ovl, 0, sizeof(old_npc->ovl));
371 old_npc->listening = FALSE;
374 static RPC_STATUS rpcrt4_ncacn_np_handoff(RpcConnection *old_conn, RpcConnection *new_conn)
378 static const char prefix[] = "\\\\.";
380 rpcrt4_conn_np_handoff((RpcConnection_np *)old_conn, (RpcConnection_np *)new_conn);
382 pname = I_RpcAllocate(strlen(prefix) + strlen(old_conn->Endpoint) + 1);
383 strcat(strcpy(pname, prefix), old_conn->Endpoint);
384 status = rpcrt4_conn_create_pipe(old_conn, pname);
390 static RPC_STATUS rpcrt4_ncalrpc_handoff(RpcConnection *old_conn, RpcConnection *new_conn)
394 static const char prefix[] = "\\\\.\\pipe\\lrpc\\";
396 TRACE("%s\n", old_conn->Endpoint);
398 rpcrt4_conn_np_handoff((RpcConnection_np *)old_conn, (RpcConnection_np *)new_conn);
400 pname = I_RpcAllocate(strlen(prefix) + strlen(old_conn->Endpoint) + 1);
401 strcat(strcpy(pname, prefix), old_conn->Endpoint);
402 status = rpcrt4_conn_create_pipe(old_conn, pname);
408 static int rpcrt4_conn_np_read(RpcConnection *Connection,
409 void *buffer, unsigned int count)
411 RpcConnection_np *npc = (RpcConnection_np *) Connection;
414 unsigned int bytes_left = count;
419 ret = ReadFile(npc->pipe, buf, bytes_left, &bytes_read, NULL);
420 if (!ret && GetLastError() == ERROR_MORE_DATA)
422 if (!ret || !bytes_read)
424 bytes_left -= bytes_read;
427 return ret ? count : -1;
430 static int rpcrt4_conn_np_write(RpcConnection *Connection,
431 const void *buffer, unsigned int count)
433 RpcConnection_np *npc = (RpcConnection_np *) Connection;
434 const char *buf = buffer;
436 unsigned int bytes_left = count;
441 ret = WriteFile(npc->pipe, buf, bytes_left, &bytes_written, NULL);
442 if (!ret || !bytes_written)
444 bytes_left -= bytes_written;
445 buf += bytes_written;
447 return ret ? count : -1;
450 static int rpcrt4_conn_np_close(RpcConnection *Connection)
452 RpcConnection_np *npc = (RpcConnection_np *) Connection;
454 FlushFileBuffers(npc->pipe);
455 CloseHandle(npc->pipe);
458 if (npc->ovl.hEvent) {
459 CloseHandle(npc->ovl.hEvent);
465 static void rpcrt4_conn_np_cancel_call(RpcConnection *Connection)
467 /* FIXME: implement when named pipe writes use overlapped I/O */
470 static int rpcrt4_conn_np_wait_for_incoming_data(RpcConnection *Connection)
472 /* FIXME: implement when named pipe writes use overlapped I/O */
476 static size_t rpcrt4_ncacn_np_get_top_of_tower(unsigned char *tower_data,
477 const char *networkaddr,
478 const char *endpoint)
480 twr_empty_floor_t *smb_floor;
481 twr_empty_floor_t *nb_floor;
483 size_t networkaddr_size;
484 size_t endpoint_size;
486 TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint);
488 networkaddr_size = networkaddr ? strlen(networkaddr) + 1 : 1;
489 endpoint_size = endpoint ? strlen(endpoint) + 1 : 1;
490 size = sizeof(*smb_floor) + endpoint_size + sizeof(*nb_floor) + networkaddr_size;
495 smb_floor = (twr_empty_floor_t *)tower_data;
497 tower_data += sizeof(*smb_floor);
499 smb_floor->count_lhs = sizeof(smb_floor->protid);
500 smb_floor->protid = EPM_PROTOCOL_SMB;
501 smb_floor->count_rhs = endpoint_size;
504 memcpy(tower_data, endpoint, endpoint_size);
507 tower_data += endpoint_size;
509 nb_floor = (twr_empty_floor_t *)tower_data;
511 tower_data += sizeof(*nb_floor);
513 nb_floor->count_lhs = sizeof(nb_floor->protid);
514 nb_floor->protid = EPM_PROTOCOL_NETBIOS;
515 nb_floor->count_rhs = networkaddr_size;
518 memcpy(tower_data, networkaddr, networkaddr_size);
525 static RPC_STATUS rpcrt4_ncacn_np_parse_top_of_tower(const unsigned char *tower_data,
530 const twr_empty_floor_t *smb_floor = (const twr_empty_floor_t *)tower_data;
531 const twr_empty_floor_t *nb_floor;
533 TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint);
535 if (tower_size < sizeof(*smb_floor))
536 return EPT_S_NOT_REGISTERED;
538 tower_data += sizeof(*smb_floor);
539 tower_size -= sizeof(*smb_floor);
541 if ((smb_floor->count_lhs != sizeof(smb_floor->protid)) ||
542 (smb_floor->protid != EPM_PROTOCOL_SMB) ||
543 (smb_floor->count_rhs > tower_size) ||
544 (tower_data[smb_floor->count_rhs - 1] != '\0'))
545 return EPT_S_NOT_REGISTERED;
549 *endpoint = I_RpcAllocate(smb_floor->count_rhs);
551 return RPC_S_OUT_OF_RESOURCES;
552 memcpy(*endpoint, tower_data, smb_floor->count_rhs);
554 tower_data += smb_floor->count_rhs;
555 tower_size -= smb_floor->count_rhs;
557 if (tower_size < sizeof(*nb_floor))
558 return EPT_S_NOT_REGISTERED;
560 nb_floor = (const twr_empty_floor_t *)tower_data;
562 tower_data += sizeof(*nb_floor);
563 tower_size -= sizeof(*nb_floor);
565 if ((nb_floor->count_lhs != sizeof(nb_floor->protid)) ||
566 (nb_floor->protid != EPM_PROTOCOL_NETBIOS) ||
567 (nb_floor->count_rhs > tower_size) ||
568 (tower_data[nb_floor->count_rhs - 1] != '\0'))
569 return EPT_S_NOT_REGISTERED;
573 *networkaddr = I_RpcAllocate(nb_floor->count_rhs);
578 I_RpcFree(*endpoint);
581 return RPC_S_OUT_OF_RESOURCES;
583 memcpy(*networkaddr, tower_data, nb_floor->count_rhs);
589 static RPC_STATUS rpcrt4_conn_np_impersonate_client(RpcConnection *conn)
591 RpcConnection_np *npc = (RpcConnection_np *)conn;
594 TRACE("(%p)\n", conn);
596 if (conn->AuthInfo && SecIsValidHandle(&conn->ctx))
597 return RPCRT4_default_impersonate_client(conn);
599 ret = ImpersonateNamedPipeClient(npc->pipe);
602 DWORD error = GetLastError();
603 WARN("ImpersonateNamedPipeClient failed with error %u\n", error);
606 case ERROR_CANNOT_IMPERSONATE:
607 return RPC_S_NO_CONTEXT_AVAILABLE;
613 static RPC_STATUS rpcrt4_conn_np_revert_to_self(RpcConnection *conn)
617 TRACE("(%p)\n", conn);
619 if (conn->AuthInfo && SecIsValidHandle(&conn->ctx))
620 return RPCRT4_default_revert_to_self(conn);
622 ret = RevertToSelf();
625 WARN("RevertToSelf failed with error %u\n", GetLastError());
626 return RPC_S_NO_CONTEXT_AVAILABLE;
631 typedef struct _RpcServerProtseq_np
633 RpcServerProtseq common;
635 } RpcServerProtseq_np;
637 static RpcServerProtseq *rpcrt4_protseq_np_alloc(void)
639 RpcServerProtseq_np *ps = HeapAlloc(GetProcessHeap(), 0, sizeof(*ps));
641 ps->mgr_event = CreateEventW(NULL, FALSE, FALSE, NULL);
645 static void rpcrt4_protseq_np_signal_state_changed(RpcServerProtseq *protseq)
647 RpcServerProtseq_np *npps = CONTAINING_RECORD(protseq, RpcServerProtseq_np, common);
648 SetEvent(npps->mgr_event);
651 static void *rpcrt4_protseq_np_get_wait_array(RpcServerProtseq *protseq, void *prev_array, unsigned int *count)
653 HANDLE *objs = prev_array;
654 RpcConnection_np *conn;
655 RpcServerProtseq_np *npps = CONTAINING_RECORD(protseq, RpcServerProtseq_np, common);
657 EnterCriticalSection(&protseq->cs);
659 /* open and count connections */
661 conn = CONTAINING_RECORD(protseq->conn, RpcConnection_np, common);
663 rpcrt4_conn_listen_pipe(conn);
664 if (conn->ovl.hEvent)
666 conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_np, common);
669 /* make array of connections */
671 objs = HeapReAlloc(GetProcessHeap(), 0, objs, *count*sizeof(HANDLE));
673 objs = HeapAlloc(GetProcessHeap(), 0, *count*sizeof(HANDLE));
676 ERR("couldn't allocate objs\n");
677 LeaveCriticalSection(&protseq->cs);
681 objs[0] = npps->mgr_event;
683 conn = CONTAINING_RECORD(protseq->conn, RpcConnection_np, common);
685 if ((objs[*count] = conn->ovl.hEvent))
687 conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_np, common);
689 LeaveCriticalSection(&protseq->cs);
693 static void rpcrt4_protseq_np_free_wait_array(RpcServerProtseq *protseq, void *array)
695 HeapFree(GetProcessHeap(), 0, array);
698 static int rpcrt4_protseq_np_wait_for_new_connection(RpcServerProtseq *protseq, unsigned int count, void *wait_array)
701 HANDLE *objs = wait_array;
703 RpcConnection *cconn;
704 RpcConnection_np *conn;
711 /* an alertable wait isn't strictly necessary, but due to our
712 * overlapped I/O implementation in Wine we need to free some memory
713 * by the file user APC being called, even if no completion routine was
714 * specified at the time of starting the async operation */
715 res = WaitForMultipleObjectsEx(count, objs, FALSE, INFINITE, TRUE);
716 } while (res == WAIT_IO_COMPLETION);
718 if (res == WAIT_OBJECT_0)
720 else if (res == WAIT_FAILED)
722 ERR("wait failed with error %d\n", GetLastError());
727 b_handle = objs[res - WAIT_OBJECT_0];
728 /* find which connection got a RPC */
729 EnterCriticalSection(&protseq->cs);
730 conn = CONTAINING_RECORD(protseq->conn, RpcConnection_np, common);
732 if (b_handle == conn->ovl.hEvent) break;
733 conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_np, common);
737 RPCRT4_SpawnConnection(&cconn, &conn->common);
739 ERR("failed to locate connection for handle %p\n", b_handle);
740 LeaveCriticalSection(&protseq->cs);
743 RPCRT4_new_client(cconn);
750 static size_t rpcrt4_ncalrpc_get_top_of_tower(unsigned char *tower_data,
751 const char *networkaddr,
752 const char *endpoint)
754 twr_empty_floor_t *pipe_floor;
756 size_t endpoint_size;
758 TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint);
760 endpoint_size = strlen(endpoint) + 1;
761 size = sizeof(*pipe_floor) + endpoint_size;
766 pipe_floor = (twr_empty_floor_t *)tower_data;
768 tower_data += sizeof(*pipe_floor);
770 pipe_floor->count_lhs = sizeof(pipe_floor->protid);
771 pipe_floor->protid = EPM_PROTOCOL_PIPE;
772 pipe_floor->count_rhs = endpoint_size;
774 memcpy(tower_data, endpoint, endpoint_size);
779 static RPC_STATUS rpcrt4_ncalrpc_parse_top_of_tower(const unsigned char *tower_data,
784 const twr_empty_floor_t *pipe_floor = (const twr_empty_floor_t *)tower_data;
786 TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint);
788 if (tower_size < sizeof(*pipe_floor))
789 return EPT_S_NOT_REGISTERED;
791 tower_data += sizeof(*pipe_floor);
792 tower_size -= sizeof(*pipe_floor);
794 if ((pipe_floor->count_lhs != sizeof(pipe_floor->protid)) ||
795 (pipe_floor->protid != EPM_PROTOCOL_PIPE) ||
796 (pipe_floor->count_rhs > tower_size) ||
797 (tower_data[pipe_floor->count_rhs - 1] != '\0'))
798 return EPT_S_NOT_REGISTERED;
805 *endpoint = I_RpcAllocate(pipe_floor->count_rhs);
807 return RPC_S_OUT_OF_RESOURCES;
808 memcpy(*endpoint, tower_data, pipe_floor->count_rhs);
814 static BOOL rpcrt4_ncalrpc_is_authorized(RpcConnection *conn)
819 static RPC_STATUS rpcrt4_ncalrpc_authorize(RpcConnection *conn, BOOL first_time,
820 unsigned char *in_buffer,
821 unsigned int in_size,
822 unsigned char *out_buffer,
823 unsigned int *out_size)
825 /* since this protocol is local to the machine there is no need to
826 * authenticate the caller */
831 static RPC_STATUS rpcrt4_ncalrpc_secure_packet(RpcConnection *conn,
832 enum secure_packet_direction dir,
833 RpcPktHdr *hdr, unsigned int hdr_size,
834 unsigned char *stub_data, unsigned int stub_data_size,
835 RpcAuthVerifier *auth_hdr,
836 unsigned char *auth_value, unsigned int auth_value_size)
838 /* since this protocol is local to the machine there is no need to secure
843 static RPC_STATUS rpcrt4_ncalrpc_inquire_auth_client(
844 RpcConnection *conn, RPC_AUTHZ_HANDLE *privs, RPC_WSTR *server_princ_name,
845 ULONG *authn_level, ULONG *authn_svc, ULONG *authz_svc, ULONG flags)
847 TRACE("(%p, %p, %p, %p, %p, %p, 0x%x)\n", conn, privs,
848 server_princ_name, authn_level, authn_svc, authz_svc, flags);
852 FIXME("privs not implemented\n");
855 if (server_princ_name)
857 FIXME("server_princ_name not implemented\n");
858 *server_princ_name = NULL;
860 if (authn_level) *authn_level = RPC_C_AUTHN_LEVEL_PKT_PRIVACY;
861 if (authn_svc) *authn_svc = RPC_C_AUTHN_WINNT;
864 FIXME("authorization service not implemented\n");
865 *authz_svc = RPC_C_AUTHZ_NONE;
868 FIXME("flags 0x%x not implemented\n", flags);
873 /**** ncacn_ip_tcp support ****/
875 static size_t rpcrt4_ip_tcp_get_top_of_tower(unsigned char *tower_data,
876 const char *networkaddr,
877 unsigned char tcp_protid,
878 const char *endpoint)
880 twr_tcp_floor_t *tcp_floor;
881 twr_ipv4_floor_t *ipv4_floor;
883 struct addrinfo hints;
885 size_t size = sizeof(*tcp_floor) + sizeof(*ipv4_floor);
887 TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint);
892 tcp_floor = (twr_tcp_floor_t *)tower_data;
893 tower_data += sizeof(*tcp_floor);
895 ipv4_floor = (twr_ipv4_floor_t *)tower_data;
897 tcp_floor->count_lhs = sizeof(tcp_floor->protid);
898 tcp_floor->protid = tcp_protid;
899 tcp_floor->count_rhs = sizeof(tcp_floor->port);
901 ipv4_floor->count_lhs = sizeof(ipv4_floor->protid);
902 ipv4_floor->protid = EPM_PROTOCOL_IP;
903 ipv4_floor->count_rhs = sizeof(ipv4_floor->ipv4addr);
905 hints.ai_flags = AI_NUMERICHOST;
906 /* FIXME: only support IPv4 at the moment. how is IPv6 represented by the EPM? */
907 hints.ai_family = PF_INET;
908 hints.ai_socktype = SOCK_STREAM;
909 hints.ai_protocol = IPPROTO_TCP;
910 hints.ai_addrlen = 0;
911 hints.ai_addr = NULL;
912 hints.ai_canonname = NULL;
913 hints.ai_next = NULL;
915 ret = getaddrinfo(networkaddr, endpoint, &hints, &ai);
918 ret = getaddrinfo("0.0.0.0", endpoint, &hints, &ai);
921 ERR("getaddrinfo failed: %s\n", gai_strerror(ret));
926 if (ai->ai_family == PF_INET)
928 const struct sockaddr_in *sin = (const struct sockaddr_in *)ai->ai_addr;
929 tcp_floor->port = sin->sin_port;
930 ipv4_floor->ipv4addr = sin->sin_addr.s_addr;
934 ERR("unexpected protocol family %d\n", ai->ai_family);
943 static RPC_STATUS rpcrt4_ip_tcp_parse_top_of_tower(const unsigned char *tower_data,
946 unsigned char tcp_protid,
949 const twr_tcp_floor_t *tcp_floor = (const twr_tcp_floor_t *)tower_data;
950 const twr_ipv4_floor_t *ipv4_floor;
951 struct in_addr in_addr;
953 TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint);
955 if (tower_size < sizeof(*tcp_floor))
956 return EPT_S_NOT_REGISTERED;
958 tower_data += sizeof(*tcp_floor);
959 tower_size -= sizeof(*tcp_floor);
961 if (tower_size < sizeof(*ipv4_floor))
962 return EPT_S_NOT_REGISTERED;
964 ipv4_floor = (const twr_ipv4_floor_t *)tower_data;
966 if ((tcp_floor->count_lhs != sizeof(tcp_floor->protid)) ||
967 (tcp_floor->protid != tcp_protid) ||
968 (tcp_floor->count_rhs != sizeof(tcp_floor->port)) ||
969 (ipv4_floor->count_lhs != sizeof(ipv4_floor->protid)) ||
970 (ipv4_floor->protid != EPM_PROTOCOL_IP) ||
971 (ipv4_floor->count_rhs != sizeof(ipv4_floor->ipv4addr)))
972 return EPT_S_NOT_REGISTERED;
976 *endpoint = I_RpcAllocate(6 /* sizeof("65535") + 1 */);
978 return RPC_S_OUT_OF_RESOURCES;
979 sprintf(*endpoint, "%u", ntohs(tcp_floor->port));
984 *networkaddr = I_RpcAllocate(INET_ADDRSTRLEN);
989 I_RpcFree(*endpoint);
992 return RPC_S_OUT_OF_RESOURCES;
994 in_addr.s_addr = ipv4_floor->ipv4addr;
995 if (!inet_ntop(AF_INET, &in_addr, *networkaddr, INET_ADDRSTRLEN))
997 ERR("inet_ntop: %s\n", strerror(errno));
998 I_RpcFree(*networkaddr);
1002 I_RpcFree(*endpoint);
1005 return EPT_S_NOT_REGISTERED;
1012 typedef struct _RpcConnection_tcp
1014 RpcConnection common;
1016 #ifdef HAVE_SOCKETPAIR
1020 HANDLE cancel_event;
1022 } RpcConnection_tcp;
1024 #ifdef HAVE_SOCKETPAIR
1026 static BOOL rpcrt4_sock_wait_init(RpcConnection_tcp *tcpc)
1028 if (socketpair(PF_UNIX, SOCK_STREAM, 0, tcpc->cancel_fds) < 0)
1030 ERR("socketpair() failed: %s\n", strerror(errno));
1036 static BOOL rpcrt4_sock_wait_for_recv(RpcConnection_tcp *tcpc)
1038 struct pollfd pfds[2];
1039 pfds[0].fd = tcpc->sock;
1040 pfds[0].events = POLLIN;
1041 pfds[1].fd = tcpc->cancel_fds[0];
1042 pfds[1].events = POLLIN;
1043 if (poll(pfds, 2, -1 /* infinite */) == -1 && errno != EINTR)
1045 ERR("poll() failed: %s\n", strerror(errno));
1048 if (pfds[1].revents & POLLIN) /* canceled */
1051 read(pfds[1].fd, &dummy, sizeof(dummy));
1057 static BOOL rpcrt4_sock_wait_for_send(RpcConnection_tcp *tcpc)
1060 pfd.fd = tcpc->sock;
1061 pfd.events = POLLOUT;
1062 if (poll(&pfd, 1, -1 /* infinite */) == -1 && errno != EINTR)
1064 ERR("poll() failed: %s\n", strerror(errno));
1070 static void rpcrt4_sock_wait_cancel(RpcConnection_tcp *tcpc)
1074 write(tcpc->cancel_fds[1], &dummy, 1);
1077 static void rpcrt4_sock_wait_destroy(RpcConnection_tcp *tcpc)
1079 close(tcpc->cancel_fds[0]);
1080 close(tcpc->cancel_fds[1]);
1083 #else /* HAVE_SOCKETPAIR */
1085 static BOOL rpcrt4_sock_wait_init(RpcConnection_tcp *tcpc)
1087 static BOOL wsa_inited;
1091 WSAStartup(MAKEWORD(2, 2), &wsadata);
1092 /* Note: WSAStartup can be called more than once so we don't bother with
1093 * making accesses to wsa_inited thread-safe */
1096 tcpc->sock_event = CreateEventW(NULL, FALSE, FALSE, NULL);
1097 tcpc->cancel_event = CreateEventW(NULL, FALSE, FALSE, NULL);
1098 if (!tcpc->sock_event || !tcpc->cancel_event)
1100 ERR("event creation failed\n");
1101 if (tcpc->sock_event) CloseHandle(tcpc->sock_event);
1107 static BOOL rpcrt4_sock_wait_for_recv(RpcConnection_tcp *tcpc)
1109 HANDLE wait_handles[2];
1111 if (WSAEventSelect(tcpc->sock, tcpc->sock_event, FD_READ | FD_CLOSE) == SOCKET_ERROR)
1113 ERR("WSAEventSelect() failed with error %d\n", WSAGetLastError());
1116 wait_handles[0] = tcpc->sock_event;
1117 wait_handles[1] = tcpc->cancel_event;
1118 res = WaitForMultipleObjects(2, wait_handles, FALSE, INFINITE);
1123 case WAIT_OBJECT_0 + 1:
1126 ERR("WaitForMultipleObjects() failed with error %d\n", GetLastError());
1131 static BOOL rpcrt4_sock_wait_for_send(RpcConnection_tcp *tcpc)
1134 if (WSAEventSelect(tcpc->sock, tcpc->sock_event, FD_WRITE | FD_CLOSE) == SOCKET_ERROR)
1136 ERR("WSAEventSelect() failed with error %d\n", WSAGetLastError());
1139 res = WaitForSingleObject(tcpc->sock_event, INFINITE);
1145 ERR("WaitForMultipleObjects() failed with error %d\n", GetLastError());
1150 static void rpcrt4_sock_wait_cancel(RpcConnection_tcp *tcpc)
1152 SetEvent(tcpc->cancel_event);
1155 static void rpcrt4_sock_wait_destroy(RpcConnection_tcp *tcpc)
1157 CloseHandle(tcpc->sock_event);
1158 CloseHandle(tcpc->cancel_event);
1163 static RpcConnection *rpcrt4_conn_tcp_alloc(void)
1165 RpcConnection_tcp *tcpc;
1166 tcpc = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcConnection_tcp));
1170 if (!rpcrt4_sock_wait_init(tcpc))
1172 HeapFree(GetProcessHeap(), 0, tcpc);
1175 return &tcpc->common;
1178 static RPC_STATUS rpcrt4_ncacn_ip_tcp_open(RpcConnection* Connection)
1180 RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
1183 struct addrinfo *ai;
1184 struct addrinfo *ai_cur;
1185 struct addrinfo hints;
1187 TRACE("(%s, %s)\n", Connection->NetworkAddr, Connection->Endpoint);
1189 if (tcpc->sock != -1)
1193 hints.ai_family = PF_UNSPEC;
1194 hints.ai_socktype = SOCK_STREAM;
1195 hints.ai_protocol = IPPROTO_TCP;
1196 hints.ai_addrlen = 0;
1197 hints.ai_addr = NULL;
1198 hints.ai_canonname = NULL;
1199 hints.ai_next = NULL;
1201 ret = getaddrinfo(Connection->NetworkAddr, Connection->Endpoint, &hints, &ai);
1204 ERR("getaddrinfo for %s:%s failed: %s\n", Connection->NetworkAddr,
1205 Connection->Endpoint, gai_strerror(ret));
1206 return RPC_S_SERVER_UNAVAILABLE;
1209 for (ai_cur = ai; ai_cur; ai_cur = ai_cur->ai_next)
1214 if (ai_cur->ai_family != AF_INET && ai_cur->ai_family != AF_INET6)
1216 TRACE("skipping non-IP/IPv6 address family\n");
1224 getnameinfo(ai_cur->ai_addr, ai_cur->ai_addrlen,
1225 host, sizeof(host), service, sizeof(service),
1226 NI_NUMERICHOST | NI_NUMERICSERV);
1227 TRACE("trying %s:%s\n", host, service);
1230 sock = socket(ai_cur->ai_family, ai_cur->ai_socktype, ai_cur->ai_protocol);
1233 WARN("socket() failed: %s\n", strerror(errno));
1237 if (0>connect(sock, ai_cur->ai_addr, ai_cur->ai_addrlen))
1239 WARN("connect() failed: %s\n", strerror(errno));
1244 /* RPC depends on having minimal latency so disable the Nagle algorithm */
1246 setsockopt(sock, SOL_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
1248 ioctlsocket(sock, FIONBIO, &nonblocking);
1253 TRACE("connected\n");
1258 ERR("couldn't connect to %s:%s\n", Connection->NetworkAddr, Connection->Endpoint);
1259 return RPC_S_SERVER_UNAVAILABLE;
1262 static RPC_STATUS rpcrt4_protseq_ncacn_ip_tcp_open_endpoint(RpcServerProtseq *protseq, const char *endpoint)
1264 RPC_STATUS status = RPC_S_CANT_CREATE_ENDPOINT;
1267 struct addrinfo *ai;
1268 struct addrinfo *ai_cur;
1269 struct addrinfo hints;
1270 RpcConnection *first_connection = NULL;
1272 TRACE("(%p, %s)\n", protseq, endpoint);
1274 hints.ai_flags = AI_PASSIVE /* for non-localhost addresses */;
1275 hints.ai_family = PF_UNSPEC;
1276 hints.ai_socktype = SOCK_STREAM;
1277 hints.ai_protocol = IPPROTO_TCP;
1278 hints.ai_addrlen = 0;
1279 hints.ai_addr = NULL;
1280 hints.ai_canonname = NULL;
1281 hints.ai_next = NULL;
1283 ret = getaddrinfo(NULL, endpoint ? endpoint : "0", &hints, &ai);
1286 ERR("getaddrinfo for port %s failed: %s\n", endpoint,
1288 if ((ret == EAI_SERVICE) || (ret == EAI_NONAME))
1289 return RPC_S_INVALID_ENDPOINT_FORMAT;
1290 return RPC_S_CANT_CREATE_ENDPOINT;
1293 for (ai_cur = ai; ai_cur; ai_cur = ai_cur->ai_next)
1295 RpcConnection_tcp *tcpc;
1296 RPC_STATUS create_status;
1297 struct sockaddr_storage sa;
1299 char service[NI_MAXSERV];
1302 if (ai_cur->ai_family != AF_INET && ai_cur->ai_family != AF_INET6)
1304 TRACE("skipping non-IP/IPv6 address family\n");
1311 getnameinfo(ai_cur->ai_addr, ai_cur->ai_addrlen,
1312 host, sizeof(host), service, sizeof(service),
1313 NI_NUMERICHOST | NI_NUMERICSERV);
1314 TRACE("trying %s:%s\n", host, service);
1317 sock = socket(ai_cur->ai_family, ai_cur->ai_socktype, ai_cur->ai_protocol);
1320 WARN("socket() failed: %s\n", strerror(errno));
1321 status = RPC_S_CANT_CREATE_ENDPOINT;
1325 ret = bind(sock, ai_cur->ai_addr, ai_cur->ai_addrlen);
1328 WARN("bind failed: %s\n", strerror(errno));
1330 if (errno == EADDRINUSE)
1331 status = RPC_S_DUPLICATE_ENDPOINT;
1333 status = RPC_S_CANT_CREATE_ENDPOINT;
1337 sa_len = sizeof(sa);
1338 if (getsockname(sock, (struct sockaddr *)&sa, &sa_len))
1340 WARN("getsockname() failed: %s\n", strerror(errno));
1341 status = RPC_S_CANT_CREATE_ENDPOINT;
1345 ret = getnameinfo((struct sockaddr *)&sa, sa_len,
1346 NULL, 0, service, sizeof(service),
1350 WARN("getnameinfo failed: %s\n", gai_strerror(ret));
1351 status = RPC_S_CANT_CREATE_ENDPOINT;
1355 create_status = RPCRT4_CreateConnection((RpcConnection **)&tcpc, TRUE,
1356 protseq->Protseq, NULL,
1357 service, NULL, NULL, NULL);
1358 if (create_status != RPC_S_OK)
1361 status = create_status;
1366 ret = listen(sock, protseq->MaxCalls);
1369 WARN("listen failed: %s\n", strerror(errno));
1370 RPCRT4_DestroyConnection(&tcpc->common);
1371 status = RPC_S_OUT_OF_RESOURCES;
1374 /* need a non-blocking socket, otherwise accept() has a potential
1375 * race-condition (poll() says it is readable, connection drops,
1376 * and accept() blocks until the next connection comes...)
1379 ret = ioctlsocket(sock, FIONBIO, &nonblocking);
1382 WARN("couldn't make socket non-blocking, error %d\n", ret);
1383 RPCRT4_DestroyConnection(&tcpc->common);
1384 status = RPC_S_OUT_OF_RESOURCES;
1388 tcpc->common.Next = first_connection;
1389 first_connection = &tcpc->common;
1391 /* since IPv4 and IPv6 share the same port space, we only need one
1392 * successful bind to listen for both */
1398 /* if at least one connection was created for an endpoint then
1400 if (first_connection)
1402 RpcConnection *conn;
1404 /* find last element in list */
1405 for (conn = first_connection; conn->Next; conn = conn->Next)
1408 EnterCriticalSection(&protseq->cs);
1409 conn->Next = protseq->conn;
1410 protseq->conn = first_connection;
1411 LeaveCriticalSection(&protseq->cs);
1413 TRACE("listening on %s\n", endpoint);
1417 ERR("couldn't listen on port %s\n", endpoint);
1421 static RPC_STATUS rpcrt4_conn_tcp_handoff(RpcConnection *old_conn, RpcConnection *new_conn)
1424 struct sockaddr_in address;
1426 RpcConnection_tcp *server = (RpcConnection_tcp*) old_conn;
1427 RpcConnection_tcp *client = (RpcConnection_tcp*) new_conn;
1430 addrsize = sizeof(address);
1431 ret = accept(server->sock, (struct sockaddr*) &address, &addrsize);
1434 ERR("Failed to accept a TCP connection: error %d\n", ret);
1435 return RPC_S_OUT_OF_RESOURCES;
1438 ioctlsocket(ret, FIONBIO, &nonblocking);
1440 TRACE("Accepted a new TCP connection\n");
1444 static int rpcrt4_conn_tcp_read(RpcConnection *Connection,
1445 void *buffer, unsigned int count)
1447 RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
1449 while (bytes_read != count)
1451 int r = recv(tcpc->sock, (char *)buffer + bytes_read, count - bytes_read, 0);
1456 else if (errno != EAGAIN)
1458 WARN("recv() failed: %s\n", strerror(errno));
1463 if (!rpcrt4_sock_wait_for_recv(tcpc))
1467 TRACE("%d %p %u -> %d\n", tcpc->sock, buffer, count, bytes_read);
1471 static int rpcrt4_conn_tcp_write(RpcConnection *Connection,
1472 const void *buffer, unsigned int count)
1474 RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
1475 int bytes_written = 0;
1476 while (bytes_written != count)
1478 int r = send(tcpc->sock, (const char *)buffer + bytes_written, count - bytes_written, 0);
1481 else if (errno != EAGAIN)
1485 if (!rpcrt4_sock_wait_for_send(tcpc))
1489 TRACE("%d %p %u -> %d\n", tcpc->sock, buffer, count, bytes_written);
1490 return bytes_written;
1493 static int rpcrt4_conn_tcp_close(RpcConnection *Connection)
1495 RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
1497 TRACE("%d\n", tcpc->sock);
1499 if (tcpc->sock != -1)
1500 closesocket(tcpc->sock);
1502 rpcrt4_sock_wait_destroy(tcpc);
1506 static void rpcrt4_conn_tcp_cancel_call(RpcConnection *Connection)
1508 RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
1509 TRACE("%p\n", Connection);
1510 rpcrt4_sock_wait_cancel(tcpc);
1513 static int rpcrt4_conn_tcp_wait_for_incoming_data(RpcConnection *Connection)
1515 RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
1517 TRACE("%p\n", Connection);
1519 if (!rpcrt4_sock_wait_for_recv(tcpc))
1524 static size_t rpcrt4_ncacn_ip_tcp_get_top_of_tower(unsigned char *tower_data,
1525 const char *networkaddr,
1526 const char *endpoint)
1528 return rpcrt4_ip_tcp_get_top_of_tower(tower_data, networkaddr,
1529 EPM_PROTOCOL_TCP, endpoint);
1532 #ifdef HAVE_SOCKETPAIR
1534 typedef struct _RpcServerProtseq_sock
1536 RpcServerProtseq common;
1539 } RpcServerProtseq_sock;
1541 static RpcServerProtseq *rpcrt4_protseq_sock_alloc(void)
1543 RpcServerProtseq_sock *ps = HeapAlloc(GetProcessHeap(), 0, sizeof(*ps));
1547 if (!socketpair(PF_UNIX, SOCK_DGRAM, 0, fds))
1549 fcntl(fds[0], F_SETFL, O_NONBLOCK);
1550 fcntl(fds[1], F_SETFL, O_NONBLOCK);
1551 ps->mgr_event_rcv = fds[0];
1552 ps->mgr_event_snd = fds[1];
1556 ERR("socketpair failed with error %s\n", strerror(errno));
1557 HeapFree(GetProcessHeap(), 0, ps);
1564 static void rpcrt4_protseq_sock_signal_state_changed(RpcServerProtseq *protseq)
1566 RpcServerProtseq_sock *sockps = CONTAINING_RECORD(protseq, RpcServerProtseq_sock, common);
1568 write(sockps->mgr_event_snd, &dummy, sizeof(dummy));
1571 static void *rpcrt4_protseq_sock_get_wait_array(RpcServerProtseq *protseq, void *prev_array, unsigned int *count)
1573 struct pollfd *poll_info = prev_array;
1574 RpcConnection_tcp *conn;
1575 RpcServerProtseq_sock *sockps = CONTAINING_RECORD(protseq, RpcServerProtseq_sock, common);
1577 EnterCriticalSection(&protseq->cs);
1579 /* open and count connections */
1581 conn = (RpcConnection_tcp *)protseq->conn;
1583 if (conn->sock != -1)
1585 conn = (RpcConnection_tcp *)conn->common.Next;
1588 /* make array of connections */
1590 poll_info = HeapReAlloc(GetProcessHeap(), 0, poll_info, *count*sizeof(*poll_info));
1592 poll_info = HeapAlloc(GetProcessHeap(), 0, *count*sizeof(*poll_info));
1595 ERR("couldn't allocate poll_info\n");
1596 LeaveCriticalSection(&protseq->cs);
1600 poll_info[0].fd = sockps->mgr_event_rcv;
1601 poll_info[0].events = POLLIN;
1603 conn = CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common);
1605 if (conn->sock != -1)
1607 poll_info[*count].fd = conn->sock;
1608 poll_info[*count].events = POLLIN;
1611 conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common);
1613 LeaveCriticalSection(&protseq->cs);
1617 static void rpcrt4_protseq_sock_free_wait_array(RpcServerProtseq *protseq, void *array)
1619 HeapFree(GetProcessHeap(), 0, array);
1622 static int rpcrt4_protseq_sock_wait_for_new_connection(RpcServerProtseq *protseq, unsigned int count, void *wait_array)
1624 struct pollfd *poll_info = wait_array;
1627 RpcConnection *cconn;
1628 RpcConnection_tcp *conn;
1633 ret = poll(poll_info, count, -1);
1636 ERR("poll failed with error %d\n", ret);
1640 for (i = 0; i < count; i++)
1641 if (poll_info[i].revents & POLLIN)
1643 /* RPC server event */
1647 read(poll_info[0].fd, &dummy, sizeof(dummy));
1651 /* find which connection got a RPC */
1652 EnterCriticalSection(&protseq->cs);
1653 conn = CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common);
1655 if (poll_info[i].fd == conn->sock) break;
1656 conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common);
1660 RPCRT4_SpawnConnection(&cconn, &conn->common);
1662 ERR("failed to locate connection for fd %d\n", poll_info[i].fd);
1663 LeaveCriticalSection(&protseq->cs);
1665 RPCRT4_new_client(cconn);
1673 #else /* HAVE_SOCKETPAIR */
1675 typedef struct _RpcServerProtseq_sock
1677 RpcServerProtseq common;
1679 } RpcServerProtseq_sock;
1681 static RpcServerProtseq *rpcrt4_protseq_sock_alloc(void)
1683 RpcServerProtseq_sock *ps = HeapAlloc(GetProcessHeap(), 0, sizeof(*ps));
1686 static BOOL wsa_inited;
1690 WSAStartup(MAKEWORD(2, 2), &wsadata);
1691 /* Note: WSAStartup can be called more than once so we don't bother with
1692 * making accesses to wsa_inited thread-safe */
1695 ps->mgr_event = CreateEventW(NULL, FALSE, FALSE, NULL);
1700 static void rpcrt4_protseq_sock_signal_state_changed(RpcServerProtseq *protseq)
1702 RpcServerProtseq_sock *sockps = CONTAINING_RECORD(protseq, RpcServerProtseq_sock, common);
1703 SetEvent(sockps->mgr_event);
1706 static void *rpcrt4_protseq_sock_get_wait_array(RpcServerProtseq *protseq, void *prev_array, unsigned int *count)
1708 HANDLE *objs = prev_array;
1709 RpcConnection_tcp *conn;
1710 RpcServerProtseq_sock *sockps = CONTAINING_RECORD(protseq, RpcServerProtseq_sock, common);
1712 EnterCriticalSection(&protseq->cs);
1714 /* open and count connections */
1716 conn = CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common);
1719 if (conn->sock != -1)
1721 conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common);
1724 /* make array of connections */
1726 objs = HeapReAlloc(GetProcessHeap(), 0, objs, *count*sizeof(HANDLE));
1728 objs = HeapAlloc(GetProcessHeap(), 0, *count*sizeof(HANDLE));
1731 ERR("couldn't allocate objs\n");
1732 LeaveCriticalSection(&protseq->cs);
1736 objs[0] = sockps->mgr_event;
1738 conn = CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common);
1741 if (conn->sock != -1)
1743 int res = WSAEventSelect(conn->sock, conn->sock_event, FD_ACCEPT);
1744 if (res == SOCKET_ERROR)
1745 ERR("WSAEventSelect() failed with error %d\n", WSAGetLastError());
1748 objs[*count] = conn->sock_event;
1752 conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common);
1754 LeaveCriticalSection(&protseq->cs);
1758 static void rpcrt4_protseq_sock_free_wait_array(RpcServerProtseq *protseq, void *array)
1760 HeapFree(GetProcessHeap(), 0, array);
1763 static int rpcrt4_protseq_sock_wait_for_new_connection(RpcServerProtseq *protseq, unsigned int count, void *wait_array)
1766 HANDLE *objs = wait_array;
1768 RpcConnection *cconn;
1769 RpcConnection_tcp *conn;
1776 /* an alertable wait isn't strictly necessary, but due to our
1777 * overlapped I/O implementation in Wine we need to free some memory
1778 * by the file user APC being called, even if no completion routine was
1779 * specified at the time of starting the async operation */
1780 res = WaitForMultipleObjectsEx(count, objs, FALSE, INFINITE, TRUE);
1781 } while (res == WAIT_IO_COMPLETION);
1783 if (res == WAIT_OBJECT_0)
1785 else if (res == WAIT_FAILED)
1787 ERR("wait failed with error %d\n", GetLastError());
1792 b_handle = objs[res - WAIT_OBJECT_0];
1793 /* find which connection got a RPC */
1794 EnterCriticalSection(&protseq->cs);
1795 conn = CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common);
1798 if (b_handle == conn->sock_event) break;
1799 conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common);
1803 RPCRT4_SpawnConnection(&cconn, &conn->common);
1805 ERR("failed to locate connection for handle %p\n", b_handle);
1806 LeaveCriticalSection(&protseq->cs);
1809 RPCRT4_new_client(cconn);
1816 #endif /* HAVE_SOCKETPAIR */
1818 static RPC_STATUS rpcrt4_ncacn_ip_tcp_parse_top_of_tower(const unsigned char *tower_data,
1823 return rpcrt4_ip_tcp_parse_top_of_tower(tower_data, tower_size,
1824 networkaddr, EPM_PROTOCOL_TCP,
1828 /**** ncacn_http support ****/
1830 /* 60 seconds is the period native uses */
1831 #define HTTP_IDLE_TIME 60000
1833 /* reference counted to avoid a race between a cancelled call's connection
1834 * being destroyed and the asynchronous InternetReadFileEx call being
1836 typedef struct _RpcHttpAsyncData
1839 HANDLE completion_event;
1840 INTERNET_BUFFERSA inet_buffers;
1841 void *destination_buffer; /* the address that inet_buffers.lpvBuffer will be
1842 * copied into when the call completes */
1843 CRITICAL_SECTION cs;
1846 static ULONG RpcHttpAsyncData_AddRef(RpcHttpAsyncData *data)
1848 return InterlockedIncrement(&data->refs);
1851 static ULONG RpcHttpAsyncData_Release(RpcHttpAsyncData *data)
1853 ULONG refs = InterlockedDecrement(&data->refs);
1856 TRACE("destroying async data %p\n", data);
1857 CloseHandle(data->completion_event);
1858 HeapFree(GetProcessHeap(), 0, data->inet_buffers.lpvBuffer);
1859 DeleteCriticalSection(&data->cs);
1860 HeapFree(GetProcessHeap(), 0, data);
1865 typedef struct _RpcConnection_http
1867 RpcConnection common;
1870 HINTERNET in_request;
1871 HINTERNET out_request;
1872 HANDLE timer_cancelled;
1873 HANDLE cancel_event;
1874 DWORD last_sent_time;
1875 ULONG bytes_received;
1876 ULONG flow_control_mark; /* send a control packet to the server when this many bytes received */
1877 ULONG flow_control_increment; /* number of bytes to increment flow_control_mark by */
1878 UUID connection_uuid;
1881 RpcHttpAsyncData *async_data;
1882 } RpcConnection_http;
1884 static RpcConnection *rpcrt4_ncacn_http_alloc(void)
1886 RpcConnection_http *httpc;
1887 httpc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*httpc));
1888 if (!httpc) return NULL;
1889 httpc->async_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcHttpAsyncData));
1890 if (!httpc->async_data)
1892 HeapFree(GetProcessHeap(), 0, httpc);
1895 TRACE("async data = %p\n", httpc->async_data);
1896 httpc->cancel_event = CreateEventW(NULL, FALSE, FALSE, NULL);
1897 httpc->async_data->refs = 1;
1898 httpc->async_data->inet_buffers.dwStructSize = sizeof(INTERNET_BUFFERSA);
1899 httpc->async_data->inet_buffers.lpvBuffer = NULL;
1900 httpc->async_data->destination_buffer = NULL;
1901 InitializeCriticalSection(&httpc->async_data->cs);
1902 return &httpc->common;
1905 typedef struct _HttpTimerThreadData
1908 DWORD *last_sent_time;
1909 HANDLE timer_cancelled;
1910 } HttpTimerThreadData;
1912 static VOID rpcrt4_http_keep_connection_active_timer_proc(PVOID param, BOOLEAN dummy)
1914 HINTERNET in_request = param;
1915 RpcPktHdr *idle_pkt;
1917 idle_pkt = RPCRT4_BuildHttpHeader(NDR_LOCAL_DATA_REPRESENTATION, 0x0001,
1921 DWORD bytes_written;
1922 InternetWriteFile(in_request, idle_pkt, idle_pkt->common.frag_len, &bytes_written);
1923 RPCRT4_FreeHeader(idle_pkt);
1927 static inline DWORD rpcrt4_http_timer_calc_timeout(DWORD *last_sent_time)
1929 DWORD cur_time = GetTickCount();
1930 DWORD cached_last_sent_time = *last_sent_time;
1931 return HTTP_IDLE_TIME - (cur_time - cached_last_sent_time > HTTP_IDLE_TIME ? 0 : cur_time - cached_last_sent_time);
1934 static DWORD CALLBACK rpcrt4_http_timer_thread(PVOID param)
1936 HttpTimerThreadData *data_in = param;
1937 HttpTimerThreadData data;
1941 HeapFree(GetProcessHeap(), 0, data_in);
1943 for (timeout = HTTP_IDLE_TIME;
1944 WaitForSingleObject(data.timer_cancelled, timeout) == WAIT_TIMEOUT;
1945 timeout = rpcrt4_http_timer_calc_timeout(data.last_sent_time))
1947 /* are we too soon after last send? */
1948 if (GetTickCount() - HTTP_IDLE_TIME < *data.last_sent_time)
1950 rpcrt4_http_keep_connection_active_timer_proc(data.timer_param, TRUE);
1953 CloseHandle(data.timer_cancelled);
1957 static VOID WINAPI rpcrt4_http_internet_callback(
1958 HINTERNET hInternet,
1959 DWORD_PTR dwContext,
1960 DWORD dwInternetStatus,
1961 LPVOID lpvStatusInformation,
1962 DWORD dwStatusInformationLength)
1964 RpcHttpAsyncData *async_data = (RpcHttpAsyncData *)dwContext;
1966 switch (dwInternetStatus)
1968 case INTERNET_STATUS_REQUEST_COMPLETE:
1969 TRACE("INTERNET_STATUS_REQUEST_COMPLETED\n");
1972 if (async_data->inet_buffers.lpvBuffer)
1974 EnterCriticalSection(&async_data->cs);
1975 if (async_data->destination_buffer)
1977 memcpy(async_data->destination_buffer,
1978 async_data->inet_buffers.lpvBuffer,
1979 async_data->inet_buffers.dwBufferLength);
1980 async_data->destination_buffer = NULL;
1982 LeaveCriticalSection(&async_data->cs);
1984 HeapFree(GetProcessHeap(), 0, async_data->inet_buffers.lpvBuffer);
1985 async_data->inet_buffers.lpvBuffer = NULL;
1986 SetEvent(async_data->completion_event);
1987 RpcHttpAsyncData_Release(async_data);
1993 static RPC_STATUS rpcrt4_http_check_response(HINTERNET hor)
2000 WCHAR *status_text = buf;
2004 size = sizeof(status_code);
2005 ret = HttpQueryInfoW(hor, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &status_code, &size, &index);
2007 return GetLastError();
2008 if (status_code < 400)
2012 ret = HttpQueryInfoW(hor, HTTP_QUERY_STATUS_TEXT, status_text, &size, &index);
2013 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
2015 status_text = HeapAlloc(GetProcessHeap(), 0, size);
2016 ret = HttpQueryInfoW(hor, HTTP_QUERY_STATUS_TEXT, status_text, &size, &index);
2019 ERR("server returned: %d %s\n", status_code, ret ? debugstr_w(status_text) : "<status text unavailable>");
2020 if(status_text != buf) HeapFree(GetProcessHeap(), 0, status_text);
2022 if (status_code == HTTP_STATUS_DENIED)
2023 return ERROR_ACCESS_DENIED;
2024 return RPC_S_SERVER_UNAVAILABLE;
2027 static RPC_STATUS rpcrt4_http_internet_connect(RpcConnection_http *httpc)
2029 static const WCHAR wszUserAgent[] = {'M','S','R','P','C',0};
2030 LPWSTR proxy = NULL;
2032 LPWSTR password = NULL;
2033 LPWSTR servername = NULL;
2034 const WCHAR *option;
2035 INTERNET_PORT port = INTERNET_INVALID_PORT_NUMBER; /* use default port */
2037 if (httpc->common.QOS &&
2038 (httpc->common.QOS->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP))
2040 const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_cred = httpc->common.QOS->qos->u.HttpCredentials;
2041 if (http_cred->TransportCredentials)
2044 const SEC_WINNT_AUTH_IDENTITY_W *cred = http_cred->TransportCredentials;
2045 ULONG len = cred->DomainLength + 1 + cred->UserLength;
2046 user = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
2048 return RPC_S_OUT_OF_RESOURCES;
2050 if (cred->DomainLength)
2052 memcpy(p, cred->Domain, cred->DomainLength * sizeof(WCHAR));
2053 p += cred->DomainLength;
2057 memcpy(p, cred->User, cred->UserLength * sizeof(WCHAR));
2058 p[cred->UserLength] = 0;
2060 password = RPCRT4_strndupW(cred->Password, cred->PasswordLength);
2064 for (option = httpc->common.NetworkOptions; option;
2065 option = (strchrW(option, ',') ? strchrW(option, ',')+1 : NULL))
2067 static const WCHAR wszRpcProxy[] = {'R','p','c','P','r','o','x','y','=',0};
2068 static const WCHAR wszHttpProxy[] = {'H','t','t','p','P','r','o','x','y','=',0};
2070 if (!strncmpiW(option, wszRpcProxy, sizeof(wszRpcProxy)/sizeof(wszRpcProxy[0])-1))
2072 const WCHAR *value_start = option + sizeof(wszRpcProxy)/sizeof(wszRpcProxy[0])-1;
2073 const WCHAR *value_end;
2076 value_end = strchrW(option, ',');
2078 value_end = value_start + strlenW(value_start);
2079 for (p = value_start; p < value_end; p++)
2086 TRACE("RpcProxy value is %s\n", debugstr_wn(value_start, value_end-value_start));
2087 servername = RPCRT4_strndupW(value_start, value_end-value_start);
2089 else if (!strncmpiW(option, wszHttpProxy, sizeof(wszHttpProxy)/sizeof(wszHttpProxy[0])-1))
2091 const WCHAR *value_start = option + sizeof(wszHttpProxy)/sizeof(wszHttpProxy[0])-1;
2092 const WCHAR *value_end;
2094 value_end = strchrW(option, ',');
2096 value_end = value_start + strlenW(value_start);
2097 TRACE("HttpProxy value is %s\n", debugstr_wn(value_start, value_end-value_start));
2098 proxy = RPCRT4_strndupW(value_start, value_end-value_start);
2101 FIXME("unhandled option %s\n", debugstr_w(option));
2104 httpc->app_info = InternetOpenW(wszUserAgent, proxy ? INTERNET_OPEN_TYPE_PROXY : INTERNET_OPEN_TYPE_PRECONFIG,
2105 NULL, NULL, INTERNET_FLAG_ASYNC);
2106 if (!httpc->app_info)
2108 HeapFree(GetProcessHeap(), 0, password);
2109 HeapFree(GetProcessHeap(), 0, user);
2110 ERR("InternetOpenW failed with error %d\n", GetLastError());
2111 return RPC_S_SERVER_UNAVAILABLE;
2113 InternetSetStatusCallbackW(httpc->app_info, rpcrt4_http_internet_callback);
2115 /* if no RpcProxy option specified, set the HTTP server address to the
2116 * RPC server address */
2119 servername = HeapAlloc(GetProcessHeap(), 0, (strlen(httpc->common.NetworkAddr) + 1)*sizeof(WCHAR));
2122 HeapFree(GetProcessHeap(), 0, password);
2123 HeapFree(GetProcessHeap(), 0, user);
2124 return RPC_S_OUT_OF_RESOURCES;
2126 MultiByteToWideChar(CP_ACP, 0, httpc->common.NetworkAddr, -1, servername, strlen(httpc->common.NetworkAddr) + 1);
2129 httpc->session = InternetConnectW(httpc->app_info, servername, port, user, password,
2130 INTERNET_SERVICE_HTTP, 0, 0);
2132 HeapFree(GetProcessHeap(), 0, password);
2133 HeapFree(GetProcessHeap(), 0, user);
2134 HeapFree(GetProcessHeap(), 0, servername);
2136 if (!httpc->session)
2138 ERR("InternetConnectW failed with error %d\n", GetLastError());
2139 return RPC_S_SERVER_UNAVAILABLE;
2145 /* prepare the in pipe for use by RPC packets */
2146 static RPC_STATUS rpcrt4_http_prepare_in_pipe(HINTERNET in_request, RpcHttpAsyncData *async_data,
2147 const UUID *connection_uuid,
2148 const UUID *in_pipe_uuid,
2149 const UUID *association_uuid)
2155 INTERNET_BUFFERSW buffers_in;
2156 DWORD bytes_read, bytes_written;
2158 /* prepare in pipe */
2159 ResetEvent(async_data->completion_event);
2160 RpcHttpAsyncData_AddRef(async_data);
2161 ret = HttpSendRequestW(in_request, NULL, 0, NULL, 0);
2164 if (GetLastError() == ERROR_IO_PENDING)
2165 WaitForSingleObject(async_data->completion_event, INFINITE);
2168 RpcHttpAsyncData_Release(async_data);
2169 ERR("HttpSendRequestW failed with error %d\n", GetLastError());
2170 return RPC_S_SERVER_UNAVAILABLE;
2173 status = rpcrt4_http_check_response(in_request);
2174 if (status != RPC_S_OK) return status;
2176 InternetReadFile(in_request, packet, 20, &bytes_read);
2177 /* FIXME: do something with retrieved data */
2179 memset(&buffers_in, 0, sizeof(buffers_in));
2180 buffers_in.dwStructSize = sizeof(buffers_in);
2181 /* FIXME: get this from the registry */
2182 buffers_in.dwBufferTotal = 1024 * 1024 * 1024; /* 1Gb */
2183 ResetEvent(async_data->completion_event);
2184 RpcHttpAsyncData_AddRef(async_data);
2185 ret = HttpSendRequestExW(in_request, &buffers_in, NULL, 0, 0);
2188 if (GetLastError() == ERROR_IO_PENDING)
2189 WaitForSingleObject(async_data->completion_event, INFINITE);
2192 RpcHttpAsyncData_Release(async_data);
2193 ERR("HttpSendRequestExW failed with error %d\n", GetLastError());
2194 return RPC_S_SERVER_UNAVAILABLE;
2198 TRACE("sending HTTP connect header to server\n");
2199 hdr = RPCRT4_BuildHttpConnectHeader(0, FALSE, connection_uuid, in_pipe_uuid, association_uuid);
2200 if (!hdr) return RPC_S_OUT_OF_RESOURCES;
2201 ret = InternetWriteFile(in_request, hdr, hdr->common.frag_len, &bytes_written);
2202 RPCRT4_FreeHeader(hdr);
2205 ERR("InternetWriteFile failed with error %d\n", GetLastError());
2206 return RPC_S_SERVER_UNAVAILABLE;
2212 static RPC_STATUS rpcrt4_http_read_http_packet(HINTERNET request, RpcPktHdr *hdr, BYTE **data)
2216 unsigned short data_len;
2218 ret = InternetReadFile(request, hdr, sizeof(hdr->common), &bytes_read);
2220 return RPC_S_SERVER_UNAVAILABLE;
2221 if (hdr->common.ptype != PKT_HTTP || hdr->common.frag_len < sizeof(hdr->http))
2223 ERR("wrong packet type received %d or wrong frag_len %d\n",
2224 hdr->common.ptype, hdr->common.frag_len);
2225 return RPC_S_PROTOCOL_ERROR;
2228 ret = InternetReadFile(request, &hdr->common + 1, sizeof(hdr->http) - sizeof(hdr->common), &bytes_read);
2230 return RPC_S_SERVER_UNAVAILABLE;
2232 data_len = hdr->common.frag_len - sizeof(hdr->http);
2235 *data = HeapAlloc(GetProcessHeap(), 0, data_len);
2237 return RPC_S_OUT_OF_RESOURCES;
2238 ret = InternetReadFile(request, *data, data_len, &bytes_read);
2241 HeapFree(GetProcessHeap(), 0, *data);
2242 return RPC_S_SERVER_UNAVAILABLE;
2248 if (!RPCRT4_IsValidHttpPacket(hdr, *data, data_len))
2250 ERR("invalid http packet\n");
2251 return RPC_S_PROTOCOL_ERROR;
2257 /* prepare the out pipe for use by RPC packets */
2258 static RPC_STATUS rpcrt4_http_prepare_out_pipe(HINTERNET out_request,
2259 RpcHttpAsyncData *async_data,
2260 const UUID *connection_uuid,
2261 const UUID *out_pipe_uuid,
2262 ULONG *flow_control_increment)
2269 BYTE *data_from_server;
2270 RpcPktHdr pkt_from_server;
2271 ULONG field1, field3;
2273 ResetEvent(async_data->completion_event);
2274 RpcHttpAsyncData_AddRef(async_data);
2275 ret = HttpSendRequestW(out_request, NULL, 0, NULL, 0);
2278 if (GetLastError() == ERROR_IO_PENDING)
2279 WaitForSingleObject(async_data->completion_event, INFINITE);
2282 RpcHttpAsyncData_Release(async_data);
2283 ERR("HttpSendRequestW failed with error %d\n", GetLastError());
2284 return RPC_S_SERVER_UNAVAILABLE;
2287 status = rpcrt4_http_check_response(out_request);
2288 if (status != RPC_S_OK) return status;
2290 InternetReadFile(out_request, packet, 20, &bytes_read);
2291 /* FIXME: do something with retrieved data */
2293 hdr = RPCRT4_BuildHttpConnectHeader(0, TRUE, connection_uuid, out_pipe_uuid, NULL);
2294 if (!hdr) return RPC_S_OUT_OF_RESOURCES;
2295 ResetEvent(async_data->completion_event);
2296 RpcHttpAsyncData_AddRef(async_data);
2297 ret = HttpSendRequestW(out_request, NULL, 0, hdr, hdr->common.frag_len);
2300 if (GetLastError() == ERROR_IO_PENDING)
2301 WaitForSingleObject(async_data->completion_event, INFINITE);
2304 RpcHttpAsyncData_Release(async_data);
2305 ERR("HttpSendRequestW failed with error %d\n", GetLastError());
2306 RPCRT4_FreeHeader(hdr);
2307 return RPC_S_SERVER_UNAVAILABLE;
2310 RPCRT4_FreeHeader(hdr);
2311 status = rpcrt4_http_check_response(out_request);
2312 if (status != RPC_S_OK) return status;
2314 status = rpcrt4_http_read_http_packet(out_request, &pkt_from_server,
2316 if (status != RPC_S_OK) return status;
2317 status = RPCRT4_ParseHttpPrepareHeader1(&pkt_from_server, data_from_server,
2319 HeapFree(GetProcessHeap(), 0, data_from_server);
2320 if (status != RPC_S_OK) return status;
2321 TRACE("received (%d) from first prepare header\n", field1);
2323 status = rpcrt4_http_read_http_packet(out_request, &pkt_from_server,
2325 if (status != RPC_S_OK) return status;
2326 status = RPCRT4_ParseHttpPrepareHeader2(&pkt_from_server, data_from_server,
2327 &field1, flow_control_increment,
2329 HeapFree(GetProcessHeap(), 0, data_from_server);
2330 if (status != RPC_S_OK) return status;
2331 TRACE("received (0x%08x 0x%08x %d) from second prepare header\n", field1, *flow_control_increment, field3);
2336 static RPC_STATUS rpcrt4_ncacn_http_open(RpcConnection* Connection)
2338 RpcConnection_http *httpc = (RpcConnection_http *)Connection;
2339 static const WCHAR wszVerbIn[] = {'R','P','C','_','I','N','_','D','A','T','A',0};
2340 static const WCHAR wszVerbOut[] = {'R','P','C','_','O','U','T','_','D','A','T','A',0};
2341 static const WCHAR wszRpcProxyPrefix[] = {'/','r','p','c','/','r','p','c','p','r','o','x','y','.','d','l','l','?',0};
2342 static const WCHAR wszColon[] = {':',0};
2343 static const WCHAR wszAcceptType[] = {'a','p','p','l','i','c','a','t','i','o','n','/','r','p','c',0};
2344 LPCWSTR wszAcceptTypes[] = { wszAcceptType, NULL };
2348 HttpTimerThreadData *timer_data;
2351 TRACE("(%s, %s)\n", Connection->NetworkAddr, Connection->Endpoint);
2353 if (Connection->server)
2355 ERR("ncacn_http servers not supported yet\n");
2356 return RPC_S_SERVER_UNAVAILABLE;
2359 if (httpc->in_request)
2362 httpc->async_data->completion_event = CreateEventW(NULL, FALSE, FALSE, NULL);
2364 status = UuidCreate(&httpc->connection_uuid);
2365 status = UuidCreate(&httpc->in_pipe_uuid);
2366 status = UuidCreate(&httpc->out_pipe_uuid);
2368 status = rpcrt4_http_internet_connect(httpc);
2369 if (status != RPC_S_OK)
2372 url = HeapAlloc(GetProcessHeap(), 0, sizeof(wszRpcProxyPrefix) + (strlen(Connection->NetworkAddr) + 1 + strlen(Connection->Endpoint))*sizeof(WCHAR));
2374 return RPC_S_OUT_OF_MEMORY;
2375 memcpy(url, wszRpcProxyPrefix, sizeof(wszRpcProxyPrefix));
2376 MultiByteToWideChar(CP_ACP, 0, Connection->NetworkAddr, -1, url+sizeof(wszRpcProxyPrefix)/sizeof(wszRpcProxyPrefix[0])-1, strlen(Connection->NetworkAddr)+1);
2377 strcatW(url, wszColon);
2378 MultiByteToWideChar(CP_ACP, 0, Connection->Endpoint, -1, url+strlenW(url), strlen(Connection->Endpoint)+1);
2380 secure = httpc->common.QOS &&
2381 (httpc->common.QOS->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP) &&
2382 (httpc->common.QOS->qos->u.HttpCredentials->Flags & RPC_C_HTTP_FLAG_USE_SSL);
2384 httpc->in_request = HttpOpenRequestW(httpc->session, wszVerbIn, url, NULL, NULL,
2386 (secure ? INTERNET_FLAG_SECURE : 0)|INTERNET_FLAG_KEEP_CONNECTION|INTERNET_FLAG_PRAGMA_NOCACHE,
2387 (DWORD_PTR)httpc->async_data);
2388 if (!httpc->in_request)
2390 ERR("HttpOpenRequestW failed with error %d\n", GetLastError());
2391 return RPC_S_SERVER_UNAVAILABLE;
2393 httpc->out_request = HttpOpenRequestW(httpc->session, wszVerbOut, url, NULL, NULL,
2395 (secure ? INTERNET_FLAG_SECURE : 0)|INTERNET_FLAG_KEEP_CONNECTION|INTERNET_FLAG_PRAGMA_NOCACHE,
2396 (DWORD_PTR)httpc->async_data);
2397 if (!httpc->out_request)
2399 ERR("HttpOpenRequestW failed with error %d\n", GetLastError());
2400 return RPC_S_SERVER_UNAVAILABLE;
2403 status = rpcrt4_http_prepare_in_pipe(httpc->in_request,
2405 &httpc->connection_uuid,
2406 &httpc->in_pipe_uuid,
2407 &Connection->assoc->http_uuid);
2408 if (status != RPC_S_OK)
2411 status = rpcrt4_http_prepare_out_pipe(httpc->out_request,
2413 &httpc->connection_uuid,
2414 &httpc->out_pipe_uuid,
2415 &httpc->flow_control_increment);
2416 if (status != RPC_S_OK)
2419 httpc->flow_control_mark = httpc->flow_control_increment / 2;
2420 httpc->last_sent_time = GetTickCount();
2421 httpc->timer_cancelled = CreateEventW(NULL, FALSE, FALSE, NULL);
2423 timer_data = HeapAlloc(GetProcessHeap(), 0, sizeof(*timer_data));
2425 return ERROR_OUTOFMEMORY;
2426 timer_data->timer_param = httpc->in_request;
2427 timer_data->last_sent_time = &httpc->last_sent_time;
2428 timer_data->timer_cancelled = httpc->timer_cancelled;
2429 /* FIXME: should use CreateTimerQueueTimer when implemented */
2430 thread = CreateThread(NULL, 0, rpcrt4_http_timer_thread, timer_data, 0, NULL);
2433 HeapFree(GetProcessHeap(), 0, timer_data);
2434 return GetLastError();
2436 CloseHandle(thread);
2441 static RPC_STATUS rpcrt4_ncacn_http_handoff(RpcConnection *old_conn, RpcConnection *new_conn)
2444 return RPC_S_SERVER_UNAVAILABLE;
2447 static int rpcrt4_ncacn_http_read(RpcConnection *Connection,
2448 void *buffer, unsigned int count)
2450 RpcConnection_http *httpc = (RpcConnection_http *) Connection;
2453 unsigned int bytes_left = count;
2455 ResetEvent(httpc->async_data->completion_event);
2458 RpcHttpAsyncData_AddRef(httpc->async_data);
2459 httpc->async_data->inet_buffers.dwBufferLength = bytes_left;
2460 httpc->async_data->inet_buffers.lpvBuffer = HeapAlloc(GetProcessHeap(), 0, bytes_left);
2461 httpc->async_data->destination_buffer = buf;
2462 ret = InternetReadFileExA(httpc->out_request, &httpc->async_data->inet_buffers, IRF_ASYNC, 0);
2465 /* INTERNET_STATUS_REQUEST_COMPLETED won't be sent, so release our
2467 RpcHttpAsyncData_Release(httpc->async_data);
2468 memcpy(buf, httpc->async_data->inet_buffers.lpvBuffer,
2469 httpc->async_data->inet_buffers.dwBufferLength);
2470 HeapFree(GetProcessHeap(), 0, httpc->async_data->inet_buffers.lpvBuffer);
2471 httpc->async_data->inet_buffers.lpvBuffer = NULL;
2472 httpc->async_data->destination_buffer = NULL;
2476 if (GetLastError() == ERROR_IO_PENDING)
2478 HANDLE handles[2] = { httpc->async_data->completion_event, httpc->cancel_event };
2479 DWORD result = WaitForMultipleObjects(2, handles, FALSE, DEFAULT_NCACN_HTTP_TIMEOUT);
2480 if (result == WAIT_OBJECT_0)
2484 TRACE("call cancelled\n");
2485 EnterCriticalSection(&httpc->async_data->cs);
2486 httpc->async_data->destination_buffer = NULL;
2487 LeaveCriticalSection(&httpc->async_data->cs);
2493 HeapFree(GetProcessHeap(), 0, httpc->async_data->inet_buffers.lpvBuffer);
2494 httpc->async_data->inet_buffers.lpvBuffer = NULL;
2495 httpc->async_data->destination_buffer = NULL;
2496 RpcHttpAsyncData_Release(httpc->async_data);
2500 if (!httpc->async_data->inet_buffers.dwBufferLength)
2502 bytes_left -= httpc->async_data->inet_buffers.dwBufferLength;
2503 buf += httpc->async_data->inet_buffers.dwBufferLength;
2505 TRACE("%p %p %u -> %s\n", httpc->out_request, buffer, count, ret ? "TRUE" : "FALSE");
2506 return ret ? count : -1;
2509 static RPC_STATUS rpcrt4_ncacn_http_receive_fragment(RpcConnection *Connection, RpcPktHdr **Header, void **Payload)
2511 RpcConnection_http *httpc = (RpcConnection_http *) Connection;
2515 RpcPktCommonHdr common_hdr;
2519 TRACE("(%p, %p, %p)\n", Connection, Header, Payload);
2522 /* read packet common header */
2523 dwRead = rpcrt4_ncacn_http_read(Connection, &common_hdr, sizeof(common_hdr));
2524 if (dwRead != sizeof(common_hdr)) {
2525 WARN("Short read of header, %d bytes\n", dwRead);
2526 status = RPC_S_PROTOCOL_ERROR;
2529 if (!memcmp(&common_hdr, "HTTP/1.1", sizeof("HTTP/1.1")) ||
2530 !memcmp(&common_hdr, "HTTP/1.0", sizeof("HTTP/1.0")))
2532 FIXME("server returned %s\n", debugstr_a((const char *)&common_hdr));
2533 status = RPC_S_PROTOCOL_ERROR;
2537 status = RPCRT4_ValidateCommonHeader(&common_hdr);
2538 if (status != RPC_S_OK) goto fail;
2540 hdr_length = RPCRT4_GetHeaderSize((RpcPktHdr*)&common_hdr);
2541 if (hdr_length == 0) {
2542 WARN("header length == 0\n");
2543 status = RPC_S_PROTOCOL_ERROR;
2547 *Header = HeapAlloc(GetProcessHeap(), 0, hdr_length);
2550 status = RPC_S_OUT_OF_RESOURCES;
2553 memcpy(*Header, &common_hdr, sizeof(common_hdr));
2555 /* read the rest of packet header */
2556 dwRead = rpcrt4_ncacn_http_read(Connection, &(*Header)->common + 1, hdr_length - sizeof(common_hdr));
2557 if (dwRead != hdr_length - sizeof(common_hdr)) {
2558 WARN("bad header length, %d bytes, hdr_length %d\n", dwRead, hdr_length);
2559 status = RPC_S_PROTOCOL_ERROR;
2563 if (common_hdr.frag_len - hdr_length)
2565 *Payload = HeapAlloc(GetProcessHeap(), 0, common_hdr.frag_len - hdr_length);
2568 status = RPC_S_OUT_OF_RESOURCES;
2572 dwRead = rpcrt4_ncacn_http_read(Connection, *Payload, common_hdr.frag_len - hdr_length);
2573 if (dwRead != common_hdr.frag_len - hdr_length)
2575 WARN("bad data length, %d/%d\n", dwRead, common_hdr.frag_len - hdr_length);
2576 status = RPC_S_PROTOCOL_ERROR;
2583 if ((*Header)->common.ptype == PKT_HTTP)
2585 if (!RPCRT4_IsValidHttpPacket(*Header, *Payload, common_hdr.frag_len - hdr_length))
2587 ERR("invalid http packet of length %d bytes\n", (*Header)->common.frag_len);
2588 status = RPC_S_PROTOCOL_ERROR;
2591 if ((*Header)->http.flags == 0x0001)
2593 TRACE("http idle packet, waiting for real packet\n");
2594 if ((*Header)->http.num_data_items != 0)
2596 ERR("HTTP idle packet should have no data items instead of %d\n", (*Header)->http.num_data_items);
2597 status = RPC_S_PROTOCOL_ERROR;
2601 else if ((*Header)->http.flags == 0x0002)
2603 ULONG bytes_transmitted;
2604 ULONG flow_control_increment;
2606 status = RPCRT4_ParseHttpFlowControlHeader(*Header, *Payload,
2609 &flow_control_increment,
2611 if (status != RPC_S_OK)
2613 TRACE("received http flow control header (0x%x, 0x%x, %s)\n",
2614 bytes_transmitted, flow_control_increment, debugstr_guid(&pipe_uuid));
2615 /* FIXME: do something with parsed data */
2619 FIXME("unrecognised http packet with flags 0x%04x\n", (*Header)->http.flags);
2620 status = RPC_S_PROTOCOL_ERROR;
2623 RPCRT4_FreeHeader(*Header);
2625 HeapFree(GetProcessHeap(), 0, *Payload);
2633 httpc->bytes_received += common_hdr.frag_len;
2635 TRACE("httpc->bytes_received = 0x%x\n", httpc->bytes_received);
2637 if (httpc->bytes_received > httpc->flow_control_mark)
2639 RpcPktHdr *hdr = RPCRT4_BuildHttpFlowControlHeader(httpc->common.server,
2640 httpc->bytes_received,
2641 httpc->flow_control_increment,
2642 &httpc->out_pipe_uuid);
2645 DWORD bytes_written;
2647 TRACE("sending flow control packet at 0x%x\n", httpc->bytes_received);
2648 ret2 = InternetWriteFile(httpc->in_request, hdr, hdr->common.frag_len, &bytes_written);
2649 RPCRT4_FreeHeader(hdr);
2651 httpc->flow_control_mark = httpc->bytes_received + httpc->flow_control_increment / 2;
2656 if (status != RPC_S_OK) {
2657 RPCRT4_FreeHeader(*Header);
2659 HeapFree(GetProcessHeap(), 0, *Payload);
2665 static int rpcrt4_ncacn_http_write(RpcConnection *Connection,
2666 const void *buffer, unsigned int count)
2668 RpcConnection_http *httpc = (RpcConnection_http *) Connection;
2669 DWORD bytes_written;
2672 httpc->last_sent_time = ~0U; /* disable idle packet sending */
2673 ret = InternetWriteFile(httpc->in_request, buffer, count, &bytes_written);
2674 httpc->last_sent_time = GetTickCount();
2675 TRACE("%p %p %u -> %s\n", httpc->in_request, buffer, count, ret ? "TRUE" : "FALSE");
2676 return ret ? bytes_written : -1;
2679 static int rpcrt4_ncacn_http_close(RpcConnection *Connection)
2681 RpcConnection_http *httpc = (RpcConnection_http *) Connection;
2685 SetEvent(httpc->timer_cancelled);
2686 if (httpc->in_request)
2687 InternetCloseHandle(httpc->in_request);
2688 httpc->in_request = NULL;
2689 if (httpc->out_request)
2690 InternetCloseHandle(httpc->out_request);
2691 httpc->out_request = NULL;
2692 if (httpc->app_info)
2693 InternetCloseHandle(httpc->app_info);
2694 httpc->app_info = NULL;
2696 InternetCloseHandle(httpc->session);
2697 httpc->session = NULL;
2698 RpcHttpAsyncData_Release(httpc->async_data);
2699 if (httpc->cancel_event)
2700 CloseHandle(httpc->cancel_event);
2705 static void rpcrt4_ncacn_http_cancel_call(RpcConnection *Connection)
2707 RpcConnection_http *httpc = (RpcConnection_http *) Connection;
2709 SetEvent(httpc->cancel_event);
2712 static int rpcrt4_ncacn_http_wait_for_incoming_data(RpcConnection *Connection)
2715 RpcConnection_http *httpc = (RpcConnection_http *) Connection;
2717 RpcHttpAsyncData_AddRef(httpc->async_data);
2718 ret = InternetQueryDataAvailable(httpc->out_request,
2719 &httpc->async_data->inet_buffers.dwBufferLength, IRF_ASYNC, 0);
2722 /* INTERNET_STATUS_REQUEST_COMPLETED won't be sent, so release our
2724 RpcHttpAsyncData_Release(httpc->async_data);
2728 if (GetLastError() == ERROR_IO_PENDING)
2730 HANDLE handles[2] = { httpc->async_data->completion_event, httpc->cancel_event };
2731 DWORD result = WaitForMultipleObjects(2, handles, FALSE, DEFAULT_NCACN_HTTP_TIMEOUT);
2732 if (result != WAIT_OBJECT_0)
2734 TRACE("call cancelled\n");
2740 RpcHttpAsyncData_Release(httpc->async_data);
2749 static size_t rpcrt4_ncacn_http_get_top_of_tower(unsigned char *tower_data,
2750 const char *networkaddr,
2751 const char *endpoint)
2753 return rpcrt4_ip_tcp_get_top_of_tower(tower_data, networkaddr,
2754 EPM_PROTOCOL_HTTP, endpoint);
2757 static RPC_STATUS rpcrt4_ncacn_http_parse_top_of_tower(const unsigned char *tower_data,
2762 return rpcrt4_ip_tcp_parse_top_of_tower(tower_data, tower_size,
2763 networkaddr, EPM_PROTOCOL_HTTP,
2767 static const struct connection_ops conn_protseq_list[] = {
2769 { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_SMB },
2770 rpcrt4_conn_np_alloc,
2771 rpcrt4_ncacn_np_open,
2772 rpcrt4_ncacn_np_handoff,
2773 rpcrt4_conn_np_read,
2774 rpcrt4_conn_np_write,
2775 rpcrt4_conn_np_close,
2776 rpcrt4_conn_np_cancel_call,
2777 rpcrt4_conn_np_wait_for_incoming_data,
2778 rpcrt4_ncacn_np_get_top_of_tower,
2779 rpcrt4_ncacn_np_parse_top_of_tower,
2781 RPCRT4_default_is_authorized,
2782 RPCRT4_default_authorize,
2783 RPCRT4_default_secure_packet,
2784 rpcrt4_conn_np_impersonate_client,
2785 rpcrt4_conn_np_revert_to_self,
2786 RPCRT4_default_inquire_auth_client,
2789 { EPM_PROTOCOL_NCALRPC, EPM_PROTOCOL_PIPE },
2790 rpcrt4_conn_np_alloc,
2791 rpcrt4_ncalrpc_open,
2792 rpcrt4_ncalrpc_handoff,
2793 rpcrt4_conn_np_read,
2794 rpcrt4_conn_np_write,
2795 rpcrt4_conn_np_close,
2796 rpcrt4_conn_np_cancel_call,
2797 rpcrt4_conn_np_wait_for_incoming_data,
2798 rpcrt4_ncalrpc_get_top_of_tower,
2799 rpcrt4_ncalrpc_parse_top_of_tower,
2801 rpcrt4_ncalrpc_is_authorized,
2802 rpcrt4_ncalrpc_authorize,
2803 rpcrt4_ncalrpc_secure_packet,
2804 rpcrt4_conn_np_impersonate_client,
2805 rpcrt4_conn_np_revert_to_self,
2806 rpcrt4_ncalrpc_inquire_auth_client,
2809 { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_TCP },
2810 rpcrt4_conn_tcp_alloc,
2811 rpcrt4_ncacn_ip_tcp_open,
2812 rpcrt4_conn_tcp_handoff,
2813 rpcrt4_conn_tcp_read,
2814 rpcrt4_conn_tcp_write,
2815 rpcrt4_conn_tcp_close,
2816 rpcrt4_conn_tcp_cancel_call,
2817 rpcrt4_conn_tcp_wait_for_incoming_data,
2818 rpcrt4_ncacn_ip_tcp_get_top_of_tower,
2819 rpcrt4_ncacn_ip_tcp_parse_top_of_tower,
2821 RPCRT4_default_is_authorized,
2822 RPCRT4_default_authorize,
2823 RPCRT4_default_secure_packet,
2824 RPCRT4_default_impersonate_client,
2825 RPCRT4_default_revert_to_self,
2826 RPCRT4_default_inquire_auth_client,
2829 { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_HTTP },
2830 rpcrt4_ncacn_http_alloc,
2831 rpcrt4_ncacn_http_open,
2832 rpcrt4_ncacn_http_handoff,
2833 rpcrt4_ncacn_http_read,
2834 rpcrt4_ncacn_http_write,
2835 rpcrt4_ncacn_http_close,
2836 rpcrt4_ncacn_http_cancel_call,
2837 rpcrt4_ncacn_http_wait_for_incoming_data,
2838 rpcrt4_ncacn_http_get_top_of_tower,
2839 rpcrt4_ncacn_http_parse_top_of_tower,
2840 rpcrt4_ncacn_http_receive_fragment,
2841 RPCRT4_default_is_authorized,
2842 RPCRT4_default_authorize,
2843 RPCRT4_default_secure_packet,
2844 RPCRT4_default_impersonate_client,
2845 RPCRT4_default_revert_to_self,
2846 RPCRT4_default_inquire_auth_client,
2851 static const struct protseq_ops protseq_list[] =
2855 rpcrt4_protseq_np_alloc,
2856 rpcrt4_protseq_np_signal_state_changed,
2857 rpcrt4_protseq_np_get_wait_array,
2858 rpcrt4_protseq_np_free_wait_array,
2859 rpcrt4_protseq_np_wait_for_new_connection,
2860 rpcrt4_protseq_ncacn_np_open_endpoint,
2864 rpcrt4_protseq_np_alloc,
2865 rpcrt4_protseq_np_signal_state_changed,
2866 rpcrt4_protseq_np_get_wait_array,
2867 rpcrt4_protseq_np_free_wait_array,
2868 rpcrt4_protseq_np_wait_for_new_connection,
2869 rpcrt4_protseq_ncalrpc_open_endpoint,
2873 rpcrt4_protseq_sock_alloc,
2874 rpcrt4_protseq_sock_signal_state_changed,
2875 rpcrt4_protseq_sock_get_wait_array,
2876 rpcrt4_protseq_sock_free_wait_array,
2877 rpcrt4_protseq_sock_wait_for_new_connection,
2878 rpcrt4_protseq_ncacn_ip_tcp_open_endpoint,
2882 #define ARRAYSIZE(a) (sizeof((a)) / sizeof((a)[0]))
2884 const struct protseq_ops *rpcrt4_get_protseq_ops(const char *protseq)
2887 for(i=0; i<ARRAYSIZE(protseq_list); i++)
2888 if (!strcmp(protseq_list[i].name, protseq))
2889 return &protseq_list[i];
2893 static const struct connection_ops *rpcrt4_get_conn_protseq_ops(const char *protseq)
2896 for(i=0; i<ARRAYSIZE(conn_protseq_list); i++)
2897 if (!strcmp(conn_protseq_list[i].name, protseq))
2898 return &conn_protseq_list[i];
2902 /**** interface to rest of code ****/
2904 RPC_STATUS RPCRT4_OpenClientConnection(RpcConnection* Connection)
2906 TRACE("(Connection == ^%p)\n", Connection);
2908 assert(!Connection->server);
2909 return Connection->ops->open_connection_client(Connection);
2912 RPC_STATUS RPCRT4_CloseConnection(RpcConnection* Connection)
2914 TRACE("(Connection == ^%p)\n", Connection);
2915 if (SecIsValidHandle(&Connection->ctx))
2917 DeleteSecurityContext(&Connection->ctx);
2918 SecInvalidateHandle(&Connection->ctx);
2920 rpcrt4_conn_close(Connection);
2924 RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server,
2925 LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint,
2926 LPCWSTR NetworkOptions, RpcAuthInfo* AuthInfo, RpcQualityOfService *QOS)
2928 static LONG next_id;
2929 const struct connection_ops *ops;
2930 RpcConnection* NewConnection;
2932 ops = rpcrt4_get_conn_protseq_ops(Protseq);
2935 FIXME("not supported for protseq %s\n", Protseq);
2936 return RPC_S_PROTSEQ_NOT_SUPPORTED;
2939 NewConnection = ops->alloc();
2940 NewConnection->Next = NULL;
2941 NewConnection->server_binding = NULL;
2942 NewConnection->server = server;
2943 NewConnection->ops = ops;
2944 NewConnection->NetworkAddr = RPCRT4_strdupA(NetworkAddr);
2945 NewConnection->Endpoint = RPCRT4_strdupA(Endpoint);
2946 NewConnection->NetworkOptions = RPCRT4_strdupW(NetworkOptions);
2947 NewConnection->MaxTransmissionSize = RPC_MAX_PACKET_SIZE;
2948 memset(&NewConnection->ActiveInterface, 0, sizeof(NewConnection->ActiveInterface));
2949 NewConnection->NextCallId = 1;
2951 SecInvalidateHandle(&NewConnection->ctx);
2952 memset(&NewConnection->exp, 0, sizeof(NewConnection->exp));
2953 NewConnection->attr = 0;
2954 if (AuthInfo) RpcAuthInfo_AddRef(AuthInfo);
2955 NewConnection->AuthInfo = AuthInfo;
2956 NewConnection->auth_context_id = InterlockedIncrement( &next_id );
2957 NewConnection->encryption_auth_len = 0;
2958 NewConnection->signature_auth_len = 0;
2959 if (QOS) RpcQualityOfService_AddRef(QOS);
2960 NewConnection->QOS = QOS;
2962 list_init(&NewConnection->conn_pool_entry);
2963 NewConnection->async_state = NULL;
2965 TRACE("connection: %p\n", NewConnection);
2966 *Connection = NewConnection;
2971 static RPC_STATUS RPCRT4_SpawnConnection(RpcConnection** Connection, RpcConnection* OldConnection)
2975 err = RPCRT4_CreateConnection(Connection, OldConnection->server,
2976 rpcrt4_conn_get_name(OldConnection),
2977 OldConnection->NetworkAddr,
2978 OldConnection->Endpoint, NULL,
2979 OldConnection->AuthInfo, OldConnection->QOS);
2980 if (err == RPC_S_OK)
2981 rpcrt4_conn_handoff(OldConnection, *Connection);
2985 RPC_STATUS RPCRT4_DestroyConnection(RpcConnection* Connection)
2987 TRACE("connection: %p\n", Connection);
2989 RPCRT4_CloseConnection(Connection);
2990 RPCRT4_strfree(Connection->Endpoint);
2991 RPCRT4_strfree(Connection->NetworkAddr);
2992 HeapFree(GetProcessHeap(), 0, Connection->NetworkOptions);
2993 if (Connection->AuthInfo) RpcAuthInfo_Release(Connection->AuthInfo);
2994 if (Connection->QOS) RpcQualityOfService_Release(Connection->QOS);
2997 if (Connection->server_binding) RPCRT4_ReleaseBinding(Connection->server_binding);
2999 HeapFree(GetProcessHeap(), 0, Connection);
3003 RPC_STATUS RpcTransport_GetTopOfTower(unsigned char *tower_data,
3005 const char *protseq,
3006 const char *networkaddr,
3007 const char *endpoint)
3009 twr_empty_floor_t *protocol_floor;
3010 const struct connection_ops *protseq_ops = rpcrt4_get_conn_protseq_ops(protseq);
3015 return RPC_S_INVALID_RPC_PROTSEQ;
3019 *tower_size = sizeof(*protocol_floor);
3020 *tower_size += protseq_ops->get_top_of_tower(NULL, networkaddr, endpoint);
3024 protocol_floor = (twr_empty_floor_t *)tower_data;
3025 protocol_floor->count_lhs = sizeof(protocol_floor->protid);
3026 protocol_floor->protid = protseq_ops->epm_protocols[0];
3027 protocol_floor->count_rhs = 0;
3029 tower_data += sizeof(*protocol_floor);
3031 *tower_size = protseq_ops->get_top_of_tower(tower_data, networkaddr, endpoint);
3033 return EPT_S_NOT_REGISTERED;
3035 *tower_size += sizeof(*protocol_floor);
3040 RPC_STATUS RpcTransport_ParseTopOfTower(const unsigned char *tower_data,
3046 const twr_empty_floor_t *protocol_floor;
3047 const twr_empty_floor_t *floor4;
3048 const struct connection_ops *protseq_ops = NULL;
3052 if (tower_size < sizeof(*protocol_floor))
3053 return EPT_S_NOT_REGISTERED;
3055 protocol_floor = (const twr_empty_floor_t *)tower_data;
3056 tower_data += sizeof(*protocol_floor);
3057 tower_size -= sizeof(*protocol_floor);
3058 if ((protocol_floor->count_lhs != sizeof(protocol_floor->protid)) ||
3059 (protocol_floor->count_rhs > tower_size))
3060 return EPT_S_NOT_REGISTERED;
3061 tower_data += protocol_floor->count_rhs;
3062 tower_size -= protocol_floor->count_rhs;
3064 floor4 = (const twr_empty_floor_t *)tower_data;
3065 if ((tower_size < sizeof(*floor4)) ||
3066 (floor4->count_lhs != sizeof(floor4->protid)))
3067 return EPT_S_NOT_REGISTERED;
3069 for(i = 0; i < ARRAYSIZE(conn_protseq_list); i++)
3070 if ((protocol_floor->protid == conn_protseq_list[i].epm_protocols[0]) &&
3071 (floor4->protid == conn_protseq_list[i].epm_protocols[1]))
3073 protseq_ops = &conn_protseq_list[i];
3078 return EPT_S_NOT_REGISTERED;
3080 status = protseq_ops->parse_top_of_tower(tower_data, tower_size, networkaddr, endpoint);
3082 if ((status == RPC_S_OK) && protseq)
3084 *protseq = I_RpcAllocate(strlen(protseq_ops->name) + 1);
3085 strcpy(*protseq, protseq_ops->name);
3091 /***********************************************************************
3092 * RpcNetworkIsProtseqValidW (RPCRT4.@)
3094 * Checks if the given protocol sequence is known by the RPC system.
3095 * If it is, returns RPC_S_OK, otherwise RPC_S_PROTSEQ_NOT_SUPPORTED.
3098 RPC_STATUS WINAPI RpcNetworkIsProtseqValidW(RPC_WSTR protseq)
3102 WideCharToMultiByte(CP_ACP, 0, protseq, -1,
3103 ps, sizeof ps, NULL, NULL);
3104 if (rpcrt4_get_conn_protseq_ops(ps))
3107 FIXME("Unknown protseq %s\n", debugstr_w(protseq));
3109 return RPC_S_INVALID_RPC_PROTSEQ;
3112 /***********************************************************************
3113 * RpcNetworkIsProtseqValidA (RPCRT4.@)
3115 RPC_STATUS WINAPI RpcNetworkIsProtseqValidA(RPC_CSTR protseq)
3117 UNICODE_STRING protseqW;
3119 if (RtlCreateUnicodeStringFromAsciiz(&protseqW, (char*)protseq))
3121 RPC_STATUS ret = RpcNetworkIsProtseqValidW(protseqW.Buffer);
3122 RtlFreeUnicodeString(&protseqW);
3125 return RPC_S_OUT_OF_MEMORY;