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