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