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