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