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