- Update to trunk
[reactos.git] / dll / win32 / rpcrt4 / rpc_transport.c
1 /*
2 * RPC transport layer
3 *
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
9 *
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.
14 *
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.
19 *
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
23 *
24 */
25
26 #include "config.h"
27
28 #include <stdarg.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <assert.h>
32 #include <stdlib.h>
33 #include <sys/types.h>
34
35 #if defined(__MINGW32__) || defined (_MSC_VER)
36 # include <ws2tcpip.h>
37 # ifndef EADDRINUSE
38 # define EADDRINUSE WSAEADDRINUSE
39 # endif
40 # ifndef EAGAIN
41 # define EAGAIN WSAEWOULDBLOCK
42 # endif
43 #else
44 # include <errno.h>
45 # ifdef HAVE_UNISTD_H
46 # include <unistd.h>
47 # endif
48 # include <fcntl.h>
49 # ifdef HAVE_SYS_SOCKET_H
50 # include <sys/socket.h>
51 # endif
52 # ifdef HAVE_NETINET_IN_H
53 # include <netinet/in.h>
54 # endif
55 # ifdef HAVE_NETINET_TCP_H
56 # include <netinet/tcp.h>
57 # endif
58 # ifdef HAVE_ARPA_INET_H
59 # include <arpa/inet.h>
60 # endif
61 # ifdef HAVE_NETDB_H
62 # include <netdb.h>
63 # endif
64 # ifdef HAVE_SYS_POLL_H
65 # include <sys/poll.h>
66 # endif
67 # ifdef HAVE_SYS_FILIO_H
68 # include <sys/filio.h>
69 # endif
70 # ifdef HAVE_SYS_IOCTL_H
71 # include <sys/ioctl.h>
72 # endif
73 # define closesocket close
74 # define ioctlsocket ioctl
75 #endif /* defined(__MINGW32__) || defined (_MSC_VER) */
76
77 #include "windef.h"
78 #include "winbase.h"
79 #include "winnls.h"
80 #include "winerror.h"
81 #include "wininet.h"
82 #include "winternl.h"
83 #include "wine/unicode.h"
84
85 #include "rpc.h"
86 #include "rpcndr.h"
87
88 #include "wine/debug.h"
89
90 #include "rpc_binding.h"
91 #include "rpc_assoc.h"
92 #include "rpc_message.h"
93 #include "rpc_server.h"
94 #include "epm_towers.h"
95
96 #ifndef SOL_TCP
97 # define SOL_TCP IPPROTO_TCP
98 #endif
99
100 WINE_DEFAULT_DEBUG_CHANNEL(rpc);
101
102 static RPC_STATUS RPCRT4_SpawnConnection(RpcConnection** Connection, RpcConnection* OldConnection);
103
104 /**** ncacn_np support ****/
105
106 typedef struct _RpcConnection_np
107 {
108 RpcConnection common;
109 HANDLE pipe;
110 OVERLAPPED ovl[2];
111 BOOL listening;
112 } RpcConnection_np;
113
114 static RpcConnection *rpcrt4_conn_np_alloc(void)
115 {
116 RpcConnection_np *npc = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcConnection_np));
117 if (npc)
118 {
119 npc->pipe = NULL;
120 memset(&npc->ovl, 0, sizeof(npc->ovl));
121 npc->listening = FALSE;
122 }
123 return &npc->common;
124 }
125
126 static RPC_STATUS rpcrt4_conn_listen_pipe(RpcConnection_np *npc)
127 {
128 if (npc->listening)
129 return RPC_S_OK;
130
131 npc->listening = TRUE;
132 for (;;)
133 {
134 if (ConnectNamedPipe(npc->pipe, &npc->ovl[0]))
135 return RPC_S_OK;
136
137 switch(GetLastError())
138 {
139 case ERROR_PIPE_CONNECTED:
140 SetEvent(npc->ovl[0].hEvent);
141 return RPC_S_OK;
142 case ERROR_IO_PENDING:
143 /* will be completed in rpcrt4_protseq_np_wait_for_new_connection */
144 return RPC_S_OK;
145 case ERROR_NO_DATA_DETECTED:
146 /* client has disconnected, retry */
147 DisconnectNamedPipe( npc->pipe );
148 break;
149 default:
150 npc->listening = FALSE;
151 WARN("Couldn't ConnectNamedPipe (error was %d)\n", GetLastError());
152 return RPC_S_OUT_OF_RESOURCES;
153 }
154 }
155 }
156
157 static RPC_STATUS rpcrt4_conn_create_pipe(RpcConnection *Connection, LPCSTR pname)
158 {
159 RpcConnection_np *npc = (RpcConnection_np *) Connection;
160 TRACE("listening on %s\n", pname);
161
162 npc->pipe = CreateNamedPipeA(pname, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
163 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE,
164 PIPE_UNLIMITED_INSTANCES,
165 RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE, 5000, NULL);
166 if (npc->pipe == INVALID_HANDLE_VALUE) {
167 WARN("CreateNamedPipe failed with error %d\n", GetLastError());
168 if (GetLastError() == ERROR_FILE_EXISTS)
169 return RPC_S_DUPLICATE_ENDPOINT;
170 else
171 return RPC_S_CANT_CREATE_ENDPOINT;
172 }
173
174 memset(&npc->ovl, 0, sizeof(npc->ovl));
175 npc->ovl[0].hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
176 npc->ovl[1].hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
177
178 /* Note: we don't call ConnectNamedPipe here because it must be done in the
179 * server thread as the thread must be alertable */
180 return RPC_S_OK;
181 }
182
183 static RPC_STATUS rpcrt4_conn_open_pipe(RpcConnection *Connection, LPCSTR pname, BOOL wait)
184 {
185 RpcConnection_np *npc = (RpcConnection_np *) Connection;
186 HANDLE pipe;
187 DWORD err, dwMode;
188
189 TRACE("connecting to %s\n", pname);
190
191 while (TRUE) {
192 DWORD dwFlags = 0;
193 if (Connection->QOS)
194 {
195 dwFlags = SECURITY_SQOS_PRESENT;
196 switch (Connection->QOS->qos->ImpersonationType)
197 {
198 case RPC_C_IMP_LEVEL_DEFAULT:
199 /* FIXME: what to do here? */
200 break;
201 case RPC_C_IMP_LEVEL_ANONYMOUS:
202 dwFlags |= SECURITY_ANONYMOUS;
203 break;
204 case RPC_C_IMP_LEVEL_IDENTIFY:
205 dwFlags |= SECURITY_IDENTIFICATION;
206 break;
207 case RPC_C_IMP_LEVEL_IMPERSONATE:
208 dwFlags |= SECURITY_IMPERSONATION;
209 break;
210 case RPC_C_IMP_LEVEL_DELEGATE:
211 dwFlags |= SECURITY_DELEGATION;
212 break;
213 }
214 if (Connection->QOS->qos->IdentityTracking == RPC_C_QOS_IDENTITY_DYNAMIC)
215 dwFlags |= SECURITY_CONTEXT_TRACKING;
216 }
217 pipe = CreateFileA(pname, GENERIC_READ|GENERIC_WRITE, 0, NULL,
218 OPEN_EXISTING, dwFlags, 0);
219 if (pipe != INVALID_HANDLE_VALUE) break;
220 err = GetLastError();
221 if (err == ERROR_PIPE_BUSY) {
222 TRACE("connection failed, error=%x\n", err);
223 return RPC_S_SERVER_TOO_BUSY;
224 }
225 if (!wait || !WaitNamedPipeA(pname, NMPWAIT_WAIT_FOREVER)) {
226 err = GetLastError();
227 WARN("connection failed, error=%x\n", err);
228 return RPC_S_SERVER_UNAVAILABLE;
229 }
230 }
231
232 /* success */
233 memset(&npc->ovl, 0, sizeof(npc->ovl));
234 /* pipe is connected; change to message-read mode. */
235 dwMode = PIPE_READMODE_MESSAGE;
236 SetNamedPipeHandleState(pipe, &dwMode, NULL, NULL);
237 npc->ovl[0].hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
238 npc->ovl[1].hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
239 npc->pipe = pipe;
240
241 return RPC_S_OK;
242 }
243
244 static RPC_STATUS rpcrt4_ncalrpc_open(RpcConnection* Connection)
245 {
246 RpcConnection_np *npc = (RpcConnection_np *) Connection;
247 static const char prefix[] = "\\\\.\\pipe\\lrpc\\";
248 RPC_STATUS r;
249 LPSTR pname;
250
251 /* already connected? */
252 if (npc->pipe)
253 return RPC_S_OK;
254
255 /* protseq=ncalrpc: supposed to use NT LPC ports,
256 * but we'll implement it with named pipes for now */
257 pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1);
258 strcat(strcpy(pname, prefix), Connection->Endpoint);
259 r = rpcrt4_conn_open_pipe(Connection, pname, TRUE);
260 I_RpcFree(pname);
261
262 return r;
263 }
264
265 static RPC_STATUS rpcrt4_protseq_ncalrpc_open_endpoint(RpcServerProtseq* protseq, LPSTR endpoint)
266 {
267 static const char prefix[] = "\\\\.\\pipe\\lrpc\\";
268 RPC_STATUS r;
269 LPSTR pname;
270 RpcConnection *Connection;
271 char generated_endpoint[22];
272
273 if (!endpoint)
274 {
275 static LONG lrpc_nameless_id;
276 DWORD process_id = GetCurrentProcessId();
277 ULONG id = InterlockedIncrement(&lrpc_nameless_id);
278 snprintf(generated_endpoint, sizeof(generated_endpoint),
279 "LRPC%08x.%08x", process_id, id);
280 endpoint = generated_endpoint;
281 }
282
283 r = RPCRT4_CreateConnection(&Connection, TRUE, protseq->Protseq, NULL,
284 endpoint, NULL, NULL, NULL);
285 if (r != RPC_S_OK)
286 return r;
287
288 /* protseq=ncalrpc: supposed to use NT LPC ports,
289 * but we'll implement it with named pipes for now */
290 pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1);
291 strcat(strcpy(pname, prefix), Connection->Endpoint);
292 r = rpcrt4_conn_create_pipe(Connection, pname);
293 I_RpcFree(pname);
294
295 EnterCriticalSection(&protseq->cs);
296 Connection->Next = protseq->conn;
297 protseq->conn = Connection;
298 LeaveCriticalSection(&protseq->cs);
299
300 return r;
301 }
302
303 static RPC_STATUS rpcrt4_ncacn_np_open(RpcConnection* Connection)
304 {
305 RpcConnection_np *npc = (RpcConnection_np *) Connection;
306 static const char prefix[] = "\\\\.";
307 RPC_STATUS r;
308 LPSTR pname;
309
310 /* already connected? */
311 if (npc->pipe)
312 return RPC_S_OK;
313
314 /* protseq=ncacn_np: named pipes */
315 pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1);
316 strcat(strcpy(pname, prefix), Connection->Endpoint);
317 r = rpcrt4_conn_open_pipe(Connection, pname, FALSE);
318 I_RpcFree(pname);
319
320 return r;
321 }
322
323 static RPC_STATUS rpcrt4_protseq_ncacn_np_open_endpoint(RpcServerProtseq *protseq, LPSTR endpoint)
324 {
325 static const char prefix[] = "\\\\.";
326 RPC_STATUS r;
327 LPSTR pname;
328 RpcConnection *Connection;
329 char generated_endpoint[21];
330
331 if (!endpoint)
332 {
333 static LONG np_nameless_id;
334 DWORD process_id = GetCurrentProcessId();
335 ULONG id = InterlockedExchangeAdd(&np_nameless_id, 1 );
336 snprintf(generated_endpoint, sizeof(generated_endpoint),
337 "\\\\pipe\\\\%08x.%03x", process_id, id);
338 endpoint = generated_endpoint;
339 }
340
341 r = RPCRT4_CreateConnection(&Connection, TRUE, protseq->Protseq, NULL,
342 endpoint, NULL, NULL, NULL);
343 if (r != RPC_S_OK)
344 return r;
345
346 /* protseq=ncacn_np: named pipes */
347 pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1);
348 strcat(strcpy(pname, prefix), Connection->Endpoint);
349 r = rpcrt4_conn_create_pipe(Connection, pname);
350 I_RpcFree(pname);
351
352 EnterCriticalSection(&protseq->cs);
353 Connection->Next = protseq->conn;
354 protseq->conn = Connection;
355 LeaveCriticalSection(&protseq->cs);
356
357 return r;
358 }
359
360 static void rpcrt4_conn_np_handoff(RpcConnection_np *old_npc, RpcConnection_np *new_npc)
361 {
362 /* because of the way named pipes work, we'll transfer the connected pipe
363 * to the child, then reopen the server binding to continue listening */
364
365 new_npc->pipe = old_npc->pipe;
366 new_npc->ovl[0] = old_npc->ovl[0];
367 new_npc->ovl[1] = old_npc->ovl[1];
368 old_npc->pipe = 0;
369 memset(&old_npc->ovl, 0, sizeof(old_npc->ovl));
370 old_npc->listening = FALSE;
371 }
372
373 static RPC_STATUS rpcrt4_ncacn_np_handoff(RpcConnection *old_conn, RpcConnection *new_conn)
374 {
375 RPC_STATUS status;
376 LPSTR pname;
377 static const char prefix[] = "\\\\.";
378
379 rpcrt4_conn_np_handoff((RpcConnection_np *)old_conn, (RpcConnection_np *)new_conn);
380
381 pname = I_RpcAllocate(strlen(prefix) + strlen(old_conn->Endpoint) + 1);
382 strcat(strcpy(pname, prefix), old_conn->Endpoint);
383 status = rpcrt4_conn_create_pipe(old_conn, pname);
384 I_RpcFree(pname);
385
386 return status;
387 }
388
389 static RPC_STATUS rpcrt4_ncalrpc_handoff(RpcConnection *old_conn, RpcConnection *new_conn)
390 {
391 RPC_STATUS status;
392 LPSTR pname;
393 static const char prefix[] = "\\\\.\\pipe\\lrpc\\";
394
395 TRACE("%s\n", old_conn->Endpoint);
396
397 rpcrt4_conn_np_handoff((RpcConnection_np *)old_conn, (RpcConnection_np *)new_conn);
398
399 pname = I_RpcAllocate(strlen(prefix) + strlen(old_conn->Endpoint) + 1);
400 strcat(strcpy(pname, prefix), old_conn->Endpoint);
401 status = rpcrt4_conn_create_pipe(old_conn, pname);
402 I_RpcFree(pname);
403
404 return status;
405 }
406
407 static int rpcrt4_conn_np_read(RpcConnection *Connection,
408 void *buffer, unsigned int count)
409 {
410 RpcConnection_np *npc = (RpcConnection_np *) Connection;
411 char *buf = buffer;
412 BOOL ret = TRUE;
413 unsigned int bytes_left = count;
414
415 while (bytes_left)
416 {
417 DWORD bytes_read;
418 ret = ReadFile(npc->pipe, buf, bytes_left, &bytes_read, &npc->ovl[0]);
419 if ((!ret || !bytes_read) && (GetLastError() != ERROR_IO_PENDING))
420 break;
421
422 ret = GetOverlappedResult(npc->pipe, &npc->ovl[0], &bytes_read, TRUE);
423 if (!ret && (GetLastError() != ERROR_MORE_DATA))
424 break;
425
426 bytes_left -= bytes_read;
427 buf += bytes_read;
428 }
429 return ret ? count : -1;
430 }
431
432 static int rpcrt4_conn_np_write(RpcConnection *Connection,
433 const void *buffer, unsigned int count)
434 {
435 RpcConnection_np *npc = (RpcConnection_np *) Connection;
436 const char *buf = buffer;
437 BOOL ret = TRUE;
438 unsigned int bytes_left = count;
439
440 while (bytes_left)
441 {
442 DWORD bytes_written;
443 ret = WriteFile(npc->pipe, buf, bytes_left, &bytes_written, &npc->ovl[1]);
444 if ((!ret || !bytes_written) && (GetLastError() != ERROR_IO_PENDING))
445 break;
446
447 ret = GetOverlappedResult(npc->pipe, &npc->ovl[1], &bytes_written, TRUE);
448 if (!ret && (GetLastError() != ERROR_MORE_DATA))
449 break;
450
451 bytes_left -= bytes_written;
452 buf += bytes_written;
453 }
454 return ret ? count : -1;
455 }
456
457 static int rpcrt4_conn_np_close(RpcConnection *Connection)
458 {
459 RpcConnection_np *npc = (RpcConnection_np *) Connection;
460 if (npc->pipe) {
461 FlushFileBuffers(npc->pipe);
462 CloseHandle(npc->pipe);
463 npc->pipe = 0;
464 }
465 if (npc->ovl[0].hEvent) {
466 CloseHandle(npc->ovl[0].hEvent);
467 npc->ovl[0].hEvent = 0;
468 }
469 if (npc->ovl[1].hEvent) {
470 CloseHandle(npc->ovl[1].hEvent);
471 npc->ovl[1].hEvent = 0;
472 }
473 return 0;
474 }
475
476 static void rpcrt4_conn_np_cancel_call(RpcConnection *Connection)
477 {
478 /* FIXME: implement when named pipe writes use overlapped I/O */
479 }
480
481 static int rpcrt4_conn_np_wait_for_incoming_data(RpcConnection *Connection)
482 {
483 /* FIXME: implement when named pipe writes use overlapped I/O */
484 return -1;
485 }
486
487 static size_t rpcrt4_ncacn_np_get_top_of_tower(unsigned char *tower_data,
488 const char *networkaddr,
489 const char *endpoint)
490 {
491 twr_empty_floor_t *smb_floor;
492 twr_empty_floor_t *nb_floor;
493 size_t size;
494 size_t networkaddr_size;
495 size_t endpoint_size;
496
497 TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint);
498
499 networkaddr_size = networkaddr ? strlen(networkaddr) + 1 : 1;
500 endpoint_size = endpoint ? strlen(endpoint) + 1 : 1;
501 size = sizeof(*smb_floor) + endpoint_size + sizeof(*nb_floor) + networkaddr_size;
502
503 if (!tower_data)
504 return size;
505
506 smb_floor = (twr_empty_floor_t *)tower_data;
507
508 tower_data += sizeof(*smb_floor);
509
510 smb_floor->count_lhs = sizeof(smb_floor->protid);
511 smb_floor->protid = EPM_PROTOCOL_SMB;
512 smb_floor->count_rhs = endpoint_size;
513
514 if (endpoint)
515 memcpy(tower_data, endpoint, endpoint_size);
516 else
517 tower_data[0] = 0;
518 tower_data += endpoint_size;
519
520 nb_floor = (twr_empty_floor_t *)tower_data;
521
522 tower_data += sizeof(*nb_floor);
523
524 nb_floor->count_lhs = sizeof(nb_floor->protid);
525 nb_floor->protid = EPM_PROTOCOL_NETBIOS;
526 nb_floor->count_rhs = networkaddr_size;
527
528 if (networkaddr)
529 memcpy(tower_data, networkaddr, networkaddr_size);
530 else
531 tower_data[0] = 0;
532
533 return size;
534 }
535
536 static RPC_STATUS rpcrt4_ncacn_np_parse_top_of_tower(const unsigned char *tower_data,
537 size_t tower_size,
538 char **networkaddr,
539 char **endpoint)
540 {
541 const twr_empty_floor_t *smb_floor = (const twr_empty_floor_t *)tower_data;
542 const twr_empty_floor_t *nb_floor;
543
544 TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint);
545
546 if (tower_size < sizeof(*smb_floor))
547 return EPT_S_NOT_REGISTERED;
548
549 tower_data += sizeof(*smb_floor);
550 tower_size -= sizeof(*smb_floor);
551
552 if ((smb_floor->count_lhs != sizeof(smb_floor->protid)) ||
553 (smb_floor->protid != EPM_PROTOCOL_SMB) ||
554 (smb_floor->count_rhs > tower_size) ||
555 (tower_data[smb_floor->count_rhs - 1] != '\0'))
556 return EPT_S_NOT_REGISTERED;
557
558 if (endpoint)
559 {
560 *endpoint = I_RpcAllocate(smb_floor->count_rhs);
561 if (!*endpoint)
562 return RPC_S_OUT_OF_RESOURCES;
563 memcpy(*endpoint, tower_data, smb_floor->count_rhs);
564 }
565 tower_data += smb_floor->count_rhs;
566 tower_size -= smb_floor->count_rhs;
567
568 if (tower_size < sizeof(*nb_floor))
569 return EPT_S_NOT_REGISTERED;
570
571 nb_floor = (const twr_empty_floor_t *)tower_data;
572
573 tower_data += sizeof(*nb_floor);
574 tower_size -= sizeof(*nb_floor);
575
576 if ((nb_floor->count_lhs != sizeof(nb_floor->protid)) ||
577 (nb_floor->protid != EPM_PROTOCOL_NETBIOS) ||
578 (nb_floor->count_rhs > tower_size) ||
579 (tower_data[nb_floor->count_rhs - 1] != '\0'))
580 return EPT_S_NOT_REGISTERED;
581
582 if (networkaddr)
583 {
584 *networkaddr = I_RpcAllocate(nb_floor->count_rhs);
585 if (!*networkaddr)
586 {
587 if (endpoint)
588 {
589 I_RpcFree(*endpoint);
590 *endpoint = NULL;
591 }
592 return RPC_S_OUT_OF_RESOURCES;
593 }
594 memcpy(*networkaddr, tower_data, nb_floor->count_rhs);
595 }
596
597 return RPC_S_OK;
598 }
599
600 typedef struct _RpcServerProtseq_np
601 {
602 RpcServerProtseq common;
603 HANDLE mgr_event;
604 } RpcServerProtseq_np;
605
606 static RpcServerProtseq *rpcrt4_protseq_np_alloc(void)
607 {
608 RpcServerProtseq_np *ps = HeapAlloc(GetProcessHeap(), 0, sizeof(*ps));
609 if (ps)
610 ps->mgr_event = CreateEventW(NULL, FALSE, FALSE, NULL);
611 return &ps->common;
612 }
613
614 static void rpcrt4_protseq_np_signal_state_changed(RpcServerProtseq *protseq)
615 {
616 RpcServerProtseq_np *npps = CONTAINING_RECORD(protseq, RpcServerProtseq_np, common);
617 SetEvent(npps->mgr_event);
618 }
619
620 static void *rpcrt4_protseq_np_get_wait_array(RpcServerProtseq *protseq, void *prev_array, unsigned int *count)
621 {
622 HANDLE *objs = prev_array;
623 RpcConnection_np *conn;
624 RpcServerProtseq_np *npps = CONTAINING_RECORD(protseq, RpcServerProtseq_np, common);
625
626 EnterCriticalSection(&protseq->cs);
627
628 /* open and count connections */
629 *count = 1;
630 conn = CONTAINING_RECORD(protseq->conn, RpcConnection_np, common);
631 while (conn) {
632 rpcrt4_conn_listen_pipe(conn);
633 if (conn->ovl[0].hEvent)
634 (*count)++;
635 conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_np, common);
636 }
637
638 /* make array of connections */
639 if (objs)
640 objs = HeapReAlloc(GetProcessHeap(), 0, objs, *count*sizeof(HANDLE));
641 else
642 objs = HeapAlloc(GetProcessHeap(), 0, *count*sizeof(HANDLE));
643 if (!objs)
644 {
645 ERR("couldn't allocate objs\n");
646 LeaveCriticalSection(&protseq->cs);
647 return NULL;
648 }
649
650 objs[0] = npps->mgr_event;
651 *count = 1;
652 conn = CONTAINING_RECORD(protseq->conn, RpcConnection_np, common);
653 while (conn) {
654 if ((objs[*count] = conn->ovl[0].hEvent))
655 (*count)++;
656 conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_np, common);
657 }
658 LeaveCriticalSection(&protseq->cs);
659 return objs;
660 }
661
662 static void rpcrt4_protseq_np_free_wait_array(RpcServerProtseq *protseq, void *array)
663 {
664 HeapFree(GetProcessHeap(), 0, array);
665 }
666
667 static int rpcrt4_protseq_np_wait_for_new_connection(RpcServerProtseq *protseq, unsigned int count, void *wait_array)
668 {
669 HANDLE b_handle;
670 HANDLE *objs = wait_array;
671 DWORD res;
672 RpcConnection *cconn;
673 RpcConnection_np *conn;
674
675 if (!objs)
676 return -1;
677
678 do
679 {
680 /* an alertable wait isn't strictly necessary, but due to our
681 * overlapped I/O implementation in Wine we need to free some memory
682 * by the file user APC being called, even if no completion routine was
683 * specified at the time of starting the async operation */
684 res = WaitForMultipleObjectsEx(count, objs, FALSE, INFINITE, TRUE);
685 } while (res == WAIT_IO_COMPLETION);
686
687 if (res == WAIT_OBJECT_0)
688 return 0;
689 else if (res == WAIT_FAILED)
690 {
691 ERR("wait failed with error %d\n", GetLastError());
692 return -1;
693 }
694 else
695 {
696 b_handle = objs[res - WAIT_OBJECT_0];
697 /* find which connection got a RPC */
698 EnterCriticalSection(&protseq->cs);
699 conn = CONTAINING_RECORD(protseq->conn, RpcConnection_np, common);
700 while (conn) {
701 if (b_handle == conn->ovl[0].hEvent) break;
702 conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_np, common);
703 }
704 cconn = NULL;
705 if (conn)
706 RPCRT4_SpawnConnection(&cconn, &conn->common);
707 else
708 ERR("failed to locate connection for handle %p\n", b_handle);
709 LeaveCriticalSection(&protseq->cs);
710 if (cconn)
711 {
712 RPCRT4_new_client(cconn);
713 return 1;
714 }
715 else return -1;
716 }
717 }
718
719 static size_t rpcrt4_ncalrpc_get_top_of_tower(unsigned char *tower_data,
720 const char *networkaddr,
721 const char *endpoint)
722 {
723 twr_empty_floor_t *pipe_floor;
724 size_t size;
725 size_t endpoint_size;
726
727 TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint);
728
729 endpoint_size = strlen(endpoint) + 1;
730 size = sizeof(*pipe_floor) + endpoint_size;
731
732 if (!tower_data)
733 return size;
734
735 pipe_floor = (twr_empty_floor_t *)tower_data;
736
737 tower_data += sizeof(*pipe_floor);
738
739 pipe_floor->count_lhs = sizeof(pipe_floor->protid);
740 pipe_floor->protid = EPM_PROTOCOL_PIPE;
741 pipe_floor->count_rhs = endpoint_size;
742
743 memcpy(tower_data, endpoint, endpoint_size);
744
745 return size;
746 }
747
748 static RPC_STATUS rpcrt4_ncalrpc_parse_top_of_tower(const unsigned char *tower_data,
749 size_t tower_size,
750 char **networkaddr,
751 char **endpoint)
752 {
753 const twr_empty_floor_t *pipe_floor = (const twr_empty_floor_t *)tower_data;
754
755 TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint);
756
757 if (tower_size < sizeof(*pipe_floor))
758 return EPT_S_NOT_REGISTERED;
759
760 tower_data += sizeof(*pipe_floor);
761 tower_size -= sizeof(*pipe_floor);
762
763 if ((pipe_floor->count_lhs != sizeof(pipe_floor->protid)) ||
764 (pipe_floor->protid != EPM_PROTOCOL_PIPE) ||
765 (pipe_floor->count_rhs > tower_size) ||
766 (tower_data[pipe_floor->count_rhs - 1] != '\0'))
767 return EPT_S_NOT_REGISTERED;
768
769 if (networkaddr)
770 *networkaddr = NULL;
771
772 if (endpoint)
773 {
774 *endpoint = I_RpcAllocate(pipe_floor->count_rhs);
775 if (!*endpoint)
776 return RPC_S_OUT_OF_RESOURCES;
777 memcpy(*endpoint, tower_data, pipe_floor->count_rhs);
778 }
779
780 return RPC_S_OK;
781 }
782
783 /**** ncacn_ip_tcp support ****/
784
785 static size_t rpcrt4_ip_tcp_get_top_of_tower(unsigned char *tower_data,
786 const char *networkaddr,
787 unsigned char tcp_protid,
788 const char *endpoint)
789 {
790 twr_tcp_floor_t *tcp_floor;
791 twr_ipv4_floor_t *ipv4_floor;
792 struct addrinfo *ai;
793 struct addrinfo hints;
794 int ret;
795 size_t size = sizeof(*tcp_floor) + sizeof(*ipv4_floor);
796
797 TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint);
798
799 if (!tower_data)
800 return size;
801
802 tcp_floor = (twr_tcp_floor_t *)tower_data;
803 tower_data += sizeof(*tcp_floor);
804
805 ipv4_floor = (twr_ipv4_floor_t *)tower_data;
806
807 tcp_floor->count_lhs = sizeof(tcp_floor->protid);
808 tcp_floor->protid = tcp_protid;
809 tcp_floor->count_rhs = sizeof(tcp_floor->port);
810
811 ipv4_floor->count_lhs = sizeof(ipv4_floor->protid);
812 ipv4_floor->protid = EPM_PROTOCOL_IP;
813 ipv4_floor->count_rhs = sizeof(ipv4_floor->ipv4addr);
814
815 hints.ai_flags = AI_NUMERICHOST;
816 /* FIXME: only support IPv4 at the moment. how is IPv6 represented by the EPM? */
817 hints.ai_family = PF_INET;
818 hints.ai_socktype = SOCK_STREAM;
819 hints.ai_protocol = IPPROTO_TCP;
820 hints.ai_addrlen = 0;
821 hints.ai_addr = NULL;
822 hints.ai_canonname = NULL;
823 hints.ai_next = NULL;
824
825 ret = getaddrinfo(networkaddr, endpoint, &hints, &ai);
826 if (ret)
827 {
828 ret = getaddrinfo("0.0.0.0", endpoint, &hints, &ai);
829 if (ret)
830 {
831 ERR("getaddrinfo failed: %s\n", gai_strerror(ret));
832 return 0;
833 }
834 }
835
836 if (ai->ai_family == PF_INET)
837 {
838 const struct sockaddr_in *sin = (const struct sockaddr_in *)ai->ai_addr;
839 tcp_floor->port = sin->sin_port;
840 ipv4_floor->ipv4addr = sin->sin_addr.s_addr;
841 }
842 else
843 {
844 ERR("unexpected protocol family %d\n", ai->ai_family);
845 return 0;
846 }
847
848 freeaddrinfo(ai);
849
850 return size;
851 }
852
853 static RPC_STATUS rpcrt4_ip_tcp_parse_top_of_tower(const unsigned char *tower_data,
854 size_t tower_size,
855 char **networkaddr,
856 unsigned char tcp_protid,
857 char **endpoint)
858 {
859 const twr_tcp_floor_t *tcp_floor = (const twr_tcp_floor_t *)tower_data;
860 const twr_ipv4_floor_t *ipv4_floor;
861 struct in_addr in_addr;
862
863 TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint);
864
865 if (tower_size < sizeof(*tcp_floor))
866 return EPT_S_NOT_REGISTERED;
867
868 tower_data += sizeof(*tcp_floor);
869 tower_size -= sizeof(*tcp_floor);
870
871 if (tower_size < sizeof(*ipv4_floor))
872 return EPT_S_NOT_REGISTERED;
873
874 ipv4_floor = (const twr_ipv4_floor_t *)tower_data;
875
876 if ((tcp_floor->count_lhs != sizeof(tcp_floor->protid)) ||
877 (tcp_floor->protid != tcp_protid) ||
878 (tcp_floor->count_rhs != sizeof(tcp_floor->port)) ||
879 (ipv4_floor->count_lhs != sizeof(ipv4_floor->protid)) ||
880 (ipv4_floor->protid != EPM_PROTOCOL_IP) ||
881 (ipv4_floor->count_rhs != sizeof(ipv4_floor->ipv4addr)))
882 return EPT_S_NOT_REGISTERED;
883
884 if (endpoint)
885 {
886 *endpoint = I_RpcAllocate(6 /* sizeof("65535") + 1 */);
887 if (!*endpoint)
888 return RPC_S_OUT_OF_RESOURCES;
889 sprintf(*endpoint, "%u", ntohs(tcp_floor->port));
890 }
891
892 if (networkaddr)
893 {
894 *networkaddr = I_RpcAllocate(INET_ADDRSTRLEN);
895 if (!*networkaddr)
896 {
897 if (endpoint)
898 {
899 I_RpcFree(*endpoint);
900 *endpoint = NULL;
901 }
902 return RPC_S_OUT_OF_RESOURCES;
903 }
904 in_addr.s_addr = ipv4_floor->ipv4addr;
905 if (!inet_ntop(AF_INET, &in_addr, *networkaddr, INET_ADDRSTRLEN))
906 {
907 ERR("inet_ntop: %s\n", strerror(errno));
908 I_RpcFree(*networkaddr);
909 *networkaddr = NULL;
910 if (endpoint)
911 {
912 I_RpcFree(*endpoint);
913 *endpoint = NULL;
914 }
915 return EPT_S_NOT_REGISTERED;
916 }
917 }
918
919 return RPC_S_OK;
920 }
921
922 typedef struct _RpcConnection_tcp
923 {
924 RpcConnection common;
925 int sock;
926 #ifdef HAVE_SOCKETPAIR
927 int cancel_fds[2];
928 #else
929 HANDLE sock_event;
930 HANDLE cancel_event;
931 #endif
932 } RpcConnection_tcp;
933
934 #ifdef HAVE_SOCKETPAIR
935
936 static BOOL rpcrt4_sock_wait_init(RpcConnection_tcp *tcpc)
937 {
938 if (socketpair(PF_UNIX, SOCK_STREAM, 0, tcpc->cancel_fds) < 0)
939 {
940 ERR("socketpair() failed: %s\n", strerror(errno));
941 return FALSE;
942 }
943 return TRUE;
944 }
945
946 static BOOL rpcrt4_sock_wait_for_recv(RpcConnection_tcp *tcpc)
947 {
948 struct pollfd pfds[2];
949 pfds[0].fd = tcpc->sock;
950 pfds[0].events = POLLIN;
951 pfds[1].fd = tcpc->cancel_fds[0];
952 pfds[1].events = POLLIN;
953 if (poll(pfds, 2, -1 /* infinite */) == -1 && errno != EINTR)
954 {
955 ERR("poll() failed: %s\n", strerror(errno));
956 return FALSE;
957 }
958 if (pfds[1].revents & POLLIN) /* canceled */
959 {
960 char dummy;
961 read(pfds[1].fd, &dummy, sizeof(dummy));
962 return FALSE;
963 }
964 return TRUE;
965 }
966
967 static BOOL rpcrt4_sock_wait_for_send(RpcConnection_tcp *tcpc)
968 {
969 struct pollfd pfd;
970 pfd.fd = tcpc->sock;
971 pfd.events = POLLOUT;
972 if (poll(&pfd, 1, -1 /* infinite */) == -1 && errno != EINTR)
973 {
974 ERR("poll() failed: %s\n", strerror(errno));
975 return FALSE;
976 }
977 return TRUE;
978 }
979
980 static void rpcrt4_sock_wait_cancel(RpcConnection_tcp *tcpc)
981 {
982 char dummy = 1;
983
984 write(tcpc->cancel_fds[1], &dummy, 1);
985 }
986
987 static void rpcrt4_sock_wait_destroy(RpcConnection_tcp *tcpc)
988 {
989 close(tcpc->cancel_fds[0]);
990 close(tcpc->cancel_fds[1]);
991 }
992
993 #else /* HAVE_SOCKETPAIR */
994
995 static BOOL rpcrt4_sock_wait_init(RpcConnection_tcp *tcpc)
996 {
997 static BOOL wsa_inited;
998 if (!wsa_inited)
999 {
1000 WSADATA wsadata;
1001 WSAStartup(MAKEWORD(2, 2), &wsadata);
1002 /* Note: WSAStartup can be called more than once so we don't bother with
1003 * making accesses to wsa_inited thread-safe */
1004 wsa_inited = TRUE;
1005 }
1006 tcpc->sock_event = CreateEventW(NULL, FALSE, FALSE, NULL);
1007 tcpc->cancel_event = CreateEventW(NULL, FALSE, FALSE, NULL);
1008 if (!tcpc->sock_event || !tcpc->cancel_event)
1009 {
1010 ERR("event creation failed\n");
1011 if (tcpc->sock_event) CloseHandle(tcpc->sock_event);
1012 return FALSE;
1013 }
1014 return TRUE;
1015 }
1016
1017 static BOOL rpcrt4_sock_wait_for_recv(RpcConnection_tcp *tcpc)
1018 {
1019 HANDLE wait_handles[2];
1020 DWORD res;
1021 if (WSAEventSelect(tcpc->sock, tcpc->sock_event, FD_READ | FD_CLOSE) == SOCKET_ERROR)
1022 {
1023 ERR("WSAEventSelect() failed with error %d\n", WSAGetLastError());
1024 return FALSE;
1025 }
1026 wait_handles[0] = tcpc->sock_event;
1027 wait_handles[1] = tcpc->cancel_event;
1028 res = WaitForMultipleObjects(2, wait_handles, FALSE, INFINITE);
1029 switch (res)
1030 {
1031 case WAIT_OBJECT_0:
1032 return TRUE;
1033 case WAIT_OBJECT_0 + 1:
1034 return FALSE;
1035 default:
1036 ERR("WaitForMultipleObjects() failed with error %d\n", GetLastError());
1037 return FALSE;
1038 }
1039 }
1040
1041 static BOOL rpcrt4_sock_wait_for_send(RpcConnection_tcp *tcpc)
1042 {
1043 DWORD res;
1044 if (WSAEventSelect(tcpc->sock, tcpc->sock_event, FD_WRITE | FD_CLOSE) == SOCKET_ERROR)
1045 {
1046 ERR("WSAEventSelect() failed with error %d\n", WSAGetLastError());
1047 return FALSE;
1048 }
1049 res = WaitForSingleObject(tcpc->sock_event, INFINITE);
1050 switch (res)
1051 {
1052 case WAIT_OBJECT_0:
1053 return TRUE;
1054 default:
1055 ERR("WaitForMultipleObjects() failed with error %d\n", GetLastError());
1056 return FALSE;
1057 }
1058 }
1059
1060 static void rpcrt4_sock_wait_cancel(RpcConnection_tcp *tcpc)
1061 {
1062 SetEvent(tcpc->cancel_event);
1063 }
1064
1065 static void rpcrt4_sock_wait_destroy(RpcConnection_tcp *tcpc)
1066 {
1067 CloseHandle(tcpc->sock_event);
1068 CloseHandle(tcpc->cancel_event);
1069 }
1070
1071 #endif
1072
1073 static RpcConnection *rpcrt4_conn_tcp_alloc(void)
1074 {
1075 RpcConnection_tcp *tcpc;
1076 tcpc = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcConnection_tcp));
1077 if (tcpc == NULL)
1078 return NULL;
1079 tcpc->sock = -1;
1080 if (!rpcrt4_sock_wait_init(tcpc))
1081 {
1082 HeapFree(GetProcessHeap(), 0, tcpc);
1083 return NULL;
1084 }
1085 return &tcpc->common;
1086 }
1087
1088 static RPC_STATUS rpcrt4_ncacn_ip_tcp_open(RpcConnection* Connection)
1089 {
1090 RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
1091 int sock;
1092 int ret;
1093 struct addrinfo *ai;
1094 struct addrinfo *ai_cur;
1095 struct addrinfo hints;
1096
1097 TRACE("(%s, %s)\n", Connection->NetworkAddr, Connection->Endpoint);
1098
1099 if (tcpc->sock != -1)
1100 return RPC_S_OK;
1101
1102 hints.ai_flags = 0;
1103 hints.ai_family = PF_UNSPEC;
1104 hints.ai_socktype = SOCK_STREAM;
1105 hints.ai_protocol = IPPROTO_TCP;
1106 hints.ai_addrlen = 0;
1107 hints.ai_addr = NULL;
1108 hints.ai_canonname = NULL;
1109 hints.ai_next = NULL;
1110
1111 ret = getaddrinfo(Connection->NetworkAddr, Connection->Endpoint, &hints, &ai);
1112 if (ret)
1113 {
1114 ERR("getaddrinfo for %s:%s failed: %s\n", Connection->NetworkAddr,
1115 Connection->Endpoint, gai_strerror(ret));
1116 return RPC_S_SERVER_UNAVAILABLE;
1117 }
1118
1119 for (ai_cur = ai; ai_cur; ai_cur = ai_cur->ai_next)
1120 {
1121 int val;
1122 u_long nonblocking;
1123
1124 if (ai_cur->ai_family != AF_INET && ai_cur->ai_family != AF_INET6)
1125 {
1126 TRACE("skipping non-IP/IPv6 address family\n");
1127 continue;
1128 }
1129
1130 if (TRACE_ON(rpc))
1131 {
1132 char host[256];
1133 char service[256];
1134 getnameinfo(ai_cur->ai_addr, ai_cur->ai_addrlen,
1135 host, sizeof(host), service, sizeof(service),
1136 NI_NUMERICHOST | NI_NUMERICSERV);
1137 TRACE("trying %s:%s\n", host, service);
1138 }
1139
1140 sock = socket(ai_cur->ai_family, ai_cur->ai_socktype, ai_cur->ai_protocol);
1141 if (sock == -1)
1142 {
1143 WARN("socket() failed: %s\n", strerror(errno));
1144 continue;
1145 }
1146
1147 if (0>connect(sock, ai_cur->ai_addr, ai_cur->ai_addrlen))
1148 {
1149 WARN("connect() failed: %s\n", strerror(errno));
1150 closesocket(sock);
1151 continue;
1152 }
1153
1154 /* RPC depends on having minimal latency so disable the Nagle algorithm */
1155 val = 1;
1156 setsockopt(sock, SOL_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
1157 nonblocking = 1;
1158 ioctlsocket(sock, FIONBIO, &nonblocking);
1159
1160 tcpc->sock = sock;
1161
1162 freeaddrinfo(ai);
1163 TRACE("connected\n");
1164 return RPC_S_OK;
1165 }
1166
1167 freeaddrinfo(ai);
1168 ERR("couldn't connect to %s:%s\n", Connection->NetworkAddr, Connection->Endpoint);
1169 return RPC_S_SERVER_UNAVAILABLE;
1170 }
1171
1172 static RPC_STATUS rpcrt4_protseq_ncacn_ip_tcp_open_endpoint(RpcServerProtseq *protseq, LPSTR endpoint)
1173 {
1174 RPC_STATUS status = RPC_S_CANT_CREATE_ENDPOINT;
1175 int sock;
1176 int ret;
1177 struct addrinfo *ai;
1178 struct addrinfo *ai_cur;
1179 struct addrinfo hints;
1180 RpcConnection *first_connection = NULL;
1181
1182 TRACE("(%p, %s)\n", protseq, endpoint);
1183
1184 hints.ai_flags = AI_PASSIVE /* for non-localhost addresses */;
1185 hints.ai_family = PF_UNSPEC;
1186 hints.ai_socktype = SOCK_STREAM;
1187 hints.ai_protocol = IPPROTO_TCP;
1188 hints.ai_addrlen = 0;
1189 hints.ai_addr = NULL;
1190 hints.ai_canonname = NULL;
1191 hints.ai_next = NULL;
1192
1193 ret = getaddrinfo(NULL, endpoint ? endpoint : "0", &hints, &ai);
1194 if (ret)
1195 {
1196 ERR("getaddrinfo for port %s failed: %s\n", endpoint,
1197 gai_strerror(ret));
1198 if ((ret == EAI_SERVICE) || (ret == EAI_NONAME))
1199 return RPC_S_INVALID_ENDPOINT_FORMAT;
1200 return RPC_S_CANT_CREATE_ENDPOINT;
1201 }
1202
1203 for (ai_cur = ai; ai_cur; ai_cur = ai_cur->ai_next)
1204 {
1205 RpcConnection_tcp *tcpc;
1206 RPC_STATUS create_status;
1207 struct sockaddr_storage sa;
1208 socklen_t sa_len;
1209 char service[NI_MAXSERV];
1210 u_long nonblocking;
1211
1212 if (ai_cur->ai_family != AF_INET && ai_cur->ai_family != AF_INET6)
1213 {
1214 TRACE("skipping non-IP/IPv6 address family\n");
1215 continue;
1216 }
1217
1218 if (TRACE_ON(rpc))
1219 {
1220 char host[256];
1221 getnameinfo(ai_cur->ai_addr, ai_cur->ai_addrlen,
1222 host, sizeof(host), service, sizeof(service),
1223 NI_NUMERICHOST | NI_NUMERICSERV);
1224 TRACE("trying %s:%s\n", host, service);
1225 }
1226
1227 sock = socket(ai_cur->ai_family, ai_cur->ai_socktype, ai_cur->ai_protocol);
1228 if (sock == -1)
1229 {
1230 WARN("socket() failed: %s\n", strerror(errno));
1231 status = RPC_S_CANT_CREATE_ENDPOINT;
1232 continue;
1233 }
1234
1235 ret = bind(sock, ai_cur->ai_addr, ai_cur->ai_addrlen);
1236 if (ret < 0)
1237 {
1238 WARN("bind failed: %s\n", strerror(errno));
1239 closesocket(sock);
1240 if (errno == EADDRINUSE)
1241 status = RPC_S_DUPLICATE_ENDPOINT;
1242 else
1243 status = RPC_S_CANT_CREATE_ENDPOINT;
1244 continue;
1245 }
1246
1247 sa_len = sizeof(sa);
1248 if (getsockname(sock, (struct sockaddr *)&sa, &sa_len))
1249 {
1250 WARN("getsockname() failed: %s\n", strerror(errno));
1251 status = RPC_S_CANT_CREATE_ENDPOINT;
1252 continue;
1253 }
1254
1255 ret = getnameinfo((struct sockaddr *)&sa, sa_len,
1256 NULL, 0, service, sizeof(service),
1257 NI_NUMERICSERV);
1258 if (ret)
1259 {
1260 WARN("getnameinfo failed: %s\n", gai_strerror(ret));
1261 status = RPC_S_CANT_CREATE_ENDPOINT;
1262 continue;
1263 }
1264
1265 create_status = RPCRT4_CreateConnection((RpcConnection **)&tcpc, TRUE,
1266 protseq->Protseq, NULL,
1267 service, NULL, NULL, NULL);
1268 if (create_status != RPC_S_OK)
1269 {
1270 closesocket(sock);
1271 status = create_status;
1272 continue;
1273 }
1274
1275 tcpc->sock = sock;
1276 ret = listen(sock, protseq->MaxCalls);
1277 if (ret < 0)
1278 {
1279 WARN("listen failed: %s\n", strerror(errno));
1280 RPCRT4_DestroyConnection(&tcpc->common);
1281 status = RPC_S_OUT_OF_RESOURCES;
1282 continue;
1283 }
1284 /* need a non-blocking socket, otherwise accept() has a potential
1285 * race-condition (poll() says it is readable, connection drops,
1286 * and accept() blocks until the next connection comes...)
1287 */
1288 nonblocking = 1;
1289 ret = ioctlsocket(sock, FIONBIO, &nonblocking);
1290 if (ret < 0)
1291 {
1292 WARN("couldn't make socket non-blocking, error %d\n", ret);
1293 RPCRT4_DestroyConnection(&tcpc->common);
1294 status = RPC_S_OUT_OF_RESOURCES;
1295 continue;
1296 }
1297
1298 tcpc->common.Next = first_connection;
1299 first_connection = &tcpc->common;
1300
1301 /* since IPv4 and IPv6 share the same port space, we only need one
1302 * successful bind to listen for both */
1303 break;
1304 }
1305
1306 freeaddrinfo(ai);
1307
1308 /* if at least one connection was created for an endpoint then
1309 * return success */
1310 if (first_connection)
1311 {
1312 RpcConnection *conn;
1313
1314 /* find last element in list */
1315 for (conn = first_connection; conn->Next; conn = conn->Next)
1316 ;
1317
1318 EnterCriticalSection(&protseq->cs);
1319 conn->Next = protseq->conn;
1320 protseq->conn = first_connection;
1321 LeaveCriticalSection(&protseq->cs);
1322
1323 TRACE("listening on %s\n", endpoint);
1324 return RPC_S_OK;
1325 }
1326
1327 ERR("couldn't listen on port %s\n", endpoint);
1328 return status;
1329 }
1330
1331 static RPC_STATUS rpcrt4_conn_tcp_handoff(RpcConnection *old_conn, RpcConnection *new_conn)
1332 {
1333 int ret;
1334 struct sockaddr_in address;
1335 socklen_t addrsize;
1336 RpcConnection_tcp *server = (RpcConnection_tcp*) old_conn;
1337 RpcConnection_tcp *client = (RpcConnection_tcp*) new_conn;
1338 u_long nonblocking;
1339
1340 addrsize = sizeof(address);
1341 ret = accept(server->sock, (struct sockaddr*) &address, &addrsize);
1342 if (ret < 0)
1343 {
1344 ERR("Failed to accept a TCP connection: error %d\n", ret);
1345 return RPC_S_OUT_OF_RESOURCES;
1346 }
1347 nonblocking = 1;
1348 ioctlsocket(ret, FIONBIO, &nonblocking);
1349 client->sock = ret;
1350 TRACE("Accepted a new TCP connection\n");
1351 return RPC_S_OK;
1352 }
1353
1354 static int rpcrt4_conn_tcp_read(RpcConnection *Connection,
1355 void *buffer, unsigned int count)
1356 {
1357 RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
1358 int bytes_read = 0;
1359 while (bytes_read != count)
1360 {
1361 int r = recv(tcpc->sock, (char *)buffer + bytes_read, count - bytes_read, 0);
1362 if (!r)
1363 return -1;
1364 else if (r > 0)
1365 bytes_read += r;
1366 else if (errno != EAGAIN)
1367 {
1368 WARN("recv() failed: %s\n", strerror(errno));
1369 return -1;
1370 }
1371 else
1372 {
1373 if (!rpcrt4_sock_wait_for_recv(tcpc))
1374 return -1;
1375 }
1376 }
1377 TRACE("%d %p %u -> %d\n", tcpc->sock, buffer, count, bytes_read);
1378 return bytes_read;
1379 }
1380
1381 static int rpcrt4_conn_tcp_write(RpcConnection *Connection,
1382 const void *buffer, unsigned int count)
1383 {
1384 RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
1385 int bytes_written = 0;
1386 while (bytes_written != count)
1387 {
1388 int r = send(tcpc->sock, (const char *)buffer + bytes_written, count - bytes_written, 0);
1389 if (r >= 0)
1390 bytes_written += r;
1391 else if (errno != EAGAIN)
1392 return -1;
1393 else
1394 {
1395 if (!rpcrt4_sock_wait_for_send(tcpc))
1396 return -1;
1397 }
1398 }
1399 TRACE("%d %p %u -> %d\n", tcpc->sock, buffer, count, bytes_written);
1400 return bytes_written;
1401 }
1402
1403 static int rpcrt4_conn_tcp_close(RpcConnection *Connection)
1404 {
1405 RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
1406
1407 TRACE("%d\n", tcpc->sock);
1408
1409 if (tcpc->sock != -1)
1410 closesocket(tcpc->sock);
1411 tcpc->sock = -1;
1412 rpcrt4_sock_wait_destroy(tcpc);
1413 return 0;
1414 }
1415
1416 static void rpcrt4_conn_tcp_cancel_call(RpcConnection *Connection)
1417 {
1418 RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
1419 TRACE("%p\n", Connection);
1420 rpcrt4_sock_wait_cancel(tcpc);
1421 }
1422
1423 static int rpcrt4_conn_tcp_wait_for_incoming_data(RpcConnection *Connection)
1424 {
1425 RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
1426
1427 TRACE("%p\n", Connection);
1428
1429 if (!rpcrt4_sock_wait_for_recv(tcpc))
1430 return -1;
1431 return 0;
1432 }
1433
1434 static size_t rpcrt4_ncacn_ip_tcp_get_top_of_tower(unsigned char *tower_data,
1435 const char *networkaddr,
1436 const char *endpoint)
1437 {
1438 return rpcrt4_ip_tcp_get_top_of_tower(tower_data, networkaddr,
1439 EPM_PROTOCOL_TCP, endpoint);
1440 }
1441
1442 #ifdef HAVE_SOCKETPAIR
1443
1444 typedef struct _RpcServerProtseq_sock
1445 {
1446 RpcServerProtseq common;
1447 int mgr_event_rcv;
1448 int mgr_event_snd;
1449 } RpcServerProtseq_sock;
1450
1451 static RpcServerProtseq *rpcrt4_protseq_sock_alloc(void)
1452 {
1453 RpcServerProtseq_sock *ps = HeapAlloc(GetProcessHeap(), 0, sizeof(*ps));
1454 if (ps)
1455 {
1456 int fds[2];
1457 if (!socketpair(PF_UNIX, SOCK_DGRAM, 0, fds))
1458 {
1459 fcntl(fds[0], F_SETFL, O_NONBLOCK);
1460 fcntl(fds[1], F_SETFL, O_NONBLOCK);
1461 ps->mgr_event_rcv = fds[0];
1462 ps->mgr_event_snd = fds[1];
1463 }
1464 else
1465 {
1466 ERR("socketpair failed with error %s\n", strerror(errno));
1467 HeapFree(GetProcessHeap(), 0, ps);
1468 return NULL;
1469 }
1470 }
1471 return &ps->common;
1472 }
1473
1474 static void rpcrt4_protseq_sock_signal_state_changed(RpcServerProtseq *protseq)
1475 {
1476 RpcServerProtseq_sock *sockps = CONTAINING_RECORD(protseq, RpcServerProtseq_sock, common);
1477 char dummy = 1;
1478 write(sockps->mgr_event_snd, &dummy, sizeof(dummy));
1479 }
1480
1481 static void *rpcrt4_protseq_sock_get_wait_array(RpcServerProtseq *protseq, void *prev_array, unsigned int *count)
1482 {
1483 struct pollfd *poll_info = prev_array;
1484 RpcConnection_tcp *conn;
1485 RpcServerProtseq_sock *sockps = CONTAINING_RECORD(protseq, RpcServerProtseq_sock, common);
1486
1487 EnterCriticalSection(&protseq->cs);
1488
1489 /* open and count connections */
1490 *count = 1;
1491 conn = (RpcConnection_tcp *)protseq->conn;
1492 while (conn) {
1493 if (conn->sock != -1)
1494 (*count)++;
1495 conn = (RpcConnection_tcp *)conn->common.Next;
1496 }
1497
1498 /* make array of connections */
1499 if (poll_info)
1500 poll_info = HeapReAlloc(GetProcessHeap(), 0, poll_info, *count*sizeof(*poll_info));
1501 else
1502 poll_info = HeapAlloc(GetProcessHeap(), 0, *count*sizeof(*poll_info));
1503 if (!poll_info)
1504 {
1505 ERR("couldn't allocate poll_info\n");
1506 LeaveCriticalSection(&protseq->cs);
1507 return NULL;
1508 }
1509
1510 poll_info[0].fd = sockps->mgr_event_rcv;
1511 poll_info[0].events = POLLIN;
1512 *count = 1;
1513 conn = CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common);
1514 while (conn) {
1515 if (conn->sock != -1)
1516 {
1517 poll_info[*count].fd = conn->sock;
1518 poll_info[*count].events = POLLIN;
1519 (*count)++;
1520 }
1521 conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common);
1522 }
1523 LeaveCriticalSection(&protseq->cs);
1524 return poll_info;
1525 }
1526
1527 static void rpcrt4_protseq_sock_free_wait_array(RpcServerProtseq *protseq, void *array)
1528 {
1529 HeapFree(GetProcessHeap(), 0, array);
1530 }
1531
1532 static int rpcrt4_protseq_sock_wait_for_new_connection(RpcServerProtseq *protseq, unsigned int count, void *wait_array)
1533 {
1534 struct pollfd *poll_info = wait_array;
1535 int ret;
1536 unsigned int i;
1537 RpcConnection *cconn;
1538 RpcConnection_tcp *conn;
1539
1540 if (!poll_info)
1541 return -1;
1542
1543 ret = poll(poll_info, count, -1);
1544 if (ret < 0)
1545 {
1546 ERR("poll failed with error %d\n", ret);
1547 return -1;
1548 }
1549
1550 for (i = 0; i < count; i++)
1551 if (poll_info[i].revents & POLLIN)
1552 {
1553 /* RPC server event */
1554 if (i == 0)
1555 {
1556 char dummy;
1557 read(poll_info[0].fd, &dummy, sizeof(dummy));
1558 return 0;
1559 }
1560
1561 /* find which connection got a RPC */
1562 EnterCriticalSection(&protseq->cs);
1563 conn = CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common);
1564 while (conn) {
1565 if (poll_info[i].fd == conn->sock) break;
1566 conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common);
1567 }
1568 cconn = NULL;
1569 if (conn)
1570 RPCRT4_SpawnConnection(&cconn, &conn->common);
1571 else
1572 ERR("failed to locate connection for fd %d\n", poll_info[i].fd);
1573 LeaveCriticalSection(&protseq->cs);
1574 if (cconn)
1575 RPCRT4_new_client(cconn);
1576 else
1577 return -1;
1578 }
1579
1580 return 1;
1581 }
1582
1583 #else /* HAVE_SOCKETPAIR */
1584
1585 typedef struct _RpcServerProtseq_sock
1586 {
1587 RpcServerProtseq common;
1588 HANDLE mgr_event;
1589 } RpcServerProtseq_sock;
1590
1591 static RpcServerProtseq *rpcrt4_protseq_sock_alloc(void)
1592 {
1593 RpcServerProtseq_sock *ps = HeapAlloc(GetProcessHeap(), 0, sizeof(*ps));
1594 if (ps)
1595 {
1596 static BOOL wsa_inited;
1597 if (!wsa_inited)
1598 {
1599 WSADATA wsadata;
1600 WSAStartup(MAKEWORD(2, 2), &wsadata);
1601 /* Note: WSAStartup can be called more than once so we don't bother with
1602 * making accesses to wsa_inited thread-safe */
1603 wsa_inited = TRUE;
1604 }
1605 ps->mgr_event = CreateEventW(NULL, FALSE, FALSE, NULL);
1606 }
1607 return &ps->common;
1608 }
1609
1610 static void rpcrt4_protseq_sock_signal_state_changed(RpcServerProtseq *protseq)
1611 {
1612 RpcServerProtseq_sock *sockps = CONTAINING_RECORD(protseq, RpcServerProtseq_sock, common);
1613 SetEvent(sockps->mgr_event);
1614 }
1615
1616 static void *rpcrt4_protseq_sock_get_wait_array(RpcServerProtseq *protseq, void *prev_array, unsigned int *count)
1617 {
1618 HANDLE *objs = prev_array;
1619 RpcConnection_tcp *conn;
1620 RpcServerProtseq_sock *sockps = CONTAINING_RECORD(protseq, RpcServerProtseq_sock, common);
1621
1622 EnterCriticalSection(&protseq->cs);
1623
1624 /* open and count connections */
1625 *count = 1;
1626 conn = CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common);
1627 while (conn)
1628 {
1629 if (conn->sock != -1)
1630 (*count)++;
1631 conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common);
1632 }
1633
1634 /* make array of connections */
1635 if (objs)
1636 objs = HeapReAlloc(GetProcessHeap(), 0, objs, *count*sizeof(HANDLE));
1637 else
1638 objs = HeapAlloc(GetProcessHeap(), 0, *count*sizeof(HANDLE));
1639 if (!objs)
1640 {
1641 ERR("couldn't allocate objs\n");
1642 LeaveCriticalSection(&protseq->cs);
1643 return NULL;
1644 }
1645
1646 objs[0] = sockps->mgr_event;
1647 *count = 1;
1648 conn = CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common);
1649 while (conn)
1650 {
1651 if (conn->sock != -1)
1652 {
1653 int res = WSAEventSelect(conn->sock, conn->sock_event, FD_ACCEPT);
1654 if (res == SOCKET_ERROR)
1655 ERR("WSAEventSelect() failed with error %d\n", WSAGetLastError());
1656 else
1657 {
1658 objs[*count] = conn->sock_event;
1659 (*count)++;
1660 }
1661 }
1662 conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common);
1663 }
1664 LeaveCriticalSection(&protseq->cs);
1665 return objs;
1666 }
1667
1668 static void rpcrt4_protseq_sock_free_wait_array(RpcServerProtseq *protseq, void *array)
1669 {
1670 HeapFree(GetProcessHeap(), 0, array);
1671 }
1672
1673 static int rpcrt4_protseq_sock_wait_for_new_connection(RpcServerProtseq *protseq, unsigned int count, void *wait_array)
1674 {
1675 HANDLE b_handle;
1676 HANDLE *objs = wait_array;
1677 DWORD res;
1678 RpcConnection *cconn;
1679 RpcConnection_tcp *conn;
1680
1681 if (!objs)
1682 return -1;
1683
1684 do
1685 {
1686 /* an alertable wait isn't strictly necessary, but due to our
1687 * overlapped I/O implementation in Wine we need to free some memory
1688 * by the file user APC being called, even if no completion routine was
1689 * specified at the time of starting the async operation */
1690 res = WaitForMultipleObjectsEx(count, objs, FALSE, INFINITE, TRUE);
1691 } while (res == WAIT_IO_COMPLETION);
1692
1693 if (res == WAIT_OBJECT_0)
1694 return 0;
1695 else if (res == WAIT_FAILED)
1696 {
1697 ERR("wait failed with error %d\n", GetLastError());
1698 return -1;
1699 }
1700 else
1701 {
1702 b_handle = objs[res - WAIT_OBJECT_0];
1703 /* find which connection got a RPC */
1704 EnterCriticalSection(&protseq->cs);
1705 conn = CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common);
1706 while (conn)
1707 {
1708 if (b_handle == conn->sock_event) break;
1709 conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common);
1710 }
1711 cconn = NULL;
1712 if (conn)
1713 RPCRT4_SpawnConnection(&cconn, &conn->common);
1714 else
1715 ERR("failed to locate connection for handle %p\n", b_handle);
1716 LeaveCriticalSection(&protseq->cs);
1717 if (cconn)
1718 {
1719 RPCRT4_new_client(cconn);
1720 return 1;
1721 }
1722 else return -1;
1723 }
1724 }
1725
1726 #endif /* HAVE_SOCKETPAIR */
1727
1728 static RPC_STATUS rpcrt4_ncacn_ip_tcp_parse_top_of_tower(const unsigned char *tower_data,
1729 size_t tower_size,
1730 char **networkaddr,
1731 char **endpoint)
1732 {
1733 return rpcrt4_ip_tcp_parse_top_of_tower(tower_data, tower_size,
1734 networkaddr, EPM_PROTOCOL_TCP,
1735 endpoint);
1736 }
1737
1738 static const struct connection_ops conn_protseq_list[] = {
1739 { "ncacn_np",
1740 { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_SMB },
1741 rpcrt4_conn_np_alloc,
1742 rpcrt4_ncacn_np_open,
1743 rpcrt4_ncacn_np_handoff,
1744 rpcrt4_conn_np_read,
1745 rpcrt4_conn_np_write,
1746 rpcrt4_conn_np_close,
1747 rpcrt4_conn_np_cancel_call,
1748 rpcrt4_conn_np_wait_for_incoming_data,
1749 rpcrt4_ncacn_np_get_top_of_tower,
1750 rpcrt4_ncacn_np_parse_top_of_tower,
1751 },
1752 { "ncalrpc",
1753 { EPM_PROTOCOL_NCALRPC, EPM_PROTOCOL_PIPE },
1754 rpcrt4_conn_np_alloc,
1755 rpcrt4_ncalrpc_open,
1756 rpcrt4_ncalrpc_handoff,
1757 rpcrt4_conn_np_read,
1758 rpcrt4_conn_np_write,
1759 rpcrt4_conn_np_close,
1760 rpcrt4_conn_np_cancel_call,
1761 rpcrt4_conn_np_wait_for_incoming_data,
1762 rpcrt4_ncalrpc_get_top_of_tower,
1763 rpcrt4_ncalrpc_parse_top_of_tower,
1764 },
1765 { "ncacn_ip_tcp",
1766 { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_TCP },
1767 rpcrt4_conn_tcp_alloc,
1768 rpcrt4_ncacn_ip_tcp_open,
1769 rpcrt4_conn_tcp_handoff,
1770 rpcrt4_conn_tcp_read,
1771 rpcrt4_conn_tcp_write,
1772 rpcrt4_conn_tcp_close,
1773 rpcrt4_conn_tcp_cancel_call,
1774 rpcrt4_conn_tcp_wait_for_incoming_data,
1775 rpcrt4_ncacn_ip_tcp_get_top_of_tower,
1776 rpcrt4_ncacn_ip_tcp_parse_top_of_tower,
1777 }
1778
1779 };
1780
1781
1782 static const struct protseq_ops protseq_list[] =
1783 {
1784 {
1785 "ncacn_np",
1786 rpcrt4_protseq_np_alloc,
1787 rpcrt4_protseq_np_signal_state_changed,
1788 rpcrt4_protseq_np_get_wait_array,
1789 rpcrt4_protseq_np_free_wait_array,
1790 rpcrt4_protseq_np_wait_for_new_connection,
1791 rpcrt4_protseq_ncacn_np_open_endpoint,
1792 },
1793 {
1794 "ncalrpc",
1795 rpcrt4_protseq_np_alloc,
1796 rpcrt4_protseq_np_signal_state_changed,
1797 rpcrt4_protseq_np_get_wait_array,
1798 rpcrt4_protseq_np_free_wait_array,
1799 rpcrt4_protseq_np_wait_for_new_connection,
1800 rpcrt4_protseq_ncalrpc_open_endpoint,
1801 },
1802 {
1803 "ncacn_ip_tcp",
1804 rpcrt4_protseq_sock_alloc,
1805 rpcrt4_protseq_sock_signal_state_changed,
1806 rpcrt4_protseq_sock_get_wait_array,
1807 rpcrt4_protseq_sock_free_wait_array,
1808 rpcrt4_protseq_sock_wait_for_new_connection,
1809 rpcrt4_protseq_ncacn_ip_tcp_open_endpoint,
1810 },
1811 };
1812
1813 #define ARRAYSIZE(a) (sizeof((a)) / sizeof((a)[0]))
1814
1815 const struct protseq_ops *rpcrt4_get_protseq_ops(const char *protseq)
1816 {
1817 unsigned int i;
1818 for(i=0; i<ARRAYSIZE(protseq_list); i++)
1819 if (!strcmp(protseq_list[i].name, protseq))
1820 return &protseq_list[i];
1821 return NULL;
1822 }
1823
1824 static const struct connection_ops *rpcrt4_get_conn_protseq_ops(const char *protseq)
1825 {
1826 unsigned int i;
1827 for(i=0; i<ARRAYSIZE(conn_protseq_list); i++)
1828 if (!strcmp(conn_protseq_list[i].name, protseq))
1829 return &conn_protseq_list[i];
1830 return NULL;
1831 }
1832
1833 /**** interface to rest of code ****/
1834
1835 RPC_STATUS RPCRT4_OpenClientConnection(RpcConnection* Connection)
1836 {
1837 TRACE("(Connection == ^%p)\n", Connection);
1838
1839 assert(!Connection->server);
1840 return Connection->ops->open_connection_client(Connection);
1841 }
1842
1843 RPC_STATUS RPCRT4_CloseConnection(RpcConnection* Connection)
1844 {
1845 TRACE("(Connection == ^%p)\n", Connection);
1846 if (SecIsValidHandle(&Connection->ctx))
1847 {
1848 DeleteSecurityContext(&Connection->ctx);
1849 SecInvalidateHandle(&Connection->ctx);
1850 }
1851 rpcrt4_conn_close(Connection);
1852 return RPC_S_OK;
1853 }
1854
1855 RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server,
1856 LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint,
1857 LPCWSTR NetworkOptions, RpcAuthInfo* AuthInfo, RpcQualityOfService *QOS)
1858 {
1859 const struct connection_ops *ops;
1860 RpcConnection* NewConnection;
1861
1862 ops = rpcrt4_get_conn_protseq_ops(Protseq);
1863 if (!ops)
1864 {
1865 FIXME("not supported for protseq %s\n", Protseq);
1866 return RPC_S_PROTSEQ_NOT_SUPPORTED;
1867 }
1868
1869 NewConnection = ops->alloc();
1870 NewConnection->Next = NULL;
1871 NewConnection->server_binding = NULL;
1872 NewConnection->server = server;
1873 NewConnection->ops = ops;
1874 NewConnection->NetworkAddr = RPCRT4_strdupA(NetworkAddr);
1875 NewConnection->Endpoint = RPCRT4_strdupA(Endpoint);
1876 NewConnection->NetworkOptions = RPCRT4_strdupW(NetworkOptions);
1877 NewConnection->MaxTransmissionSize = RPC_MAX_PACKET_SIZE;
1878 memset(&NewConnection->ActiveInterface, 0, sizeof(NewConnection->ActiveInterface));
1879 NewConnection->NextCallId = 1;
1880
1881 SecInvalidateHandle(&NewConnection->ctx);
1882 memset(&NewConnection->exp, 0, sizeof(NewConnection->exp));
1883 NewConnection->attr = 0;
1884 if (AuthInfo) RpcAuthInfo_AddRef(AuthInfo);
1885 NewConnection->AuthInfo = AuthInfo;
1886 NewConnection->encryption_auth_len = 0;
1887 NewConnection->signature_auth_len = 0;
1888 if (QOS) RpcQualityOfService_AddRef(QOS);
1889 NewConnection->QOS = QOS;
1890
1891 list_init(&NewConnection->conn_pool_entry);
1892 NewConnection->async_state = NULL;
1893
1894 TRACE("connection: %p\n", NewConnection);
1895 *Connection = NewConnection;
1896
1897 return RPC_S_OK;
1898 }
1899
1900 static RPC_STATUS RPCRT4_SpawnConnection(RpcConnection** Connection, RpcConnection* OldConnection)
1901 {
1902 RPC_STATUS err;
1903
1904 err = RPCRT4_CreateConnection(Connection, OldConnection->server,
1905 rpcrt4_conn_get_name(OldConnection),
1906 OldConnection->NetworkAddr,
1907 OldConnection->Endpoint, NULL,
1908 OldConnection->AuthInfo, OldConnection->QOS);
1909 if (err == RPC_S_OK)
1910 rpcrt4_conn_handoff(OldConnection, *Connection);
1911 return err;
1912 }
1913
1914 RPC_STATUS RPCRT4_DestroyConnection(RpcConnection* Connection)
1915 {
1916 TRACE("connection: %p\n", Connection);
1917
1918 RPCRT4_CloseConnection(Connection);
1919 RPCRT4_strfree(Connection->Endpoint);
1920 RPCRT4_strfree(Connection->NetworkAddr);
1921 HeapFree(GetProcessHeap(), 0, Connection->NetworkOptions);
1922 if (Connection->AuthInfo) RpcAuthInfo_Release(Connection->AuthInfo);
1923 if (Connection->QOS) RpcQualityOfService_Release(Connection->QOS);
1924
1925 /* server-only */
1926 if (Connection->server_binding) RPCRT4_ReleaseBinding(Connection->server_binding);
1927
1928 HeapFree(GetProcessHeap(), 0, Connection);
1929 return RPC_S_OK;
1930 }
1931
1932 RPC_STATUS RpcTransport_GetTopOfTower(unsigned char *tower_data,
1933 size_t *tower_size,
1934 const char *protseq,
1935 const char *networkaddr,
1936 const char *endpoint)
1937 {
1938 twr_empty_floor_t *protocol_floor;
1939 const struct connection_ops *protseq_ops = rpcrt4_get_conn_protseq_ops(protseq);
1940
1941 *tower_size = 0;
1942
1943 if (!protseq_ops)
1944 return RPC_S_INVALID_RPC_PROTSEQ;
1945
1946 if (!tower_data)
1947 {
1948 *tower_size = sizeof(*protocol_floor);
1949 *tower_size += protseq_ops->get_top_of_tower(NULL, networkaddr, endpoint);
1950 return RPC_S_OK;
1951 }
1952
1953 protocol_floor = (twr_empty_floor_t *)tower_data;
1954 protocol_floor->count_lhs = sizeof(protocol_floor->protid);
1955 protocol_floor->protid = protseq_ops->epm_protocols[0];
1956 protocol_floor->count_rhs = 0;
1957
1958 tower_data += sizeof(*protocol_floor);
1959
1960 *tower_size = protseq_ops->get_top_of_tower(tower_data, networkaddr, endpoint);
1961 if (!*tower_size)
1962 return EPT_S_NOT_REGISTERED;
1963
1964 *tower_size += sizeof(*protocol_floor);
1965
1966 return RPC_S_OK;
1967 }
1968
1969 RPC_STATUS RpcTransport_ParseTopOfTower(const unsigned char *tower_data,
1970 size_t tower_size,
1971 char **protseq,
1972 char **networkaddr,
1973 char **endpoint)
1974 {
1975 const twr_empty_floor_t *protocol_floor;
1976 const twr_empty_floor_t *floor4;
1977 const struct connection_ops *protseq_ops = NULL;
1978 RPC_STATUS status;
1979 unsigned int i;
1980
1981 if (tower_size < sizeof(*protocol_floor))
1982 return EPT_S_NOT_REGISTERED;
1983
1984 protocol_floor = (const twr_empty_floor_t *)tower_data;
1985 tower_data += sizeof(*protocol_floor);
1986 tower_size -= sizeof(*protocol_floor);
1987 if ((protocol_floor->count_lhs != sizeof(protocol_floor->protid)) ||
1988 (protocol_floor->count_rhs > tower_size))
1989 return EPT_S_NOT_REGISTERED;
1990 tower_data += protocol_floor->count_rhs;
1991 tower_size -= protocol_floor->count_rhs;
1992
1993 floor4 = (const twr_empty_floor_t *)tower_data;
1994 if ((tower_size < sizeof(*floor4)) ||
1995 (floor4->count_lhs != sizeof(floor4->protid)))
1996 return EPT_S_NOT_REGISTERED;
1997
1998 for(i = 0; i < ARRAYSIZE(conn_protseq_list); i++)
1999 if ((protocol_floor->protid == conn_protseq_list[i].epm_protocols[0]) &&
2000 (floor4->protid == conn_protseq_list[i].epm_protocols[1]))
2001 {
2002 protseq_ops = &conn_protseq_list[i];
2003 break;
2004 }
2005
2006 if (!protseq_ops)
2007 return EPT_S_NOT_REGISTERED;
2008
2009 status = protseq_ops->parse_top_of_tower(tower_data, tower_size, networkaddr, endpoint);
2010
2011 if ((status == RPC_S_OK) && protseq)
2012 {
2013 *protseq = I_RpcAllocate(strlen(protseq_ops->name) + 1);
2014 strcpy(*protseq, protseq_ops->name);
2015 }
2016
2017 return status;
2018 }
2019
2020 /***********************************************************************
2021 * RpcNetworkIsProtseqValidW (RPCRT4.@)
2022 *
2023 * Checks if the given protocol sequence is known by the RPC system.
2024 * If it is, returns RPC_S_OK, otherwise RPC_S_PROTSEQ_NOT_SUPPORTED.
2025 *
2026 */
2027 RPC_STATUS WINAPI RpcNetworkIsProtseqValidW(RPC_WSTR protseq)
2028 {
2029 char ps[0x10];
2030
2031 WideCharToMultiByte(CP_ACP, 0, protseq, -1,
2032 ps, sizeof ps, NULL, NULL);
2033 if (rpcrt4_get_conn_protseq_ops(ps))
2034 return RPC_S_OK;
2035
2036 FIXME("Unknown protseq %s\n", debugstr_w(protseq));
2037
2038 return RPC_S_INVALID_RPC_PROTSEQ;
2039 }
2040
2041 /***********************************************************************
2042 * RpcNetworkIsProtseqValidA (RPCRT4.@)
2043 */
2044 RPC_STATUS WINAPI RpcNetworkIsProtseqValidA(RPC_CSTR protseq)
2045 {
2046 UNICODE_STRING protseqW;
2047
2048 if (RtlCreateUnicodeStringFromAsciiz(&protseqW, (char*)protseq))
2049 {
2050 RPC_STATUS ret = RpcNetworkIsProtseqValidW(protseqW.Buffer);
2051 RtlFreeUnicodeString(&protseqW);
2052 return ret;
2053 }
2054 return RPC_S_OUT_OF_MEMORY;
2055 }