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