msvcr71: Forward more functions to msvcrt.dll.
[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 # undef errno
44 # define errno WSAGetLastError()
45 #else
46 # include <errno.h>
47 # ifdef HAVE_UNISTD_H
48 #  include <unistd.h>
49 # endif
50 # include <fcntl.h>
51 # ifdef HAVE_SYS_SOCKET_H
52 #  include <sys/socket.h>
53 # endif
54 # ifdef HAVE_NETINET_IN_H
55 #  include <netinet/in.h>
56 # endif
57 # ifdef HAVE_NETINET_TCP_H
58 #  include <netinet/tcp.h>
59 # endif
60 # ifdef HAVE_ARPA_INET_H
61 #  include <arpa/inet.h>
62 # endif
63 # ifdef HAVE_NETDB_H
64 #  include <netdb.h>
65 # endif
66 # ifdef HAVE_SYS_POLL_H
67 #  include <sys/poll.h>
68 # endif
69 # ifdef HAVE_SYS_FILIO_H
70 #  include <sys/filio.h>
71 # endif
72 # ifdef HAVE_SYS_IOCTL_H
73 #  include <sys/ioctl.h>
74 # endif
75 # define closesocket close
76 # define ioctlsocket ioctl
77 #endif /* defined(__MINGW32__) || defined (_MSC_VER) */
78
79 #include "windef.h"
80 #include "winbase.h"
81 #include "winnls.h"
82 #include "winerror.h"
83 #include "wininet.h"
84 #include "winternl.h"
85 #include "wine/unicode.h"
86
87 #include "rpc.h"
88 #include "rpcndr.h"
89
90 #include "wine/debug.h"
91
92 #include "rpc_binding.h"
93 #include "rpc_assoc.h"
94 #include "rpc_message.h"
95 #include "rpc_server.h"
96 #include "epm_towers.h"
97
98 #ifndef SOL_TCP
99 # define SOL_TCP IPPROTO_TCP
100 #endif
101
102 #define DEFAULT_NCACN_HTTP_TIMEOUT (60 * 1000)
103
104 WINE_DEFAULT_DEBUG_CHANNEL(rpc);
105
106 static RPC_STATUS RPCRT4_SpawnConnection(RpcConnection** Connection, RpcConnection* OldConnection);
107
108 /**** ncacn_np support ****/
109
110 typedef struct _RpcConnection_np
111 {
112   RpcConnection common;
113   HANDLE pipe;
114   OVERLAPPED ovl;
115   BOOL listening;
116 } RpcConnection_np;
117
118 static RpcConnection *rpcrt4_conn_np_alloc(void)
119 {
120   RpcConnection_np *npc = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcConnection_np));
121   if (npc)
122   {
123     npc->pipe = NULL;
124     memset(&npc->ovl, 0, sizeof(npc->ovl));
125     npc->listening = FALSE;
126   }
127   return &npc->common;
128 }
129
130 static RPC_STATUS rpcrt4_conn_listen_pipe(RpcConnection_np *npc)
131 {
132   if (npc->listening)
133     return RPC_S_OK;
134
135   npc->listening = TRUE;
136   for (;;)
137   {
138       if (ConnectNamedPipe(npc->pipe, &npc->ovl))
139           return RPC_S_OK;
140
141       switch(GetLastError())
142       {
143       case ERROR_PIPE_CONNECTED:
144           SetEvent(npc->ovl.hEvent);
145           return RPC_S_OK;
146       case ERROR_IO_PENDING:
147           /* will be completed in rpcrt4_protseq_np_wait_for_new_connection */
148           return RPC_S_OK;
149       case ERROR_NO_DATA_DETECTED:
150           /* client has disconnected, retry */
151           DisconnectNamedPipe( npc->pipe );
152           break;
153       default:
154           npc->listening = FALSE;
155           WARN("Couldn't ConnectNamedPipe (error was %d)\n", GetLastError());
156           return RPC_S_OUT_OF_RESOURCES;
157       }
158   }
159 }
160
161 static RPC_STATUS rpcrt4_conn_create_pipe(RpcConnection *Connection, LPCSTR pname)
162 {
163   RpcConnection_np *npc = (RpcConnection_np *) Connection;
164   TRACE("listening on %s\n", pname);
165
166   npc->pipe = CreateNamedPipeA(pname, PIPE_ACCESS_DUPLEX,
167                                PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE,
168                                PIPE_UNLIMITED_INSTANCES,
169                                RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE, 5000, NULL);
170   if (npc->pipe == INVALID_HANDLE_VALUE) {
171     WARN("CreateNamedPipe failed with error %d\n", GetLastError());
172     if (GetLastError() == ERROR_FILE_EXISTS)
173       return RPC_S_DUPLICATE_ENDPOINT;
174     else
175       return RPC_S_CANT_CREATE_ENDPOINT;
176   }
177
178   memset(&npc->ovl, 0, sizeof(npc->ovl));
179   npc->ovl.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
180
181   /* Note: we don't call ConnectNamedPipe here because it must be done in the
182    * server thread as the thread must be alertable */
183   return RPC_S_OK;
184 }
185
186 static RPC_STATUS rpcrt4_conn_open_pipe(RpcConnection *Connection, LPCSTR pname, BOOL wait)
187 {
188   RpcConnection_np *npc = (RpcConnection_np *) Connection;
189   HANDLE pipe;
190   DWORD err, dwMode;
191
192   TRACE("connecting to %s\n", pname);
193
194   while (TRUE) {
195     DWORD dwFlags = 0;
196     if (Connection->QOS)
197     {
198         dwFlags = SECURITY_SQOS_PRESENT;
199         switch (Connection->QOS->qos->ImpersonationType)
200         {
201             case RPC_C_IMP_LEVEL_DEFAULT:
202                 /* FIXME: what to do here? */
203                 break;
204             case RPC_C_IMP_LEVEL_ANONYMOUS:
205                 dwFlags |= SECURITY_ANONYMOUS;
206                 break;
207             case RPC_C_IMP_LEVEL_IDENTIFY:
208                 dwFlags |= SECURITY_IDENTIFICATION;
209                 break;
210             case RPC_C_IMP_LEVEL_IMPERSONATE:
211                 dwFlags |= SECURITY_IMPERSONATION;
212                 break;
213             case RPC_C_IMP_LEVEL_DELEGATE:
214                 dwFlags |= SECURITY_DELEGATION;
215                 break;
216         }
217         if (Connection->QOS->qos->IdentityTracking == RPC_C_QOS_IDENTITY_DYNAMIC)
218             dwFlags |= SECURITY_CONTEXT_TRACKING;
219     }
220     pipe = CreateFileA(pname, GENERIC_READ|GENERIC_WRITE, 0, NULL,
221                        OPEN_EXISTING, dwFlags, 0);
222     if (pipe != INVALID_HANDLE_VALUE) break;
223     err = GetLastError();
224     if (err == ERROR_PIPE_BUSY) {
225       TRACE("connection failed, error=%x\n", err);
226       return RPC_S_SERVER_TOO_BUSY;
227     }
228     if (!wait || !WaitNamedPipeA(pname, NMPWAIT_WAIT_FOREVER)) {
229       err = GetLastError();
230       WARN("connection failed, error=%x\n", err);
231       return RPC_S_SERVER_UNAVAILABLE;
232     }
233   }
234
235   /* success */
236   memset(&npc->ovl, 0, sizeof(npc->ovl));
237   /* pipe is connected; change to message-read mode. */
238   dwMode = PIPE_READMODE_MESSAGE;
239   SetNamedPipeHandleState(pipe, &dwMode, NULL, NULL);
240   npc->ovl.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
241   npc->pipe = pipe;
242
243   return RPC_S_OK;
244 }
245
246 static RPC_STATUS rpcrt4_ncalrpc_open(RpcConnection* Connection)
247 {
248   RpcConnection_np *npc = (RpcConnection_np *) Connection;
249   static const char prefix[] = "\\\\.\\pipe\\lrpc\\";
250   RPC_STATUS r;
251   LPSTR pname;
252
253   /* already connected? */
254   if (npc->pipe)
255     return RPC_S_OK;
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_open_pipe(Connection, pname, TRUE);
262   I_RpcFree(pname);
263
264   return r;
265 }
266
267 static RPC_STATUS rpcrt4_protseq_ncalrpc_open_endpoint(RpcServerProtseq* protseq, const char *endpoint)
268 {
269   static const char prefix[] = "\\\\.\\pipe\\lrpc\\";
270   RPC_STATUS r;
271   LPSTR pname;
272   RpcConnection *Connection;
273   char generated_endpoint[22];
274
275   if (!endpoint)
276   {
277     static LONG lrpc_nameless_id;
278     DWORD process_id = GetCurrentProcessId();
279     ULONG id = InterlockedIncrement(&lrpc_nameless_id);
280     snprintf(generated_endpoint, sizeof(generated_endpoint),
281              "LRPC%08x.%08x", process_id, id);
282     endpoint = generated_endpoint;
283   }
284
285   r = RPCRT4_CreateConnection(&Connection, TRUE, protseq->Protseq, NULL,
286                               endpoint, NULL, NULL, NULL);
287   if (r != RPC_S_OK)
288       return r;
289
290   /* protseq=ncalrpc: supposed to use NT LPC ports,
291    * but we'll implement it with named pipes for now */
292   pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1);
293   strcat(strcpy(pname, prefix), Connection->Endpoint);
294   r = rpcrt4_conn_create_pipe(Connection, pname);
295   I_RpcFree(pname);
296
297   EnterCriticalSection(&protseq->cs);
298   Connection->Next = protseq->conn;
299   protseq->conn = Connection;
300   LeaveCriticalSection(&protseq->cs);
301
302   return r;
303 }
304
305 static RPC_STATUS rpcrt4_ncacn_np_open(RpcConnection* Connection)
306 {
307   RpcConnection_np *npc = (RpcConnection_np *) Connection;
308   static const char prefix[] = "\\\\.";
309   RPC_STATUS r;
310   LPSTR pname;
311
312   /* already connected? */
313   if (npc->pipe)
314     return RPC_S_OK;
315
316   /* protseq=ncacn_np: named pipes */
317   pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1);
318   strcat(strcpy(pname, prefix), Connection->Endpoint);
319   r = rpcrt4_conn_open_pipe(Connection, pname, FALSE);
320   I_RpcFree(pname);
321
322   return r;
323 }
324
325 static RPC_STATUS rpcrt4_protseq_ncacn_np_open_endpoint(RpcServerProtseq *protseq, const char *endpoint)
326 {
327   static const char prefix[] = "\\\\.";
328   RPC_STATUS r;
329   LPSTR pname;
330   RpcConnection *Connection;
331   char generated_endpoint[21];
332
333   if (!endpoint)
334   {
335     static LONG np_nameless_id;
336     DWORD process_id = GetCurrentProcessId();
337     ULONG id = InterlockedExchangeAdd(&np_nameless_id, 1 );
338     snprintf(generated_endpoint, sizeof(generated_endpoint),
339              "\\\\pipe\\\\%08x.%03x", process_id, id);
340     endpoint = generated_endpoint;
341   }
342
343   r = RPCRT4_CreateConnection(&Connection, TRUE, protseq->Protseq, NULL,
344                               endpoint, NULL, NULL, NULL);
345   if (r != RPC_S_OK)
346     return r;
347
348   /* protseq=ncacn_np: named pipes */
349   pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1);
350   strcat(strcpy(pname, prefix), Connection->Endpoint);
351   r = rpcrt4_conn_create_pipe(Connection, pname);
352   I_RpcFree(pname);
353
354   EnterCriticalSection(&protseq->cs);
355   Connection->Next = protseq->conn;
356   protseq->conn = Connection;
357   LeaveCriticalSection(&protseq->cs);
358
359   return r;
360 }
361
362 static void rpcrt4_conn_np_handoff(RpcConnection_np *old_npc, RpcConnection_np *new_npc)
363 {    
364   /* because of the way named pipes work, we'll transfer the connected pipe
365    * to the child, then reopen the server binding to continue listening */
366
367   new_npc->pipe = old_npc->pipe;
368   new_npc->ovl = old_npc->ovl;
369   old_npc->pipe = 0;
370   memset(&old_npc->ovl, 0, sizeof(old_npc->ovl));
371   old_npc->listening = FALSE;
372 }
373
374 static RPC_STATUS rpcrt4_ncacn_np_handoff(RpcConnection *old_conn, RpcConnection *new_conn)
375 {
376   RPC_STATUS status;
377   LPSTR pname;
378   static const char prefix[] = "\\\\.";
379
380   rpcrt4_conn_np_handoff((RpcConnection_np *)old_conn, (RpcConnection_np *)new_conn);
381
382   pname = I_RpcAllocate(strlen(prefix) + strlen(old_conn->Endpoint) + 1);
383   strcat(strcpy(pname, prefix), old_conn->Endpoint);
384   status = rpcrt4_conn_create_pipe(old_conn, pname);
385   I_RpcFree(pname);
386
387   return status;
388 }
389
390 static RPC_STATUS rpcrt4_ncalrpc_handoff(RpcConnection *old_conn, RpcConnection *new_conn)
391 {
392   RPC_STATUS status;
393   LPSTR pname;
394   static const char prefix[] = "\\\\.\\pipe\\lrpc\\";
395
396   TRACE("%s\n", old_conn->Endpoint);
397
398   rpcrt4_conn_np_handoff((RpcConnection_np *)old_conn, (RpcConnection_np *)new_conn);
399
400   pname = I_RpcAllocate(strlen(prefix) + strlen(old_conn->Endpoint) + 1);
401   strcat(strcpy(pname, prefix), old_conn->Endpoint);
402   status = rpcrt4_conn_create_pipe(old_conn, pname);
403   I_RpcFree(pname);
404     
405   return status;
406 }
407
408 static int rpcrt4_conn_np_read(RpcConnection *Connection,
409                         void *buffer, unsigned int count)
410 {
411   RpcConnection_np *npc = (RpcConnection_np *) Connection;
412   char *buf = buffer;
413   BOOL ret = TRUE;
414   unsigned int bytes_left = count;
415
416   while (bytes_left)
417   {
418     DWORD bytes_read;
419     ret = ReadFile(npc->pipe, buf, bytes_left, &bytes_read, NULL);
420     if (!ret && GetLastError() == ERROR_MORE_DATA)
421         ret = TRUE;
422     if (!ret || !bytes_read)
423         break;
424     bytes_left -= bytes_read;
425     buf += bytes_read;
426   }
427   return ret ? count : -1;
428 }
429
430 static int rpcrt4_conn_np_write(RpcConnection *Connection,
431                              const void *buffer, unsigned int count)
432 {
433   RpcConnection_np *npc = (RpcConnection_np *) Connection;
434   const char *buf = buffer;
435   BOOL ret = TRUE;
436   unsigned int bytes_left = count;
437
438   while (bytes_left)
439   {
440     DWORD bytes_written;
441     ret = WriteFile(npc->pipe, buf, bytes_left, &bytes_written, NULL);
442     if (!ret || !bytes_written)
443         break;
444     bytes_left -= bytes_written;
445     buf += bytes_written;
446   }
447   return ret ? count : -1;
448 }
449
450 static int rpcrt4_conn_np_close(RpcConnection *Connection)
451 {
452   RpcConnection_np *npc = (RpcConnection_np *) Connection;
453   if (npc->pipe) {
454     FlushFileBuffers(npc->pipe);
455     CloseHandle(npc->pipe);
456     npc->pipe = 0;
457   }
458   if (npc->ovl.hEvent) {
459     CloseHandle(npc->ovl.hEvent);
460     npc->ovl.hEvent = 0;
461   }
462   return 0;
463 }
464
465 static void rpcrt4_conn_np_cancel_call(RpcConnection *Connection)
466 {
467     /* FIXME: implement when named pipe writes use overlapped I/O */
468 }
469
470 static int rpcrt4_conn_np_wait_for_incoming_data(RpcConnection *Connection)
471 {
472     /* FIXME: implement when named pipe writes use overlapped I/O */
473     return -1;
474 }
475
476 static size_t rpcrt4_ncacn_np_get_top_of_tower(unsigned char *tower_data,
477                                                const char *networkaddr,
478                                                const char *endpoint)
479 {
480     twr_empty_floor_t *smb_floor;
481     twr_empty_floor_t *nb_floor;
482     size_t size;
483     size_t networkaddr_size;
484     size_t endpoint_size;
485
486     TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint);
487
488     networkaddr_size = networkaddr ? strlen(networkaddr) + 1 : 1;
489     endpoint_size = endpoint ? strlen(endpoint) + 1 : 1;
490     size = sizeof(*smb_floor) + endpoint_size + sizeof(*nb_floor) + networkaddr_size;
491
492     if (!tower_data)
493         return size;
494
495     smb_floor = (twr_empty_floor_t *)tower_data;
496
497     tower_data += sizeof(*smb_floor);
498
499     smb_floor->count_lhs = sizeof(smb_floor->protid);
500     smb_floor->protid = EPM_PROTOCOL_SMB;
501     smb_floor->count_rhs = endpoint_size;
502
503     if (endpoint)
504         memcpy(tower_data, endpoint, endpoint_size);
505     else
506         tower_data[0] = 0;
507     tower_data += endpoint_size;
508
509     nb_floor = (twr_empty_floor_t *)tower_data;
510
511     tower_data += sizeof(*nb_floor);
512
513     nb_floor->count_lhs = sizeof(nb_floor->protid);
514     nb_floor->protid = EPM_PROTOCOL_NETBIOS;
515     nb_floor->count_rhs = networkaddr_size;
516
517     if (networkaddr)
518         memcpy(tower_data, networkaddr, networkaddr_size);
519     else
520         tower_data[0] = 0;
521
522     return size;
523 }
524
525 static RPC_STATUS rpcrt4_ncacn_np_parse_top_of_tower(const unsigned char *tower_data,
526                                                      size_t tower_size,
527                                                      char **networkaddr,
528                                                      char **endpoint)
529 {
530     const twr_empty_floor_t *smb_floor = (const twr_empty_floor_t *)tower_data;
531     const twr_empty_floor_t *nb_floor;
532
533     TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint);
534
535     if (tower_size < sizeof(*smb_floor))
536         return EPT_S_NOT_REGISTERED;
537
538     tower_data += sizeof(*smb_floor);
539     tower_size -= sizeof(*smb_floor);
540
541     if ((smb_floor->count_lhs != sizeof(smb_floor->protid)) ||
542         (smb_floor->protid != EPM_PROTOCOL_SMB) ||
543         (smb_floor->count_rhs > tower_size) ||
544         (tower_data[smb_floor->count_rhs - 1] != '\0'))
545         return EPT_S_NOT_REGISTERED;
546
547     if (endpoint)
548     {
549         *endpoint = I_RpcAllocate(smb_floor->count_rhs);
550         if (!*endpoint)
551             return RPC_S_OUT_OF_RESOURCES;
552         memcpy(*endpoint, tower_data, smb_floor->count_rhs);
553     }
554     tower_data += smb_floor->count_rhs;
555     tower_size -= smb_floor->count_rhs;
556
557     if (tower_size < sizeof(*nb_floor))
558         return EPT_S_NOT_REGISTERED;
559
560     nb_floor = (const twr_empty_floor_t *)tower_data;
561
562     tower_data += sizeof(*nb_floor);
563     tower_size -= sizeof(*nb_floor);
564
565     if ((nb_floor->count_lhs != sizeof(nb_floor->protid)) ||
566         (nb_floor->protid != EPM_PROTOCOL_NETBIOS) ||
567         (nb_floor->count_rhs > tower_size) ||
568         (tower_data[nb_floor->count_rhs - 1] != '\0'))
569         return EPT_S_NOT_REGISTERED;
570
571     if (networkaddr)
572     {
573         *networkaddr = I_RpcAllocate(nb_floor->count_rhs);
574         if (!*networkaddr)
575         {
576             if (endpoint)
577             {
578                 I_RpcFree(*endpoint);
579                 *endpoint = NULL;
580             }
581             return RPC_S_OUT_OF_RESOURCES;
582         }
583         memcpy(*networkaddr, tower_data, nb_floor->count_rhs);
584     }
585
586     return RPC_S_OK;
587 }
588
589 static RPC_STATUS rpcrt4_conn_np_impersonate_client(RpcConnection *conn)
590 {
591     RpcConnection_np *npc = (RpcConnection_np *)conn;
592     BOOL ret;
593
594     TRACE("(%p)\n", conn);
595
596     if (conn->AuthInfo && SecIsValidHandle(&conn->ctx))
597         return RPCRT4_default_impersonate_client(conn);
598
599     ret = ImpersonateNamedPipeClient(npc->pipe);
600     if (!ret)
601     {
602         DWORD error = GetLastError();
603         WARN("ImpersonateNamedPipeClient failed with error %u\n", error);
604         switch (error)
605         {
606         case ERROR_CANNOT_IMPERSONATE:
607             return RPC_S_NO_CONTEXT_AVAILABLE;
608         }
609     }
610     return RPC_S_OK;
611 }
612
613 static RPC_STATUS rpcrt4_conn_np_revert_to_self(RpcConnection *conn)
614 {
615     BOOL ret;
616
617     TRACE("(%p)\n", conn);
618
619     if (conn->AuthInfo && SecIsValidHandle(&conn->ctx))
620         return RPCRT4_default_revert_to_self(conn);
621
622     ret = RevertToSelf();
623     if (!ret)
624     {
625         WARN("RevertToSelf failed with error %u\n", GetLastError());
626         return RPC_S_NO_CONTEXT_AVAILABLE;
627     }
628     return RPC_S_OK;
629 }
630
631 typedef struct _RpcServerProtseq_np
632 {
633     RpcServerProtseq common;
634     HANDLE mgr_event;
635 } RpcServerProtseq_np;
636
637 static RpcServerProtseq *rpcrt4_protseq_np_alloc(void)
638 {
639     RpcServerProtseq_np *ps = HeapAlloc(GetProcessHeap(), 0, sizeof(*ps));
640     if (ps)
641         ps->mgr_event = CreateEventW(NULL, FALSE, FALSE, NULL);
642     return &ps->common;
643 }
644
645 static void rpcrt4_protseq_np_signal_state_changed(RpcServerProtseq *protseq)
646 {
647     RpcServerProtseq_np *npps = CONTAINING_RECORD(protseq, RpcServerProtseq_np, common);
648     SetEvent(npps->mgr_event);
649 }
650
651 static void *rpcrt4_protseq_np_get_wait_array(RpcServerProtseq *protseq, void *prev_array, unsigned int *count)
652 {
653     HANDLE *objs = prev_array;
654     RpcConnection_np *conn;
655     RpcServerProtseq_np *npps = CONTAINING_RECORD(protseq, RpcServerProtseq_np, common);
656     
657     EnterCriticalSection(&protseq->cs);
658     
659     /* open and count connections */
660     *count = 1;
661     conn = CONTAINING_RECORD(protseq->conn, RpcConnection_np, common);
662     while (conn) {
663         rpcrt4_conn_listen_pipe(conn);
664         if (conn->ovl.hEvent)
665             (*count)++;
666         conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_np, common);
667     }
668     
669     /* make array of connections */
670     if (objs)
671         objs = HeapReAlloc(GetProcessHeap(), 0, objs, *count*sizeof(HANDLE));
672     else
673         objs = HeapAlloc(GetProcessHeap(), 0, *count*sizeof(HANDLE));
674     if (!objs)
675     {
676         ERR("couldn't allocate objs\n");
677         LeaveCriticalSection(&protseq->cs);
678         return NULL;
679     }
680     
681     objs[0] = npps->mgr_event;
682     *count = 1;
683     conn = CONTAINING_RECORD(protseq->conn, RpcConnection_np, common);
684     while (conn) {
685         if ((objs[*count] = conn->ovl.hEvent))
686             (*count)++;
687         conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_np, common);
688     }
689     LeaveCriticalSection(&protseq->cs);
690     return objs;
691 }
692
693 static void rpcrt4_protseq_np_free_wait_array(RpcServerProtseq *protseq, void *array)
694 {
695     HeapFree(GetProcessHeap(), 0, array);
696 }
697
698 static int rpcrt4_protseq_np_wait_for_new_connection(RpcServerProtseq *protseq, unsigned int count, void *wait_array)
699 {
700     HANDLE b_handle;
701     HANDLE *objs = wait_array;
702     DWORD res;
703     RpcConnection *cconn;
704     RpcConnection_np *conn;
705     
706     if (!objs)
707         return -1;
708
709     do
710     {
711         /* an alertable wait isn't strictly necessary, but due to our
712          * overlapped I/O implementation in Wine we need to free some memory
713          * by the file user APC being called, even if no completion routine was
714          * specified at the time of starting the async operation */
715         res = WaitForMultipleObjectsEx(count, objs, FALSE, INFINITE, TRUE);
716     } while (res == WAIT_IO_COMPLETION);
717
718     if (res == WAIT_OBJECT_0)
719         return 0;
720     else if (res == WAIT_FAILED)
721     {
722         ERR("wait failed with error %d\n", GetLastError());
723         return -1;
724     }
725     else
726     {
727         b_handle = objs[res - WAIT_OBJECT_0];
728         /* find which connection got a RPC */
729         EnterCriticalSection(&protseq->cs);
730         conn = CONTAINING_RECORD(protseq->conn, RpcConnection_np, common);
731         while (conn) {
732             if (b_handle == conn->ovl.hEvent) break;
733             conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_np, common);
734         }
735         cconn = NULL;
736         if (conn)
737             RPCRT4_SpawnConnection(&cconn, &conn->common);
738         else
739             ERR("failed to locate connection for handle %p\n", b_handle);
740         LeaveCriticalSection(&protseq->cs);
741         if (cconn)
742         {
743             RPCRT4_new_client(cconn);
744             return 1;
745         }
746         else return -1;
747     }
748 }
749
750 static size_t rpcrt4_ncalrpc_get_top_of_tower(unsigned char *tower_data,
751                                               const char *networkaddr,
752                                               const char *endpoint)
753 {
754     twr_empty_floor_t *pipe_floor;
755     size_t size;
756     size_t endpoint_size;
757
758     TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint);
759
760     endpoint_size = strlen(endpoint) + 1;
761     size = sizeof(*pipe_floor) + endpoint_size;
762
763     if (!tower_data)
764         return size;
765
766     pipe_floor = (twr_empty_floor_t *)tower_data;
767
768     tower_data += sizeof(*pipe_floor);
769
770     pipe_floor->count_lhs = sizeof(pipe_floor->protid);
771     pipe_floor->protid = EPM_PROTOCOL_PIPE;
772     pipe_floor->count_rhs = endpoint_size;
773
774     memcpy(tower_data, endpoint, endpoint_size);
775
776     return size;
777 }
778
779 static RPC_STATUS rpcrt4_ncalrpc_parse_top_of_tower(const unsigned char *tower_data,
780                                                     size_t tower_size,
781                                                     char **networkaddr,
782                                                     char **endpoint)
783 {
784     const twr_empty_floor_t *pipe_floor = (const twr_empty_floor_t *)tower_data;
785
786     TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint);
787
788     if (tower_size < sizeof(*pipe_floor))
789         return EPT_S_NOT_REGISTERED;
790
791     tower_data += sizeof(*pipe_floor);
792     tower_size -= sizeof(*pipe_floor);
793
794     if ((pipe_floor->count_lhs != sizeof(pipe_floor->protid)) ||
795         (pipe_floor->protid != EPM_PROTOCOL_PIPE) ||
796         (pipe_floor->count_rhs > tower_size) ||
797         (tower_data[pipe_floor->count_rhs - 1] != '\0'))
798         return EPT_S_NOT_REGISTERED;
799
800     if (networkaddr)
801         *networkaddr = NULL;
802
803     if (endpoint)
804     {
805         *endpoint = I_RpcAllocate(pipe_floor->count_rhs);
806         if (!*endpoint)
807             return RPC_S_OUT_OF_RESOURCES;
808         memcpy(*endpoint, tower_data, pipe_floor->count_rhs);
809     }
810
811     return RPC_S_OK;
812 }
813
814 static BOOL rpcrt4_ncalrpc_is_authorized(RpcConnection *conn)
815 {
816     return FALSE;
817 }
818
819 static RPC_STATUS rpcrt4_ncalrpc_authorize(RpcConnection *conn, BOOL first_time,
820                                            unsigned char *in_buffer,
821                                            unsigned int in_size,
822                                            unsigned char *out_buffer,
823                                            unsigned int *out_size)
824 {
825     /* since this protocol is local to the machine there is no need to
826      * authenticate the caller */
827     *out_size = 0;
828     return RPC_S_OK;
829 }
830
831 static RPC_STATUS rpcrt4_ncalrpc_secure_packet(RpcConnection *conn,
832     enum secure_packet_direction dir,
833     RpcPktHdr *hdr, unsigned int hdr_size,
834     unsigned char *stub_data, unsigned int stub_data_size,
835     RpcAuthVerifier *auth_hdr,
836     unsigned char *auth_value, unsigned int auth_value_size)
837 {
838     /* since this protocol is local to the machine there is no need to secure
839      * the packet */
840     return RPC_S_OK;
841 }
842
843 static RPC_STATUS rpcrt4_ncalrpc_inquire_auth_client(
844     RpcConnection *conn, RPC_AUTHZ_HANDLE *privs, RPC_WSTR *server_princ_name,
845     ULONG *authn_level, ULONG *authn_svc, ULONG *authz_svc, ULONG flags)
846 {
847     TRACE("(%p, %p, %p, %p, %p, %p, 0x%x)\n", conn, privs,
848           server_princ_name, authn_level, authn_svc, authz_svc, flags);
849
850     if (privs)
851     {
852         FIXME("privs not implemented\n");
853         *privs = NULL;
854     }
855     if (server_princ_name)
856     {
857         FIXME("server_princ_name not implemented\n");
858         *server_princ_name = NULL;
859     }
860     if (authn_level) *authn_level = RPC_C_AUTHN_LEVEL_PKT_PRIVACY;
861     if (authn_svc) *authn_svc = RPC_C_AUTHN_WINNT;
862     if (authz_svc)
863     {
864         FIXME("authorization service not implemented\n");
865         *authz_svc = RPC_C_AUTHZ_NONE;
866     }
867     if (flags)
868         FIXME("flags 0x%x not implemented\n", flags);
869
870     return RPC_S_OK;
871 }
872
873 /**** ncacn_ip_tcp support ****/
874
875 static size_t rpcrt4_ip_tcp_get_top_of_tower(unsigned char *tower_data,
876                                              const char *networkaddr,
877                                              unsigned char tcp_protid,
878                                              const char *endpoint)
879 {
880     twr_tcp_floor_t *tcp_floor;
881     twr_ipv4_floor_t *ipv4_floor;
882     struct addrinfo *ai;
883     struct addrinfo hints;
884     int ret;
885     size_t size = sizeof(*tcp_floor) + sizeof(*ipv4_floor);
886
887     TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint);
888
889     if (!tower_data)
890         return size;
891
892     tcp_floor = (twr_tcp_floor_t *)tower_data;
893     tower_data += sizeof(*tcp_floor);
894
895     ipv4_floor = (twr_ipv4_floor_t *)tower_data;
896
897     tcp_floor->count_lhs = sizeof(tcp_floor->protid);
898     tcp_floor->protid = tcp_protid;
899     tcp_floor->count_rhs = sizeof(tcp_floor->port);
900
901     ipv4_floor->count_lhs = sizeof(ipv4_floor->protid);
902     ipv4_floor->protid = EPM_PROTOCOL_IP;
903     ipv4_floor->count_rhs = sizeof(ipv4_floor->ipv4addr);
904
905     hints.ai_flags          = AI_NUMERICHOST;
906     /* FIXME: only support IPv4 at the moment. how is IPv6 represented by the EPM? */
907     hints.ai_family         = PF_INET;
908     hints.ai_socktype       = SOCK_STREAM;
909     hints.ai_protocol       = IPPROTO_TCP;
910     hints.ai_addrlen        = 0;
911     hints.ai_addr           = NULL;
912     hints.ai_canonname      = NULL;
913     hints.ai_next           = NULL;
914
915     ret = getaddrinfo(networkaddr, endpoint, &hints, &ai);
916     if (ret)
917     {
918         ret = getaddrinfo("0.0.0.0", endpoint, &hints, &ai);
919         if (ret)
920         {
921             ERR("getaddrinfo failed: %s\n", gai_strerror(ret));
922             return 0;
923         }
924     }
925
926     if (ai->ai_family == PF_INET)
927     {
928         const struct sockaddr_in *sin = (const struct sockaddr_in *)ai->ai_addr;
929         tcp_floor->port = sin->sin_port;
930         ipv4_floor->ipv4addr = sin->sin_addr.s_addr;
931     }
932     else
933     {
934         ERR("unexpected protocol family %d\n", ai->ai_family);
935         return 0;
936     }
937
938     freeaddrinfo(ai);
939
940     return size;
941 }
942
943 static RPC_STATUS rpcrt4_ip_tcp_parse_top_of_tower(const unsigned char *tower_data,
944                                                    size_t tower_size,
945                                                    char **networkaddr,
946                                                    unsigned char tcp_protid,
947                                                    char **endpoint)
948 {
949     const twr_tcp_floor_t *tcp_floor = (const twr_tcp_floor_t *)tower_data;
950     const twr_ipv4_floor_t *ipv4_floor;
951     struct in_addr in_addr;
952
953     TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint);
954
955     if (tower_size < sizeof(*tcp_floor))
956         return EPT_S_NOT_REGISTERED;
957
958     tower_data += sizeof(*tcp_floor);
959     tower_size -= sizeof(*tcp_floor);
960
961     if (tower_size < sizeof(*ipv4_floor))
962         return EPT_S_NOT_REGISTERED;
963
964     ipv4_floor = (const twr_ipv4_floor_t *)tower_data;
965
966     if ((tcp_floor->count_lhs != sizeof(tcp_floor->protid)) ||
967         (tcp_floor->protid != tcp_protid) ||
968         (tcp_floor->count_rhs != sizeof(tcp_floor->port)) ||
969         (ipv4_floor->count_lhs != sizeof(ipv4_floor->protid)) ||
970         (ipv4_floor->protid != EPM_PROTOCOL_IP) ||
971         (ipv4_floor->count_rhs != sizeof(ipv4_floor->ipv4addr)))
972         return EPT_S_NOT_REGISTERED;
973
974     if (endpoint)
975     {
976         *endpoint = I_RpcAllocate(6 /* sizeof("65535") + 1 */);
977         if (!*endpoint)
978             return RPC_S_OUT_OF_RESOURCES;
979         sprintf(*endpoint, "%u", ntohs(tcp_floor->port));
980     }
981
982     if (networkaddr)
983     {
984         *networkaddr = I_RpcAllocate(INET_ADDRSTRLEN);
985         if (!*networkaddr)
986         {
987             if (endpoint)
988             {
989                 I_RpcFree(*endpoint);
990                 *endpoint = NULL;
991             }
992             return RPC_S_OUT_OF_RESOURCES;
993         }
994         in_addr.s_addr = ipv4_floor->ipv4addr;
995         if (!inet_ntop(AF_INET, &in_addr, *networkaddr, INET_ADDRSTRLEN))
996         {
997             ERR("inet_ntop: %s\n", strerror(errno));
998             I_RpcFree(*networkaddr);
999             *networkaddr = NULL;
1000             if (endpoint)
1001             {
1002                 I_RpcFree(*endpoint);
1003                 *endpoint = NULL;
1004             }
1005             return EPT_S_NOT_REGISTERED;
1006         }
1007     }
1008
1009     return RPC_S_OK;
1010 }
1011
1012 typedef struct _RpcConnection_tcp
1013 {
1014   RpcConnection common;
1015   int sock;
1016 #ifdef HAVE_SOCKETPAIR
1017   int cancel_fds[2];
1018 #else
1019   HANDLE sock_event;
1020   HANDLE cancel_event;
1021 #endif
1022 } RpcConnection_tcp;
1023
1024 #ifdef HAVE_SOCKETPAIR
1025
1026 static BOOL rpcrt4_sock_wait_init(RpcConnection_tcp *tcpc)
1027 {
1028   if (socketpair(PF_UNIX, SOCK_STREAM, 0, tcpc->cancel_fds) < 0)
1029   {
1030     ERR("socketpair() failed: %s\n", strerror(errno));
1031     return FALSE;
1032   }
1033   return TRUE;
1034 }
1035
1036 static BOOL rpcrt4_sock_wait_for_recv(RpcConnection_tcp *tcpc)
1037 {
1038   struct pollfd pfds[2];
1039   pfds[0].fd = tcpc->sock;
1040   pfds[0].events = POLLIN;
1041   pfds[1].fd = tcpc->cancel_fds[0];
1042   pfds[1].events = POLLIN;
1043   if (poll(pfds, 2, -1 /* infinite */) == -1 && errno != EINTR)
1044   {
1045     ERR("poll() failed: %s\n", strerror(errno));
1046     return FALSE;
1047   }
1048   if (pfds[1].revents & POLLIN) /* canceled */
1049   {
1050     char dummy;
1051     read(pfds[1].fd, &dummy, sizeof(dummy));
1052     return FALSE;
1053   }
1054   return TRUE;
1055 }
1056
1057 static BOOL rpcrt4_sock_wait_for_send(RpcConnection_tcp *tcpc)
1058 {
1059   struct pollfd pfd;
1060   pfd.fd = tcpc->sock;
1061   pfd.events = POLLOUT;
1062   if (poll(&pfd, 1, -1 /* infinite */) == -1 && errno != EINTR)
1063   {
1064     ERR("poll() failed: %s\n", strerror(errno));
1065     return FALSE;
1066   }
1067   return TRUE;
1068 }
1069
1070 static void rpcrt4_sock_wait_cancel(RpcConnection_tcp *tcpc)
1071 {
1072   char dummy = 1;
1073
1074   write(tcpc->cancel_fds[1], &dummy, 1);
1075 }
1076
1077 static void rpcrt4_sock_wait_destroy(RpcConnection_tcp *tcpc)
1078 {
1079   close(tcpc->cancel_fds[0]);
1080   close(tcpc->cancel_fds[1]);
1081 }
1082
1083 #else /* HAVE_SOCKETPAIR */
1084
1085 static BOOL rpcrt4_sock_wait_init(RpcConnection_tcp *tcpc)
1086 {
1087   static BOOL wsa_inited;
1088   if (!wsa_inited)
1089   {
1090     WSADATA wsadata;
1091     WSAStartup(MAKEWORD(2, 2), &wsadata);
1092     /* Note: WSAStartup can be called more than once so we don't bother with
1093      * making accesses to wsa_inited thread-safe */
1094     wsa_inited = TRUE;
1095   }
1096   tcpc->sock_event = CreateEventW(NULL, FALSE, FALSE, NULL);
1097   tcpc->cancel_event = CreateEventW(NULL, FALSE, FALSE, NULL);
1098   if (!tcpc->sock_event || !tcpc->cancel_event)
1099   {
1100     ERR("event creation failed\n");
1101     if (tcpc->sock_event) CloseHandle(tcpc->sock_event);
1102     return FALSE;
1103   }
1104   return TRUE;
1105 }
1106
1107 static BOOL rpcrt4_sock_wait_for_recv(RpcConnection_tcp *tcpc)
1108 {
1109   HANDLE wait_handles[2];
1110   DWORD res;
1111   if (WSAEventSelect(tcpc->sock, tcpc->sock_event, FD_READ | FD_CLOSE) == SOCKET_ERROR)
1112   {
1113     ERR("WSAEventSelect() failed with error %d\n", WSAGetLastError());
1114     return FALSE;
1115   }
1116   wait_handles[0] = tcpc->sock_event;
1117   wait_handles[1] = tcpc->cancel_event;
1118   res = WaitForMultipleObjects(2, wait_handles, FALSE, INFINITE);
1119   switch (res)
1120   {
1121   case WAIT_OBJECT_0:
1122     return TRUE;
1123   case WAIT_OBJECT_0 + 1:
1124     return FALSE;
1125   default:
1126     ERR("WaitForMultipleObjects() failed with error %d\n", GetLastError());
1127     return FALSE;
1128   }
1129 }
1130
1131 static BOOL rpcrt4_sock_wait_for_send(RpcConnection_tcp *tcpc)
1132 {
1133   DWORD res;
1134   if (WSAEventSelect(tcpc->sock, tcpc->sock_event, FD_WRITE | FD_CLOSE) == SOCKET_ERROR)
1135   {
1136     ERR("WSAEventSelect() failed with error %d\n", WSAGetLastError());
1137     return FALSE;
1138   }
1139   res = WaitForSingleObject(tcpc->sock_event, INFINITE);
1140   switch (res)
1141   {
1142   case WAIT_OBJECT_0:
1143     return TRUE;
1144   default:
1145     ERR("WaitForMultipleObjects() failed with error %d\n", GetLastError());
1146     return FALSE;
1147   }
1148 }
1149
1150 static void rpcrt4_sock_wait_cancel(RpcConnection_tcp *tcpc)
1151 {
1152   SetEvent(tcpc->cancel_event);
1153 }
1154
1155 static void rpcrt4_sock_wait_destroy(RpcConnection_tcp *tcpc)
1156 {
1157   CloseHandle(tcpc->sock_event);
1158   CloseHandle(tcpc->cancel_event);
1159 }
1160
1161 #endif
1162
1163 static RpcConnection *rpcrt4_conn_tcp_alloc(void)
1164 {
1165   RpcConnection_tcp *tcpc;
1166   tcpc = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcConnection_tcp));
1167   if (tcpc == NULL)
1168     return NULL;
1169   tcpc->sock = -1;
1170   if (!rpcrt4_sock_wait_init(tcpc))
1171   {
1172     HeapFree(GetProcessHeap(), 0, tcpc);
1173     return NULL;
1174   }
1175   return &tcpc->common;
1176 }
1177
1178 static RPC_STATUS rpcrt4_ncacn_ip_tcp_open(RpcConnection* Connection)
1179 {
1180   RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
1181   int sock;
1182   int ret;
1183   struct addrinfo *ai;
1184   struct addrinfo *ai_cur;
1185   struct addrinfo hints;
1186
1187   TRACE("(%s, %s)\n", Connection->NetworkAddr, Connection->Endpoint);
1188
1189   if (tcpc->sock != -1)
1190     return RPC_S_OK;
1191
1192   hints.ai_flags          = 0;
1193   hints.ai_family         = PF_UNSPEC;
1194   hints.ai_socktype       = SOCK_STREAM;
1195   hints.ai_protocol       = IPPROTO_TCP;
1196   hints.ai_addrlen        = 0;
1197   hints.ai_addr           = NULL;
1198   hints.ai_canonname      = NULL;
1199   hints.ai_next           = NULL;
1200
1201   ret = getaddrinfo(Connection->NetworkAddr, Connection->Endpoint, &hints, &ai);
1202   if (ret)
1203   {
1204     ERR("getaddrinfo for %s:%s failed: %s\n", Connection->NetworkAddr,
1205       Connection->Endpoint, gai_strerror(ret));
1206     return RPC_S_SERVER_UNAVAILABLE;
1207   }
1208
1209   for (ai_cur = ai; ai_cur; ai_cur = ai_cur->ai_next)
1210   {
1211     int val;
1212     u_long nonblocking;
1213
1214     if (ai_cur->ai_family != AF_INET && ai_cur->ai_family != AF_INET6)
1215     {
1216       TRACE("skipping non-IP/IPv6 address family\n");
1217       continue;
1218     }
1219
1220     if (TRACE_ON(rpc))
1221     {
1222       char host[256];
1223       char service[256];
1224       getnameinfo(ai_cur->ai_addr, ai_cur->ai_addrlen,
1225         host, sizeof(host), service, sizeof(service),
1226         NI_NUMERICHOST | NI_NUMERICSERV);
1227       TRACE("trying %s:%s\n", host, service);
1228     }
1229
1230     sock = socket(ai_cur->ai_family, ai_cur->ai_socktype, ai_cur->ai_protocol);
1231     if (sock == -1)
1232     {
1233       WARN("socket() failed: %s\n", strerror(errno));
1234       continue;
1235     }
1236
1237     if (0>connect(sock, ai_cur->ai_addr, ai_cur->ai_addrlen))
1238     {
1239       WARN("connect() failed: %s\n", strerror(errno));
1240       closesocket(sock);
1241       continue;
1242     }
1243
1244     /* RPC depends on having minimal latency so disable the Nagle algorithm */
1245     val = 1;
1246     setsockopt(sock, SOL_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
1247     nonblocking = 1;
1248     ioctlsocket(sock, FIONBIO, &nonblocking);
1249
1250     tcpc->sock = sock;
1251
1252     freeaddrinfo(ai);
1253     TRACE("connected\n");
1254     return RPC_S_OK;
1255   }
1256
1257   freeaddrinfo(ai);
1258   ERR("couldn't connect to %s:%s\n", Connection->NetworkAddr, Connection->Endpoint);
1259   return RPC_S_SERVER_UNAVAILABLE;
1260 }
1261
1262 static RPC_STATUS rpcrt4_protseq_ncacn_ip_tcp_open_endpoint(RpcServerProtseq *protseq, const char *endpoint)
1263 {
1264     RPC_STATUS status = RPC_S_CANT_CREATE_ENDPOINT;
1265     int sock;
1266     int ret;
1267     struct addrinfo *ai;
1268     struct addrinfo *ai_cur;
1269     struct addrinfo hints;
1270     RpcConnection *first_connection = NULL;
1271
1272     TRACE("(%p, %s)\n", protseq, endpoint);
1273
1274     hints.ai_flags          = AI_PASSIVE /* for non-localhost addresses */;
1275     hints.ai_family         = PF_UNSPEC;
1276     hints.ai_socktype       = SOCK_STREAM;
1277     hints.ai_protocol       = IPPROTO_TCP;
1278     hints.ai_addrlen        = 0;
1279     hints.ai_addr           = NULL;
1280     hints.ai_canonname      = NULL;
1281     hints.ai_next           = NULL;
1282
1283     ret = getaddrinfo(NULL, endpoint ? endpoint : "0", &hints, &ai);
1284     if (ret)
1285     {
1286         ERR("getaddrinfo for port %s failed: %s\n", endpoint,
1287             gai_strerror(ret));
1288         if ((ret == EAI_SERVICE) || (ret == EAI_NONAME))
1289             return RPC_S_INVALID_ENDPOINT_FORMAT;
1290         return RPC_S_CANT_CREATE_ENDPOINT;
1291     }
1292
1293     for (ai_cur = ai; ai_cur; ai_cur = ai_cur->ai_next)
1294     {
1295         RpcConnection_tcp *tcpc;
1296         RPC_STATUS create_status;
1297         struct sockaddr_storage sa;
1298         socklen_t sa_len;
1299         char service[NI_MAXSERV];
1300         u_long nonblocking;
1301
1302         if (ai_cur->ai_family != AF_INET && ai_cur->ai_family != AF_INET6)
1303         {
1304             TRACE("skipping non-IP/IPv6 address family\n");
1305             continue;
1306         }
1307
1308         if (TRACE_ON(rpc))
1309         {
1310             char host[256];
1311             getnameinfo(ai_cur->ai_addr, ai_cur->ai_addrlen,
1312                         host, sizeof(host), service, sizeof(service),
1313                         NI_NUMERICHOST | NI_NUMERICSERV);
1314             TRACE("trying %s:%s\n", host, service);
1315         }
1316
1317         sock = socket(ai_cur->ai_family, ai_cur->ai_socktype, ai_cur->ai_protocol);
1318         if (sock == -1)
1319         {
1320             WARN("socket() failed: %s\n", strerror(errno));
1321             status = RPC_S_CANT_CREATE_ENDPOINT;
1322             continue;
1323         }
1324
1325         ret = bind(sock, ai_cur->ai_addr, ai_cur->ai_addrlen);
1326         if (ret < 0)
1327         {
1328             WARN("bind failed: %s\n", strerror(errno));
1329             closesocket(sock);
1330             if (errno == EADDRINUSE)
1331               status = RPC_S_DUPLICATE_ENDPOINT;
1332             else
1333               status = RPC_S_CANT_CREATE_ENDPOINT;
1334             continue;
1335         }
1336
1337         sa_len = sizeof(sa);
1338         if (getsockname(sock, (struct sockaddr *)&sa, &sa_len))
1339         {
1340             WARN("getsockname() failed: %s\n", strerror(errno));
1341             status = RPC_S_CANT_CREATE_ENDPOINT;
1342             continue;
1343         }
1344
1345         ret = getnameinfo((struct sockaddr *)&sa, sa_len,
1346                           NULL, 0, service, sizeof(service),
1347                           NI_NUMERICSERV);
1348         if (ret)
1349         {
1350             WARN("getnameinfo failed: %s\n", gai_strerror(ret));
1351             status = RPC_S_CANT_CREATE_ENDPOINT;
1352             continue;
1353         }
1354
1355         create_status = RPCRT4_CreateConnection((RpcConnection **)&tcpc, TRUE,
1356                                                 protseq->Protseq, NULL,
1357                                                 service, NULL, NULL, NULL);
1358         if (create_status != RPC_S_OK)
1359         {
1360             closesocket(sock);
1361             status = create_status;
1362             continue;
1363         }
1364
1365         tcpc->sock = sock;
1366         ret = listen(sock, protseq->MaxCalls);
1367         if (ret < 0)
1368         {
1369             WARN("listen failed: %s\n", strerror(errno));
1370             RPCRT4_DestroyConnection(&tcpc->common);
1371             status = RPC_S_OUT_OF_RESOURCES;
1372             continue;
1373         }
1374         /* need a non-blocking socket, otherwise accept() has a potential
1375          * race-condition (poll() says it is readable, connection drops,
1376          * and accept() blocks until the next connection comes...)
1377          */
1378         nonblocking = 1;
1379         ret = ioctlsocket(sock, FIONBIO, &nonblocking);
1380         if (ret < 0)
1381         {
1382             WARN("couldn't make socket non-blocking, error %d\n", ret);
1383             RPCRT4_DestroyConnection(&tcpc->common);
1384             status = RPC_S_OUT_OF_RESOURCES;
1385             continue;
1386         }
1387
1388         tcpc->common.Next = first_connection;
1389         first_connection = &tcpc->common;
1390
1391         /* since IPv4 and IPv6 share the same port space, we only need one
1392          * successful bind to listen for both */
1393         break;
1394     }
1395
1396     freeaddrinfo(ai);
1397
1398     /* if at least one connection was created for an endpoint then
1399      * return success */
1400     if (first_connection)
1401     {
1402         RpcConnection *conn;
1403
1404         /* find last element in list */
1405         for (conn = first_connection; conn->Next; conn = conn->Next)
1406             ;
1407
1408         EnterCriticalSection(&protseq->cs);
1409         conn->Next = protseq->conn;
1410         protseq->conn = first_connection;
1411         LeaveCriticalSection(&protseq->cs);
1412         
1413         TRACE("listening on %s\n", endpoint);
1414         return RPC_S_OK;
1415     }
1416
1417     ERR("couldn't listen on port %s\n", endpoint);
1418     return status;
1419 }
1420
1421 static RPC_STATUS rpcrt4_conn_tcp_handoff(RpcConnection *old_conn, RpcConnection *new_conn)
1422 {
1423   int ret;
1424   struct sockaddr_in address;
1425   socklen_t addrsize;
1426   RpcConnection_tcp *server = (RpcConnection_tcp*) old_conn;
1427   RpcConnection_tcp *client = (RpcConnection_tcp*) new_conn;
1428   u_long nonblocking;
1429
1430   addrsize = sizeof(address);
1431   ret = accept(server->sock, (struct sockaddr*) &address, &addrsize);
1432   if (ret < 0)
1433   {
1434     ERR("Failed to accept a TCP connection: error %d\n", ret);
1435     return RPC_S_OUT_OF_RESOURCES;
1436   }
1437   nonblocking = 1;
1438   ioctlsocket(ret, FIONBIO, &nonblocking);
1439   client->sock = ret;
1440   TRACE("Accepted a new TCP connection\n");
1441   return RPC_S_OK;
1442 }
1443
1444 static int rpcrt4_conn_tcp_read(RpcConnection *Connection,
1445                                 void *buffer, unsigned int count)
1446 {
1447   RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
1448   int bytes_read = 0;
1449   while (bytes_read != count)
1450   {
1451     int r = recv(tcpc->sock, (char *)buffer + bytes_read, count - bytes_read, 0);
1452     if (!r)
1453       return -1;
1454     else if (r > 0)
1455       bytes_read += r;
1456     else if (errno != EAGAIN)
1457     {
1458       WARN("recv() failed: %s\n", strerror(errno));
1459       return -1;
1460     }
1461     else
1462     {
1463       if (!rpcrt4_sock_wait_for_recv(tcpc))
1464         return -1;
1465     }
1466   }
1467   TRACE("%d %p %u -> %d\n", tcpc->sock, buffer, count, bytes_read);
1468   return bytes_read;
1469 }
1470
1471 static int rpcrt4_conn_tcp_write(RpcConnection *Connection,
1472                                  const void *buffer, unsigned int count)
1473 {
1474   RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
1475   int bytes_written = 0;
1476   while (bytes_written != count)
1477   {
1478     int r = send(tcpc->sock, (const char *)buffer + bytes_written, count - bytes_written, 0);
1479     if (r >= 0)
1480       bytes_written += r;
1481     else if (errno != EAGAIN)
1482       return -1;
1483     else
1484     {
1485       if (!rpcrt4_sock_wait_for_send(tcpc))
1486         return -1;
1487     }
1488   }
1489   TRACE("%d %p %u -> %d\n", tcpc->sock, buffer, count, bytes_written);
1490   return bytes_written;
1491 }
1492
1493 static int rpcrt4_conn_tcp_close(RpcConnection *Connection)
1494 {
1495   RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
1496
1497   TRACE("%d\n", tcpc->sock);
1498
1499   if (tcpc->sock != -1)
1500     closesocket(tcpc->sock);
1501   tcpc->sock = -1;
1502   rpcrt4_sock_wait_destroy(tcpc);
1503   return 0;
1504 }
1505
1506 static void rpcrt4_conn_tcp_cancel_call(RpcConnection *Connection)
1507 {
1508     RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
1509     TRACE("%p\n", Connection);
1510     rpcrt4_sock_wait_cancel(tcpc);
1511 }
1512
1513 static int rpcrt4_conn_tcp_wait_for_incoming_data(RpcConnection *Connection)
1514 {
1515     RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
1516
1517     TRACE("%p\n", Connection);
1518
1519     if (!rpcrt4_sock_wait_for_recv(tcpc))
1520         return -1;
1521     return 0;
1522 }
1523
1524 static size_t rpcrt4_ncacn_ip_tcp_get_top_of_tower(unsigned char *tower_data,
1525                                                    const char *networkaddr,
1526                                                    const char *endpoint)
1527 {
1528     return rpcrt4_ip_tcp_get_top_of_tower(tower_data, networkaddr,
1529                                           EPM_PROTOCOL_TCP, endpoint);
1530 }
1531
1532 #ifdef HAVE_SOCKETPAIR
1533
1534 typedef struct _RpcServerProtseq_sock
1535 {
1536     RpcServerProtseq common;
1537     int mgr_event_rcv;
1538     int mgr_event_snd;
1539 } RpcServerProtseq_sock;
1540
1541 static RpcServerProtseq *rpcrt4_protseq_sock_alloc(void)
1542 {
1543     RpcServerProtseq_sock *ps = HeapAlloc(GetProcessHeap(), 0, sizeof(*ps));
1544     if (ps)
1545     {
1546         int fds[2];
1547         if (!socketpair(PF_UNIX, SOCK_DGRAM, 0, fds))
1548         {
1549             fcntl(fds[0], F_SETFL, O_NONBLOCK);
1550             fcntl(fds[1], F_SETFL, O_NONBLOCK);
1551             ps->mgr_event_rcv = fds[0];
1552             ps->mgr_event_snd = fds[1];
1553         }
1554         else
1555         {
1556             ERR("socketpair failed with error %s\n", strerror(errno));
1557             HeapFree(GetProcessHeap(), 0, ps);
1558             return NULL;
1559         }
1560     }
1561     return &ps->common;
1562 }
1563
1564 static void rpcrt4_protseq_sock_signal_state_changed(RpcServerProtseq *protseq)
1565 {
1566     RpcServerProtseq_sock *sockps = CONTAINING_RECORD(protseq, RpcServerProtseq_sock, common);
1567     char dummy = 1;
1568     write(sockps->mgr_event_snd, &dummy, sizeof(dummy));
1569 }
1570
1571 static void *rpcrt4_protseq_sock_get_wait_array(RpcServerProtseq *protseq, void *prev_array, unsigned int *count)
1572 {
1573     struct pollfd *poll_info = prev_array;
1574     RpcConnection_tcp *conn;
1575     RpcServerProtseq_sock *sockps = CONTAINING_RECORD(protseq, RpcServerProtseq_sock, common);
1576
1577     EnterCriticalSection(&protseq->cs);
1578     
1579     /* open and count connections */
1580     *count = 1;
1581     conn = (RpcConnection_tcp *)protseq->conn;
1582     while (conn) {
1583         if (conn->sock != -1)
1584             (*count)++;
1585         conn = (RpcConnection_tcp *)conn->common.Next;
1586     }
1587     
1588     /* make array of connections */
1589     if (poll_info)
1590         poll_info = HeapReAlloc(GetProcessHeap(), 0, poll_info, *count*sizeof(*poll_info));
1591     else
1592         poll_info = HeapAlloc(GetProcessHeap(), 0, *count*sizeof(*poll_info));
1593     if (!poll_info)
1594     {
1595         ERR("couldn't allocate poll_info\n");
1596         LeaveCriticalSection(&protseq->cs);
1597         return NULL;
1598     }
1599
1600     poll_info[0].fd = sockps->mgr_event_rcv;
1601     poll_info[0].events = POLLIN;
1602     *count = 1;
1603     conn =  CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common);
1604     while (conn) {
1605         if (conn->sock != -1)
1606         {
1607             poll_info[*count].fd = conn->sock;
1608             poll_info[*count].events = POLLIN;
1609             (*count)++;
1610         }
1611         conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common);
1612     }
1613     LeaveCriticalSection(&protseq->cs);
1614     return poll_info;
1615 }
1616
1617 static void rpcrt4_protseq_sock_free_wait_array(RpcServerProtseq *protseq, void *array)
1618 {
1619     HeapFree(GetProcessHeap(), 0, array);
1620 }
1621
1622 static int rpcrt4_protseq_sock_wait_for_new_connection(RpcServerProtseq *protseq, unsigned int count, void *wait_array)
1623 {
1624     struct pollfd *poll_info = wait_array;
1625     int ret;
1626     unsigned int i;
1627     RpcConnection *cconn;
1628     RpcConnection_tcp *conn;
1629     
1630     if (!poll_info)
1631         return -1;
1632     
1633     ret = poll(poll_info, count, -1);
1634     if (ret < 0)
1635     {
1636         ERR("poll failed with error %d\n", ret);
1637         return -1;
1638     }
1639
1640     for (i = 0; i < count; i++)
1641         if (poll_info[i].revents & POLLIN)
1642         {
1643             /* RPC server event */
1644             if (i == 0)
1645             {
1646                 char dummy;
1647                 read(poll_info[0].fd, &dummy, sizeof(dummy));
1648                 return 0;
1649             }
1650
1651             /* find which connection got a RPC */
1652             EnterCriticalSection(&protseq->cs);
1653             conn = CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common);
1654             while (conn) {
1655                 if (poll_info[i].fd == conn->sock) break;
1656                 conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common);
1657             }
1658             cconn = NULL;
1659             if (conn)
1660                 RPCRT4_SpawnConnection(&cconn, &conn->common);
1661             else
1662                 ERR("failed to locate connection for fd %d\n", poll_info[i].fd);
1663             LeaveCriticalSection(&protseq->cs);
1664             if (cconn)
1665                 RPCRT4_new_client(cconn);
1666             else
1667                 return -1;
1668         }
1669
1670     return 1;
1671 }
1672
1673 #else /* HAVE_SOCKETPAIR */
1674
1675 typedef struct _RpcServerProtseq_sock
1676 {
1677     RpcServerProtseq common;
1678     HANDLE mgr_event;
1679 } RpcServerProtseq_sock;
1680
1681 static RpcServerProtseq *rpcrt4_protseq_sock_alloc(void)
1682 {
1683     RpcServerProtseq_sock *ps = HeapAlloc(GetProcessHeap(), 0, sizeof(*ps));
1684     if (ps)
1685     {
1686         static BOOL wsa_inited;
1687         if (!wsa_inited)
1688         {
1689             WSADATA wsadata;
1690             WSAStartup(MAKEWORD(2, 2), &wsadata);
1691             /* Note: WSAStartup can be called more than once so we don't bother with
1692              * making accesses to wsa_inited thread-safe */
1693             wsa_inited = TRUE;
1694         }
1695         ps->mgr_event = CreateEventW(NULL, FALSE, FALSE, NULL);
1696     }
1697     return &ps->common;
1698 }
1699
1700 static void rpcrt4_protseq_sock_signal_state_changed(RpcServerProtseq *protseq)
1701 {
1702     RpcServerProtseq_sock *sockps = CONTAINING_RECORD(protseq, RpcServerProtseq_sock, common);
1703     SetEvent(sockps->mgr_event);
1704 }
1705
1706 static void *rpcrt4_protseq_sock_get_wait_array(RpcServerProtseq *protseq, void *prev_array, unsigned int *count)
1707 {
1708     HANDLE *objs = prev_array;
1709     RpcConnection_tcp *conn;
1710     RpcServerProtseq_sock *sockps = CONTAINING_RECORD(protseq, RpcServerProtseq_sock, common);
1711
1712     EnterCriticalSection(&protseq->cs);
1713
1714     /* open and count connections */
1715     *count = 1;
1716     conn = CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common);
1717     while (conn)
1718     {
1719         if (conn->sock != -1)
1720             (*count)++;
1721         conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common);
1722     }
1723
1724     /* make array of connections */
1725     if (objs)
1726         objs = HeapReAlloc(GetProcessHeap(), 0, objs, *count*sizeof(HANDLE));
1727     else
1728         objs = HeapAlloc(GetProcessHeap(), 0, *count*sizeof(HANDLE));
1729     if (!objs)
1730     {
1731         ERR("couldn't allocate objs\n");
1732         LeaveCriticalSection(&protseq->cs);
1733         return NULL;
1734     }
1735
1736     objs[0] = sockps->mgr_event;
1737     *count = 1;
1738     conn = CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common);
1739     while (conn)
1740     {
1741         if (conn->sock != -1)
1742         {
1743             int res = WSAEventSelect(conn->sock, conn->sock_event, FD_ACCEPT);
1744             if (res == SOCKET_ERROR)
1745                 ERR("WSAEventSelect() failed with error %d\n", WSAGetLastError());
1746             else
1747             {
1748                 objs[*count] = conn->sock_event;
1749                 (*count)++;
1750             }
1751         }
1752         conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common);
1753     }
1754     LeaveCriticalSection(&protseq->cs);
1755     return objs;
1756 }
1757
1758 static void rpcrt4_protseq_sock_free_wait_array(RpcServerProtseq *protseq, void *array)
1759 {
1760     HeapFree(GetProcessHeap(), 0, array);
1761 }
1762
1763 static int rpcrt4_protseq_sock_wait_for_new_connection(RpcServerProtseq *protseq, unsigned int count, void *wait_array)
1764 {
1765     HANDLE b_handle;
1766     HANDLE *objs = wait_array;
1767     DWORD res;
1768     RpcConnection *cconn;
1769     RpcConnection_tcp *conn;
1770
1771     if (!objs)
1772         return -1;
1773
1774     do
1775     {
1776         /* an alertable wait isn't strictly necessary, but due to our
1777          * overlapped I/O implementation in Wine we need to free some memory
1778          * by the file user APC being called, even if no completion routine was
1779          * specified at the time of starting the async operation */
1780         res = WaitForMultipleObjectsEx(count, objs, FALSE, INFINITE, TRUE);
1781     } while (res == WAIT_IO_COMPLETION);
1782
1783     if (res == WAIT_OBJECT_0)
1784         return 0;
1785     else if (res == WAIT_FAILED)
1786     {
1787         ERR("wait failed with error %d\n", GetLastError());
1788         return -1;
1789     }
1790     else
1791     {
1792         b_handle = objs[res - WAIT_OBJECT_0];
1793         /* find which connection got a RPC */
1794         EnterCriticalSection(&protseq->cs);
1795         conn = CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common);
1796         while (conn)
1797         {
1798             if (b_handle == conn->sock_event) break;
1799             conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common);
1800         }
1801         cconn = NULL;
1802         if (conn)
1803             RPCRT4_SpawnConnection(&cconn, &conn->common);
1804         else
1805             ERR("failed to locate connection for handle %p\n", b_handle);
1806         LeaveCriticalSection(&protseq->cs);
1807         if (cconn)
1808         {
1809             RPCRT4_new_client(cconn);
1810             return 1;
1811         }
1812         else return -1;
1813     }
1814 }
1815
1816 #endif  /* HAVE_SOCKETPAIR */
1817
1818 static RPC_STATUS rpcrt4_ncacn_ip_tcp_parse_top_of_tower(const unsigned char *tower_data,
1819                                                          size_t tower_size,
1820                                                          char **networkaddr,
1821                                                          char **endpoint)
1822 {
1823     return rpcrt4_ip_tcp_parse_top_of_tower(tower_data, tower_size,
1824                                             networkaddr, EPM_PROTOCOL_TCP,
1825                                             endpoint);
1826 }
1827
1828 /**** ncacn_http support ****/
1829
1830 /* 60 seconds is the period native uses */
1831 #define HTTP_IDLE_TIME 60000
1832
1833 /* reference counted to avoid a race between a cancelled call's connection
1834  * being destroyed and the asynchronous InternetReadFileEx call being
1835  * completed */
1836 typedef struct _RpcHttpAsyncData
1837 {
1838     LONG refs;
1839     HANDLE completion_event;
1840     INTERNET_BUFFERSA inet_buffers;
1841     void *destination_buffer; /* the address that inet_buffers.lpvBuffer will be
1842                                * copied into when the call completes */
1843     CRITICAL_SECTION cs;
1844 } RpcHttpAsyncData;
1845
1846 static ULONG RpcHttpAsyncData_AddRef(RpcHttpAsyncData *data)
1847 {
1848     return InterlockedIncrement(&data->refs);
1849 }
1850
1851 static ULONG RpcHttpAsyncData_Release(RpcHttpAsyncData *data)
1852 {
1853     ULONG refs = InterlockedDecrement(&data->refs);
1854     if (!refs)
1855     {
1856         TRACE("destroying async data %p\n", data);
1857         CloseHandle(data->completion_event);
1858         HeapFree(GetProcessHeap(), 0, data->inet_buffers.lpvBuffer);
1859         DeleteCriticalSection(&data->cs);
1860         HeapFree(GetProcessHeap(), 0, data);
1861     }
1862     return refs;
1863 }
1864
1865 typedef struct _RpcConnection_http
1866 {
1867     RpcConnection common;
1868     HINTERNET app_info;
1869     HINTERNET session;
1870     HINTERNET in_request;
1871     HINTERNET out_request;
1872     HANDLE timer_cancelled;
1873     HANDLE cancel_event;
1874     DWORD last_sent_time;
1875     ULONG bytes_received;
1876     ULONG flow_control_mark; /* send a control packet to the server when this many bytes received */
1877     ULONG flow_control_increment; /* number of bytes to increment flow_control_mark by */
1878     UUID connection_uuid;
1879     UUID in_pipe_uuid;
1880     UUID out_pipe_uuid;
1881     RpcHttpAsyncData *async_data;
1882 } RpcConnection_http;
1883
1884 static RpcConnection *rpcrt4_ncacn_http_alloc(void)
1885 {
1886     RpcConnection_http *httpc;
1887     httpc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*httpc));
1888     if (!httpc) return NULL;
1889     httpc->async_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcHttpAsyncData));
1890     if (!httpc->async_data)
1891     {
1892         HeapFree(GetProcessHeap(), 0, httpc);
1893         return NULL;
1894     }
1895     TRACE("async data = %p\n", httpc->async_data);
1896     httpc->cancel_event = CreateEventW(NULL, FALSE, FALSE, NULL);
1897     httpc->async_data->refs = 1;
1898     httpc->async_data->inet_buffers.dwStructSize = sizeof(INTERNET_BUFFERSA);
1899     httpc->async_data->inet_buffers.lpvBuffer = NULL;
1900     httpc->async_data->destination_buffer = NULL;
1901     InitializeCriticalSection(&httpc->async_data->cs);
1902     return &httpc->common;
1903 }
1904
1905 typedef struct _HttpTimerThreadData
1906 {
1907     PVOID timer_param;
1908     DWORD *last_sent_time;
1909     HANDLE timer_cancelled;
1910 } HttpTimerThreadData;
1911
1912 static VOID rpcrt4_http_keep_connection_active_timer_proc(PVOID param, BOOLEAN dummy)
1913 {
1914     HINTERNET in_request = param;
1915     RpcPktHdr *idle_pkt;
1916
1917     idle_pkt = RPCRT4_BuildHttpHeader(NDR_LOCAL_DATA_REPRESENTATION, 0x0001,
1918                                       0, 0);
1919     if (idle_pkt)
1920     {
1921         DWORD bytes_written;
1922         InternetWriteFile(in_request, idle_pkt, idle_pkt->common.frag_len, &bytes_written);
1923         RPCRT4_FreeHeader(idle_pkt);
1924     }
1925 }
1926
1927 static inline DWORD rpcrt4_http_timer_calc_timeout(DWORD *last_sent_time)
1928 {
1929     DWORD cur_time = GetTickCount();
1930     DWORD cached_last_sent_time = *last_sent_time;
1931     return HTTP_IDLE_TIME - (cur_time - cached_last_sent_time > HTTP_IDLE_TIME ? 0 : cur_time - cached_last_sent_time);
1932 }
1933
1934 static DWORD CALLBACK rpcrt4_http_timer_thread(PVOID param)
1935 {
1936     HttpTimerThreadData *data_in = param;
1937     HttpTimerThreadData data;
1938     DWORD timeout;
1939
1940     data = *data_in;
1941     HeapFree(GetProcessHeap(), 0, data_in);
1942
1943     for (timeout = HTTP_IDLE_TIME;
1944          WaitForSingleObject(data.timer_cancelled, timeout) == WAIT_TIMEOUT;
1945          timeout = rpcrt4_http_timer_calc_timeout(data.last_sent_time))
1946     {
1947         /* are we too soon after last send? */
1948         if (GetTickCount() - HTTP_IDLE_TIME < *data.last_sent_time)
1949             continue;
1950         rpcrt4_http_keep_connection_active_timer_proc(data.timer_param, TRUE);
1951     }
1952
1953     CloseHandle(data.timer_cancelled);
1954     return 0;
1955 }
1956
1957 static VOID WINAPI rpcrt4_http_internet_callback(
1958      HINTERNET hInternet,
1959      DWORD_PTR dwContext,
1960      DWORD dwInternetStatus,
1961      LPVOID lpvStatusInformation,
1962      DWORD dwStatusInformationLength)
1963 {
1964     RpcHttpAsyncData *async_data = (RpcHttpAsyncData *)dwContext;
1965
1966     switch (dwInternetStatus)
1967     {
1968     case INTERNET_STATUS_REQUEST_COMPLETE:
1969         TRACE("INTERNET_STATUS_REQUEST_COMPLETED\n");
1970         if (async_data)
1971         {
1972             if (async_data->inet_buffers.lpvBuffer)
1973             {
1974                 EnterCriticalSection(&async_data->cs);
1975                 if (async_data->destination_buffer)
1976                 {
1977                     memcpy(async_data->destination_buffer,
1978                            async_data->inet_buffers.lpvBuffer,
1979                            async_data->inet_buffers.dwBufferLength);
1980                     async_data->destination_buffer = NULL;
1981                 }
1982                 LeaveCriticalSection(&async_data->cs);
1983             }
1984             HeapFree(GetProcessHeap(), 0, async_data->inet_buffers.lpvBuffer);
1985             async_data->inet_buffers.lpvBuffer = NULL;
1986             SetEvent(async_data->completion_event);
1987             RpcHttpAsyncData_Release(async_data);
1988         }
1989         break;
1990     }
1991 }
1992
1993 static RPC_STATUS rpcrt4_http_check_response(HINTERNET hor)
1994 {
1995     BOOL ret;
1996     DWORD status_code;
1997     DWORD size;
1998     DWORD index;
1999     WCHAR buf[32];
2000     WCHAR *status_text = buf;
2001     TRACE("\n");
2002
2003     index = 0;
2004     size = sizeof(status_code);
2005     ret = HttpQueryInfoW(hor, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &status_code, &size, &index);
2006     if (!ret)
2007         return GetLastError();
2008     if (status_code < 400)
2009         return RPC_S_OK;
2010     index = 0;
2011     size = sizeof(buf);
2012     ret = HttpQueryInfoW(hor, HTTP_QUERY_STATUS_TEXT, status_text, &size, &index);
2013     if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
2014     {
2015         status_text = HeapAlloc(GetProcessHeap(), 0, size);
2016         ret = HttpQueryInfoW(hor, HTTP_QUERY_STATUS_TEXT, status_text, &size, &index);
2017     }
2018
2019     ERR("server returned: %d %s\n", status_code, ret ? debugstr_w(status_text) : "<status text unavailable>");
2020     if(status_text != buf) HeapFree(GetProcessHeap(), 0, status_text);
2021
2022     if (status_code == HTTP_STATUS_DENIED)
2023         return ERROR_ACCESS_DENIED;
2024     return RPC_S_SERVER_UNAVAILABLE;
2025 }
2026
2027 static RPC_STATUS rpcrt4_http_internet_connect(RpcConnection_http *httpc)
2028 {
2029     static const WCHAR wszUserAgent[] = {'M','S','R','P','C',0};
2030     LPWSTR proxy = NULL;
2031     LPWSTR user = NULL;
2032     LPWSTR password = NULL;
2033     LPWSTR servername = NULL;
2034     const WCHAR *option;
2035     INTERNET_PORT port = INTERNET_INVALID_PORT_NUMBER; /* use default port */
2036
2037     if (httpc->common.QOS &&
2038         (httpc->common.QOS->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP))
2039     {
2040         const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_cred = httpc->common.QOS->qos->u.HttpCredentials;
2041         if (http_cred->TransportCredentials)
2042         {
2043             WCHAR *p;
2044             const SEC_WINNT_AUTH_IDENTITY_W *cred = http_cred->TransportCredentials;
2045             ULONG len = cred->DomainLength + 1 + cred->UserLength;
2046             user = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
2047             if (!user)
2048                 return RPC_S_OUT_OF_RESOURCES;
2049             p = user;
2050             if (cred->DomainLength)
2051             {
2052                 memcpy(p, cred->Domain, cred->DomainLength * sizeof(WCHAR));
2053                 p += cred->DomainLength;
2054                 *p = '\\';
2055                 p++;
2056             }
2057             memcpy(p, cred->User, cred->UserLength * sizeof(WCHAR));
2058             p[cred->UserLength] = 0;
2059
2060             password = RPCRT4_strndupW(cred->Password, cred->PasswordLength);
2061         }
2062     }
2063
2064     for (option = httpc->common.NetworkOptions; option;
2065          option = (strchrW(option, ',') ? strchrW(option, ',')+1 : NULL))
2066     {
2067         static const WCHAR wszRpcProxy[] = {'R','p','c','P','r','o','x','y','=',0};
2068         static const WCHAR wszHttpProxy[] = {'H','t','t','p','P','r','o','x','y','=',0};
2069
2070         if (!strncmpiW(option, wszRpcProxy, sizeof(wszRpcProxy)/sizeof(wszRpcProxy[0])-1))
2071         {
2072             const WCHAR *value_start = option + sizeof(wszRpcProxy)/sizeof(wszRpcProxy[0])-1;
2073             const WCHAR *value_end;
2074             const WCHAR *p;
2075
2076             value_end = strchrW(option, ',');
2077             if (!value_end)
2078                 value_end = value_start + strlenW(value_start);
2079             for (p = value_start; p < value_end; p++)
2080                 if (*p == ':')
2081                 {
2082                     port = atoiW(p+1);
2083                     value_end = p;
2084                     break;
2085                 }
2086             TRACE("RpcProxy value is %s\n", debugstr_wn(value_start, value_end-value_start));
2087             servername = RPCRT4_strndupW(value_start, value_end-value_start);
2088         }
2089         else if (!strncmpiW(option, wszHttpProxy, sizeof(wszHttpProxy)/sizeof(wszHttpProxy[0])-1))
2090         {
2091             const WCHAR *value_start = option + sizeof(wszHttpProxy)/sizeof(wszHttpProxy[0])-1;
2092             const WCHAR *value_end;
2093
2094             value_end = strchrW(option, ',');
2095             if (!value_end)
2096                 value_end = value_start + strlenW(value_start);
2097             TRACE("HttpProxy value is %s\n", debugstr_wn(value_start, value_end-value_start));
2098             proxy = RPCRT4_strndupW(value_start, value_end-value_start);
2099         }
2100         else
2101             FIXME("unhandled option %s\n", debugstr_w(option));
2102     }
2103
2104     httpc->app_info = InternetOpenW(wszUserAgent, proxy ? INTERNET_OPEN_TYPE_PROXY : INTERNET_OPEN_TYPE_PRECONFIG,
2105                                     NULL, NULL, INTERNET_FLAG_ASYNC);
2106     if (!httpc->app_info)
2107     {
2108         HeapFree(GetProcessHeap(), 0, password);
2109         HeapFree(GetProcessHeap(), 0, user);
2110         ERR("InternetOpenW failed with error %d\n", GetLastError());
2111         return RPC_S_SERVER_UNAVAILABLE;
2112     }
2113     InternetSetStatusCallbackW(httpc->app_info, rpcrt4_http_internet_callback);
2114
2115     /* if no RpcProxy option specified, set the HTTP server address to the
2116      * RPC server address */
2117     if (!servername)
2118     {
2119         servername = HeapAlloc(GetProcessHeap(), 0, (strlen(httpc->common.NetworkAddr) + 1)*sizeof(WCHAR));
2120         if (!servername)
2121         {
2122             HeapFree(GetProcessHeap(), 0, password);
2123             HeapFree(GetProcessHeap(), 0, user);
2124             return RPC_S_OUT_OF_RESOURCES;
2125         }
2126         MultiByteToWideChar(CP_ACP, 0, httpc->common.NetworkAddr, -1, servername, strlen(httpc->common.NetworkAddr) + 1);
2127     }
2128
2129     httpc->session = InternetConnectW(httpc->app_info, servername, port, user, password,
2130                                       INTERNET_SERVICE_HTTP, 0, 0);
2131
2132     HeapFree(GetProcessHeap(), 0, password);
2133     HeapFree(GetProcessHeap(), 0, user);
2134     HeapFree(GetProcessHeap(), 0, servername);
2135
2136     if (!httpc->session)
2137     {
2138         ERR("InternetConnectW failed with error %d\n", GetLastError());
2139         return RPC_S_SERVER_UNAVAILABLE;
2140     }
2141
2142     return RPC_S_OK;
2143 }
2144
2145 /* prepare the in pipe for use by RPC packets */
2146 static RPC_STATUS rpcrt4_http_prepare_in_pipe(HINTERNET in_request, RpcHttpAsyncData *async_data,
2147                                               const UUID *connection_uuid,
2148                                               const UUID *in_pipe_uuid,
2149                                               const UUID *association_uuid)
2150 {
2151     BYTE packet[44];
2152     BOOL ret;
2153     RPC_STATUS status;
2154     RpcPktHdr *hdr;
2155     INTERNET_BUFFERSW buffers_in;
2156     DWORD bytes_read, bytes_written;
2157
2158     /* prepare in pipe */
2159     ResetEvent(async_data->completion_event);
2160     RpcHttpAsyncData_AddRef(async_data);
2161     ret = HttpSendRequestW(in_request, NULL, 0, NULL, 0);
2162     if (!ret)
2163     {
2164         if (GetLastError() == ERROR_IO_PENDING)
2165             WaitForSingleObject(async_data->completion_event, INFINITE);
2166         else
2167         {
2168             RpcHttpAsyncData_Release(async_data);
2169             ERR("HttpSendRequestW failed with error %d\n", GetLastError());
2170             return RPC_S_SERVER_UNAVAILABLE;
2171         }
2172     }
2173     status = rpcrt4_http_check_response(in_request);
2174     if (status != RPC_S_OK) return status;
2175
2176     InternetReadFile(in_request, packet, 20, &bytes_read);
2177     /* FIXME: do something with retrieved data */
2178
2179     memset(&buffers_in, 0, sizeof(buffers_in));
2180     buffers_in.dwStructSize = sizeof(buffers_in);
2181     /* FIXME: get this from the registry */
2182     buffers_in.dwBufferTotal = 1024 * 1024 * 1024; /* 1Gb */
2183     ResetEvent(async_data->completion_event);
2184     RpcHttpAsyncData_AddRef(async_data);
2185     ret = HttpSendRequestExW(in_request, &buffers_in, NULL, 0, 0);
2186     if (!ret)
2187     {
2188         if (GetLastError() == ERROR_IO_PENDING)
2189             WaitForSingleObject(async_data->completion_event, INFINITE);
2190         else
2191         {
2192             RpcHttpAsyncData_Release(async_data);
2193             ERR("HttpSendRequestExW failed with error %d\n", GetLastError());
2194             return RPC_S_SERVER_UNAVAILABLE;
2195         }
2196     }
2197
2198     TRACE("sending HTTP connect header to server\n");
2199     hdr = RPCRT4_BuildHttpConnectHeader(0, FALSE, connection_uuid, in_pipe_uuid, association_uuid);
2200     if (!hdr) return RPC_S_OUT_OF_RESOURCES;
2201     ret = InternetWriteFile(in_request, hdr, hdr->common.frag_len, &bytes_written);
2202     RPCRT4_FreeHeader(hdr);
2203     if (!ret)
2204     {
2205         ERR("InternetWriteFile failed with error %d\n", GetLastError());
2206         return RPC_S_SERVER_UNAVAILABLE;
2207     }
2208
2209     return RPC_S_OK;
2210 }
2211
2212 static RPC_STATUS rpcrt4_http_read_http_packet(HINTERNET request, RpcPktHdr *hdr, BYTE **data)
2213 {
2214     BOOL ret;
2215     DWORD bytes_read;
2216     unsigned short data_len;
2217
2218     ret = InternetReadFile(request, hdr, sizeof(hdr->common), &bytes_read);
2219     if (!ret)
2220         return RPC_S_SERVER_UNAVAILABLE;
2221     if (hdr->common.ptype != PKT_HTTP || hdr->common.frag_len < sizeof(hdr->http))
2222     {
2223         ERR("wrong packet type received %d or wrong frag_len %d\n",
2224             hdr->common.ptype, hdr->common.frag_len);
2225         return RPC_S_PROTOCOL_ERROR;
2226     }
2227
2228     ret = InternetReadFile(request, &hdr->common + 1, sizeof(hdr->http) - sizeof(hdr->common), &bytes_read);
2229     if (!ret)
2230         return RPC_S_SERVER_UNAVAILABLE;
2231
2232     data_len = hdr->common.frag_len - sizeof(hdr->http);
2233     if (data_len)
2234     {
2235         *data = HeapAlloc(GetProcessHeap(), 0, data_len);
2236         if (!*data)
2237             return RPC_S_OUT_OF_RESOURCES;
2238         ret = InternetReadFile(request, *data, data_len, &bytes_read);
2239         if (!ret)
2240         {
2241             HeapFree(GetProcessHeap(), 0, *data);
2242             return RPC_S_SERVER_UNAVAILABLE;
2243         }
2244     }
2245     else
2246         *data = NULL;
2247
2248     if (!RPCRT4_IsValidHttpPacket(hdr, *data, data_len))
2249     {
2250         ERR("invalid http packet\n");
2251         return RPC_S_PROTOCOL_ERROR;
2252     }
2253
2254     return RPC_S_OK;
2255 }
2256
2257 /* prepare the out pipe for use by RPC packets */
2258 static RPC_STATUS rpcrt4_http_prepare_out_pipe(HINTERNET out_request,
2259                                                RpcHttpAsyncData *async_data,
2260                                                const UUID *connection_uuid,
2261                                                const UUID *out_pipe_uuid,
2262                                                ULONG *flow_control_increment)
2263 {
2264     BYTE packet[20];
2265     BOOL ret;
2266     RPC_STATUS status;
2267     RpcPktHdr *hdr;
2268     DWORD bytes_read;
2269     BYTE *data_from_server;
2270     RpcPktHdr pkt_from_server;
2271     ULONG field1, field3;
2272
2273     ResetEvent(async_data->completion_event);
2274     RpcHttpAsyncData_AddRef(async_data);
2275     ret = HttpSendRequestW(out_request, NULL, 0, NULL, 0);
2276     if (!ret)
2277     {
2278         if (GetLastError() == ERROR_IO_PENDING)
2279             WaitForSingleObject(async_data->completion_event, INFINITE);
2280         else
2281         {
2282             RpcHttpAsyncData_Release(async_data);
2283             ERR("HttpSendRequestW failed with error %d\n", GetLastError());
2284             return RPC_S_SERVER_UNAVAILABLE;
2285         }
2286     }
2287     status = rpcrt4_http_check_response(out_request);
2288     if (status != RPC_S_OK) return status;
2289
2290     InternetReadFile(out_request, packet, 20, &bytes_read);
2291     /* FIXME: do something with retrieved data */
2292
2293     hdr = RPCRT4_BuildHttpConnectHeader(0, TRUE, connection_uuid, out_pipe_uuid, NULL);
2294     if (!hdr) return RPC_S_OUT_OF_RESOURCES;
2295     ResetEvent(async_data->completion_event);
2296     RpcHttpAsyncData_AddRef(async_data);
2297     ret = HttpSendRequestW(out_request, NULL, 0, hdr, hdr->common.frag_len);
2298     if (!ret)
2299     {
2300         if (GetLastError() == ERROR_IO_PENDING)
2301             WaitForSingleObject(async_data->completion_event, INFINITE);
2302         else
2303         {
2304             RpcHttpAsyncData_Release(async_data);
2305             ERR("HttpSendRequestW failed with error %d\n", GetLastError());
2306             RPCRT4_FreeHeader(hdr);
2307             return RPC_S_SERVER_UNAVAILABLE;
2308         }
2309     }
2310     RPCRT4_FreeHeader(hdr);
2311     status = rpcrt4_http_check_response(out_request);
2312     if (status != RPC_S_OK) return status;
2313
2314     status = rpcrt4_http_read_http_packet(out_request, &pkt_from_server,
2315                                           &data_from_server);
2316     if (status != RPC_S_OK) return status;
2317     status = RPCRT4_ParseHttpPrepareHeader1(&pkt_from_server, data_from_server,
2318                                             &field1);
2319     HeapFree(GetProcessHeap(), 0, data_from_server);
2320     if (status != RPC_S_OK) return status;
2321     TRACE("received (%d) from first prepare header\n", field1);
2322
2323     status = rpcrt4_http_read_http_packet(out_request, &pkt_from_server,
2324                                           &data_from_server);
2325     if (status != RPC_S_OK) return status;
2326     status = RPCRT4_ParseHttpPrepareHeader2(&pkt_from_server, data_from_server,
2327                                             &field1, flow_control_increment,
2328                                             &field3);
2329     HeapFree(GetProcessHeap(), 0, data_from_server);
2330     if (status != RPC_S_OK) return status;
2331     TRACE("received (0x%08x 0x%08x %d) from second prepare header\n", field1, *flow_control_increment, field3);
2332
2333     return RPC_S_OK;
2334 }
2335
2336 static RPC_STATUS rpcrt4_ncacn_http_open(RpcConnection* Connection)
2337 {
2338     RpcConnection_http *httpc = (RpcConnection_http *)Connection;
2339     static const WCHAR wszVerbIn[] = {'R','P','C','_','I','N','_','D','A','T','A',0};
2340     static const WCHAR wszVerbOut[] = {'R','P','C','_','O','U','T','_','D','A','T','A',0};
2341     static const WCHAR wszRpcProxyPrefix[] = {'/','r','p','c','/','r','p','c','p','r','o','x','y','.','d','l','l','?',0};
2342     static const WCHAR wszColon[] = {':',0};
2343     static const WCHAR wszAcceptType[] = {'a','p','p','l','i','c','a','t','i','o','n','/','r','p','c',0};
2344     LPCWSTR wszAcceptTypes[] = { wszAcceptType, NULL };
2345     WCHAR *url;
2346     RPC_STATUS status;
2347     BOOL secure;
2348     HttpTimerThreadData *timer_data;
2349     HANDLE thread;
2350
2351     TRACE("(%s, %s)\n", Connection->NetworkAddr, Connection->Endpoint);
2352
2353     if (Connection->server)
2354     {
2355         ERR("ncacn_http servers not supported yet\n");
2356         return RPC_S_SERVER_UNAVAILABLE;
2357     }
2358
2359     if (httpc->in_request)
2360         return RPC_S_OK;
2361
2362     httpc->async_data->completion_event = CreateEventW(NULL, FALSE, FALSE, NULL);
2363
2364     status = UuidCreate(&httpc->connection_uuid);
2365     status = UuidCreate(&httpc->in_pipe_uuid);
2366     status = UuidCreate(&httpc->out_pipe_uuid);
2367
2368     status = rpcrt4_http_internet_connect(httpc);
2369     if (status != RPC_S_OK)
2370         return status;
2371
2372     url = HeapAlloc(GetProcessHeap(), 0, sizeof(wszRpcProxyPrefix) + (strlen(Connection->NetworkAddr) + 1 + strlen(Connection->Endpoint))*sizeof(WCHAR));
2373     if (!url)
2374         return RPC_S_OUT_OF_MEMORY;
2375     memcpy(url, wszRpcProxyPrefix, sizeof(wszRpcProxyPrefix));
2376     MultiByteToWideChar(CP_ACP, 0, Connection->NetworkAddr, -1, url+sizeof(wszRpcProxyPrefix)/sizeof(wszRpcProxyPrefix[0])-1, strlen(Connection->NetworkAddr)+1);
2377     strcatW(url, wszColon);
2378     MultiByteToWideChar(CP_ACP, 0, Connection->Endpoint, -1, url+strlenW(url), strlen(Connection->Endpoint)+1);
2379
2380     secure = httpc->common.QOS &&
2381              (httpc->common.QOS->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP) &&
2382              (httpc->common.QOS->qos->u.HttpCredentials->Flags & RPC_C_HTTP_FLAG_USE_SSL);
2383
2384     httpc->in_request = HttpOpenRequestW(httpc->session, wszVerbIn, url, NULL, NULL,
2385                                          wszAcceptTypes,
2386                                          (secure ? INTERNET_FLAG_SECURE : 0)|INTERNET_FLAG_KEEP_CONNECTION|INTERNET_FLAG_PRAGMA_NOCACHE,
2387                                          (DWORD_PTR)httpc->async_data);
2388     if (!httpc->in_request)
2389     {
2390         ERR("HttpOpenRequestW failed with error %d\n", GetLastError());
2391         return RPC_S_SERVER_UNAVAILABLE;
2392     }
2393     httpc->out_request = HttpOpenRequestW(httpc->session, wszVerbOut, url, NULL, NULL,
2394                                           wszAcceptTypes,
2395                                           (secure ? INTERNET_FLAG_SECURE : 0)|INTERNET_FLAG_KEEP_CONNECTION|INTERNET_FLAG_PRAGMA_NOCACHE,
2396                                           (DWORD_PTR)httpc->async_data);
2397     if (!httpc->out_request)
2398     {
2399         ERR("HttpOpenRequestW failed with error %d\n", GetLastError());
2400         return RPC_S_SERVER_UNAVAILABLE;
2401     }
2402
2403     status = rpcrt4_http_prepare_in_pipe(httpc->in_request,
2404                                          httpc->async_data,
2405                                          &httpc->connection_uuid,
2406                                          &httpc->in_pipe_uuid,
2407                                          &Connection->assoc->http_uuid);
2408     if (status != RPC_S_OK)
2409         return status;
2410
2411     status = rpcrt4_http_prepare_out_pipe(httpc->out_request,
2412                                           httpc->async_data,
2413                                           &httpc->connection_uuid,
2414                                           &httpc->out_pipe_uuid,
2415                                           &httpc->flow_control_increment);
2416     if (status != RPC_S_OK)
2417         return status;
2418
2419     httpc->flow_control_mark = httpc->flow_control_increment / 2;
2420     httpc->last_sent_time = GetTickCount();
2421     httpc->timer_cancelled = CreateEventW(NULL, FALSE, FALSE, NULL);
2422
2423     timer_data = HeapAlloc(GetProcessHeap(), 0, sizeof(*timer_data));
2424     if (!timer_data)
2425         return ERROR_OUTOFMEMORY;
2426     timer_data->timer_param = httpc->in_request;
2427     timer_data->last_sent_time = &httpc->last_sent_time;
2428     timer_data->timer_cancelled = httpc->timer_cancelled;
2429     /* FIXME: should use CreateTimerQueueTimer when implemented */
2430     thread = CreateThread(NULL, 0, rpcrt4_http_timer_thread, timer_data, 0, NULL);
2431     if (!thread)
2432     {
2433         HeapFree(GetProcessHeap(), 0, timer_data);
2434         return GetLastError();
2435     }
2436     CloseHandle(thread);
2437
2438     return RPC_S_OK;
2439 }
2440
2441 static RPC_STATUS rpcrt4_ncacn_http_handoff(RpcConnection *old_conn, RpcConnection *new_conn)
2442 {
2443     assert(0);
2444     return RPC_S_SERVER_UNAVAILABLE;
2445 }
2446
2447 static int rpcrt4_ncacn_http_read(RpcConnection *Connection,
2448                                 void *buffer, unsigned int count)
2449 {
2450   RpcConnection_http *httpc = (RpcConnection_http *) Connection;
2451   char *buf = buffer;
2452   BOOL ret = TRUE;
2453   unsigned int bytes_left = count;
2454
2455   ResetEvent(httpc->async_data->completion_event);
2456   while (bytes_left)
2457   {
2458     RpcHttpAsyncData_AddRef(httpc->async_data);
2459     httpc->async_data->inet_buffers.dwBufferLength = bytes_left;
2460     httpc->async_data->inet_buffers.lpvBuffer = HeapAlloc(GetProcessHeap(), 0, bytes_left);
2461     httpc->async_data->destination_buffer = buf;
2462     ret = InternetReadFileExA(httpc->out_request, &httpc->async_data->inet_buffers, IRF_ASYNC, 0);
2463     if (ret)
2464     {
2465         /* INTERNET_STATUS_REQUEST_COMPLETED won't be sent, so release our
2466          * async ref now */
2467         RpcHttpAsyncData_Release(httpc->async_data);
2468         memcpy(buf, httpc->async_data->inet_buffers.lpvBuffer,
2469                httpc->async_data->inet_buffers.dwBufferLength);
2470         HeapFree(GetProcessHeap(), 0, httpc->async_data->inet_buffers.lpvBuffer);
2471         httpc->async_data->inet_buffers.lpvBuffer = NULL;
2472         httpc->async_data->destination_buffer = NULL;
2473     }
2474     else
2475     {
2476         if (GetLastError() == ERROR_IO_PENDING)
2477         {
2478             HANDLE handles[2] = { httpc->async_data->completion_event, httpc->cancel_event };
2479             DWORD result = WaitForMultipleObjects(2, handles, FALSE, DEFAULT_NCACN_HTTP_TIMEOUT);
2480             if (result == WAIT_OBJECT_0)
2481                 ret = TRUE;
2482             else
2483             {
2484                 TRACE("call cancelled\n");
2485                 EnterCriticalSection(&httpc->async_data->cs);
2486                 httpc->async_data->destination_buffer = NULL;
2487                 LeaveCriticalSection(&httpc->async_data->cs);
2488                 break;
2489             }
2490         }
2491         else
2492         {
2493             HeapFree(GetProcessHeap(), 0, httpc->async_data->inet_buffers.lpvBuffer);
2494             httpc->async_data->inet_buffers.lpvBuffer = NULL;
2495             httpc->async_data->destination_buffer = NULL;
2496             RpcHttpAsyncData_Release(httpc->async_data);
2497             break;
2498         }
2499     }
2500     if (!httpc->async_data->inet_buffers.dwBufferLength)
2501         break;
2502     bytes_left -= httpc->async_data->inet_buffers.dwBufferLength;
2503     buf += httpc->async_data->inet_buffers.dwBufferLength;
2504   }
2505   TRACE("%p %p %u -> %s\n", httpc->out_request, buffer, count, ret ? "TRUE" : "FALSE");
2506   return ret ? count : -1;
2507 }
2508
2509 static RPC_STATUS rpcrt4_ncacn_http_receive_fragment(RpcConnection *Connection, RpcPktHdr **Header, void **Payload)
2510 {
2511   RpcConnection_http *httpc = (RpcConnection_http *) Connection;
2512   RPC_STATUS status;
2513   DWORD hdr_length;
2514   LONG dwRead;
2515   RpcPktCommonHdr common_hdr;
2516
2517   *Header = NULL;
2518
2519   TRACE("(%p, %p, %p)\n", Connection, Header, Payload);
2520
2521 again:
2522   /* read packet common header */
2523   dwRead = rpcrt4_ncacn_http_read(Connection, &common_hdr, sizeof(common_hdr));
2524   if (dwRead != sizeof(common_hdr)) {
2525     WARN("Short read of header, %d bytes\n", dwRead);
2526     status = RPC_S_PROTOCOL_ERROR;
2527     goto fail;
2528   }
2529   if (!memcmp(&common_hdr, "HTTP/1.1", sizeof("HTTP/1.1")) ||
2530       !memcmp(&common_hdr, "HTTP/1.0", sizeof("HTTP/1.0")))
2531   {
2532     FIXME("server returned %s\n", debugstr_a((const char *)&common_hdr));
2533     status = RPC_S_PROTOCOL_ERROR;
2534     goto fail;
2535   }
2536
2537   status = RPCRT4_ValidateCommonHeader(&common_hdr);
2538   if (status != RPC_S_OK) goto fail;
2539
2540   hdr_length = RPCRT4_GetHeaderSize((RpcPktHdr*)&common_hdr);
2541   if (hdr_length == 0) {
2542     WARN("header length == 0\n");
2543     status = RPC_S_PROTOCOL_ERROR;
2544     goto fail;
2545   }
2546
2547   *Header = HeapAlloc(GetProcessHeap(), 0, hdr_length);
2548   if (!*Header)
2549   {
2550     status = RPC_S_OUT_OF_RESOURCES;
2551     goto fail;
2552   }
2553   memcpy(*Header, &common_hdr, sizeof(common_hdr));
2554
2555   /* read the rest of packet header */
2556   dwRead = rpcrt4_ncacn_http_read(Connection, &(*Header)->common + 1, hdr_length - sizeof(common_hdr));
2557   if (dwRead != hdr_length - sizeof(common_hdr)) {
2558     WARN("bad header length, %d bytes, hdr_length %d\n", dwRead, hdr_length);
2559     status = RPC_S_PROTOCOL_ERROR;
2560     goto fail;
2561   }
2562
2563   if (common_hdr.frag_len - hdr_length)
2564   {
2565     *Payload = HeapAlloc(GetProcessHeap(), 0, common_hdr.frag_len - hdr_length);
2566     if (!*Payload)
2567     {
2568       status = RPC_S_OUT_OF_RESOURCES;
2569       goto fail;
2570     }
2571
2572     dwRead = rpcrt4_ncacn_http_read(Connection, *Payload, common_hdr.frag_len - hdr_length);
2573     if (dwRead != common_hdr.frag_len - hdr_length)
2574     {
2575       WARN("bad data length, %d/%d\n", dwRead, common_hdr.frag_len - hdr_length);
2576       status = RPC_S_PROTOCOL_ERROR;
2577       goto fail;
2578     }
2579   }
2580   else
2581     *Payload = NULL;
2582
2583   if ((*Header)->common.ptype == PKT_HTTP)
2584   {
2585     if (!RPCRT4_IsValidHttpPacket(*Header, *Payload, common_hdr.frag_len - hdr_length))
2586     {
2587       ERR("invalid http packet of length %d bytes\n", (*Header)->common.frag_len);
2588       status = RPC_S_PROTOCOL_ERROR;
2589       goto fail;
2590     }
2591     if ((*Header)->http.flags == 0x0001)
2592     {
2593       TRACE("http idle packet, waiting for real packet\n");
2594       if ((*Header)->http.num_data_items != 0)
2595       {
2596         ERR("HTTP idle packet should have no data items instead of %d\n", (*Header)->http.num_data_items);
2597         status = RPC_S_PROTOCOL_ERROR;
2598         goto fail;
2599       }
2600     }
2601     else if ((*Header)->http.flags == 0x0002)
2602     {
2603       ULONG bytes_transmitted;
2604       ULONG flow_control_increment;
2605       UUID pipe_uuid;
2606       status = RPCRT4_ParseHttpFlowControlHeader(*Header, *Payload,
2607                                                  Connection->server,
2608                                                  &bytes_transmitted,
2609                                                  &flow_control_increment,
2610                                                  &pipe_uuid);
2611       if (status != RPC_S_OK)
2612         goto fail;
2613       TRACE("received http flow control header (0x%x, 0x%x, %s)\n",
2614             bytes_transmitted, flow_control_increment, debugstr_guid(&pipe_uuid));
2615       /* FIXME: do something with parsed data */
2616     }
2617     else
2618     {
2619       FIXME("unrecognised http packet with flags 0x%04x\n", (*Header)->http.flags);
2620       status = RPC_S_PROTOCOL_ERROR;
2621       goto fail;
2622     }
2623     RPCRT4_FreeHeader(*Header);
2624     *Header = NULL;
2625     HeapFree(GetProcessHeap(), 0, *Payload);
2626     *Payload = NULL;
2627     goto again;
2628   }
2629
2630   /* success */
2631   status = RPC_S_OK;
2632
2633   httpc->bytes_received += common_hdr.frag_len;
2634
2635   TRACE("httpc->bytes_received = 0x%x\n", httpc->bytes_received);
2636
2637   if (httpc->bytes_received > httpc->flow_control_mark)
2638   {
2639     RpcPktHdr *hdr = RPCRT4_BuildHttpFlowControlHeader(httpc->common.server,
2640                                                        httpc->bytes_received,
2641                                                        httpc->flow_control_increment,
2642                                                        &httpc->out_pipe_uuid);
2643     if (hdr)
2644     {
2645       DWORD bytes_written;
2646       BOOL ret2;
2647       TRACE("sending flow control packet at 0x%x\n", httpc->bytes_received);
2648       ret2 = InternetWriteFile(httpc->in_request, hdr, hdr->common.frag_len, &bytes_written);
2649       RPCRT4_FreeHeader(hdr);
2650       if (ret2)
2651         httpc->flow_control_mark = httpc->bytes_received + httpc->flow_control_increment / 2;
2652     }
2653   }
2654
2655 fail:
2656   if (status != RPC_S_OK) {
2657     RPCRT4_FreeHeader(*Header);
2658     *Header = NULL;
2659     HeapFree(GetProcessHeap(), 0, *Payload);
2660     *Payload = NULL;
2661   }
2662   return status;
2663 }
2664
2665 static int rpcrt4_ncacn_http_write(RpcConnection *Connection,
2666                                  const void *buffer, unsigned int count)
2667 {
2668   RpcConnection_http *httpc = (RpcConnection_http *) Connection;
2669   DWORD bytes_written;
2670   BOOL ret;
2671
2672   httpc->last_sent_time = ~0U; /* disable idle packet sending */
2673   ret = InternetWriteFile(httpc->in_request, buffer, count, &bytes_written);
2674   httpc->last_sent_time = GetTickCount();
2675   TRACE("%p %p %u -> %s\n", httpc->in_request, buffer, count, ret ? "TRUE" : "FALSE");
2676   return ret ? bytes_written : -1;
2677 }
2678
2679 static int rpcrt4_ncacn_http_close(RpcConnection *Connection)
2680 {
2681   RpcConnection_http *httpc = (RpcConnection_http *) Connection;
2682
2683   TRACE("\n");
2684
2685   SetEvent(httpc->timer_cancelled);
2686   if (httpc->in_request)
2687     InternetCloseHandle(httpc->in_request);
2688   httpc->in_request = NULL;
2689   if (httpc->out_request)
2690     InternetCloseHandle(httpc->out_request);
2691   httpc->out_request = NULL;
2692   if (httpc->app_info)
2693     InternetCloseHandle(httpc->app_info);
2694   httpc->app_info = NULL;
2695   if (httpc->session)
2696     InternetCloseHandle(httpc->session);
2697   httpc->session = NULL;
2698   RpcHttpAsyncData_Release(httpc->async_data);
2699   if (httpc->cancel_event)
2700     CloseHandle(httpc->cancel_event);
2701
2702   return 0;
2703 }
2704
2705 static void rpcrt4_ncacn_http_cancel_call(RpcConnection *Connection)
2706 {
2707   RpcConnection_http *httpc = (RpcConnection_http *) Connection;
2708
2709   SetEvent(httpc->cancel_event);
2710 }
2711
2712 static int rpcrt4_ncacn_http_wait_for_incoming_data(RpcConnection *Connection)
2713 {
2714   BOOL ret;
2715   RpcConnection_http *httpc = (RpcConnection_http *) Connection;
2716
2717   RpcHttpAsyncData_AddRef(httpc->async_data);
2718   ret = InternetQueryDataAvailable(httpc->out_request,
2719     &httpc->async_data->inet_buffers.dwBufferLength, IRF_ASYNC, 0);
2720   if (ret)
2721   {
2722       /* INTERNET_STATUS_REQUEST_COMPLETED won't be sent, so release our
2723        * async ref now */
2724       RpcHttpAsyncData_Release(httpc->async_data);
2725   }
2726   else
2727   {
2728     if (GetLastError() == ERROR_IO_PENDING)
2729     {
2730       HANDLE handles[2] = { httpc->async_data->completion_event, httpc->cancel_event };
2731       DWORD result = WaitForMultipleObjects(2, handles, FALSE, DEFAULT_NCACN_HTTP_TIMEOUT);
2732       if (result != WAIT_OBJECT_0)
2733       {
2734         TRACE("call cancelled\n");
2735         return -1;
2736       }
2737     }
2738     else
2739     {
2740       RpcHttpAsyncData_Release(httpc->async_data);
2741       return -1;
2742     }
2743   }
2744
2745   /* success */
2746   return 0;
2747 }
2748
2749 static size_t rpcrt4_ncacn_http_get_top_of_tower(unsigned char *tower_data,
2750                                                  const char *networkaddr,
2751                                                  const char *endpoint)
2752 {
2753     return rpcrt4_ip_tcp_get_top_of_tower(tower_data, networkaddr,
2754                                           EPM_PROTOCOL_HTTP, endpoint);
2755 }
2756
2757 static RPC_STATUS rpcrt4_ncacn_http_parse_top_of_tower(const unsigned char *tower_data,
2758                                                        size_t tower_size,
2759                                                        char **networkaddr,
2760                                                        char **endpoint)
2761 {
2762     return rpcrt4_ip_tcp_parse_top_of_tower(tower_data, tower_size,
2763                                             networkaddr, EPM_PROTOCOL_HTTP,
2764                                             endpoint);
2765 }
2766
2767 static const struct connection_ops conn_protseq_list[] = {
2768   { "ncacn_np",
2769     { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_SMB },
2770     rpcrt4_conn_np_alloc,
2771     rpcrt4_ncacn_np_open,
2772     rpcrt4_ncacn_np_handoff,
2773     rpcrt4_conn_np_read,
2774     rpcrt4_conn_np_write,
2775     rpcrt4_conn_np_close,
2776     rpcrt4_conn_np_cancel_call,
2777     rpcrt4_conn_np_wait_for_incoming_data,
2778     rpcrt4_ncacn_np_get_top_of_tower,
2779     rpcrt4_ncacn_np_parse_top_of_tower,
2780     NULL,
2781     RPCRT4_default_is_authorized,
2782     RPCRT4_default_authorize,
2783     RPCRT4_default_secure_packet,
2784     rpcrt4_conn_np_impersonate_client,
2785     rpcrt4_conn_np_revert_to_self,
2786     RPCRT4_default_inquire_auth_client,
2787   },
2788   { "ncalrpc",
2789     { EPM_PROTOCOL_NCALRPC, EPM_PROTOCOL_PIPE },
2790     rpcrt4_conn_np_alloc,
2791     rpcrt4_ncalrpc_open,
2792     rpcrt4_ncalrpc_handoff,
2793     rpcrt4_conn_np_read,
2794     rpcrt4_conn_np_write,
2795     rpcrt4_conn_np_close,
2796     rpcrt4_conn_np_cancel_call,
2797     rpcrt4_conn_np_wait_for_incoming_data,
2798     rpcrt4_ncalrpc_get_top_of_tower,
2799     rpcrt4_ncalrpc_parse_top_of_tower,
2800     NULL,
2801     rpcrt4_ncalrpc_is_authorized,
2802     rpcrt4_ncalrpc_authorize,
2803     rpcrt4_ncalrpc_secure_packet,
2804     rpcrt4_conn_np_impersonate_client,
2805     rpcrt4_conn_np_revert_to_self,
2806     rpcrt4_ncalrpc_inquire_auth_client,
2807   },
2808   { "ncacn_ip_tcp",
2809     { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_TCP },
2810     rpcrt4_conn_tcp_alloc,
2811     rpcrt4_ncacn_ip_tcp_open,
2812     rpcrt4_conn_tcp_handoff,
2813     rpcrt4_conn_tcp_read,
2814     rpcrt4_conn_tcp_write,
2815     rpcrt4_conn_tcp_close,
2816     rpcrt4_conn_tcp_cancel_call,
2817     rpcrt4_conn_tcp_wait_for_incoming_data,
2818     rpcrt4_ncacn_ip_tcp_get_top_of_tower,
2819     rpcrt4_ncacn_ip_tcp_parse_top_of_tower,
2820     NULL,
2821     RPCRT4_default_is_authorized,
2822     RPCRT4_default_authorize,
2823     RPCRT4_default_secure_packet,
2824     RPCRT4_default_impersonate_client,
2825     RPCRT4_default_revert_to_self,
2826     RPCRT4_default_inquire_auth_client,
2827   },
2828   { "ncacn_http",
2829     { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_HTTP },
2830     rpcrt4_ncacn_http_alloc,
2831     rpcrt4_ncacn_http_open,
2832     rpcrt4_ncacn_http_handoff,
2833     rpcrt4_ncacn_http_read,
2834     rpcrt4_ncacn_http_write,
2835     rpcrt4_ncacn_http_close,
2836     rpcrt4_ncacn_http_cancel_call,
2837     rpcrt4_ncacn_http_wait_for_incoming_data,
2838     rpcrt4_ncacn_http_get_top_of_tower,
2839     rpcrt4_ncacn_http_parse_top_of_tower,
2840     rpcrt4_ncacn_http_receive_fragment,
2841     RPCRT4_default_is_authorized,
2842     RPCRT4_default_authorize,
2843     RPCRT4_default_secure_packet,
2844     RPCRT4_default_impersonate_client,
2845     RPCRT4_default_revert_to_self,
2846     RPCRT4_default_inquire_auth_client,
2847   },
2848 };
2849
2850
2851 static const struct protseq_ops protseq_list[] =
2852 {
2853     {
2854         "ncacn_np",
2855         rpcrt4_protseq_np_alloc,
2856         rpcrt4_protseq_np_signal_state_changed,
2857         rpcrt4_protseq_np_get_wait_array,
2858         rpcrt4_protseq_np_free_wait_array,
2859         rpcrt4_protseq_np_wait_for_new_connection,
2860         rpcrt4_protseq_ncacn_np_open_endpoint,
2861     },
2862     {
2863         "ncalrpc",
2864         rpcrt4_protseq_np_alloc,
2865         rpcrt4_protseq_np_signal_state_changed,
2866         rpcrt4_protseq_np_get_wait_array,
2867         rpcrt4_protseq_np_free_wait_array,
2868         rpcrt4_protseq_np_wait_for_new_connection,
2869         rpcrt4_protseq_ncalrpc_open_endpoint,
2870     },
2871     {
2872         "ncacn_ip_tcp",
2873         rpcrt4_protseq_sock_alloc,
2874         rpcrt4_protseq_sock_signal_state_changed,
2875         rpcrt4_protseq_sock_get_wait_array,
2876         rpcrt4_protseq_sock_free_wait_array,
2877         rpcrt4_protseq_sock_wait_for_new_connection,
2878         rpcrt4_protseq_ncacn_ip_tcp_open_endpoint,
2879     },
2880 };
2881
2882 #define ARRAYSIZE(a) (sizeof((a)) / sizeof((a)[0]))
2883
2884 const struct protseq_ops *rpcrt4_get_protseq_ops(const char *protseq)
2885 {
2886   unsigned int i;
2887   for(i=0; i<ARRAYSIZE(protseq_list); i++)
2888     if (!strcmp(protseq_list[i].name, protseq))
2889       return &protseq_list[i];
2890   return NULL;
2891 }
2892
2893 static const struct connection_ops *rpcrt4_get_conn_protseq_ops(const char *protseq)
2894 {
2895     unsigned int i;
2896     for(i=0; i<ARRAYSIZE(conn_protseq_list); i++)
2897         if (!strcmp(conn_protseq_list[i].name, protseq))
2898             return &conn_protseq_list[i];
2899     return NULL;
2900 }
2901
2902 /**** interface to rest of code ****/
2903
2904 RPC_STATUS RPCRT4_OpenClientConnection(RpcConnection* Connection)
2905 {
2906   TRACE("(Connection == ^%p)\n", Connection);
2907
2908   assert(!Connection->server);
2909   return Connection->ops->open_connection_client(Connection);
2910 }
2911
2912 RPC_STATUS RPCRT4_CloseConnection(RpcConnection* Connection)
2913 {
2914   TRACE("(Connection == ^%p)\n", Connection);
2915   if (SecIsValidHandle(&Connection->ctx))
2916   {
2917     DeleteSecurityContext(&Connection->ctx);
2918     SecInvalidateHandle(&Connection->ctx);
2919   }
2920   rpcrt4_conn_close(Connection);
2921   return RPC_S_OK;
2922 }
2923
2924 RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server,
2925     LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint,
2926     LPCWSTR NetworkOptions, RpcAuthInfo* AuthInfo, RpcQualityOfService *QOS)
2927 {
2928   static LONG next_id;
2929   const struct connection_ops *ops;
2930   RpcConnection* NewConnection;
2931
2932   ops = rpcrt4_get_conn_protseq_ops(Protseq);
2933   if (!ops)
2934   {
2935     FIXME("not supported for protseq %s\n", Protseq);
2936     return RPC_S_PROTSEQ_NOT_SUPPORTED;
2937   }
2938
2939   NewConnection = ops->alloc();
2940   NewConnection->Next = NULL;
2941   NewConnection->server_binding = NULL;
2942   NewConnection->server = server;
2943   NewConnection->ops = ops;
2944   NewConnection->NetworkAddr = RPCRT4_strdupA(NetworkAddr);
2945   NewConnection->Endpoint = RPCRT4_strdupA(Endpoint);
2946   NewConnection->NetworkOptions = RPCRT4_strdupW(NetworkOptions);
2947   NewConnection->MaxTransmissionSize = RPC_MAX_PACKET_SIZE;
2948   memset(&NewConnection->ActiveInterface, 0, sizeof(NewConnection->ActiveInterface));
2949   NewConnection->NextCallId = 1;
2950
2951   SecInvalidateHandle(&NewConnection->ctx);
2952   memset(&NewConnection->exp, 0, sizeof(NewConnection->exp));
2953   NewConnection->attr = 0;
2954   if (AuthInfo) RpcAuthInfo_AddRef(AuthInfo);
2955   NewConnection->AuthInfo = AuthInfo;
2956   NewConnection->auth_context_id = InterlockedIncrement( &next_id );
2957   NewConnection->encryption_auth_len = 0;
2958   NewConnection->signature_auth_len = 0;
2959   if (QOS) RpcQualityOfService_AddRef(QOS);
2960   NewConnection->QOS = QOS;
2961
2962   list_init(&NewConnection->conn_pool_entry);
2963   NewConnection->async_state = NULL;
2964
2965   TRACE("connection: %p\n", NewConnection);
2966   *Connection = NewConnection;
2967
2968   return RPC_S_OK;
2969 }
2970
2971 static RPC_STATUS RPCRT4_SpawnConnection(RpcConnection** Connection, RpcConnection* OldConnection)
2972 {
2973   RPC_STATUS err;
2974
2975   err = RPCRT4_CreateConnection(Connection, OldConnection->server,
2976                                 rpcrt4_conn_get_name(OldConnection),
2977                                 OldConnection->NetworkAddr,
2978                                 OldConnection->Endpoint, NULL,
2979                                 OldConnection->AuthInfo, OldConnection->QOS);
2980   if (err == RPC_S_OK)
2981     rpcrt4_conn_handoff(OldConnection, *Connection);
2982   return err;
2983 }
2984
2985 RPC_STATUS RPCRT4_DestroyConnection(RpcConnection* Connection)
2986 {
2987   TRACE("connection: %p\n", Connection);
2988
2989   RPCRT4_CloseConnection(Connection);
2990   RPCRT4_strfree(Connection->Endpoint);
2991   RPCRT4_strfree(Connection->NetworkAddr);
2992   HeapFree(GetProcessHeap(), 0, Connection->NetworkOptions);
2993   if (Connection->AuthInfo) RpcAuthInfo_Release(Connection->AuthInfo);
2994   if (Connection->QOS) RpcQualityOfService_Release(Connection->QOS);
2995
2996   /* server-only */
2997   if (Connection->server_binding) RPCRT4_ReleaseBinding(Connection->server_binding);
2998
2999   HeapFree(GetProcessHeap(), 0, Connection);
3000   return RPC_S_OK;
3001 }
3002
3003 RPC_STATUS RpcTransport_GetTopOfTower(unsigned char *tower_data,
3004                                       size_t *tower_size,
3005                                       const char *protseq,
3006                                       const char *networkaddr,
3007                                       const char *endpoint)
3008 {
3009     twr_empty_floor_t *protocol_floor;
3010     const struct connection_ops *protseq_ops = rpcrt4_get_conn_protseq_ops(protseq);
3011
3012     *tower_size = 0;
3013
3014     if (!protseq_ops)
3015         return RPC_S_INVALID_RPC_PROTSEQ;
3016
3017     if (!tower_data)
3018     {
3019         *tower_size = sizeof(*protocol_floor);
3020         *tower_size += protseq_ops->get_top_of_tower(NULL, networkaddr, endpoint);
3021         return RPC_S_OK;
3022     }
3023
3024     protocol_floor = (twr_empty_floor_t *)tower_data;
3025     protocol_floor->count_lhs = sizeof(protocol_floor->protid);
3026     protocol_floor->protid = protseq_ops->epm_protocols[0];
3027     protocol_floor->count_rhs = 0;
3028
3029     tower_data += sizeof(*protocol_floor);
3030
3031     *tower_size = protseq_ops->get_top_of_tower(tower_data, networkaddr, endpoint);
3032     if (!*tower_size)
3033         return EPT_S_NOT_REGISTERED;
3034
3035     *tower_size += sizeof(*protocol_floor);
3036
3037     return RPC_S_OK;
3038 }
3039
3040 RPC_STATUS RpcTransport_ParseTopOfTower(const unsigned char *tower_data,
3041                                         size_t tower_size,
3042                                         char **protseq,
3043                                         char **networkaddr,
3044                                         char **endpoint)
3045 {
3046     const twr_empty_floor_t *protocol_floor;
3047     const twr_empty_floor_t *floor4;
3048     const struct connection_ops *protseq_ops = NULL;
3049     RPC_STATUS status;
3050     unsigned int i;
3051
3052     if (tower_size < sizeof(*protocol_floor))
3053         return EPT_S_NOT_REGISTERED;
3054
3055     protocol_floor = (const twr_empty_floor_t *)tower_data;
3056     tower_data += sizeof(*protocol_floor);
3057     tower_size -= sizeof(*protocol_floor);
3058     if ((protocol_floor->count_lhs != sizeof(protocol_floor->protid)) ||
3059         (protocol_floor->count_rhs > tower_size))
3060         return EPT_S_NOT_REGISTERED;
3061     tower_data += protocol_floor->count_rhs;
3062     tower_size -= protocol_floor->count_rhs;
3063
3064     floor4 = (const twr_empty_floor_t *)tower_data;
3065     if ((tower_size < sizeof(*floor4)) ||
3066         (floor4->count_lhs != sizeof(floor4->protid)))
3067         return EPT_S_NOT_REGISTERED;
3068
3069     for(i = 0; i < ARRAYSIZE(conn_protseq_list); i++)
3070         if ((protocol_floor->protid == conn_protseq_list[i].epm_protocols[0]) &&
3071             (floor4->protid == conn_protseq_list[i].epm_protocols[1]))
3072         {
3073             protseq_ops = &conn_protseq_list[i];
3074             break;
3075         }
3076
3077     if (!protseq_ops)
3078         return EPT_S_NOT_REGISTERED;
3079
3080     status = protseq_ops->parse_top_of_tower(tower_data, tower_size, networkaddr, endpoint);
3081
3082     if ((status == RPC_S_OK) && protseq)
3083     {
3084         *protseq = I_RpcAllocate(strlen(protseq_ops->name) + 1);
3085         strcpy(*protseq, protseq_ops->name);
3086     }
3087
3088     return status;
3089 }
3090
3091 /***********************************************************************
3092  *             RpcNetworkIsProtseqValidW (RPCRT4.@)
3093  *
3094  * Checks if the given protocol sequence is known by the RPC system.
3095  * If it is, returns RPC_S_OK, otherwise RPC_S_PROTSEQ_NOT_SUPPORTED.
3096  *
3097  */
3098 RPC_STATUS WINAPI RpcNetworkIsProtseqValidW(RPC_WSTR protseq)
3099 {
3100   char ps[0x10];
3101
3102   WideCharToMultiByte(CP_ACP, 0, protseq, -1,
3103                       ps, sizeof ps, NULL, NULL);
3104   if (rpcrt4_get_conn_protseq_ops(ps))
3105     return RPC_S_OK;
3106
3107   FIXME("Unknown protseq %s\n", debugstr_w(protseq));
3108
3109   return RPC_S_INVALID_RPC_PROTSEQ;
3110 }
3111
3112 /***********************************************************************
3113  *             RpcNetworkIsProtseqValidA (RPCRT4.@)
3114  */
3115 RPC_STATUS WINAPI RpcNetworkIsProtseqValidA(RPC_CSTR protseq)
3116 {
3117   UNICODE_STRING protseqW;
3118
3119   if (RtlCreateUnicodeStringFromAsciiz(&protseqW, (char*)protseq))
3120   {
3121     RPC_STATUS ret = RpcNetworkIsProtseqValidW(protseqW.Buffer);
3122     RtlFreeUnicodeString(&protseqW);
3123     return ret;
3124   }
3125   return RPC_S_OUT_OF_MEMORY;
3126 }