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