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