ReactOS  0.4.14-dev-1296-g56aa513
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)
#define TRUE
Definition: types.h:120
static HANDLE PIO_APC_ROUTINE PVOID PIO_STATUS_BLOCK ULONG PVOID ULONG PVOID ULONG out_size
Definition: file.c:100
static RPC_STATUS rpcrt4_conn_tcp_handoff(RpcConnection *old_conn, RpcConnection *new_conn)
static VOID WINAPI rpcrt4_http_internet_callback(HINTERNET hInternet, DWORD_PTR dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInformation, DWORD dwStatusInformationLength)
static void rpcrt4_protseq_np_signal_state_changed(RpcServerProtseq *protseq)
unsigned short * User
Definition: rpcdce.h:223
#define CloseHandle
Definition: compat.h:406
#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:101
SECURITY_STATUS WINAPI AcquireCredentialsHandleW(SEC_WCHAR *pszPrincipal, SEC_WCHAR *pszPackage, ULONG fCredentialsUse, PLUID pvLogonID, PVOID pAuthData, SEC_GET_KEY_FN pGetKeyFn, PVOID pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
Definition: wrapper.c:105
#define error(str)
Definition: mkdosfs.c:1605
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
RPC_STATUS RPCRT4_default_revert_to_self(RpcConnection *conn)
Definition: rpc_message.c:1159
void WINAPI I_RpcFree(void *Object)
Definition: rpcrt4_main.c: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:247
SECURITY_STATUS WINAPI FreeContextBuffer(PVOID pv)
Definition: sspi.c:699
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
INT WSAAPI bind(IN SOCKET s, IN CONST struct sockaddr *name, IN INT namelen)
Definition: socklife.c:36
unsigned short * Password
Definition: rpcdce.h:227
ULONG ulVersion
Definition: sspi.h: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:99
u_int32 ipv4addr
Definition: epm_towers.h:78
RPC_STATUS RpcTransport_ParseTopOfTower(const unsigned char *tower_data, size_t tower_size, char **protseq, char **networkaddr, char **endpoint)
GLuint GLuint GLsizei count
Definition: gl.h:1545
HANDLE WINAPI CreateNamedPipeA(LPCSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD nMaxInstances, DWORD nOutBufferSize, DWORD nInBufferSize, DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: npipe.c:220
#define SecIsValidHandle(x)
Definition: sspi.h:63
char CHAR
Definition: xmlstorage.h:175
unsigned int Count
Definition: rpcdce.h:90
const GLint * first
Definition: glext.h:5794
#define WARN(fmt,...)
Definition: debug.h:111
#define U(x)
Definition: wordpad.c: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:27
__WINE_SERVER_LIST_INLINE void list_add_head(struct list *list, struct list *elem)
Definition: list.h:96
static HANDLE PIO_APC_ROUTINE void PIO_STATUS_BLOCK io_status
Definition: comm.c:54
_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:399
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:1059
static RPC_STATUS wait_async_request(RpcHttpAsyncData *async_data, BOOL call_ret, HANDLE cancel_event)
GLuint buffer
Definition: glext.h:5915
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
USHORT NextCallId
Definition: rpc_binding.h:93
RPC_STATUS RPCRT4_CloseConnection(RpcConnection *Connection)
DWORD dwUserNameLength
Definition: wininet.h:219
BOOL WINAPI InternetCloseHandle(HINTERNET hInternet)
Definition: internet.c: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
GLuint GLuint end
Definition: gl.h:1545
RPC_HTTP_TRANSPORT_CREDENTIALS_W * HttpCredentials
Definition: rpcdce.h:279
#define RPC_C_IMP_LEVEL_IDENTIFY
Definition: rpcdce.h:175
_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:415
static const struct connection_ops * rpcrt4_get_conn_protseq_ops(const char *protseq)
LPWSTR lpszHostName
Definition: wininet.h:215
INT WSAAPI connect(IN SOCKET s, IN CONST struct sockaddr *name, IN INT namelen)
Definition: sockctrl.c:23
u32_t s_addr
Definition: inet.h:45
#define ERROR_CANNOT_IMPERSONATE
Definition: winerror.h:849
#define EPM_PROTOCOL_NETBIOS
Definition: epm_towers.h:39
#define EPM_PROTOCOL_NCACN
Definition: epm_towers.h:33
Definition: send.c:47
static LONG next_id
Definition: changenotify.c:91
const struct connection_ops * ops
Definition: rpc_binding.h:70
DWORD dwBufferLength
Definition: wininet.h:278
RPC_STATUS RPCRT4_OpenClientConnection(RpcConnection *Connection)
GLbitfield GLuint64 timeout
Definition: glext.h:7164
#define 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
struct _test_info info[]
Definition: SetCursorPos.c:19
#define TCP_NODELAY
Definition: tcpdef.h:117
WORD INTERNET_PORT
Definition: winhttp.h:38
#define FD_WRITE
Definition: winsock.h:406
BOOL WINAPI WaitNamedPipeA(LPCSTR lpNamedPipeName, DWORD nTimeOut)
Definition: npipe.c:433
unsigned int len
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
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
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
static void rpcrt4_ncacn_http_close_read(RpcConnection *conn)
RpcPktCommonHdr common
Definition: rpc_defs.h:152
void rpcrt4_conn_release_and_wait(RpcConnection *connection)
static size_t rpcrt4_ncacn_np_get_top_of_tower(unsigned char *tower_data, const char *networkaddr, const char *endpoint)
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 ERROR_ACCESS_DENIED
Definition: compat.h:87
Definition: Header.h:8
#define RPC_S_OUT_OF_MEMORY
Definition: rpcnterr.h:24
struct _RpcConnection_tcp RpcConnection_tcp
INTERNET_PORT nPort
Definition: wininet.h:217
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG</