ReactOS  0.4.13-dev-66-gc714b7f
rpc_transport.c
Go to the documentation of this file.
1 /*
2  * RPC transport layer
3  *
4  * Copyright 2001 Ove K√•ven, TransGaming Technologies
5  * Copyright 2003 Mike Hearn
6  * Copyright 2004 Filip Navara
7  * Copyright 2006 Mike McCormack
8  * Copyright 2006 Damjan Jovanovic
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23  *
24  */
25 
26 #include "ntstatus.h"
27 #define WIN32_NO_STATUS
28 #ifdef __REACTOS__
29 #define NONAMELESSUNION
30 #endif
31 #include "ws2tcpip.h"
32 
33 #include <stdarg.h>
34 #include <stdio.h>
35 #include <string.h>
36 #include <assert.h>
37 
38 #include "windef.h"
39 #include "winbase.h"
40 #include "winnls.h"
41 #include "winerror.h"
42 #include "wininet.h"
43 #include "wine/winternl.h"
44 #include "winioctl.h"
45 #include "wine/unicode.h"
46 
47 #include "rpc.h"
48 #include "rpcndr.h"
49 
50 #include "wine/debug.h"
51 
52 #include "rpc_binding.h"
53 #include "rpc_assoc.h"
54 #include "rpc_message.h"
55 #include "rpc_server.h"
56 #include "epm_towers.h"
57 
58 #define DEFAULT_NCACN_HTTP_TIMEOUT (60 * 1000)
59 
61 
62 #ifdef __REACTOS__ /* FIXME: Inspect */
64 {
66 
68  if (io_status.u.Status)
69  {
71  return FALSE;
72  }
73  return TRUE;
74 }
75 #endif
76 
77 static RpcConnection *rpcrt4_spawn_connection(RpcConnection *old_connection);
78 
79 /**** ncacn_np support ****/
80 
81 typedef struct _RpcConnection_np
82 {
86  char *listen_pipe;
91 
93 {
95  return &npc->common;
96 }
97 
99 {
100  HANDLE event = InterlockedExchangePointer(&connection->event_cache, NULL);
101  return event ? event : CreateEventW(NULL, TRUE, FALSE, NULL);
102 }
103 
105 {
106  event = InterlockedExchangePointer(&connection->event_cache, event);
107  if (event)
109 }
110 
112 {
113  RpcConnection_np *connection = (RpcConnection_np *) conn;
114 
115  TRACE("listening on %s\n", connection->listen_pipe);
116 
121  if (connection->pipe == INVALID_HANDLE_VALUE)
122  {
123  WARN("CreateNamedPipe failed with error %d\n", GetLastError());
126  else
128  }
129 
130  return RPC_S_OK;
131 }
132 
134 {
135  RpcConnection_np *npc = (RpcConnection_np *) Connection;
136  HANDLE pipe;
137  DWORD err, dwMode;
138 
139  TRACE("connecting to %s\n", pname);
140 
141  while (TRUE) {
142  DWORD dwFlags = 0;
143  if (Connection->QOS)
144  {
146  switch (Connection->QOS->qos->ImpersonationType)
147  {
149  /* FIXME: what to do here? */
150  break;
153  break;
156  break;
159  break;
162  break;
163  }
164  if (Connection->QOS->qos->IdentityTracking == RPC_C_QOS_IDENTITY_DYNAMIC)
166  }
169  if (pipe != INVALID_HANDLE_VALUE) break;
170  err = GetLastError();
171  if (err == ERROR_PIPE_BUSY) {
173  TRACE("retrying busy server\n");
174  continue;
175  }
176  TRACE("connection failed, error=%x\n", err);
177  return RPC_S_SERVER_TOO_BUSY;
178  }
179  if (!wait || !WaitNamedPipeA(pname, NMPWAIT_WAIT_FOREVER)) {
180  err = GetLastError();
181  WARN("connection failed, error=%x\n", err);
183  }
184  }
185 
186  /* success */
187  /* pipe is connected; change to message-read mode. */
188  dwMode = PIPE_READMODE_MESSAGE;
189  SetNamedPipeHandleState(pipe, &dwMode, NULL, NULL);
190  npc->pipe = pipe;
191 
192  return RPC_S_OK;
193 }
194 
195 static char *ncalrpc_pipe_name(const char *endpoint)
196 {
197  static const char prefix[] = "\\\\.\\pipe\\lrpc\\";
198  char *pipe_name;
199 
200  /* protseq=ncalrpc: supposed to use NT LPC ports,
201  * but we'll implement it with named pipes for now */
202  pipe_name = I_RpcAllocate(sizeof(prefix) + strlen(endpoint));
203  strcat(strcpy(pipe_name, prefix), endpoint);
204  return pipe_name;
205 }
206 
208 {
209  RpcConnection_np *npc = (RpcConnection_np *) Connection;
210  RPC_STATUS r;
211  LPSTR pname;
212 
213  /* already connected? */
214  if (npc->pipe)
215  return RPC_S_OK;
216 
217  pname = ncalrpc_pipe_name(Connection->Endpoint);
218  r = rpcrt4_conn_open_pipe(Connection, pname, TRUE);
219  I_RpcFree(pname);
220 
221  return r;
222 }
223 
225 {
226  RPC_STATUS r;
227  RpcConnection *Connection;
228  char generated_endpoint[22];
229 
230  if (!endpoint)
231  {
232  static LONG lrpc_nameless_id;
233  DWORD process_id = GetCurrentProcessId();
234  ULONG id = InterlockedIncrement(&lrpc_nameless_id);
235  snprintf(generated_endpoint, sizeof(generated_endpoint),
236  "LRPC%08x.%08x", process_id, id);
237  endpoint = generated_endpoint;
238  }
239 
240  r = RPCRT4_CreateConnection(&Connection, TRUE, protseq->Protseq, NULL,
241  endpoint, NULL, NULL, NULL, NULL);
242  if (r != RPC_S_OK)
243  return r;
244 
245  ((RpcConnection_np*)Connection)->listen_pipe = ncalrpc_pipe_name(Connection->Endpoint);
246  r = rpcrt4_conn_create_pipe(Connection);
247 
248  EnterCriticalSection(&protseq->cs);
249  list_add_head(&protseq->listeners, &Connection->protseq_entry);
250  Connection->protseq = protseq;
251  LeaveCriticalSection(&protseq->cs);
252 
253  return r;
254 }
255 
256 #ifdef __REACTOS__
257 static char *ncacn_pipe_name(const char *server, const char *endpoint)
258 #else
259 static char *ncacn_pipe_name(const char *endpoint)
260 #endif
261 {
262 #ifdef __REACTOS__
263  static const char prefix[] = "\\\\";
264  static const char local[] = ".";
265  char ComputerName[MAX_COMPUTERNAME_LENGTH + 1];
266 #else
267  static const char prefix[] = "\\\\.";
268 #endif
269  char *pipe_name;
270 
271 #ifdef __REACTOS__
272  DWORD bufLen = ARRAYSIZE(ComputerName);
273 
274  GetComputerNameA(ComputerName, &bufLen);
275 
276  if (server == NULL || *server == 0 || stricmp(ComputerName, server) == 0)
277  server = local;
278 #endif
279 
280  /* protseq=ncacn_np: named pipes */
281 #ifdef __REACTOS__
282  pipe_name = I_RpcAllocate(sizeof(prefix) + strlen(server) + strlen(endpoint));
283  strcpy(pipe_name, prefix);
284  strcat(pipe_name, server);
285  strcat(pipe_name, endpoint);
286 #else
287  pipe_name = I_RpcAllocate(sizeof(prefix) + strlen(endpoint));
288  strcat(strcpy(pipe_name, prefix), endpoint);
289 #endif
290  return pipe_name;
291 }
292 
294 {
295  RpcConnection_np *npc = (RpcConnection_np *) Connection;
296  RPC_STATUS r;
297  LPSTR pname;
298 
299  /* already connected? */
300  if (npc->pipe)
301  return RPC_S_OK;
302 
303 #ifdef __REACTOS__
304  pname = ncacn_pipe_name(Connection->NetworkAddr, Connection->Endpoint);
305 #else
306  pname = ncacn_pipe_name(Connection->Endpoint);
307 #endif
308  r = rpcrt4_conn_open_pipe(Connection, pname, FALSE);
309  I_RpcFree(pname);
310 
311  return r;
312 }
313 
315 {
316  RPC_STATUS r;
317  RpcConnection *Connection;
318  char generated_endpoint[26];
319 
320  if (!endpoint)
321  {
322  static LONG np_nameless_id;
323  DWORD process_id = GetCurrentProcessId();
324  ULONG id = InterlockedExchangeAdd(&np_nameless_id, 1 );
325  snprintf(generated_endpoint, sizeof(generated_endpoint),
326  "\\\\pipe\\\\%08x.%03x", process_id, id);
327  endpoint = generated_endpoint;
328  }
329 
330  r = RPCRT4_CreateConnection(&Connection, TRUE, protseq->Protseq, NULL,
331  endpoint, NULL, NULL, NULL, NULL);
332  if (r != RPC_S_OK)
333  return r;
334 
335 #ifdef __REACTOS__
336  ((RpcConnection_np*)Connection)->listen_pipe = ncacn_pipe_name(NULL, Connection->Endpoint);
337 #else
338  ((RpcConnection_np*)Connection)->listen_pipe = ncacn_pipe_name(Connection->Endpoint);
339 #endif
340  r = rpcrt4_conn_create_pipe(Connection);
341 
342  EnterCriticalSection(&protseq->cs);
343  list_add_head(&protseq->listeners, &Connection->protseq_entry);
344  Connection->protseq = protseq;
345  LeaveCriticalSection(&protseq->cs);
346 
347  return r;
348 }
349 
351 {
352  /* because of the way named pipes work, we'll transfer the connected pipe
353  * to the child, then reopen the server binding to continue listening */
354 
355  new_npc->pipe = old_npc->pipe;
356  old_npc->pipe = 0;
357  assert(!old_npc->listen_event);
358 }
359 
361 {
364 
365  rpcrt4_conn_np_handoff((RpcConnection_np *)old_conn, (RpcConnection_np *)new_conn);
366  status = rpcrt4_conn_create_pipe(old_conn);
367 
368  /* Store the local computer name as the NetworkAddr for ncacn_np as long as
369  * we don't support named pipes over the network. */
370  new_conn->NetworkAddr = HeapAlloc(GetProcessHeap(), 0, len);
371  if (!GetComputerNameA(new_conn->NetworkAddr, &len))
372  {
373  ERR("Failed to retrieve the computer name, error %u\n", GetLastError());
374  return RPC_S_OUT_OF_RESOURCES;
375  }
376 
377  return status;
378 }
379 
380 static RPC_STATUS is_pipe_listening(const char *pipe_name)
381 {
382  return WaitNamedPipeA(pipe_name, 1) ? RPC_S_OK : RPC_S_NOT_LISTENING;
383 }
384 
386 {
387  char *pipe_name;
389 
390 #ifdef __REACTOS__
391  pipe_name = ncacn_pipe_name(NULL, endpoint);
392 #else
393  pipe_name = ncacn_pipe_name(endpoint);
394 #endif
395  status = is_pipe_listening(pipe_name);
396  I_RpcFree(pipe_name);
397  return status;
398 }
399 
401 {
402  char *pipe_name;
404 
405  pipe_name = ncalrpc_pipe_name(endpoint);
406  status = is_pipe_listening(pipe_name);
407  I_RpcFree(pipe_name);
408  return status;
409 }
410 
412 {
415 
416  TRACE("%s\n", old_conn->Endpoint);
417 
418  rpcrt4_conn_np_handoff((RpcConnection_np *)old_conn, (RpcConnection_np *)new_conn);
419  status = rpcrt4_conn_create_pipe(old_conn);
420 
421  /* Store the local computer name as the NetworkAddr for ncalrpc. */
422  new_conn->NetworkAddr = HeapAlloc(GetProcessHeap(), 0, len);
423  if (!GetComputerNameA(new_conn->NetworkAddr, &len))
424  {
425  ERR("Failed to retrieve the computer name, error %u\n", GetLastError());
426  return RPC_S_OUT_OF_RESOURCES;
427  }
428 
429  return status;
430 }
431 
432 static int rpcrt4_conn_np_read(RpcConnection *conn, void *buffer, unsigned int count)
433 {
434  RpcConnection_np *connection = (RpcConnection_np *) conn;
435  HANDLE event;
437 
438  event = get_np_event(connection);
439  if (!event)
440  return -1;
441 
442  if (connection->read_closed)
444  else
445  status = NtReadFile(connection->pipe, event, NULL, NULL, &connection->io_status, buffer, count, NULL, NULL);
446  if (status == STATUS_PENDING)
447  {
448  /* check read_closed again before waiting to avoid a race */
449  if (connection->read_closed)
450  {
452 #ifdef __REACTOS__ /* FIXME: We should also cancel I/O for other threads */
453  NtCancelIoFile(connection->pipe, &io_status);
454 #else
455  NtCancelIoFileEx(connection->pipe, &connection->io_status, &io_status);
456 #endif
457  }
459  status = connection->io_status.u.Status;
460  }
461  release_np_event(connection, event);
462  return status && status != STATUS_BUFFER_OVERFLOW ? -1 : connection->io_status.Information;
463 }
464 
465 static int rpcrt4_conn_np_write(RpcConnection *conn, const void *buffer, unsigned int count)
466 {
467  RpcConnection_np *connection = (RpcConnection_np *) conn;
469  HANDLE event;
471 
472  event = get_np_event(connection);
473  if (!event)
474  return -1;
475 
476  status = NtWriteFile(connection->pipe, event, NULL, NULL, &io_status, buffer, count, NULL, NULL);
477  if (status == STATUS_PENDING)
478  {
480  status = io_status.u.Status;
481  }
482  release_np_event(connection, event);
483  if (status)
484  return -1;
485 
486  assert(io_status.Information == count);
487  return count;
488 }
489 
491 {
492  RpcConnection_np *connection = (RpcConnection_np *) conn;
493  if (connection->pipe)
494  {
495  FlushFileBuffers(connection->pipe);
496  CloseHandle(connection->pipe);
497  connection->pipe = 0;
498  }
499  if (connection->listen_event)
500  {
501  CloseHandle(connection->listen_event);
502  connection->listen_event = 0;
503  }
504  if (connection->event_cache)
505  {
506  CloseHandle(connection->event_cache);
507  connection->event_cache = 0;
508  }
509  return 0;
510 }
511 
513 {
514  RpcConnection_np *connection = (RpcConnection_np*)conn;
516 
517  connection->read_closed = TRUE;
518 #ifdef __REACTOS__ /* FIXME: We should also cancel I/O for other threads */
519  NtCancelIoFile(connection->pipe, &io_status);
520 #else
521  NtCancelIoFileEx(connection->pipe, &connection->io_status, &io_status);
522 #endif
523 }
524 
526 {
527  RpcConnection_np *connection = (RpcConnection_np *)conn;
528  CancelIoEx(connection->pipe, NULL);
529 }
530 
532 {
533  /* FIXME: implement when named pipe writes use overlapped I/O */
534  return -1;
535 }
536 
537 static size_t rpcrt4_ncacn_np_get_top_of_tower(unsigned char *tower_data,
538  const char *networkaddr,
539  const char *endpoint)
540 {
541  twr_empty_floor_t *smb_floor;
542  twr_empty_floor_t *nb_floor;
543  size_t size;
544  size_t networkaddr_size;
545  size_t endpoint_size;
546 
547  TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint);
548 
549  networkaddr_size = networkaddr ? strlen(networkaddr) + 1 : 1;
550  endpoint_size = endpoint ? strlen(endpoint) + 1 : 1;
551  size = sizeof(*smb_floor) + endpoint_size + sizeof(*nb_floor) + networkaddr_size;
552 
553  if (!tower_data)
554  return size;
555 
556  smb_floor = (twr_empty_floor_t *)tower_data;
557 
558  tower_data += sizeof(*smb_floor);
559 
560  smb_floor->count_lhs = sizeof(smb_floor->protid);
561  smb_floor->protid = EPM_PROTOCOL_SMB;
562  smb_floor->count_rhs = endpoint_size;
563 
564  if (endpoint)
565  memcpy(tower_data, endpoint, endpoint_size);
566  else
567  tower_data[0] = 0;
568  tower_data += endpoint_size;
569 
570  nb_floor = (twr_empty_floor_t *)tower_data;
571 
572  tower_data += sizeof(*nb_floor);
573 
574  nb_floor->count_lhs = sizeof(nb_floor->protid);
575  nb_floor->protid = EPM_PROTOCOL_NETBIOS;
576  nb_floor->count_rhs = networkaddr_size;
577 
578  if (networkaddr)
579  memcpy(tower_data, networkaddr, networkaddr_size);
580  else
581  tower_data[0] = 0;
582 
583  return size;
584 }
585 
586 static RPC_STATUS rpcrt4_ncacn_np_parse_top_of_tower(const unsigned char *tower_data,
587  size_t tower_size,
588  char **networkaddr,
589  char **endpoint)
590 {
591  const twr_empty_floor_t *smb_floor = (const twr_empty_floor_t *)tower_data;
592  const twr_empty_floor_t *nb_floor;
593 
594  TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint);
595 
596  if (tower_size < sizeof(*smb_floor))
597  return EPT_S_NOT_REGISTERED;
598 
599  tower_data += sizeof(*smb_floor);
600  tower_size -= sizeof(*smb_floor);
601 
602  if ((smb_floor->count_lhs != sizeof(smb_floor->protid)) ||
603  (smb_floor->protid != EPM_PROTOCOL_SMB) ||
604  (smb_floor->count_rhs > tower_size) ||
605  (tower_data[smb_floor->count_rhs - 1] != '\0'))
606  return EPT_S_NOT_REGISTERED;
607 
608  if (endpoint)
609  {
610  *endpoint = I_RpcAllocate(smb_floor->count_rhs);
611  if (!*endpoint)
612  return RPC_S_OUT_OF_RESOURCES;
613  memcpy(*endpoint, tower_data, smb_floor->count_rhs);
614  }
615  tower_data += smb_floor->count_rhs;
616  tower_size -= smb_floor->count_rhs;
617 
618  if (tower_size < sizeof(*nb_floor))
619  return EPT_S_NOT_REGISTERED;
620 
621  nb_floor = (const twr_empty_floor_t *)tower_data;
622 
623  tower_data += sizeof(*nb_floor);
624  tower_size -= sizeof(*nb_floor);
625 
626  if ((nb_floor->count_lhs != sizeof(nb_floor->protid)) ||
627  (nb_floor->protid != EPM_PROTOCOL_NETBIOS) ||
628  (nb_floor->count_rhs > tower_size) ||
629  (tower_data[nb_floor->count_rhs - 1] != '\0'))
630  return EPT_S_NOT_REGISTERED;
631 
632  if (networkaddr)
633  {
634  *networkaddr = I_RpcAllocate(nb_floor->count_rhs);
635  if (!*networkaddr)
636  {
637  if (endpoint)
638  {
640  *endpoint = NULL;
641  }
642  return RPC_S_OUT_OF_RESOURCES;
643  }
644  memcpy(*networkaddr, tower_data, nb_floor->count_rhs);
645  }
646 
647  return RPC_S_OK;
648 }
649 
651 {
652  RpcConnection_np *npc = (RpcConnection_np *)conn;
653  BOOL ret;
654 
655  TRACE("(%p)\n", conn);
656 
657  if (conn->AuthInfo && SecIsValidHandle(&conn->ctx))
659 
661  if (!ret)
662  {
664  WARN("ImpersonateNamedPipeClient failed with error %u\n", error);
665  switch (error)
666  {
669  }
670  }
671  return RPC_S_OK;
672 }
673 
675 {
676  BOOL ret;
677 
678  TRACE("(%p)\n", conn);
679 
680  if (conn->AuthInfo && SecIsValidHandle(&conn->ctx))
681  return RPCRT4_default_revert_to_self(conn);
682 
683  ret = RevertToSelf();
684  if (!ret)
685  {
686  WARN("RevertToSelf failed with error %u\n", GetLastError());
688  }
689  return RPC_S_OK;
690 }
691 
692 typedef struct _RpcServerProtseq_np
693 {
697 
699 {
701  if (ps)
703  return &ps->common;
704 }
705 
707 {
709  SetEvent(npps->mgr_event);
710 }
711 
712 static void *rpcrt4_protseq_np_get_wait_array(RpcServerProtseq *protseq, void *prev_array, unsigned int *count)
713 {
714  HANDLE *objs = prev_array;
715  RpcConnection_np *conn;
717 
718  EnterCriticalSection(&protseq->cs);
719 
720  /* open and count connections */
721  *count = 1;
722  LIST_FOR_EACH_ENTRY(conn, &protseq->listeners, RpcConnection_np, common.protseq_entry)
723  {
724  if (!conn->pipe && rpcrt4_conn_create_pipe(&conn->common) != RPC_S_OK)
725  continue;
726  if (!conn->listen_event)
727  {
729  HANDLE event;
730 
731  event = get_np_event(conn);
732  if (!event)
733  continue;
734 
736  switch (status)
737  {
738  case STATUS_SUCCESS:
740  conn->io_status.u.Status = status;
741  SetEvent(event);
742  break;
743  case STATUS_PENDING:
744  break;
745  default:
746  ERR("pipe listen error %x\n", status);
747  continue;
748  }
749 
750  conn->listen_event = event;
751  }
752  (*count)++;
753  }
754 
755  /* make array of connections */
756  if (objs)
757  objs = HeapReAlloc(GetProcessHeap(), 0, objs, *count*sizeof(HANDLE));
758  else
759  objs = HeapAlloc(GetProcessHeap(), 0, *count*sizeof(HANDLE));
760  if (!objs)
761  {
762  ERR("couldn't allocate objs\n");
763  LeaveCriticalSection(&protseq->cs);
764  return NULL;
765  }
766 
767  objs[0] = npps->mgr_event;
768  *count = 1;
769  LIST_FOR_EACH_ENTRY(conn, &protseq->listeners, RpcConnection_np, common.protseq_entry)
770  {
771  if (conn->listen_event)
772  objs[(*count)++] = conn->listen_event;
773  }
774  LeaveCriticalSection(&protseq->cs);
775  return objs;
776 }
777 
779 {
781 }
782 
783 static int rpcrt4_protseq_np_wait_for_new_connection(RpcServerProtseq *protseq, unsigned int count, void *wait_array)
784 {
785  HANDLE b_handle;
786  HANDLE *objs = wait_array;
787  DWORD res;
788  RpcConnection *cconn = NULL;
789  RpcConnection_np *conn;
790 
791  if (!objs)
792  return -1;
793 
794  do
795  {
796  /* an alertable wait isn't strictly necessary, but due to our
797  * overlapped I/O implementation in Wine we need to free some memory
798  * by the file user APC being called, even if no completion routine was
799  * specified at the time of starting the async operation */
801  } while (res == WAIT_IO_COMPLETION);
802 
803  if (res == WAIT_OBJECT_0)
804  return 0;
805  else if (res == WAIT_FAILED)
806  {
807  ERR("wait failed with error %d\n", GetLastError());
808  return -1;
809  }
810  else
811  {
812  b_handle = objs[res - WAIT_OBJECT_0];
813  /* find which connection got a RPC */
814  EnterCriticalSection(&protseq->cs);
815  LIST_FOR_EACH_ENTRY(conn, &protseq->listeners, RpcConnection_np, common.protseq_entry)
816  {
817  if (b_handle == conn->listen_event)
818  {
819  release_np_event(conn, conn->listen_event);
820  conn->listen_event = NULL;
822  cconn = rpcrt4_spawn_connection(&conn->common);
823  else
824  ERR("listen failed %x\n", conn->io_status.u.Status);
825  break;
826  }
827  }
828  LeaveCriticalSection(&protseq->cs);
829  if (!cconn)
830  {
831  ERR("failed to locate connection for handle %p\n", b_handle);
832  return -1;
833  }
834  RPCRT4_new_client(cconn);
835  return 1;
836  }
837 }
838 
839 static size_t rpcrt4_ncalrpc_get_top_of_tower(unsigned char *tower_data,
840  const char *networkaddr,
841  const char *endpoint)
842 {
843  twr_empty_floor_t *pipe_floor;
844  size_t size;
845  size_t endpoint_size;
846 
847  TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint);
848 
849  endpoint_size = strlen(endpoint) + 1;
850  size = sizeof(*pipe_floor) + endpoint_size;
851 
852  if (!tower_data)
853  return size;
854 
855  pipe_floor = (twr_empty_floor_t *)tower_data;
856 
857  tower_data += sizeof(*pipe_floor);
858 
859  pipe_floor->count_lhs = sizeof(pipe_floor->protid);
860  pipe_floor->protid = EPM_PROTOCOL_PIPE;
861  pipe_floor->count_rhs = endpoint_size;
862 
863  memcpy(tower_data, endpoint, endpoint_size);
864 
865  return size;
866 }
867 
868 static RPC_STATUS rpcrt4_ncalrpc_parse_top_of_tower(const unsigned char *tower_data,
869  size_t tower_size,
870  char **networkaddr,
871  char **endpoint)
872 {
873  const twr_empty_floor_t *pipe_floor = (const twr_empty_floor_t *)tower_data;
874 
875  TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint);
876 
877  if (tower_size < sizeof(*pipe_floor))
878  return EPT_S_NOT_REGISTERED;
879 
880  tower_data += sizeof(*pipe_floor);
881  tower_size -= sizeof(*pipe_floor);
882 
883  if ((pipe_floor->count_lhs != sizeof(pipe_floor->protid)) ||
884  (pipe_floor->protid != EPM_PROTOCOL_PIPE) ||
885  (pipe_floor->count_rhs > tower_size) ||
886  (tower_data[pipe_floor->count_rhs - 1] != '\0'))
887  return EPT_S_NOT_REGISTERED;
888 
889  if (networkaddr)
890  *networkaddr = NULL;
891 
892  if (endpoint)
893  {
894  *endpoint = I_RpcAllocate(pipe_floor->count_rhs);
895  if (!*endpoint)
896  return RPC_S_OUT_OF_RESOURCES;
897  memcpy(*endpoint, tower_data, pipe_floor->count_rhs);
898  }
899 
900  return RPC_S_OK;
901 }
902 
904 {
905  return FALSE;
906 }
907 
909  unsigned char *in_buffer,
910  unsigned int in_size,
911  unsigned char *out_buffer,
912  unsigned int *out_size)
913 {
914  /* since this protocol is local to the machine there is no need to
915  * authenticate the caller */
916  *out_size = 0;
917  return RPC_S_OK;
918 }
919 
922  RpcPktHdr *hdr, unsigned int hdr_size,
923  unsigned char *stub_data, unsigned int stub_data_size,
924  RpcAuthVerifier *auth_hdr,
925  unsigned char *auth_value, unsigned int auth_value_size)
926 {
927  /* since this protocol is local to the machine there is no need to secure
928  * the packet */
929  return RPC_S_OK;
930 }
931 
933  RpcConnection *conn, RPC_AUTHZ_HANDLE *privs, RPC_WSTR *server_princ_name,
934  ULONG *authn_level, ULONG *authn_svc, ULONG *authz_svc, ULONG flags)
935 {
936  TRACE("(%p, %p, %p, %p, %p, %p, 0x%x)\n", conn, privs,
937  server_princ_name, authn_level, authn_svc, authz_svc, flags);
938 
939  if (privs)
940  {
941  FIXME("privs not implemented\n");
942  *privs = NULL;
943  }
944  if (server_princ_name)
945  {
946  FIXME("server_princ_name not implemented\n");
947  *server_princ_name = NULL;
948  }
949  if (authn_level) *authn_level = RPC_C_AUTHN_LEVEL_PKT_PRIVACY;
950  if (authn_svc) *authn_svc = RPC_C_AUTHN_WINNT;
951  if (authz_svc)
952  {
953  FIXME("authorization service not implemented\n");
954  *authz_svc = RPC_C_AUTHZ_NONE;
955  }
956  if (flags)
957  FIXME("flags 0x%x not implemented\n", flags);
958 
959  return RPC_S_OK;
960 }
961 
962 /**** ncacn_ip_tcp support ****/
963 
964 static size_t rpcrt4_ip_tcp_get_top_of_tower(unsigned char *tower_data,
965  const char *networkaddr,
966  unsigned char tcp_protid,
967  const char *endpoint)
968 {
969  twr_tcp_floor_t *tcp_floor;
970  twr_ipv4_floor_t *ipv4_floor;
971  struct addrinfo *ai;
972  struct addrinfo hints;
973  int ret;
974  size_t size = sizeof(*tcp_floor) + sizeof(*ipv4_floor);
975 
976  TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint);
977 
978  if (!tower_data)
979  return size;
980 
981  tcp_floor = (twr_tcp_floor_t *)tower_data;
982  tower_data += sizeof(*tcp_floor);
983 
984  ipv4_floor = (twr_ipv4_floor_t *)tower_data;
985 
986  tcp_floor->count_lhs = sizeof(tcp_floor->protid);
987  tcp_floor->protid = tcp_protid;
988  tcp_floor->count_rhs = sizeof(tcp_floor->port);
989 
990  ipv4_floor->count_lhs = sizeof(ipv4_floor->protid);
991  ipv4_floor->protid = EPM_PROTOCOL_IP;
992  ipv4_floor->count_rhs = sizeof(ipv4_floor->ipv4addr);
993 
994  hints.ai_flags = AI_NUMERICHOST;
995  /* FIXME: only support IPv4 at the moment. how is IPv6 represented by the EPM? */
996  hints.ai_family = PF_INET;
997  hints.ai_socktype = SOCK_STREAM;
998  hints.ai_protocol = IPPROTO_TCP;
999  hints.ai_addrlen = 0;
1000  hints.ai_addr = NULL;
1001  hints.ai_canonname = NULL;
1002  hints.ai_next = NULL;
1003 
1004  ret = getaddrinfo(networkaddr, endpoint, &hints, &ai);
1005  if (ret)
1006  {
1007  ret = getaddrinfo("0.0.0.0", endpoint, &hints, &ai);
1008  if (ret)
1009  {
1010  ERR("getaddrinfo failed: %s\n", gai_strerror(ret));
1011  return 0;
1012  }
1013  }
1014 
1015  if (ai->ai_family == PF_INET)
1016  {
1017  const struct sockaddr_in *sin = (const struct sockaddr_in *)ai->ai_addr;
1018  tcp_floor->port = sin->sin_port;
1019  ipv4_floor->ipv4addr = sin->sin_addr.s_addr;
1020  }
1021  else
1022  {
1023  ERR("unexpected protocol family %d\n", ai->ai_family);
1024  freeaddrinfo(ai);
1025  return 0;
1026  }
1027 
1028  freeaddrinfo(ai);
1029 
1030  return size;
1031 }
1032 
1033 static RPC_STATUS rpcrt4_ip_tcp_parse_top_of_tower(const unsigned char *tower_data,
1034  size_t tower_size,
1035  char **networkaddr,
1036  unsigned char tcp_protid,
1037  char **endpoint)
1038 {
1039  const twr_tcp_floor_t *tcp_floor = (const twr_tcp_floor_t *)tower_data;
1040  const twr_ipv4_floor_t *ipv4_floor;
1041  struct in_addr in_addr;
1042 
1043  TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint);
1044 
1045  if (tower_size < sizeof(*tcp_floor))
1046  return EPT_S_NOT_REGISTERED;
1047 
1048  tower_data += sizeof(*tcp_floor);
1049  tower_size -= sizeof(*tcp_floor);
1050 
1051  if (tower_size < sizeof(*ipv4_floor))
1052  return EPT_S_NOT_REGISTERED;
1053 
1054  ipv4_floor = (const twr_ipv4_floor_t *)tower_data;
1055 
1056  if ((tcp_floor->count_lhs != sizeof(tcp_floor->protid)) ||
1057  (tcp_floor->protid != tcp_protid) ||
1058  (tcp_floor->count_rhs != sizeof(tcp_floor->port)) ||
1059  (ipv4_floor->count_lhs != sizeof(ipv4_floor->protid)) ||
1060  (ipv4_floor->protid != EPM_PROTOCOL_IP) ||
1061  (ipv4_floor->count_rhs != sizeof(ipv4_floor->ipv4addr)))
1062  return EPT_S_NOT_REGISTERED;
1063 
1064  if (endpoint)
1065  {
1066  *endpoint = I_RpcAllocate(6 /* sizeof("65535") + 1 */);
1067  if (!*endpoint)
1068  return RPC_S_OUT_OF_RESOURCES;
1069  sprintf(*endpoint, "%u", ntohs(tcp_floor->port));
1070  }
1071 
1072  if (networkaddr)
1073  {
1074  *networkaddr = I_RpcAllocate(INET_ADDRSTRLEN);
1075  if (!*networkaddr)
1076  {
1077  if (endpoint)
1078  {
1079  I_RpcFree(*endpoint);
1080  *endpoint = NULL;
1081  }
1082  return RPC_S_OUT_OF_RESOURCES;
1083  }
1084  in_addr.s_addr = ipv4_floor->ipv4addr;
1085  if (!inet_ntop(AF_INET, &in_addr, *networkaddr, INET_ADDRSTRLEN))
1086  {
1087  ERR("inet_ntop: %u\n", WSAGetLastError());
1088  I_RpcFree(*networkaddr);
1089  *networkaddr = NULL;
1090  if (endpoint)
1091  {
1092  I_RpcFree(*endpoint);
1093  *endpoint = NULL;
1094  }
1095  return EPT_S_NOT_REGISTERED;
1096  }
1097  }
1098 
1099  return RPC_S_OK;
1100 }
1101 
1102 typedef struct _RpcConnection_tcp
1103 {
1105  int sock;
1109 
1111 {
1112  static BOOL wsa_inited;
1113  if (!wsa_inited)
1114  {
1115  WSADATA wsadata;
1116  WSAStartup(MAKEWORD(2, 2), &wsadata);
1117  /* Note: WSAStartup can be called more than once so we don't bother with
1118  * making accesses to wsa_inited thread-safe */
1119  wsa_inited = TRUE;
1120  }
1123  if (!tcpc->sock_event || !tcpc->cancel_event)
1124  {
1125  ERR("event creation failed\n");
1126  if (tcpc->sock_event) CloseHandle(tcpc->sock_event);
1127  return FALSE;
1128  }
1129  return TRUE;
1130 }
1131 
1133 {
1134  HANDLE wait_handles[2];
1135  DWORD res;
1136  if (WSAEventSelect(tcpc->sock, tcpc->sock_event, FD_READ | FD_CLOSE) == SOCKET_ERROR)
1137  {
1138  ERR("WSAEventSelect() failed with error %d\n", WSAGetLastError());
1139  return FALSE;
1140  }
1141  wait_handles[0] = tcpc->sock_event;
1142  wait_handles[1] = tcpc->cancel_event;
1143  res = WaitForMultipleObjects(2, wait_handles, FALSE, INFINITE);
1144  switch (res)
1145  {
1146  case WAIT_OBJECT_0:
1147  return TRUE;
1148  case WAIT_OBJECT_0 + 1:
1149  return FALSE;
1150  default:
1151  ERR("WaitForMultipleObjects() failed with error %d\n", GetLastError());
1152  return FALSE;
1153  }
1154 }
1155 
1157 {
1158  DWORD res;
1159  if (WSAEventSelect(tcpc->sock, tcpc->sock_event, FD_WRITE | FD_CLOSE) == SOCKET_ERROR)
1160  {
1161  ERR("WSAEventSelect() failed with error %d\n", WSAGetLastError());
1162  return FALSE;
1163  }
1165  switch (res)
1166  {
1167  case WAIT_OBJECT_0:
1168  return TRUE;
1169  default:
1170  ERR("WaitForMultipleObjects() failed with error %d\n", GetLastError());
1171  return FALSE;
1172  }
1173 }
1174 
1176 {
1177  RpcConnection_tcp *tcpc;
1179  if (tcpc == NULL)
1180  return NULL;
1181  tcpc->sock = -1;
1182  if (!rpcrt4_sock_wait_init(tcpc))
1183  {
1184  HeapFree(GetProcessHeap(), 0, tcpc);
1185  return NULL;
1186  }
1187  return &tcpc->common;
1188 }
1189 
1191 {
1192  RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
1193  int sock;
1194  int ret;
1195  struct addrinfo *ai;
1196  struct addrinfo *ai_cur;
1197  struct addrinfo hints;
1198 
1199  TRACE("(%s, %s)\n", Connection->NetworkAddr, Connection->Endpoint);
1200 
1201  if (tcpc->sock != -1)
1202  return RPC_S_OK;
1203 
1204  hints.ai_flags = 0;
1205  hints.ai_family = PF_UNSPEC;
1206  hints.ai_socktype = SOCK_STREAM;
1207  hints.ai_protocol = IPPROTO_TCP;
1208  hints.ai_addrlen = 0;
1209  hints.ai_addr = NULL;
1210  hints.ai_canonname = NULL;
1211  hints.ai_next = NULL;
1212 
1213  ret = getaddrinfo(Connection->NetworkAddr, Connection->Endpoint, &hints, &ai);
1214  if (ret)
1215  {
1216  ERR("getaddrinfo for %s:%s failed: %s\n", Connection->NetworkAddr,
1217  Connection->Endpoint, gai_strerror(ret));
1218  return RPC_S_SERVER_UNAVAILABLE;
1219  }
1220 
1221  for (ai_cur = ai; ai_cur; ai_cur = ai_cur->ai_next)
1222  {
1223  int val;
1224  u_long nonblocking;
1225 
1226  if (ai_cur->ai_family != AF_INET && ai_cur->ai_family != AF_INET6)
1227  {
1228  TRACE("skipping non-IP/IPv6 address family\n");
1229  continue;
1230  }
1231 
1232  if (TRACE_ON(rpc))
1233  {
1234  char host[256];
1235  char service[256];
1236  getnameinfo(ai_cur->ai_addr, ai_cur->ai_addrlen,
1237  host, sizeof(host), service, sizeof(service),
1239  TRACE("trying %s:%s\n", host, service);
1240  }
1241 
1242  sock = socket(ai_cur->ai_family, ai_cur->ai_socktype, ai_cur->ai_protocol);
1243  if (sock == -1)
1244  {
1245  WARN("socket() failed: %u\n", WSAGetLastError());
1246  continue;
1247  }
1248 
1249  if (0>connect(sock, ai_cur->ai_addr, ai_cur->ai_addrlen))
1250  {
1251  WARN("connect() failed: %u\n", WSAGetLastError());
1252  closesocket(sock);
1253  continue;
1254  }
1255 
1256  /* RPC depends on having minimal latency so disable the Nagle algorithm */
1257  val = 1;
1258  setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
1259  nonblocking = 1;
1260  ioctlsocket(sock, FIONBIO, &nonblocking);
1261 
1262  tcpc->sock = sock;
1263 
1264  freeaddrinfo(ai);
1265  TRACE("connected\n");
1266  return RPC_S_OK;
1267  }
1268 
1269  freeaddrinfo(ai);
1270  ERR("couldn't connect to %s:%s\n", Connection->NetworkAddr, Connection->Endpoint);
1271  return RPC_S_SERVER_UNAVAILABLE;
1272 }
1273 
1275 {
1277  int sock;
1278  int ret;
1279  struct addrinfo *ai;
1280  struct addrinfo *ai_cur;
1281  struct addrinfo hints;
1282 
1283  TRACE("(%p, %s)\n", protseq, endpoint);
1284 
1285  hints.ai_flags = AI_PASSIVE /* for non-localhost addresses */;
1286  hints.ai_family = PF_UNSPEC;
1287  hints.ai_socktype = SOCK_STREAM;
1288  hints.ai_protocol = IPPROTO_TCP;
1289  hints.ai_addrlen = 0;
1290  hints.ai_addr = NULL;
1291  hints.ai_canonname = NULL;
1292  hints.ai_next = NULL;
1293 
1294  ret = getaddrinfo(NULL, endpoint ? endpoint : "0", &hints, &ai);
1295  if (ret)
1296  {
1297  ERR("getaddrinfo for port %s failed: %s\n", endpoint,
1298  gai_strerror(ret));
1299  if ((ret == EAI_SERVICE) || (ret == EAI_NONAME))
1302  }
1303 
1304  for (ai_cur = ai; ai_cur; ai_cur = ai_cur->ai_next)
1305  {
1306  RpcConnection_tcp *tcpc;
1307  RPC_STATUS create_status;
1308  struct sockaddr_storage sa;
1309  socklen_t sa_len;
1310  char service[NI_MAXSERV];
1311  u_long nonblocking;
1312 
1313  if (ai_cur->ai_family != AF_INET && ai_cur->ai_family != AF_INET6)
1314  {
1315  TRACE("skipping non-IP/IPv6 address family\n");
1316  continue;
1317  }
1318 
1319  if (TRACE_ON(rpc))
1320  {
1321  char host[256];
1322  getnameinfo(ai_cur->ai_addr, ai_cur->ai_addrlen,
1323  host, sizeof(host), service, sizeof(service),
1325  TRACE("trying %s:%s\n", host, service);
1326  }
1327 
1328  sock = socket(ai_cur->ai_family, ai_cur->ai_socktype, ai_cur->ai_protocol);
1329  if (sock == -1)
1330  {
1331  WARN("socket() failed: %u\n", WSAGetLastError());
1333  continue;
1334  }
1335 
1336  ret = bind(sock, ai_cur->ai_addr, ai_cur->ai_addrlen);
1337  if (ret < 0)
1338  {
1339  WARN("bind failed: %u\n", WSAGetLastError());
1340  closesocket(sock);
1341  if (WSAGetLastError() == WSAEADDRINUSE)
1343  else
1345  continue;
1346  }
1347 
1348  sa_len = sizeof(sa);
1349  if (getsockname(sock, (struct sockaddr *)&sa, &sa_len))
1350  {
1351  WARN("getsockname() failed: %u\n", WSAGetLastError());
1352  closesocket(sock);
1354  continue;
1355  }
1356 
1357  ret = getnameinfo((struct sockaddr *)&sa, sa_len,
1358  NULL, 0, service, sizeof(service),
1359  NI_NUMERICSERV);
1360  if (ret)
1361  {
1362  WARN("getnameinfo failed: %s\n", gai_strerror(ret));
1363  closesocket(sock);
1365  continue;
1366  }
1367 
1368  create_status = RPCRT4_CreateConnection((RpcConnection **)&tcpc, TRUE,
1369  protseq->Protseq, NULL,
1370  service, NULL, NULL, NULL, NULL);
1371  if (create_status != RPC_S_OK)
1372  {
1373  closesocket(sock);
1374  status = create_status;
1375  continue;
1376  }
1377 
1378  tcpc->sock = sock;
1379  ret = listen(sock, protseq->MaxCalls);
1380  if (ret < 0)
1381  {
1382  WARN("listen failed: %u\n", WSAGetLastError());
1383  RPCRT4_ReleaseConnection(&tcpc->common);
1385  continue;
1386  }
1387  /* need a non-blocking socket, otherwise accept() has a potential
1388  * race-condition (poll() says it is readable, connection drops,
1389  * and accept() blocks until the next connection comes...)
1390  */
1391  nonblocking = 1;
1392  ret = ioctlsocket(sock, FIONBIO, &nonblocking);
1393  if (ret < 0)
1394  {
1395  WARN("couldn't make socket non-blocking, error %d\n", ret);
1396  RPCRT4_ReleaseConnection(&tcpc->common);
1398  continue;
1399  }
1400 
1401  EnterCriticalSection(&protseq->cs);
1402  list_add_tail(&protseq->listeners, &tcpc->common.protseq_entry);
1403  tcpc->common.protseq = protseq;
1404  LeaveCriticalSection(&protseq->cs);
1405 
1406  freeaddrinfo(ai);
1407 
1408  /* since IPv4 and IPv6 share the same port space, we only need one
1409  * successful bind to listen for both */
1410  TRACE("listening on %s\n", endpoint);
1411  return RPC_S_OK;
1412  }
1413 
1414  freeaddrinfo(ai);
1415  ERR("couldn't listen on port %s\n", endpoint);
1416  return status;
1417 }
1418 
1420 {
1421  int ret;
1422  struct sockaddr_in address;
1423  socklen_t addrsize;
1426  u_long nonblocking;
1427 
1428  addrsize = sizeof(address);
1429  ret = accept(server->sock, (struct sockaddr*) &address, &addrsize);
1430  if (ret < 0)
1431  {
1432  ERR("Failed to accept a TCP connection: error %d\n", ret);
1433  return RPC_S_OUT_OF_RESOURCES;
1434  }
1435 
1436  nonblocking = 1;
1437  ioctlsocket(ret, FIONBIO, &nonblocking);
1438  client->sock = ret;
1439 
1440  client->common.NetworkAddr = HeapAlloc(GetProcessHeap(), 0, INET6_ADDRSTRLEN);
1441  ret = getnameinfo((struct sockaddr*)&address, addrsize, client->common.NetworkAddr, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);
1442  if (ret != 0)
1443  {
1444  ERR("Failed to retrieve the IP address, error %d\n", ret);
1445  return RPC_S_OUT_OF_RESOURCES;
1446  }
1447 
1448  TRACE("Accepted a new TCP connection from %s\n", client->common.NetworkAddr);
1449  return RPC_S_OK;
1450 }
1451 
1452 static int rpcrt4_conn_tcp_read(RpcConnection *Connection,
1453  void *buffer, unsigned int count)
1454 {
1455  RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
1456  int bytes_read = 0;
1457  while (bytes_read != count)
1458  {
1459  int r = recv(tcpc->sock, (char *)buffer + bytes_read, count - bytes_read, 0);
1460  if (!r)
1461  return -1;
1462  else if (r > 0)
1463  bytes_read += r;
1464  else if (WSAGetLastError() == WSAEINTR)
1465  continue;
1466  else if (WSAGetLastError() != WSAEWOULDBLOCK)
1467  {
1468  WARN("recv() failed: %u\n", WSAGetLastError());
1469  return -1;
1470  }
1471  else
1472  {
1473  if (!rpcrt4_sock_wait_for_recv(tcpc))
1474  return -1;
1475  }
1476  }
1477  TRACE("%d %p %u -> %d\n", tcpc->sock, buffer, count, bytes_read);
1478  return bytes_read;
1479 }
1480 
1481 static int rpcrt4_conn_tcp_write(RpcConnection *Connection,
1482  const void *buffer, unsigned int count)
1483 {
1484  RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
1485  int bytes_written = 0;
1486  while (bytes_written != count)
1487  {
1488  int r = send(tcpc->sock, (const char *)buffer + bytes_written, count - bytes_written, 0);
1489  if (r >= 0)
1490  bytes_written += r;
1491  else if (WSAGetLastError() == WSAEINTR)
1492  continue;
1493  else if (WSAGetLastError() != WSAEWOULDBLOCK)
1494  return -1;
1495  else
1496  {
1497  if (!rpcrt4_sock_wait_for_send(tcpc))
1498  return -1;
1499  }
1500  }
1501  TRACE("%d %p %u -> %d\n", tcpc->sock, buffer, count, bytes_written);
1502  return bytes_written;
1503 }
1504 
1506 {
1507  RpcConnection_tcp *connection = (RpcConnection_tcp *) conn;
1508 
1509  TRACE("%d\n", connection->sock);
1510 
1511  if (connection->sock != -1)
1512  closesocket(connection->sock);
1513  connection->sock = -1;
1514  CloseHandle(connection->sock_event);
1515  CloseHandle(connection->cancel_event);
1516  return 0;
1517 }
1518 
1520 {
1521  RpcConnection_tcp *connection = (RpcConnection_tcp *) conn;
1522  shutdown(connection->sock, SD_RECEIVE);
1523 }
1524 
1526 {
1527  RpcConnection_tcp *connection = (RpcConnection_tcp *) conn;
1528 
1529  TRACE("%p\n", connection);
1530 
1531  SetEvent(connection->cancel_event);
1532 }
1533 
1535 {
1536  FIXME("\n");
1537  return RPC_S_ACCESS_DENIED;
1538 }
1539 
1541 {
1542  RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
1543 
1544  TRACE("%p\n", Connection);
1545 
1546  if (!rpcrt4_sock_wait_for_recv(tcpc))
1547  return -1;
1548  return 0;
1549 }
1550 
1551 static size_t rpcrt4_ncacn_ip_tcp_get_top_of_tower(unsigned char *tower_data,
1552  const char *networkaddr,
1553  const char *endpoint)
1554 {
1555  return rpcrt4_ip_tcp_get_top_of_tower(tower_data, networkaddr,
1557 }
1558 
1560 {
1564 
1566 {
1568  if (ps)
1569  {
1570  static BOOL wsa_inited;
1571  if (!wsa_inited)
1572  {
1573  WSADATA wsadata;
1574  WSAStartup(MAKEWORD(2, 2), &wsadata);
1575  /* Note: WSAStartup can be called more than once so we don't bother with
1576  * making accesses to wsa_inited thread-safe */
1577  wsa_inited = TRUE;
1578  }
1580  }
1581  return &ps->common;
1582 }
1583 
1585 {
1587  SetEvent(sockps->mgr_event);
1588 }
1589 
1590 static void *rpcrt4_protseq_sock_get_wait_array(RpcServerProtseq *protseq, void *prev_array, unsigned int *count)
1591 {
1592  HANDLE *objs = prev_array;
1593  RpcConnection_tcp *conn;
1595 
1596  EnterCriticalSection(&protseq->cs);
1597 
1598  /* open and count connections */
1599  *count = 1;
1600  LIST_FOR_EACH_ENTRY(conn, &protseq->listeners, RpcConnection_tcp, common.protseq_entry)
1601  {
1602  if (conn->sock != -1)
1603  (*count)++;
1604  }
1605 
1606  /* make array of connections */
1607  if (objs)
1608  objs = HeapReAlloc(GetProcessHeap(), 0, objs, *count*sizeof(HANDLE));
1609  else
1610  objs = HeapAlloc(GetProcessHeap(), 0, *count*sizeof(HANDLE));
1611  if (!objs)
1612  {
1613  ERR("couldn't allocate objs\n");
1614  LeaveCriticalSection(&protseq->cs);
1615  return NULL;
1616  }
1617 
1618  objs[0] = sockps->mgr_event;
1619  *count = 1;
1620  LIST_FOR_EACH_ENTRY(conn, &protseq->listeners, RpcConnection_tcp, common.protseq_entry)
1621  {
1622  if (conn->sock != -1)
1623  {
1624  int res = WSAEventSelect(conn->sock, conn->sock_event, FD_ACCEPT);
1625  if (res == SOCKET_ERROR)
1626  ERR("WSAEventSelect() failed with error %d\n", WSAGetLastError());
1627  else
1628  {
1629  objs[*count] = conn->sock_event;
1630  (*count)++;
1631  }
1632  }
1633  }
1634  LeaveCriticalSection(&protseq->cs);
1635  return objs;
1636 }
1637 
1639 {
1640  HeapFree(GetProcessHeap(), 0, array);
1641 }
1642 
1643 static int rpcrt4_protseq_sock_wait_for_new_connection(RpcServerProtseq *protseq, unsigned int count, void *wait_array)
1644 {
1645  HANDLE b_handle;
1646  HANDLE *objs = wait_array;
1647  DWORD res;
1648  RpcConnection *cconn = NULL;
1649  RpcConnection_tcp *conn;
1650 
1651  if (!objs)
1652  return -1;
1653 
1654  do
1655  {
1656  /* an alertable wait isn't strictly necessary, but due to our
1657  * overlapped I/O implementation in Wine we need to free some memory
1658  * by the file user APC being called, even if no completion routine was
1659  * specified at the time of starting the async operation */
1661  } while (res == WAIT_IO_COMPLETION);
1662 
1663  if (res == WAIT_OBJECT_0)
1664  return 0;
1665  if (res == WAIT_FAILED)
1666  {
1667  ERR("wait failed with error %d\n", GetLastError());
1668  return -1;
1669  }
1670 
1671  b_handle = objs[res - WAIT_OBJECT_0];
1672 
1673  /* find which connection got a RPC */
1674  EnterCriticalSection(&protseq->cs);
1675  LIST_FOR_EACH_ENTRY(conn, &protseq->listeners, RpcConnection_tcp, common.protseq_entry)
1676  {
1677  if (b_handle == conn->sock_event)
1678  {
1679  cconn = rpcrt4_spawn_connection(&conn->common);
1680  break;
1681  }
1682  }
1683  LeaveCriticalSection(&protseq->cs);
1684  if (!cconn)
1685  {
1686  ERR("failed to locate connection for handle %p\n", b_handle);
1687  return -1;
1688  }
1689 
1690  RPCRT4_new_client(cconn);
1691  return 1;
1692 }
1693 
1694 static RPC_STATUS rpcrt4_ncacn_ip_tcp_parse_top_of_tower(const unsigned char *tower_data,
1695  size_t tower_size,
1696  char **networkaddr,
1697  char **endpoint)
1698 {
1699  return rpcrt4_ip_tcp_parse_top_of_tower(tower_data, tower_size,
1700  networkaddr, EPM_PROTOCOL_TCP,
1701  endpoint);
1702 }
1703 
1704 /**** ncacn_http support ****/
1705 
1706 /* 60 seconds is the period native uses */
1707 #define HTTP_IDLE_TIME 60000
1708 
1709 /* reference counted to avoid a race between a cancelled call's connection
1710  * being destroyed and the asynchronous InternetReadFileEx call being
1711  * completed */
1712 typedef struct _RpcHttpAsyncData
1713 {
1720 
1722 {
1723  return InterlockedIncrement(&data->refs);
1724 }
1725 
1727 {
1728  ULONG refs = InterlockedDecrement(&data->refs);
1729  if (!refs)
1730  {
1731  TRACE("destroying async data %p\n", data);
1732  CloseHandle(data->completion_event);
1733  HeapFree(GetProcessHeap(), 0, data->inet_buffers.lpvBuffer);
1734  data->cs.DebugInfo->Spare[0] = 0;
1736  HeapFree(GetProcessHeap(), 0, data);
1737  }
1738  return refs;
1739 }
1740 
1741 static void prepare_async_request(RpcHttpAsyncData *async_data)
1742 {
1743  ResetEvent(async_data->completion_event);
1744  RpcHttpAsyncData_AddRef(async_data);
1745 }
1746 
1747 static RPC_STATUS wait_async_request(RpcHttpAsyncData *async_data, BOOL call_ret, HANDLE cancel_event)
1748 {
1749  HANDLE handles[2] = { async_data->completion_event, cancel_event };
1750  DWORD res;
1751 
1752  if(call_ret) {
1753  RpcHttpAsyncData_Release(async_data);
1754  return RPC_S_OK;
1755  }
1756 
1757  if(GetLastError() != ERROR_IO_PENDING) {
1758  RpcHttpAsyncData_Release(async_data);
1759  ERR("Request failed with error %d\n", GetLastError());
1760  return RPC_S_SERVER_UNAVAILABLE;
1761  }
1762 
1764  if(res != WAIT_OBJECT_0) {
1765  TRACE("Cancelled\n");
1766  return RPC_S_CALL_CANCELLED;
1767  }
1768 
1769  if(async_data->async_result) {
1770  ERR("Async request failed with error %d\n", async_data->async_result);
1771  return RPC_S_SERVER_UNAVAILABLE;
1772  }
1773 
1774  return RPC_S_OK;
1775 }
1776 
1777 struct authinfo
1778 {
1785  char *data;
1786  unsigned int data_len;
1787  BOOL finished; /* finished authenticating */
1788 };
1789 
1790 typedef struct _RpcConnection_http
1791 {
1802  ULONG flow_control_mark; /* send a control packet to the server when this many bytes received */
1803  ULONG flow_control_increment; /* number of bytes to increment flow_control_mark by */
1809 
1811 {
1812  RpcConnection_http *httpc;
1813  httpc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*httpc));
1814  if (!httpc) return NULL;
1816  if (!httpc->async_data)
1817  {
1818  HeapFree(GetProcessHeap(), 0, httpc);
1819  return NULL;
1820  }
1821  TRACE("async data = %p\n", httpc->async_data);
1823  httpc->async_data->refs = 1;
1826  httpc->async_data->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": RpcHttpAsyncData.cs");
1827  return &httpc->common;
1828 }
1829 
1830 typedef struct _HttpTimerThreadData
1831 {
1836 
1838 {
1839  HINTERNET in_request = param;
1840  RpcPktHdr *idle_pkt;
1841 
1843  0, 0);
1844  if (idle_pkt)
1845  {
1846  DWORD bytes_written;
1847  InternetWriteFile(in_request, idle_pkt, idle_pkt->common.frag_len, &bytes_written);
1848  RPCRT4_FreeHeader(idle_pkt);
1849  }
1850 }
1851 
1852 static inline DWORD rpcrt4_http_timer_calc_timeout(DWORD *last_sent_time)
1853 {
1855  DWORD cached_last_sent_time = *last_sent_time;
1856  return HTTP_IDLE_TIME - (cur_time - cached_last_sent_time > HTTP_IDLE_TIME ? 0 : cur_time - cached_last_sent_time);
1857 }
1858 
1860 {
1861  HttpTimerThreadData *data_in = param;
1863  DWORD timeout;
1864 
1865  data = *data_in;
1866  HeapFree(GetProcessHeap(), 0, data_in);
1867 
1868  for (timeout = HTTP_IDLE_TIME;
1869  WaitForSingleObject(data.timer_cancelled, timeout) == WAIT_TIMEOUT;
1870  timeout = rpcrt4_http_timer_calc_timeout(data.last_sent_time))
1871  {
1872  /* are we too soon after last send? */
1873  if (GetTickCount() - *data.last_sent_time < HTTP_IDLE_TIME)
1874  continue;
1876  }
1877 
1878  CloseHandle(data.timer_cancelled);
1879  return 0;
1880 }
1881 
1883  HINTERNET hInternet,
1884  DWORD_PTR dwContext,
1885  DWORD dwInternetStatus,
1886  LPVOID lpvStatusInformation,
1887  DWORD dwStatusInformationLength)
1888 {
1889  RpcHttpAsyncData *async_data = (RpcHttpAsyncData *)dwContext;
1890 
1891  switch (dwInternetStatus)
1892  {
1894  TRACE("INTERNET_STATUS_REQUEST_COMPLETED\n");
1895  if (async_data)
1896  {
1897  INTERNET_ASYNC_RESULT *async_result = lpvStatusInformation;
1898 
1899  async_data->async_result = async_result->dwResult ? ERROR_SUCCESS : async_result->dwError;
1900  SetEvent(async_data->completion_event);
1901  RpcHttpAsyncData_Release(async_data);
1902  }
1903  break;
1904  }
1905 }
1906 
1908 {
1909  BOOL ret;
1911  DWORD size;
1912  DWORD index;
1913  WCHAR buf[32];
1914  WCHAR *status_text = buf;
1915  TRACE("\n");
1916 
1917  index = 0;
1918  size = sizeof(status_code);
1920  if (!ret)
1921  return GetLastError();
1922  if (status_code == HTTP_STATUS_OK)
1923  return RPC_S_OK;
1924  index = 0;
1925  size = sizeof(buf);
1926  ret = HttpQueryInfoW(hor, HTTP_QUERY_STATUS_TEXT, status_text, &size, &index);
1928  {
1929  status_text = HeapAlloc(GetProcessHeap(), 0, size);
1930  ret = HttpQueryInfoW(hor, HTTP_QUERY_STATUS_TEXT, status_text, &size, &index);
1931  }
1932 
1933  ERR("server returned: %d %s\n", status_code, ret ? debugstr_w(status_text) : "<status text unavailable>");
1934  if(status_text != buf) HeapFree(GetProcessHeap(), 0, status_text);
1935 
1937  return ERROR_ACCESS_DENIED;
1938  return RPC_S_SERVER_UNAVAILABLE;
1939 }
1940 
1942 {
1943  static const WCHAR wszUserAgent[] = {'M','S','R','P','C',0};
1944  LPWSTR proxy = NULL;
1945  LPWSTR user = NULL;
1946  LPWSTR password = NULL;
1947  LPWSTR servername = NULL;
1948  const WCHAR *option;
1950 
1951  if (httpc->common.QOS &&
1953  {
1954  const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_cred = httpc->common.QOS->qos->u.HttpCredentials;
1955  if (http_cred->TransportCredentials)
1956  {
1957  WCHAR *p;
1958  const SEC_WINNT_AUTH_IDENTITY_W *cred = http_cred->TransportCredentials;
1959  ULONG len = cred->DomainLength + 1 + cred->UserLength;
1960  user = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
1961  if (!user)
1962  return RPC_S_OUT_OF_RESOURCES;
1963  p = user;
1964  if (cred->DomainLength)
1965  {
1966  memcpy(p, cred->Domain, cred->DomainLength * sizeof(WCHAR));
1967  p += cred->DomainLength;
1968  *p = '\\';
1969  p++;
1970  }
1971  memcpy(p, cred->User, cred->UserLength * sizeof(WCHAR));
1972  p[cred->UserLength] = 0;
1973 
1975  }
1976  }
1977 
1978  for (option = httpc->common.NetworkOptions; option;
1979  option = (strchrW(option, ',') ? strchrW(option, ',')+1 : NULL))
1980  {
1981  static const WCHAR wszRpcProxy[] = {'R','p','c','P','r','o','x','y','=',0};
1982  static const WCHAR wszHttpProxy[] = {'H','t','t','p','P','r','o','x','y','=',0};
1983 
1984  if (!strncmpiW(option, wszRpcProxy, ARRAY_SIZE(wszRpcProxy)-1))
1985  {
1986  const WCHAR *value_start = option + ARRAY_SIZE(wszRpcProxy)-1;
1987  const WCHAR *value_end;
1988  const WCHAR *p;
1989 
1990  value_end = strchrW(option, ',');
1991  if (!value_end)
1992  value_end = value_start + strlenW(value_start);
1993  for (p = value_start; p < value_end; p++)
1994  if (*p == ':')
1995  {
1996  port = atoiW(p+1);
1997  value_end = p;
1998  break;
1999  }
2000  TRACE("RpcProxy value is %s\n", debugstr_wn(value_start, value_end-value_start));
2001  servername = RPCRT4_strndupW(value_start, value_end-value_start);
2002  }
2003  else if (!strncmpiW(option, wszHttpProxy, ARRAY_SIZE(wszHttpProxy)-1))
2004  {
2005  const WCHAR *value_start = option + ARRAY_SIZE(wszHttpProxy)-1;
2006  const WCHAR *value_end;
2007 
2008  value_end = strchrW(option, ',');
2009  if (!value_end)
2010  value_end = value_start + strlenW(value_start);
2011  TRACE("HttpProxy value is %s\n", debugstr_wn(value_start, value_end-value_start));
2012  proxy = RPCRT4_strndupW(value_start, value_end-value_start);
2013  }
2014  else
2015  FIXME("unhandled option %s\n", debugstr_w(option));
2016  }
2017 
2020  if (!httpc->app_info)
2021  {
2023  HeapFree(GetProcessHeap(), 0, user);
2024  HeapFree(GetProcessHeap(), 0, proxy);
2025  HeapFree(GetProcessHeap(), 0, servername);
2026  ERR("InternetOpenW failed with error %d\n", GetLastError());
2027  return RPC_S_SERVER_UNAVAILABLE;
2028  }
2030 
2031  /* if no RpcProxy option specified, set the HTTP server address to the
2032  * RPC server address */
2033  if (!servername)
2034  {
2035  servername = HeapAlloc(GetProcessHeap(), 0, (strlen(httpc->common.NetworkAddr) + 1)*sizeof(WCHAR));
2036  if (!servername)
2037  {
2039  HeapFree(GetProcessHeap(), 0, user);
2040  HeapFree(GetProcessHeap(), 0, proxy);
2041  return RPC_S_OUT_OF_RESOURCES;
2042  }
2043  MultiByteToWideChar(CP_ACP, 0, httpc->common.NetworkAddr, -1, servername, strlen(httpc->common.NetworkAddr) + 1);
2044  }
2045 
2046  port = (httpc->common.QOS &&
2050 
2051  httpc->session = InternetConnectW(httpc->app_info, servername, port, user, password,
2052  INTERNET_SERVICE_HTTP, 0, 0);
2053 
2055  HeapFree(GetProcessHeap(), 0, user);
2056  HeapFree(GetProcessHeap(), 0, proxy);
2057 
2058  if (!httpc->session)
2059  {
2060  ERR("InternetConnectW failed with error %d\n", GetLastError());
2061  HeapFree(GetProcessHeap(), 0, servername);
2062  return RPC_S_SERVER_UNAVAILABLE;
2063  }
2064  httpc->servername = servername;
2065  return RPC_S_OK;
2066 }
2067 
2068 static int rpcrt4_http_async_read(HINTERNET req, RpcHttpAsyncData *async_data, HANDLE cancel_event,
2069  void *buffer, unsigned int count)
2070 {
2071  char *buf = buffer;
2072  BOOL ret;
2073  unsigned int bytes_left = count;
2075 
2076  async_data->inet_buffers.lpvBuffer = HeapAlloc(GetProcessHeap(), 0, count);
2077 
2078  while (bytes_left)
2079  {
2080  async_data->inet_buffers.dwBufferLength = bytes_left;
2081  prepare_async_request(async_data);
2082  ret = InternetReadFileExW(req, &async_data->inet_buffers, IRF_ASYNC, 0);
2083  status = wait_async_request(async_data, ret, cancel_event);
2084  if (status != RPC_S_OK)
2085  {
2087  TRACE("call cancelled\n");
2088  break;
2089  }
2090 
2091  if (!async_data->inet_buffers.dwBufferLength)
2092  break;
2093  memcpy(buf, async_data->inet_buffers.lpvBuffer,
2094  async_data->inet_buffers.dwBufferLength);
2095 
2096  bytes_left -= async_data->inet_buffers.dwBufferLength;
2097  buf += async_data->inet_buffers.dwBufferLength;
2098  }
2099 
2100  HeapFree(GetProcessHeap(), 0, async_data->inet_buffers.lpvBuffer);
2101  async_data->inet_buffers.lpvBuffer = NULL;
2102 
2103  TRACE("%p %p %u -> %u\n", req, buffer, count, status);
2104  return status == RPC_S_OK ? count : -1;
2105 }
2106 
2107 static RPC_STATUS send_echo_request(HINTERNET req, RpcHttpAsyncData *async_data, HANDLE cancel_event)
2108 {
2109  BYTE buf[20];
2110  BOOL ret;
2112 
2113  TRACE("sending echo request to server\n");
2114 
2115  prepare_async_request(async_data);
2116  ret = HttpSendRequestW(req, NULL, 0, NULL, 0);
2117  status = wait_async_request(async_data, ret, cancel_event);
2118  if (status != RPC_S_OK) return status;
2119 
2121  if (status != RPC_S_OK) return status;
2122 
2123  rpcrt4_http_async_read(req, async_data, cancel_event, buf, sizeof(buf));
2124  /* FIXME: do something with retrieved data */
2125 
2126  return RPC_S_OK;
2127 }
2128 
2130 {
2131  static const WCHAR fmtW[] =
2132  {'C','o','n','t','e','n','t','-','L','e','n','g','t','h',':',' ','%','u','\r','\n',0};
2133  WCHAR header[ARRAY_SIZE(fmtW) + 10];
2134 
2135  sprintfW(header, fmtW, len);
2137  return RPC_S_SERVER_UNAVAILABLE;
2138 }
2139 
2140 /* prepare the in pipe for use by RPC packets */
2141 static RPC_STATUS rpcrt4_http_prepare_in_pipe(HINTERNET in_request, RpcHttpAsyncData *async_data, HANDLE cancel_event,
2142  const UUID *connection_uuid, const UUID *in_pipe_uuid,
2143  const UUID *association_uuid, BOOL authorized)
2144 {
2145  BOOL ret;
2147  RpcPktHdr *hdr;
2148  INTERNET_BUFFERSW buffers_in;
2149  DWORD bytes_written;
2150 
2151  if (!authorized)
2152  {
2153  /* ask wininet to authorize, if necessary */
2154  status = send_echo_request(in_request, async_data, cancel_event);
2155  if (status != RPC_S_OK) return status;
2156  }
2157  memset(&buffers_in, 0, sizeof(buffers_in));
2158  buffers_in.dwStructSize = sizeof(buffers_in);
2159  /* FIXME: get this from the registry */
2160  buffers_in.dwBufferTotal = 1024 * 1024 * 1024; /* 1Gb */
2161  status = insert_content_length_header(in_request, buffers_in.dwBufferTotal);
2162  if (status != RPC_S_OK) return status;
2163 
2164  prepare_async_request(async_data);
2165  ret = HttpSendRequestExW(in_request, &buffers_in, NULL, 0, 0);
2166  status = wait_async_request(async_data, ret, cancel_event);
2167  if (status != RPC_S_OK) return status;
2168 
2169  TRACE("sending HTTP connect header to server\n");
2170  hdr = RPCRT4_BuildHttpConnectHeader(FALSE, connection_uuid, in_pipe_uuid, association_uuid);
2171  if (!hdr) return RPC_S_OUT_OF_RESOURCES;
2172  ret = InternetWriteFile(in_request, hdr, hdr->common.frag_len, &bytes_written);
2174  if (!ret)
2175  {
2176  ERR("InternetWriteFile failed with error %d\n", GetLastError());
2177  return RPC_S_SERVER_UNAVAILABLE;
2178  }
2179 
2180  return RPC_S_OK;
2181 }
2182 
2184  HANDLE cancel_event, RpcPktHdr *hdr, BYTE **data)
2185 {
2186  unsigned short data_len;
2187  unsigned int size;
2188 
2189  if (rpcrt4_http_async_read(request, async_data, cancel_event, hdr, sizeof(hdr->common)) < 0)
2190  return RPC_S_SERVER_UNAVAILABLE;
2191  if (hdr->common.ptype != PKT_HTTP || hdr->common.frag_len < sizeof(hdr->http))
2192  {
2193  ERR("wrong packet type received %d or wrong frag_len %d\n",
2194  hdr->common.ptype, hdr->common.frag_len);
2195  return RPC_S_PROTOCOL_ERROR;
2196  }
2197 
2198  size = sizeof(hdr->http) - sizeof(hdr->common);
2199  if (rpcrt4_http_async_read(request, async_data, cancel_event, &hdr->common + 1, size) < 0)
2200  return RPC_S_SERVER_UNAVAILABLE;
2201 
2202  data_len = hdr->common.frag_len - sizeof(hdr->http);
2203  if (data_len)
2204  {
2205  *data = HeapAlloc(GetProcessHeap(), 0, data_len);
2206  if (!*data)
2207  return RPC_S_OUT_OF_RESOURCES;
2208  if (rpcrt4_http_async_read(request, async_data, cancel_event, *data, data_len) < 0)
2209  {
2210  HeapFree(GetProcessHeap(), 0, *data);
2211  return RPC_S_SERVER_UNAVAILABLE;
2212  }
2213  }
2214  else
2215  *data = NULL;
2216 
2217  if (!RPCRT4_IsValidHttpPacket(hdr, *data, data_len))
2218  {
2219  ERR("invalid http packet\n");
2220  HeapFree(GetProcessHeap(), 0, *data);
2221  return RPC_S_PROTOCOL_ERROR;
2222  }
2223 
2224  return RPC_S_OK;
2225 }
2226 
2227 /* prepare the out pipe for use by RPC packets */
2229  HANDLE cancel_event, const UUID *connection_uuid,
2230  const UUID *out_pipe_uuid, ULONG *flow_control_increment,
2231  BOOL authorized)
2232 {
2233  BOOL ret;
2235  RpcPktHdr *hdr;
2236  BYTE *data_from_server;
2237  RpcPktHdr pkt_from_server;
2238  ULONG field1, field3;
2239  BYTE buf[20];
2240 
2241  if (!authorized)
2242  {
2243  /* ask wininet to authorize, if necessary */
2244  status = send_echo_request(out_request, async_data, cancel_event);
2245  if (status != RPC_S_OK) return status;
2246  }
2247  else
2248  rpcrt4_http_async_read(out_request, async_data, cancel_event, buf, sizeof(buf));
2249 
2250  hdr = RPCRT4_BuildHttpConnectHeader(TRUE, connection_uuid, out_pipe_uuid, NULL);
2251  if (!hdr) return RPC_S_OUT_OF_RESOURCES;
2252 
2253  status = insert_content_length_header(out_request, hdr->common.frag_len);
2254  if (status != RPC_S_OK)
2255  {
2257  return status;
2258  }
2259 
2260  TRACE("sending HTTP connect header to server\n");
2261  prepare_async_request(async_data);
2262  ret = HttpSendRequestW(out_request, NULL, 0, hdr, hdr->common.frag_len);
2263  status = wait_async_request(async_data, ret, cancel_event);
2265  if (status != RPC_S_OK) return status;
2266 
2267  status = rpcrt4_http_check_response(out_request);
2268  if (status != RPC_S_OK) return status;
2269 
2270  status = rpcrt4_http_read_http_packet(out_request, async_data, cancel_event,
2271  &pkt_from_server, &data_from_server);
2272  if (status != RPC_S_OK) return status;
2273  status = RPCRT4_ParseHttpPrepareHeader1(&pkt_from_server, data_from_server,
2274  &field1);
2275  HeapFree(GetProcessHeap(), 0, data_from_server);
2276  if (status != RPC_S_OK) return status;
2277  TRACE("received (%d) from first prepare header\n", field1);
2278 
2279  for (;;)
2280  {
2281  status = rpcrt4_http_read_http_packet(out_request, async_data, cancel_event,
2282  &pkt_from_server, &data_from_server);
2283  if (status != RPC_S_OK) return status;
2284  if (pkt_from_server.http.flags != 0x0001) break;
2285 
2286  TRACE("http idle packet, waiting for real packet\n");
2287  HeapFree(GetProcessHeap(), 0, data_from_server);
2288  if (pkt_from_server.http.num_data_items != 0)
2289  {
2290  ERR("HTTP idle packet should have no data items instead of %d\n",
2291  pkt_from_server.http.num_data_items);
2292  return RPC_S_PROTOCOL_ERROR;
2293  }
2294  }
2295  status = RPCRT4_ParseHttpPrepareHeader2(&pkt_from_server, data_from_server,
2296  &field1, flow_control_increment,
2297  &field3);
2298  HeapFree(GetProcessHeap(), 0, data_from_server);
2299  if (status != RPC_S_OK) return status;
2300  TRACE("received (0x%08x 0x%08x %d) from second prepare header\n", field1, *flow_control_increment, field3);
2301 
2302  return RPC_S_OK;
2303 }
2304 
2305 static UINT encode_base64(const char *bin, unsigned int len, WCHAR *base64)
2306 {
2307  static const char enc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
2308  UINT i = 0, x;
2309 
2310  while (len > 0)
2311  {
2312  /* first 6 bits, all from bin[0] */
2313  base64[i++] = enc[(bin[0] & 0xfc) >> 2];
2314  x = (bin[0] & 3) << 4;
2315 
2316  /* next 6 bits, 2 from bin[0] and 4 from bin[1] */
2317  if (len == 1)
2318  {
2319  base64[i++] = enc[x];
2320  base64[i++] = '=';
2321  base64[i++] = '=';
2322  break;
2323  }
2324  base64[i++] = enc[x | ((bin[1] & 0xf0) >> 4)];
2325  x = (bin[1] & 0x0f) << 2;
2326 
2327  /* next 6 bits 4 from bin[1] and 2 from bin[2] */
2328  if (len == 2)
2329  {
2330  base64[i++] = enc[x];
2331  base64[i++] = '=';
2332  break;
2333  }
2334  base64[i++] = enc[x | ((bin[2] & 0xc0) >> 6)];
2335 
2336  /* last 6 bits, all from bin [2] */
2337  base64[i++] = enc[bin[2] & 0x3f];
2338  bin += 3;
2339  len -= 3;
2340  }
2341  base64[i] = 0;
2342  return i;
2343 }
2344 
2345 static inline char decode_char( WCHAR c )
2346 {
2347  if (c >= 'A' && c <= 'Z') return c - 'A';
2348  if (c >= 'a' && c <= 'z') return c - 'a' + 26;
2349  if (c >= '0' && c <= '9') return c - '0' + 52;
2350  if (c == '+') return 62;
2351  if (c == '/') return 63;
2352  return 64;
2353 }
2354 
2355 static unsigned int decode_base64( const WCHAR *base64, unsigned int len, char *buf )
2356 {
2357  unsigned int i = 0;
2358  char c0, c1, c2, c3;
2359  const WCHAR *p = base64;
2360 
2361  while (len > 4)
2362  {
2363  if ((c0 = decode_char( p[0] )) > 63) return 0;
2364  if ((c1 = decode_char( p[1] )) > 63) return 0;
2365  if ((c2 = decode_char( p[2] )) > 63) return 0;
2366  if ((c3 = decode_char( p[3] )) > 63) return 0;
2367 
2368  if (buf)
2369  {
2370  buf[i + 0] = (c0 << 2) | (c1 >> 4);
2371  buf[i + 1] = (c1 << 4) | (c2 >> 2);
2372  buf[i + 2] = (c2 << 6) | c3;
2373  }
2374  len -= 4;
2375  i += 3;
2376  p += 4;
2377  }
2378  if (p[2] == '=')
2379  {
2380  if ((c0 = decode_char( p[0] )) > 63) return 0;
2381  if ((c1 = decode_char( p[1] )) > 63) return 0;
2382 
2383  if (buf) buf[i] = (c0 << 2) | (c1 >> 4);
2384  i++;
2385  }
2386  else if (p[3] == '=')
2387  {
2388  if ((c0 = decode_char( p[0] )) > 63) return 0;
2389  if ((c1 = decode_char( p[1] )) > 63) return 0;
2390  if ((c2 = decode_char( p[2] )) > 63) return 0;
2391 
2392  if (buf)
2393  {
2394  buf[i + 0] = (c0 << 2) | (c1 >> 4);
2395  buf[i + 1] = (c1 << 4) | (c2 >> 2);
2396  }
2397  i += 2;
2398  }
2399  else
2400  {
2401  if ((c0 = decode_char( p[0] )) > 63) return 0;
2402  if ((c1 = decode_char( p[1] )) > 63) return 0;
2403  if ((c2 = decode_char( p[2] )) > 63) return 0;
2404  if ((c3 = decode_char( p[3] )) > 63) return 0;
2405 
2406  if (buf)
2407  {
2408  buf[i + 0] = (c0 << 2) | (c1 >> 4);
2409  buf[i + 1] = (c1 << 4) | (c2 >> 2);
2410  buf[i + 2] = (c2 << 6) | c3;
2411  }
2412  i += 3;
2413  }
2414  return i;
2415 }
2416 
2417 static struct authinfo *alloc_authinfo(void)
2418 {
2419  struct authinfo *ret;
2420 
2421  if (!(ret = HeapAlloc(GetProcessHeap(), 0, sizeof(*ret) ))) return NULL;
2422 
2423  SecInvalidateHandle(&ret->cred);
2424  SecInvalidateHandle(&ret->ctx);
2425  memset(&ret->exp, 0, sizeof(ret->exp));
2426  ret->scheme = 0;
2427  ret->attr = 0;
2428  ret->max_token = 0;
2429  ret->data = NULL;
2430  ret->data_len = 0;
2431  ret->finished = FALSE;
2432  return ret;
2433 }
2434 
2435 static void destroy_authinfo(struct authinfo *info)
2436 {
2437  if (!info) return;
2438 
2439  if (SecIsValidHandle(&info->ctx))
2440  DeleteSecurityContext(&info->ctx);
2441  if (SecIsValidHandle(&info->cred))
2442  FreeCredentialsHandle(&info->cred);
2443 
2444  HeapFree(GetProcessHeap(), 0, info->data);
2445  HeapFree(GetProcessHeap(), 0, info);
2446 }
2447 
2448 static const WCHAR basicW[] = {'B','a','s','i','c',0};
2449 static const WCHAR ntlmW[] = {'N','T','L','M',0};
2450 static const WCHAR passportW[] = {'P','a','s','s','p','o','r','t',0};
2451 static const WCHAR digestW[] = {'D','i','g','e','s','t',0};
2452 static const WCHAR negotiateW[] = {'N','e','g','o','t','i','a','t','e',0};
2453 
2454 static const struct
2455 {
2456  const WCHAR *str;
2457  unsigned int len;
2459 }
2460 auth_schemes[] =
2461 {
2467 };
2468 
2470 {
2471  unsigned int i;
2472  for (i = 0; i < ARRAY_SIZE(auth_schemes); i++)
2473  {
2475  (header[auth_schemes[i].len] == ' ' || !header[auth_schemes[i].len])) return auth_schemes[i].scheme;
2476  }
2477  return 0;
2478 }
2479 
2481 {
2482  DWORD len, index = 0;
2483  for (;;)
2484  {
2485  len = buflen;
2487  if (auth_scheme_from_header(buffer) == scheme) break;
2488  }
2489  return TRUE;
2490 }
2491 
2493  const RPC_HTTP_TRANSPORT_CREDENTIALS_W *creds, struct authinfo **auth_ptr)
2494 {
2495  struct authinfo *info = *auth_ptr;
2498 
2499  if ((!info && !(info = alloc_authinfo()))) return RPC_S_SERVER_UNAVAILABLE;
2500 
2501  switch (creds->AuthnSchemes[0])
2502  {
2504  {
2505  int userlen = WideCharToMultiByte(CP_UTF8, 0, id->User, id->UserLength, NULL, 0, NULL, NULL);
2506  int passlen = WideCharToMultiByte(CP_UTF8, 0, id->Password, id->PasswordLength, NULL, 0, NULL, NULL);
2507 
2508  info->data_len = userlen + passlen + 1;
2509  if (!(info->data = HeapAlloc(GetProcessHeap(), 0, info->data_len)))
2510  {
2512  break;
2513  }
2514  WideCharToMultiByte(CP_UTF8, 0, id->User, id->UserLength, info->data, userlen, NULL, NULL);
2515  info->data[userlen] = ':';
2516  WideCharToMultiByte(CP_UTF8, 0, id->Password, id->PasswordLength, info->data + userlen + 1, passlen, NULL, NULL);
2517 
2519  info->finished = TRUE;
2520  status = RPC_S_OK;
2521  break;
2522  }
2525  {
2526 
2527  static SEC_WCHAR ntlmW[] = {'N','T','L','M',0}, negotiateW[] = {'N','e','g','o','t','i','a','t','e',0};
2529  SecBufferDesc out_desc, in_desc;
2530  SecBuffer out, in;
2532  SEC_WCHAR *scheme;
2533  int scheme_len;
2534  const WCHAR *p;
2535  WCHAR auth_value[2048];
2536  DWORD size = sizeof(auth_value);
2537  BOOL first = FALSE;
2538 
2540  else scheme = negotiateW;
2541  scheme_len = strlenW( scheme );
2542 
2543  if (!*auth_ptr)
2544  {
2545  TimeStamp exp;
2546  SecPkgInfoW *pkg_info;
2547 
2549  if (ret != SEC_E_OK) break;
2550 
2551  ret = QuerySecurityPackageInfoW(scheme, &pkg_info);
2552  if (ret != SEC_E_OK) break;
2553 
2554  info->max_token = pkg_info->cbMaxToken;
2555  FreeContextBuffer(pkg_info);
2556  first = TRUE;
2557  }
2558  else
2559  {
2560  if (info->finished || !get_authvalue(request, creds->AuthnSchemes[0], auth_value, size)) break;
2561  if (auth_scheme_from_header(auth_value) != info->scheme)
2562  {
2563  ERR("authentication scheme changed\n");
2564  break;
2565  }
2566  }
2567  in.BufferType = SECBUFFER_TOKEN;
2568  in.cbBuffer = 0;
2569  in.pvBuffer = NULL;
2570 
2571  in_desc.ulVersion = 0;
2572  in_desc.cBuffers = 1;
2573  in_desc.pBuffers = &in;
2574 
2575  p = auth_value + scheme_len;
2576  if (!first && *p == ' ')
2577  {
2578  int len = strlenW(++p);
2579  in.cbBuffer = decode_base64(p, len, NULL);
2580  if (!(in.pvBuffer = HeapAlloc(GetProcessHeap(), 0, in.cbBuffer))) break;
2581  decode_base64(p, len, in.pvBuffer);
2582  }
2583  out.BufferType = SECBUFFER_TOKEN;
2584  out.cbBuffer = info->max_token;
2585  if (!(out.pvBuffer = HeapAlloc(GetProcessHeap(), 0, out.cbBuffer)))
2586  {
2587  HeapFree(GetProcessHeap(), 0, in.pvBuffer);
2588  break;
2589  }
2590  out_desc.ulVersion = 0;
2591  out_desc.cBuffers = 1;
2592  out_desc.pBuffers = &out;
2593 
2594  ret = InitializeSecurityContextW(first ? &info->cred : NULL, first ? NULL : &info->ctx,
2595  first ? servername : NULL, flags, 0, SECURITY_NETWORK_DREP,
2596  in.pvBuffer ? &in_desc : NULL, 0, &info->ctx, &out_desc,
2597  &info->attr, &info->exp);
2598  HeapFree(GetProcessHeap(), 0, in.pvBuffer);
2599  if (ret == SEC_E_OK)
2600  {
2601  HeapFree(GetProcessHeap(), 0, info->data);
2602  info->data = out.pvBuffer;
2603  info->data_len = out.cbBuffer;
2604  info->finished = TRUE;
2605  TRACE("sending last auth packet\n");
2606  status = RPC_S_OK;
2607  }
2608  else if (ret == SEC_I_CONTINUE_NEEDED)
2609  {
2610  HeapFree(GetProcessHeap(), 0, info->data);
2611  info->data = out.pvBuffer;
2612  info->data_len = out.cbBuffer;
2613  TRACE("sending next auth packet\n");
2614  status = RPC_S_OK;
2615  }
2616  else
2617  {
2618  ERR("InitializeSecurityContextW failed with error 0x%08x\n", ret);
2619  HeapFree(GetProcessHeap(), 0, out.pvBuffer);
2620  break;
2621  }
2622  info->scheme = creds->AuthnSchemes[0];
2623  break;
2624  }
2625  default:
2626  FIXME("scheme %u not supported\n", creds->AuthnSchemes[0]);
2627  break;
2628  }
2629 
2630  if (status != RPC_S_OK)
2631  {
2633  *auth_ptr = NULL;
2634  return status;
2635  }
2636  *auth_ptr = info;
2637  return RPC_S_OK;
2638 }
2639 
2641 {
2642  static const WCHAR authW[] = {'A','u','t','h','o','r','i','z','a','t','i','o','n',':',' '};
2643  static const WCHAR basicW[] = {'B','a','s','i','c',' '};
2644  static const WCHAR negotiateW[] = {'N','e','g','o','t','i','a','t','e',' '};
2645  static const WCHAR ntlmW[] = {'N','T','L','M',' '};
2646  int scheme_len, auth_len = ARRAY_SIZE(authW), len = ((data_len + 2) * 4) / 3;
2647  const WCHAR *scheme_str;
2648  WCHAR *header, *ptr;
2650 
2651  switch (scheme)
2652  {
2654  scheme_str = basicW;
2655  scheme_len = ARRAY_SIZE(basicW);
2656  break;
2658  scheme_str = negotiateW;
2659  scheme_len = ARRAY_SIZE(negotiateW);
2660  break;
2662  scheme_str = ntlmW;
2663  scheme_len = ARRAY_SIZE(ntlmW);
2664  break;
2665  default:
2666  ERR("unknown scheme %u\n", scheme);
2667  return RPC_S_SERVER_UNAVAILABLE;
2668  }
2669  if ((header = HeapAlloc(GetProcessHeap(), 0, (auth_len + scheme_len + len + 2) * sizeof(WCHAR))))
2670  {
2671  memcpy(header, authW, auth_len * sizeof(WCHAR));
2672  ptr = header + auth_len;
2673  memcpy(ptr, scheme_str, scheme_len * sizeof(WCHAR));
2674  ptr += scheme_len;
2676  ptr[len++] = '\r';
2677  ptr[len++] = '\n';
2678  ptr[len] = 0;
2680  status = RPC_S_OK;
2682  }
2683  return status;
2684 }
2685 
2686 static void drain_content(HINTERNET request, RpcHttpAsyncData *async_data, HANDLE cancel_event)
2687 {
2688  DWORD count, len = 0, size = sizeof(len);
2689  char buf[2048];
2690 
2692  if (!len) return;
2693  for (;;)
2694  {
2695  count = min(sizeof(buf), len);
2696  if (rpcrt4_http_async_read(request, async_data, cancel_event, buf, count) <= 0) return;
2697  len -= count;
2698  }
2699 }
2700 
2702 {
2703  static const WCHAR authW[] = {'A','u','t','h','o','r','i','z','a','t','i','o','n',':','\r','\n',0};
2704  struct authinfo *info = NULL;
2706  BOOL ret;
2707 
2708  for (;;)
2709  {
2711  if (status != RPC_S_OK) break;
2712 
2713  status = insert_authorization_header(request, info->scheme, info->data, info->data_len);
2714  if (status != RPC_S_OK) break;
2715 
2717  ret = HttpSendRequestW(request, NULL, 0, NULL, 0);
2719  if (status != RPC_S_OK || info->finished) break;
2720 
2722  if (status != RPC_S_OK && status != ERROR_ACCESS_DENIED) break;
2723  drain_content(request, httpc->async_data, httpc->cancel_event);
2724  }
2725 
2726  if (info->scheme != RPC_C_HTTP_AUTHN_SCHEME_BASIC)
2728 
2730  return status;
2731 }
2732 
2734 {
2737 
2739  return FALSE;
2740 
2741  creds = httpc->common.QOS->qos->u.HttpCredentials;
2743  return FALSE;
2744 
2745  id = creds->TransportCredentials;
2746  if (!id || !id->User || !id->Password) return FALSE;
2747 
2748  return TRUE;
2749 }
2750 
2752 {
2753  return httpc->common.QOS &&
2756 }
2757 
2759 {
2760  static WCHAR httpW[] = {'h','t','t','p',0};
2761  static WCHAR httpsW[] = {'h','t','t','p','s',0};
2762  URL_COMPONENTSW uc;
2763  DWORD len;
2764  WCHAR *url;
2765  BOOL ret;
2766 
2767  if (!value) return RPC_S_OK;
2768 
2769  uc.dwStructSize = sizeof(uc);
2770  uc.lpszScheme = is_secure(httpc) ? httpsW : httpW;
2771  uc.dwSchemeLength = 0;
2772  uc.lpszHostName = httpc->servername;
2773  uc.dwHostNameLength = 0;
2774  uc.nPort = 0;
2775  uc.lpszUserName = NULL;
2776  uc.dwUserNameLength = 0;
2777  uc.lpszPassword = NULL;
2778  uc.dwPasswordLength = 0;
2779  uc.lpszUrlPath = NULL;
2780  uc.dwUrlPathLength = 0;
2781  uc.lpszExtraInfo = NULL;
2782  uc.dwExtraInfoLength = 0;
2783 
2785  return RPC_S_SERVER_UNAVAILABLE;
2786 
2787  if (!(url = HeapAlloc(GetProcessHeap(), 0, len))) return RPC_S_OUT_OF_MEMORY;
2788 
2789  len = len / sizeof(WCHAR) - 1;
2790  if (!InternetCreateUrlW(&uc, 0, url, &len))
2791  {
2792  HeapFree(GetProcessHeap(), 0, url);
2793  return RPC_S_SERVER_UNAVAILABLE;
2794  }
2795 
2797  HeapFree(GetProcessHeap(), 0, url);
2798  if (!ret) return RPC_S_SERVER_UNAVAILABLE;
2799 
2800  return RPC_S_OK;
2801 }
2802 
2804 {
2805  RpcConnection_http *httpc = (RpcConnection_http *)Connection;
2806  static const WCHAR wszVerbIn[] = {'R','P','C','_','I','N','_','D','A','T','A',0};
2807  static const WCHAR wszVerbOut[] = {'R','P','C','_','O','U','T','_','D','A','T','A',0};
2808  static const WCHAR wszRpcProxyPrefix[] = {'/','r','p','c','/','r','p','c','p','r','o','x','y','.','d','l','l','?',0};
2809  static const WCHAR wszColon[] = {':',0};
2810  static const WCHAR wszAcceptType[] = {'a','p','p','l','i','c','a','t','i','o','n','/','r','p','c',0};
2811  LPCWSTR wszAcceptTypes[] = { wszAcceptType, NULL };
2812  DWORD flags;
2813  WCHAR *url;
2815  BOOL secure, credentials;
2816  HttpTimerThreadData *timer_data;
2817  HANDLE thread;
2818 
2819  TRACE("(%s, %s)\n", Connection->NetworkAddr, Connection->Endpoint);
2820 
2821  if (Connection->server)
2822  {
2823  ERR("ncacn_http servers not supported yet\n");
2824  return RPC_S_SERVER_UNAVAILABLE;
2825  }
2826 
2827  if (httpc->in_request)
2828  return RPC_S_OK;
2829 
2831 
2832  UuidCreate(&httpc->connection_uuid);
2833  UuidCreate(&httpc->in_pipe_uuid);
2834  UuidCreate(&httpc->out_pipe_uuid);
2835 
2837  if (status != RPC_S_OK)
2838  return status;
2839 
2840  url = HeapAlloc(GetProcessHeap(), 0, sizeof(wszRpcProxyPrefix) + (strlen(Connection->NetworkAddr) + 1 + strlen(Connection->Endpoint))*sizeof(WCHAR));
2841  if (!url)
2842  return RPC_S_OUT_OF_MEMORY;
2843  memcpy(url, wszRpcProxyPrefix, sizeof(wszRpcProxyPrefix));
2844  MultiByteToWideChar(CP_ACP, 0, Connection->NetworkAddr, -1, url+ARRAY_SIZE(wszRpcProxyPrefix)-1,
2845  strlen(Connection->NetworkAddr)+1);
2846  strcatW(url, wszColon);
2847  MultiByteToWideChar(CP_ACP, 0, Connection->Endpoint, -1, url+strlenW(url), strlen(Connection->Endpoint)+1);
2848 
2849  secure = is_secure(httpc);
2850  credentials = has_credentials(httpc);
2851 
2854  if (secure) flags |= INTERNET_FLAG_SECURE;
2855  if (credentials) flags |= INTERNET_FLAG_NO_AUTH;
2856 
2857  status = set_auth_cookie(httpc, Connection->CookieAuth);
2858  if (status != RPC_S_OK)
2859  {
2860  HeapFree(GetProcessHeap(), 0, url);
2861  return status;
2862  }
2863  httpc->in_request = HttpOpenRequestW(httpc->session, wszVerbIn, url, NULL, NULL, wszAcceptTypes,
2864  flags, (DWORD_PTR)httpc->async_data);
2865  if (!httpc->in_request)
2866  {
2867  ERR("HttpOpenRequestW failed with error %d\n", GetLastError());
2868  HeapFree(GetProcessHeap(), 0, url);
2869  return RPC_S_SERVER_UNAVAILABLE;
2870  }
2871 
2872  if (credentials)
2873  {
2874  status = authorize_request(httpc, httpc->in_request);
2875  if (status != RPC_S_OK)
2876  {
2877  HeapFree(GetProcessHeap(), 0, url);
2878  return status;
2879  }
2881  if (status != RPC_S_OK)
2882  {
2883  HeapFree(GetProcessHeap(), 0, url);
2884  return status;
2885  }
2886  drain_content(httpc->in_request, httpc->async_data, httpc->cancel_event);
2887  }
2888 
2889  httpc->out_request = HttpOpenRequestW(httpc->session, wszVerbOut, url, NULL, NULL, wszAcceptTypes,
2890  flags, (DWORD_PTR)httpc->async_data);
2891  HeapFree(GetProcessHeap(), 0, url);
2892  if (!httpc->out_request)
2893  {
2894  ERR("HttpOpenRequestW failed with error %d\n", GetLastError());
2895  return RPC_S_SERVER_UNAVAILABLE;
2896  }
2897 
2898  if (credentials)
2899  {
2900  status = authorize_request(httpc, httpc->out_request);
2901  if (status != RPC_S_OK)
2902  return status;
2903  }
2904 
2906  &httpc->connection_uuid, &httpc->in_pipe_uuid,
2907  &Connection->assoc->http_uuid, credentials);
2908  if (status != RPC_S_OK)
2909  return status;
2910 
2912  &httpc->connection_uuid, &httpc->out_pipe_uuid,
2913  &httpc->flow_control_increment, credentials);
2914  if (status != RPC_S_OK)
2915  return status;
2916 
2917  httpc->flow_control_mark = httpc->flow_control_increment / 2;
2918  httpc->last_sent_time = GetTickCount();
2920 
2921  timer_data = HeapAlloc(GetProcessHeap(), 0, sizeof(*timer_data));
2922  if (!timer_data)
2923  return ERROR_OUTOFMEMORY;
2924  timer_data->timer_param = httpc->in_request;
2925  timer_data->last_sent_time = &httpc->last_sent_time;
2926  timer_data->timer_cancelled = httpc->timer_cancelled;
2927  /* FIXME: should use CreateTimerQueueTimer when implemented */
2928  thread = CreateThread(NULL, 0, rpcrt4_http_timer_thread, timer_data, 0, NULL);
2929  if (!thread)
2930  {
2931  HeapFree(GetProcessHeap(), 0, timer_data);
2932  return GetLastError();
2933  }
2935 
2936  return RPC_S_OK;
2937 }
2938 
2940 {
2941  assert(0);
2942  return RPC_S_SERVER_UNAVAILABLE;
2943 }
2944 
2945 static int rpcrt4_ncacn_http_read(RpcConnection *Connection,
2946  void *buffer, unsigned int count)
2947 {
2948  RpcConnection_http *httpc = (RpcConnection_http *) Connection;
2949  return rpcrt4_http_async_read(httpc->out_request, httpc->async_data, httpc->cancel_event, buffer, count);
2950 }
2951 
2953 {
2954  RpcConnection_http *httpc = (RpcConnection_http *) Connection;
2956  DWORD hdr_length;
2957  LONG dwRead;
2958  RpcPktCommonHdr common_hdr;
2959 
2960  *Header = NULL;
2961 
2962  TRACE("(%p, %p, %p)\n", Connection, Header, Payload);
2963 
2964 again:
2965  /* read packet common header */
2966  dwRead = rpcrt4_ncacn_http_read(Connection, &common_hdr, sizeof(common_hdr));
2967  if (dwRead != sizeof(common_hdr)) {
2968  WARN("Short read of header, %d bytes\n", dwRead);
2970  goto fail;
2971  }
2972  if (!memcmp(&common_hdr, "HTTP/1.1", sizeof("HTTP/1.1")) ||
2973  !memcmp(&common_hdr, "HTTP/1.0", sizeof("HTTP/1.0")))
2974  {
2975  FIXME("server returned %s\n", debugstr_a((const char *)&common_hdr));
2977  goto fail;
2978  }
2979 
2980  status = RPCRT4_ValidateCommonHeader(&common_hdr);
2981  if (status != RPC_S_OK) goto fail;
2982 
2983  hdr_length = RPCRT4_GetHeaderSize((RpcPktHdr*)&common_hdr);
2984  if (hdr_length == 0) {
2985  WARN("header length == 0\n");
2987  goto fail;
2988  }
2989 
2990  *Header = HeapAlloc(GetProcessHeap(), 0, hdr_length);
2991  if (!*Header)
2992  {
2994  goto fail;
2995  }
2996  memcpy(*Header, &common_hdr, sizeof(common_hdr));
2997 
2998  /* read the rest of packet header */
2999  dwRead = rpcrt4_ncacn_http_read(Connection, &(*Header)->common + 1, hdr_length - sizeof(common_hdr));
3000  if (dwRead != hdr_length - sizeof(common_hdr)) {
3001  WARN("bad header length, %d bytes, hdr_length %d\n", dwRead, hdr_length);
3003  goto fail;
3004  }
3005 
3006  if (common_hdr.frag_len - hdr_length)
3007  {
3008  *Payload = HeapAlloc(GetProcessHeap(), 0, common_hdr.frag_len - hdr_length);
3009  if (!*Payload)
3010  {
3012  goto fail;
3013  }
3014 
3015  dwRead = rpcrt4_ncacn_http_read(Connection, *Payload, common_hdr.frag_len - hdr_length);
3016  if (dwRead != common_hdr.frag_len - hdr_length)
3017  {
3018  WARN("bad data length, %d/%d\n", dwRead, common_hdr.frag_len - hdr_length);
3020  goto fail;
3021  }
3022  }
3023  else
3024  *Payload = NULL;
3025 
3026  if ((*Header)->common.ptype == PKT_HTTP)
3027  {
3028  if (!RPCRT4_IsValidHttpPacket(*Header, *Payload, common_hdr.frag_len - hdr_length))
3029  {
3030  ERR("invalid http packet of length %d bytes\n", (*Header)->common.frag_len);
3032  goto fail;
3033  }
3034  if ((*Header)->http.flags == 0x0001)
3035  {
3036  TRACE("http idle packet, waiting for real packet\n");
3037  if ((*Header)->http.num_data_items != 0)
3038  {
3039  ERR("HTTP idle packet should have no data items instead of %d\n", (*Header)->http.num_data_items);
3041  goto fail;
3042  }
3043  }
3044  else if ((*Header)->http.flags == 0x0002)
3045  {
3046  ULONG bytes_transmitted;
3047  ULONG flow_control_increment;
3048  UUID pipe_uuid;
3050  Connection->server,
3051  &bytes_transmitted,
3052  &flow_control_increment,
3053  &pipe_uuid);
3054  if (status != RPC_S_OK)
3055  goto fail;
3056  TRACE("received http flow control header (0x%x, 0x%x, %s)\n",
3057  bytes_transmitted, flow_control_increment, debugstr_guid(&pipe_uuid));
3058  /* FIXME: do something with parsed data */
3059  }
3060  else
3061  {
3062  FIXME("unrecognised http packet with flags 0x%04x\n", (*Header)->http.flags);
3064  goto fail;
3065  }
3067  *Header = NULL;
3068  HeapFree(GetProcessHeap(), 0, *Payload);
3069  *Payload = NULL;
3070  goto again;
3071  }
3072 
3073  /* success */
3074  status = RPC_S_OK;
3075 
3076  httpc->bytes_received += common_hdr.frag_len;
3077 
3078  TRACE("httpc->bytes_received = 0x%x\n", httpc->bytes_received);
3079 
3080  if (httpc->bytes_received > httpc->flow_control_mark)
3081  {
3083  httpc->bytes_received,
3084  httpc->flow_control_increment,
3085  &httpc->out_pipe_uuid);
3086  if (hdr)
3087  {
3088  DWORD bytes_written;
3089  BOOL ret2;
3090  TRACE("sending flow control packet at 0x%x\n", httpc->bytes_received);
3091  ret2 = InternetWriteFile(httpc->in_request, hdr, hdr->common.frag_len, &bytes_written);
3093  if (ret2)
3094  httpc->flow_control_mark = httpc->bytes_received + httpc->flow_control_increment / 2;
3095  }
3096  }
3097 
3098 fail:
3099  if (status != RPC_S_OK) {
3101  *Header = NULL;
3102  HeapFree(GetProcessHeap(), 0, *Payload);
3103  *Payload = NULL;
3104  }
3105  return status;
3106 }
3107 
3109  const void *buffer, unsigned int count)
3110 {
3111  RpcConnection_http *httpc = (RpcConnection_http *) Connection;
3112  DWORD bytes_written;
3113  BOOL ret;
3114 
3115  httpc->last_sent_time = ~0U; /* disable idle packet sending */
3116  ret = InternetWriteFile(httpc->in_request, buffer, count, &bytes_written);
3117  httpc->last_sent_time = GetTickCount();
3118  TRACE("%p %p %u -> %s\n", httpc->in_request, buffer, count, ret ? "TRUE" : "FALSE");
3119  return ret ? bytes_written : -1;
3120 }
3121 
3123 {
3124  RpcConnection_http *httpc = (RpcConnection_http *) Connection;
3125 
3126  TRACE("\n");
3127 
3128  SetEvent(httpc->timer_cancelled);
3129  if (httpc->in_request)
3131  httpc->in_request = NULL;
3132  if (httpc->out_request)
3134  httpc->out_request = NULL;
3135  if (httpc->app_info)
3136  InternetCloseHandle(httpc->app_info);
3137  httpc->app_info = NULL;
3138  if (httpc->session)
3139  InternetCloseHandle(httpc->session);
3140  httpc->session = NULL;
3142  if (httpc->cancel_event)
3143  CloseHandle(httpc->cancel_event);
3144  HeapFree(GetProcessHeap(), 0, httpc->servername);
3145  httpc->servername = NULL;
3146 
3147  return 0;
3148 }
3149 
3151 {
3152  rpcrt4_ncacn_http_close(conn); /* FIXME */
3153 }
3154 
3156 {
3157  RpcConnection_http *httpc = (RpcConnection_http *) Connection;
3158 
3159  SetEvent(httpc->cancel_event);
3160 }
3161 
3163 {
3164  FIXME("\n");
3165  return RPC_S_ACCESS_DENIED;
3166 }
3167 
3169 {
3170  RpcConnection_http *httpc = (RpcConnection_http *) Connection;
3171  BOOL ret;
3173 
3178  return status == RPC_S_OK ? 0 : -1;
3179 }
3180 
3181 static size_t rpcrt4_ncacn_http_get_top_of_tower(unsigned char *tower_data,
3182  const char *networkaddr,
3183  const char *endpoint)
3184 {
3185  return rpcrt4_ip_tcp_get_top_of_tower(tower_data, networkaddr,
3187 }
3188 
3189 static RPC_STATUS rpcrt4_ncacn_http_parse_top_of_tower(const unsigned char *tower_data,
3190  size_t tower_size,
3191  char **networkaddr,
3192  char **endpoint)
3193 {
3194  return rpcrt4_ip_tcp_parse_top_of_tower(tower_data, tower_size,
3195  networkaddr, EPM_PROTOCOL_HTTP,
3196  endpoint);
3197 }
3198 
3199 static const struct connection_ops conn_protseq_list[] = {
3200  { "ncacn_np",
3214  NULL,
3221  },
3222  { "ncalrpc",
3236  NULL,
3243  },
3244  { "ncacn_ip_tcp",
3258  NULL,
3265  },
3266  { "ncacn_http",
3287  },
3288 };
3289 
3290 
3291 static const struct protseq_ops protseq_list[] =
3292 {
3293  {
3294  "ncacn_np",
3301  },
3302  {
3303  "ncalrpc",
3310  },
3311  {
3312  "ncacn_ip_tcp",
3319  },
3320 };
3321 
3322 const struct protseq_ops *rpcrt4_get_protseq_ops(const char *protseq)
3323 {
3324  unsigned int i;
3325  for(i = 0; i < ARRAY_SIZE(protseq_list); i++)
3326  if (!strcmp(protseq_list[i].name, protseq))
3327  return &protseq_list[i];
3328  return NULL;
3329 }
3330 
3331 static const struct connection_ops *rpcrt4_get_conn_protseq_ops(const char *protseq)
3332 {
3333  unsigned int i;
3334  for(i = 0; i < ARRAY_SIZE(conn_protseq_list); i++)
3335  if (!strcmp(conn_protseq_list[i].name, protseq))
3336  return &conn_protseq_list[i];
3337  return NULL;
3338 }
3339 
3340 /**** interface to rest of code ****/
3341 
3343 {
3344  TRACE("(Connection == ^%p)\n", Connection);
3345 
3346  assert(!Connection->server);
3347  return Connection->ops->open_connection_client(Connection);
3348 }
3349 
3351 {
3352  TRACE("(Connection == ^%p)\n", Connection);
3353  if (SecIsValidHandle(&Connection->ctx))
3354  {
3355  DeleteSecurityContext(&Connection->ctx);
3356  SecInvalidateHandle(&Connection->ctx);
3357  }
3358  rpcrt4_conn_close(Connection);
3359  return RPC_S_OK;
3360 }
3361 
3363  LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint,
3364  LPCWSTR NetworkOptions, RpcAuthInfo* AuthInfo, RpcQualityOfService *QOS, LPCWSTR CookieAuth)
3365 {
3366  static LONG next_id;
3367  const struct connection_ops *ops;
3368  RpcConnection* NewConnection;
3369 
3370  ops = rpcrt4_get_conn_protseq_ops(Protseq);
3371  if (!ops)
3372  {
3373  FIXME("not supported for protseq %s\n", Protseq);
3375  }
3376 
3377  NewConnection = ops->alloc();
3378  NewConnection->ref = 1;
3379  NewConnection->server = server;
3380  NewConnection->ops = ops;
3381  NewConnection->NetworkAddr = RPCRT4_strdupA(NetworkAddr);
3382  NewConnection->Endpoint = RPCRT4_strdupA(Endpoint);
3383  NewConnection->NetworkOptions = RPCRT4_strdupW(NetworkOptions);
3384  NewConnection->CookieAuth = RPCRT4_strdupW(CookieAuth);
3385  NewConnection->MaxTransmissionSize = RPC_MAX_PACKET_SIZE;
3386  NewConnection->NextCallId = 1;
3387 
3388  SecInvalidateHandle(&NewConnection->ctx);
3389  if (AuthInfo) RpcAuthInfo_AddRef(AuthInfo);
3390  NewConnection->AuthInfo = AuthInfo;
3391  NewConnection->auth_context_id = InterlockedIncrement( &next_id );
3393  NewConnection->QOS = QOS;
3394 
3395  list_init(&NewConnection->conn_pool_entry);
3396  list_init(&NewConnection->protseq_entry);
3397 
3398  TRACE("connection: %p\n", NewConnection);
3399  *Connection = NewConnection;
3400 
3401  return RPC_S_OK;
3402 }
3403 
3405 {
3406  RpcConnection *connection;
3407  RPC_STATUS err;
3408 
3409  err = RPCRT4_CreateConnection(&connection, old_connection->server, rpcrt4_conn_get_name(old_connection),
3410  old_connection->NetworkAddr, old_connection->Endpoint, NULL,
3411  old_connection->AuthInfo, old_connection->QOS, old_connection->CookieAuth);
3412  if (err != RPC_S_OK)
3413  return NULL;
3414 
3415  rpcrt4_conn_handoff(old_connection, connection);
3416  if (old_connection->protseq)
3417  {
3418  EnterCriticalSection(&old_connection->protseq->cs);
3419  connection->protseq = old_connection->protseq;
3420  list_add_tail(&old_connection->protseq->connections, &connection->protseq_entry);
3421  LeaveCriticalSection(&old_connection->protseq->cs);
3422  }
3423  return connection;
3424 }
3425 
3427 {
3428  HANDLE event = NULL;
3429 
3430  if (connection->ref > 1)
3431  event = connection->wait_release = CreateEventW(NULL, TRUE, FALSE, NULL);
3432 
3433  RPCRT4_ReleaseConnection(connection);
3434 
3435  if(event)
3436  {
3438  CloseHandle(event);
3439  }
3440 }
3441 
3443 {
3444  LONG ref = InterlockedIncrement(&connection->ref);
3445  TRACE("%p ref=%u\n", connection, ref);
3446  return connection;
3447 }
3448 
3450 {
3451  LONG ref;
3452 
3453  /* protseq stores a list of active connections, but does not own references to them.
3454  * It may need to grab a connection from the list, which could lead to a race if
3455  * connection is being released, but not yet removed from the list. We handle that
3456  * by synchronizing on CS here. */
3457  if (connection->protseq)
3458  {
3459  EnterCriticalSection(&connection->protseq->cs);
3460  ref = InterlockedDecrement(&connection->ref);
3461  if (!ref)
3462  list_remove(&connection->protseq_entry);
3463  LeaveCriticalSection(&connection->protseq->cs);
3464  }
3465  else
3466  {
3467  ref = InterlockedDecrement(&connection->ref);
3468  }
3469 
3470  TRACE("%p ref=%u\n", connection, ref);
3471 
3472  if (!ref)
3473  {
3474  RPCRT4_CloseConnection(connection);
3475  RPCRT4_strfree(connection->Endpoint);
3476  RPCRT4_strfree(connection->NetworkAddr);
3477  HeapFree(GetProcessHeap(), 0, connection->NetworkOptions);
3478  HeapFree(GetProcessHeap(), 0, connection->CookieAuth);
3479  if (connection->AuthInfo) RpcAuthInfo_Release(connection->AuthInfo);
3480  if (connection->QOS) RpcQualityOfService_Release(connection->QOS);
3481 
3482  /* server-only */
3483  if (connection->server_binding) RPCRT4_ReleaseBinding(connection->server_binding);
3484  else if (connection->assoc) RpcAssoc_ConnectionReleased(connection->assoc);
3485 
3486  if (connection->wait_release) SetEvent(connection->wait_release);
3487 
3488  HeapFree(GetProcessHeap(), 0, connection);
3489  }
3490 }
3491 
3492 RPC_STATUS RPCRT4_IsServerListening(const char *protseq, const char *endpoint)
3493 {
3494  const struct connection_ops *ops;
3495 
3496  ops = rpcrt4_get_conn_protseq_ops(protseq);
3497  if (!ops)
3498  {
3499  FIXME("not supported for protseq %s\n", protseq);
3500  return RPC_S_INVALID_BINDING;
3501  }
3502 
3503  return ops->is_server_listening(endpoint);
3504 }
3505 
3506 RPC_STATUS RpcTransport_GetTopOfTower(unsigned char *tower_data,
3507  size_t *tower_size,
3508  const char *protseq,
3509  const char *networkaddr,
3510  const char *endpoint)
3511 {
3512  twr_empty_floor_t *protocol_floor;
3513  const struct connection_ops *protseq_ops = rpcrt4_get_conn_protseq_ops(protseq);
3514 
3515  *tower_size = 0;
3516 
3517  if (!protseq_ops)
3519 
3520  if (!tower_data)
3521  {
3522  *tower_size = sizeof(*protocol_floor);
3523  *tower_size += protseq_ops->get_top_of_tower(NULL, networkaddr, endpoint);
3524  return RPC_S_OK;
3525  }
3526 
3527  protocol_floor = (twr_empty_floor_t *)tower_data;
3528  protocol_floor->count_lhs = sizeof(protocol_floor->protid);
3529  protocol_floor->protid = protseq_ops->epm_protocols[0];
3530  protocol_floor->count_rhs = 0;
3531 
3532  tower_data += sizeof(*protocol_floor);
3533 
3534  *tower_size = protseq_ops->get_top_of_tower(tower_data, networkaddr, endpoint);
3535  if (!*tower_size)
3536  return EPT_S_NOT_REGISTERED;
3537 
3538  *tower_size += sizeof(*protocol_floor);
3539 
3540  return RPC_S_OK;
3541 }
3542 
3543 RPC_STATUS RpcTransport_ParseTopOfTower(const unsigned char *tower_data,
3544  size_t tower_size,
3545  char **protseq,
3546  char **networkaddr,
3547  char **endpoint)
3548 {
3549  const twr_empty_floor_t *protocol_floor;
3550  const twr_empty_floor_t *floor4;
3551  const struct connection_ops *protseq_ops = NULL;
3553  unsigned int i;
3554 
3555  if (tower_size < sizeof(*protocol_floor))
3556  return EPT_S_NOT_REGISTERED;
3557 
3558  protocol_floor = (const twr_empty_floor_t *)tower_data;
3559  tower_data += sizeof(*protocol_floor);
3560  tower_size -= sizeof(*protocol_floor);
3561  if ((protocol_floor->count_lhs != sizeof(protocol_floor->protid)) ||
3562  (protocol_floor->count_rhs > tower_size))
3563  return EPT_S_NOT_REGISTERED;
3564  tower_data += protocol_floor->count_rhs;
3565  tower_size -= protocol_floor->count_rhs;
3566 
3567  floor4 = (const twr_empty_floor_t *)tower_data;
3568  if ((tower_size < sizeof(*floor4)) ||
3569  (floor4->count_lhs != sizeof(floor4->protid)))
3570  return EPT_S_NOT_REGISTERED;
3571 
3572  for(i = 0; i < ARRAY_SIZE(conn_protseq_list); i++)
3573  if ((protocol_floor->protid == conn_protseq_list[i].epm_protocols[0]) &&
3574  (floor4->protid == conn_protseq_list[i].epm_protocols[1]))
3575  {
3577  break;
3578  }
3579 
3580  if (!protseq_ops)
3581  return EPT_S_NOT_REGISTERED;
3582 
3583  status = protseq_ops->parse_top_of_tower(tower_data, tower_size, networkaddr, endpoint);
3584 
3585  if ((status == RPC_S_OK) && protseq)
3586  {
3587  *protseq = I_RpcAllocate(strlen(protseq_ops->name) + 1);
3588  strcpy(*protseq, protseq_ops->name);
3589  }
3590 
3591  return status;
3592 }
3593 
3594 /***********************************************************************
3595  * RpcNetworkIsProtseqValidW (RPCRT4.@)
3596  *
3597  * Checks if the given protocol sequence is known by the RPC system.
3598  * If it is, returns RPC_S_OK, otherwise RPC_S_PROTSEQ_NOT_SUPPORTED.
3599  *
3600  */
3602 {
3603  char ps[0x10];
3604 
3605  WideCharToMultiByte(CP_ACP, 0, protseq, -1,
3606  ps, sizeof ps, NULL, NULL);
3608  return RPC_S_OK;
3609 
3610  FIXME("Unknown protseq %s\n", debugstr_w(protseq));
3611 
3613 }
3614 
3615 /***********************************************************************
3616  * RpcNetworkIsProtseqValidA (RPCRT4.@)
3617  */
3619 {
3620  UNICODE_STRING protseqW;
3621 
3622  if (RtlCreateUnicodeStringFromAsciiz(&protseqW, (char*)protseq))
3623  {
3625  RtlFreeUnicodeString(&protseqW);
3626  return ret;
3627  }
3628  return RPC_S_OUT_OF_MEMORY;
3629 }
3630 
3631 /***********************************************************************
3632  * RpcProtseqVectorFreeA (RPCRT4.@)
3633  */
3635 {
3636  TRACE("(%p)\n", protseqs);
3637 
3638  if (*protseqs)
3639  {
3640  unsigned int i;
3641  for (i = 0; i < (*protseqs)->Count; i++)
3642  HeapFree(GetProcessHeap(), 0, (*protseqs)->Protseq[i]);
3644  *protseqs = NULL;
3645  }
3646  return RPC_S_OK;
3647 }
3648 
3649 /***********************************************************************
3650  * RpcProtseqVectorFreeW (RPCRT4.@)
3651  */
3653 {
3654  TRACE("(%p)\n", protseqs);
3655 
3656  if (*protseqs)
3657  {
3658  unsigned int i;
3659  for (i = 0; i < (*protseqs)->Count; i++)
3660  HeapFree(GetProcessHeap(), 0, (*protseqs)->Protseq[i]);
3662  *protseqs = NULL;
3663  }
3664  return RPC_S_OK;
3665 }
3666 
3667 /***********************************************************************
3668  * RpcNetworkInqProtseqsW (RPCRT4.@)
3669  */
3671 {
3672  RPC_PROTSEQ_VECTORW *pvector;
3673  unsigned int i;
3675 
3676  TRACE("(%p)\n", protseqs);
3677 
3678  *protseqs = HeapAlloc(GetProcessHeap(), 0, sizeof(RPC_PROTSEQ_VECTORW)+(sizeof(unsigned short*)*ARRAY_SIZE(protseq_list)));
3679  if (!*protseqs)
3680  goto end;
3681  pvector = *protseqs;
3682  pvector->Count = 0;
3683  for (i = 0; i < ARRAY_SIZE(protseq_list); i++)
3684  {
3685  pvector->Protseq[i] = HeapAlloc(GetProcessHeap(), 0, (strlen(protseq_list[i].name)+1)*sizeof(unsigned short));
3686  if (pvector->Protseq[i] == NULL)
3687  goto end;
3689  (WCHAR*)pvector->Protseq[i], strlen(protseq_list[i].name) + 1);
3690  pvector->Count++;
3691  }
3692  status = RPC_S_OK;
3693 
3694 end:
3695  if (status != RPC_S_OK)
3697  return status;
3698 }
3699 
3700 /***********************************************************************
3701  * RpcNetworkInqProtseqsA (RPCRT4.@)
3702  */
3704 {
3705  RPC_PROTSEQ_VECTORA *pvector;
3706  unsigned int i;
3708 
3709  TRACE("(%p)\n", protseqs);
3710 
3711  *protseqs = HeapAlloc(GetProcessHeap(), 0, sizeof(RPC_PROTSEQ_VECTORW)+(sizeof(unsigned char*)*ARRAY_SIZE(protseq_list)));
3712  if (!*protseqs)
3713  goto end;
3714  pvector = *protseqs;
3715  pvector->Count = 0;
3716  for (i = 0; i < ARRAY_SIZE(protseq_list); i++)
3717  {
3718  pvector->Protseq[i] = HeapAlloc(GetProcessHeap(), 0, strlen(protseq_list[i].name)+1);
3719  if (pvector->Protseq[i] == NULL)
3720  goto end;
3721  strcpy((char*)pvector->Protseq[i], protseq_list[i].name);
3722  pvector->Count++;
3723  }
3724  status = RPC_S_OK;
3725 
3726 end:
3727  if (status != RPC_S_OK)
3729  return status;
3730 }
static RPC_STATUS rpcrt4_ncacn_http_parse_top_of_tower(const unsigned char *tower_data, size_t tower_size, char **networkaddr, char **endpoint)
#define HTTP_QUERY_CONTENT_LENGTH
Definition: wininet.h:1528
static RPC_STATUS rpcrt4_ncacn_np_is_server_listening(const char *endpoint)
DWORD dwStructSize
Definition: wininet.h:272
USHORT MaxTransmissionSize
Definition: rpc_binding.h:71
static const WCHAR basicW[]
namespace GUID const ADDRINFOEXW * hints
Definition: sock.c:80
#define SOCKET_ERROR
Definition: winsock.h:333
static void rpcrt4_conn_np_cancel_call(RpcConnection *conn)
static void drain_content(HINTERNET request, RpcHttpAsyncData *async_data, HANDLE cancel_event)
static size_t rpcrt4_ncacn_http_get_top_of_tower(unsigned char *tower_data, const char *networkaddr, const char *endpoint)
struct list protseq_entry
Definition: rpc_binding.h:94
#define INTERNET_FLAG_NO_CACHE_WRITE
Definition: wininet.h:66
static RPC_STATUS send_echo_request(HINTERNET req, RpcHttpAsyncData *async_data, HANDLE cancel_event)
static RPC_STATUS rpcrt4_ncacn_http_is_server_listening(const char *endpoint)
#define PIPE_UNLIMITED_INSTANCES
Definition: winbase.h:175
RPC_STATUS WINAPI RpcNetworkInqProtseqsW(RPC_PROTSEQ_VECTORW **protseqs)
static int rpcrt4_ncacn_http_write(RpcConnection *Connection, const void *buffer, unsigned int count)
static size_t rpcrt4_ncalrpc_get_top_of_tower(unsigned char *tower_data, const char *networkaddr, const char *endpoint)
#define RPC_C_AUTHN_WINNT
Definition: rpcdce.h:158
#define ERROR_FILE_EXISTS
Definition: winerror.h:165
static int rpcrt4_protseq_sock_wait_for_new_connection(RpcServerProtseq *protseq, unsigned int count, void *wait_array)
static struct authinfo * alloc_authinfo(void)
static int rpcrt4_http_async_read(HINTERNET req, RpcHttpAsyncData *async_data, HANDLE cancel_event, void *buffer, unsigned int count)
static int rpcrt4_conn_close(RpcConnection *Connection)
Definition: rpc_binding.h:200
BOOL WINAPI ImpersonateNamedPipeClient(HANDLE hNamedPipe)
Definition: security.c:903
unsigned short * Domain
Definition: rpcdce.h:225
static struct list protseqs
Definition: rpc_server.c:71
int proxy
Definition: main.c:67
static RPC_STATUS rpcrt4_ip_tcp_parse_top_of_tower(const unsigned char *tower_data, size_t tower_size, char **networkaddr, unsigned char tcp_protid, char **endpoint)
#define TRUE
Definition: types.h:120
static HANDLE PIO_APC_ROUTINE PVOID PIO_STATUS_BLOCK ULONG PVOID ULONG PVOID ULONG out_size
Definition: file.c:100
static RPC_STATUS rpcrt4_conn_tcp_handoff(RpcConnection *old_conn, RpcConnection *new_conn)
static VOID WINAPI rpcrt4_http_internet_callback(HINTERNET hInternet, DWORD_PTR dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInformation, DWORD dwStatusInformationLength)
static void rpcrt4_protseq_np_signal_state_changed(RpcServerProtseq *protseq)
unsigned short * User
Definition: rpcdce.h:223
#define CloseHandle
Definition: compat.h:398
#define HTTP_QUERY_STATUS_TEXT
Definition: wininet.h:1543
static RPC_STATUS rpcrt4_protseq_ncalrpc_open_endpoint(RpcServerProtseq *protseq, const char *endpoint)
char hdr[14]
Definition: iptest.cpp:33
#define SECPKG_CRED_OUTBOUND
Definition: sspi.h:277
static const char * rpcrt4_conn_get_name(const RpcConnection *Connection)
Definition: rpc_binding.h:183
static RPC_STATUS rpcrt4_ncalrpc_parse_top_of_tower(const unsigned char *tower_data, size_t tower_size, char **networkaddr, char **endpoint)
static RPC_STATUS rpcrt4_ncalrpc_authorize(RpcConnection *conn, BOOL first_time, unsigned char *in_buffer, unsigned int in_size, unsigned char *out_buffer, unsigned int *out_size)
void RpcAssoc_ConnectionReleased(RpcAssoc *assoc)
Definition: rpc_assoc.c:448
unsigned char * Protseq[1]
Definition: rpcdce.h:91
static int rpcrt4_conn_np_close(RpcConnection *conn)
static rfbScreenInfoPtr server
Definition: vnc.c:74
static SOCKET sock
Definition: syslog.c:45
SOCKET WSAAPI socket(IN INT af, IN INT type, IN INT protocol)
Definition: socklife.c:143
SEC_WINNT_AUTH_IDENTITY_W * TransportCredentials
Definition: rpcdce.h:245
static RPC_STATUS rpcrt4_ncacn_http_handoff(RpcConnection *old_conn, RpcConnection *new_conn)
ULONG RpcAuthInfo_Release(RpcAuthInfo *AuthInfo)
Definition: rpc_binding.c:1185
#define AI_PASSIVE
Definition: ws2def.h:293
static HANDLE get_np_event(RpcConnection_np *connection)
Definition: rpc_transport.c:98
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
#define freeaddrinfo
Definition: wspiapi.h:46
WINE_UNICODE_INLINE unsigned int strlenW(const WCHAR *str)
Definition: unicode.h:212
static RPC_STATUS rpcrt4_conn_np_impersonate_client(RpcConnection *conn)
unsigned long u_long
Definition: linux.h:269
static DWORD auth_scheme_from_header(const WCHAR *header)
#define NI_NUMERICHOST
Definition: ws2def.h:354
#define ERROR_SUCCESS
Definition: deptool.c:10
#define DWORD_PTR
Definition: treelist.c:76
#define WideCharToMultiByte
Definition: compat.h:101
SECURITY_STATUS WINAPI AcquireCredentialsHandleW(SEC_WCHAR *pszPrincipal, SEC_WCHAR *pszPackage, ULONG fCredentialsUse, PLUID pvLogonID, PVOID pAuthData, SEC_GET_KEY_FN pGetKeyFn, PVOID pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
Definition: wrapper.c:105
#define error(str)
Definition: mkdosfs.c:1605
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
RPC_STATUS RPCRT4_default_revert_to_self(RpcConnection *conn)
Definition: rpc_message.c:1159
void WINAPI I_RpcFree(void *Object)
Definition: rpcrt4_main.c:725
static int rpcrt4_conn_tcp_close(RpcConnection *conn)
u_int16 count_rhs
Definition: epm_towers.h:77
WCHAR SEC_WCHAR
Definition: sspi.h:29
DWORD dwStructSize
Definition: wininet.h:211
#define PIPE_TYPE_MESSAGE
Definition: winbase.h:168
static RPC_STATUS rpcrt4_ncacn_np_open(RpcConnection *Connection)
#define RPC_C_HTTP_AUTHN_TARGET_SERVER
Definition: rpcdce.h:202
RpcConnection common
Definition: rpc_transport.c:83
#define FD_ACCEPT
Definition: winsock.h:408
static RPC_STATUS rpcrt4_http_prepare_out_pipe(HINTERNET out_request, RpcHttpAsyncData *async_data, HANDLE cancel_event, const UUID *connection_uuid, const UUID *out_pipe_uuid, ULONG *flow_control_increment, BOOL authorized)
RPC_STATUS RPCRT4_ParseHttpPrepareHeader1(RpcPktHdr *header, unsigned char *data, ULONG *field1)
Definition: rpc_message.c:566
struct list listeners
Definition: rpc_server.h:36
#define RPC_S_NO_CONTEXT_AVAILABLE
Definition: winerror.h:1073
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define MAKEWORD(a, b)
Definition: typedefs.h:247
SECURITY_STATUS WINAPI FreeContextBuffer(PVOID pv)
Definition: sspi.c:699
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
INT WSAAPI bind(IN SOCKET s, IN CONST struct sockaddr *name, IN INT namelen)
Definition: socklife.c:36
unsigned short * Password
Definition: rpcdce.h:227
ULONG ulVersion
Definition: sspi.h:167
u_int16 count_rhs
Definition: epm_towers.h:85
BOOL WINAPI RevertToSelf(VOID)
Definition: security.c:1487
#define SECURITY_IDENTIFICATION
Definition: winbase.h:522
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
WINE_UNICODE_INLINE WCHAR * strchrW(const WCHAR *str, WCHAR ch)
Definition: unicode.h:248
static int rpcrt4_conn_np_read(RpcConnection *conn, void *buffer, unsigned int count)
RpcServerProtseq common
struct _RpcServerProtseq_np RpcServerProtseq_np
#define CP_ACP
Definition: compat.h:99
u_int32 ipv4addr
Definition: epm_towers.h:78
RPC_STATUS RpcTransport_ParseTopOfTower(const unsigned char *tower_data, size_t tower_size, char **protseq, char **networkaddr, char **endpoint)
GLuint GLuint GLsizei count
Definition: gl.h:1545
HANDLE WINAPI CreateNamedPipeA(LPCSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD nMaxInstances, DWORD nOutBufferSize, DWORD nInBufferSize, DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: npipe.c:220
#define SecIsValidHandle(x)
Definition: sspi.h:63
char CHAR
Definition: xmlstorage.h:175
unsigned int Count
Definition: rpcdce.h:90
const GLint * first
Definition: glext.h:5794
#define WARN(fmt,...)
Definition: debug.h:111
#define U(x)
Definition: wordpad.c:44
DWORD dwBufferTotal
Definition: wininet.h:279
RpcConnection common
static RPC_STATUS is_pipe_listening(const char *pipe_name)
#define INTERNET_FLAG_SECURE
Definition: wininet.h:71
char * host
Definition: whois.c:55
LONG NTSTATUS
Definition: precomp.h:26
VOID RPCRT4_FreeHeader(RpcPktHdr *Header)
Definition: rpc_message.c:403
static ULONG RpcHttpAsyncData_Release(RpcHttpAsyncData *data)
static int rpcrt4_conn_np_write(RpcConnection *conn, const void *buffer, unsigned int count)
#define CALLBACK
Definition: compat.h:27
__WINE_SERVER_LIST_INLINE void list_add_head(struct list *list, struct list *elem)
Definition: list.h:96
static HANDLE PIO_APC_ROUTINE void PIO_STATUS_BLOCK io_status
Definition: comm.c:54
#define WSAEWOULDBLOCK
Definition: winerror.h:1948
DWORD WINAPI GetTickCount(VOID)
Definition: time.c:445
static RPC_STATUS rpcrt4_ncalrpc_np_is_server_listening(const char *endpoint)
void RPCRT4_new_client(RpcConnection *conn)
Definition: rpc_server.c:628
time_t cur_time
#define IRF_ASYNC
Definition: wininet.h:622
static RPC_STATUS rpcrt4_ncacn_http_receive_fragment(RpcConnection *Connection, RpcPktHdr **Header, void **Payload)
#define RPC_C_HTTP_AUTHN_SCHEME_BASIC
Definition: rpcdce.h:205
DWORD scheme
#define INTERNET_OPEN_TYPE_PROXY
Definition: wininet.h:523
RPC_STATUS RPCRT4_IsServerListening(const char *protseq, const char *endpoint)
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define snprintf
Definition: wintirpc.h:48
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
void RPCRT4_ReleaseConnection(RpcConnection *connection)
#define RPC_S_SERVER_UNAVAILABLE
Definition: winerror.h:1033
#define assert(x)
Definition: debug.h:53
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:679
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
static RPC_STATUS wait_async_request(RpcHttpAsyncData *async_data, BOOL call_ret, HANDLE cancel_event)
GLuint buffer
Definition: glext.h:5915
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
USHORT NextCallId
Definition: rpc_binding.h:93
RPC_STATUS RPCRT4_CloseConnection(RpcConnection *Connection)
DWORD dwUserNameLength
Definition: wininet.h:219
BOOL WINAPI InternetCloseHandle(HINTERNET hInternet)
Definition: internet.c:1437
SECURITY_STATUS WINAPI FreeCredentialsHandle(PCredHandle phCredential)
Definition: wrapper.c:151
unsigned int Count
Definition: rpcdce.h:96
#define NI_NUMERICSERV
Definition: ws2def.h:356
#define ISC_REQ_DELEGATE
Definition: sspi.h:348
#define RPC_C_IMP_LEVEL_ANONYMOUS
Definition: rpcdce.h:174
#define HTTP_IDLE_TIME
#define FD_READ
Definition: winsock.h:405
NTSYSCALLAPI NTSTATUS NTAPI NtFsControlFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, ULONG FsControlCode, PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, ULONG OutputBufferLength)
struct _RpcServerProtseq_sock RpcServerProtseq_sock
static RpcConnection * rpcrt4_conn_tcp_alloc(void)
#define INET6_ADDRSTRLEN
Definition: request.c:1491
Definition: dhcpd.h:245
GLuint GLuint end
Definition: gl.h:1545
RPC_HTTP_TRANSPORT_CREDENTIALS_W * HttpCredentials
Definition: rpcdce.h:279
#define RPC_C_IMP_LEVEL_IDENTIFY
Definition: rpcdce.h:175
#define NMPWAIT_USE_DEFAULT_WAIT
Definition: winbase.h:134
BOOL WINAPI GetComputerNameA(LPSTR lpBuffer, LPDWORD lpnSize)
Definition: compname.c:423
#define strncmpiW(s1, s2, n)
Definition: unicode.h:40
unsigned short * RPC_WSTR
Definition: rpcdce.h:46
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
#define RPC_C_IMP_LEVEL_IMPERSONATE
Definition: rpcdce.h:176
INTERNET_BUFFERSW inet_buffers
char * LPSTR
Definition: xmlstorage.h:182
#define HTTP_QUERY_WWW_AUTHENTICATE
Definition: wininet.h:1563
#define ERROR_IO_PENDING
Definition: dderror.h:15
DWORD WINAPI WaitForMultipleObjects(IN DWORD nCount, IN CONST HANDLE *lpHandles, IN BOOL bWaitAll, IN DWORD dwMilliseconds)
Definition: synch.c:151
static const struct connection_ops * rpcrt4_get_conn_protseq_ops(const char *protseq)
LPWSTR lpszHostName
Definition: wininet.h:215
INT WSAAPI connect(IN SOCKET s, IN CONST struct sockaddr *name, IN INT namelen)
Definition: sockctrl.c:23
u32_t s_addr
Definition: inet.h:45
#define ERROR_CANNOT_IMPERSONATE
Definition: winerror.h:849
#define EPM_PROTOCOL_NETBIOS
Definition: epm_towers.h:39
#define EPM_PROTOCOL_NCACN
Definition: epm_towers.h:33
Definition: send.c:47
static LONG next_id
Definition: changenotify.c:91
const struct connection_ops * ops
Definition: rpc_binding.h:70
DWORD dwBufferLength
Definition: wininet.h:278
RPC_STATUS RPCRT4_OpenClientConnection(RpcConnection *Connection)
GLbitfield GLuint64 timeout
Definition: glext.h:7164
#define ntohs(x)
Definition: module.h:208
const char * name
Definition: rpc_server.h:50
DWORD RPCRT4_GetHeaderSize(const RpcPktHdr *Header)
Definition: rpc_message.c:57
static BOOL rpcrt4_sock_wait_init(RpcConnection_tcp *tcpc)
static HANDLE PIO_APC_ROUTINE PVOID PIO_STATUS_BLOCK ULONG PVOID ULONG PVOID out_buffer
Definition: file.c:100
#define RPC_S_INVALID_ENDPOINT_FORMAT
Definition: winerror.h:1017
#define INTERNET_DEFAULT_HTTP_PORT
Definition: winhttp.h:36
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:597
static RPC_STATUS rpcrt4_ncalrpc_handoff(RpcConnection *old_conn, RpcConnection *new_conn)
static int rpcrt4_conn_tcp_write(RpcConnection *Connection, const void *buffer, unsigned int count)
u_int16 port
Definition: epm_towers.h:70
struct list conn_pool_entry
Definition: rpc_binding.h:85
static const WCHAR negotiateW[]
#define HTTP_ADDREQ_FLAG_REPLACE
Definition: wininet.h:1711
#define RPC_S_ACCESS_DENIED
Definition: rpcnterr.h:29
LPWSTR lpszExtraInfo
Definition: wininet.h:224
struct _test_info info[]
Definition: SetCursorPos.c:19
#define TCP_NODELAY
Definition: tcpdef.h:117
WORD INTERNET_PORT
Definition: winhttp.h:38
#define FD_WRITE
Definition: winsock.h:406
BOOL WINAPI WaitNamedPipeA(LPCSTR lpNamedPipeName, DWORD nTimeOut)
Definition: npipe.c:433
unsigned int len
GLenum pname
Definition: glext.h:5645
#define EPM_PROTOCOL_PIPE
Definition: epm_towers.h:38
static void rpcrt4_ncacn_http_cancel_call(RpcConnection *Connection)
struct status_code status_code
#define sprintf(buf, format,...)
Definition: sprintf.c:55
static unsigned char * in_buffer
Definition: iccvid.c:87
#define SecInvalidateHandle(x)
Definition: sspi.h:58
__WINE_SERVER_LIST_INLINE void list_add_tail(struct list *list, struct list *elem)
Definition: list.h:102
static const struct protseq_ops protseq_list[]
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
ULONG RpcQualityOfService_Release(RpcQualityOfService *qos)
Definition: rpc_binding.c:1362
long RPC_STATUS
Definition: rpc.h:52
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:198
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
static void rpcrt4_ncacn_http_close_read(RpcConnection *conn)
RpcPktCommonHdr common
Definition: rpc_defs.h:152
void rpcrt4_conn_release_and_wait(RpcConnection *connection)
static size_t rpcrt4_ncacn_np_get_top_of_tower(unsigned char *tower_data, const char *networkaddr, const char *endpoint)
DWORD dwSchemeLength
Definition: wininet.h:213
CredHandle cred
void RPCRT4_strfree(LPSTR src)
Definition: rpc_binding.c:105
#define closesocket
Definition: main.c:39
#define CP_UTF8
Definition: nls.h:20
#define ERROR_ACCESS_DENIED
Definition: compat.h:87
Definition: Header.h:8
#define RPC_S_OUT_OF_MEMORY
Definition: rpcnterr.h:24
struct _RpcConnection_tcp RpcConnection_tcp
INTERNET_PORT nPort
Definition: wininet.h:217
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
#define SECURITY_DELEGATION
Definition: winbase.h:524
IO_STATUS_BLOCK io_status
Definition: rpc_transport.c:87
unsigned short flags
Definition: rpc_defs.h:138
ULONG RpcAuthInfo_AddRef(RpcAuthInfo *AuthInfo)
Definition: rpc_binding.c:1180
static RPC_STATUS rpcrt4_protseq_ncacn_np_open_endpoint(RpcServerProtseq *protseq, const char *endpoint)