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