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