22#include <freerdp/config.h> 
   24#include "../settings.h" 
   27#include <winpr/assert.h> 
   28#include <winpr/cast.h> 
   29#include <winpr/tchar.h> 
   30#include <winpr/synch.h> 
   31#include <winpr/dsparse.h> 
   32#include <winpr/crypto.h> 
   34#include <freerdp/log.h> 
   36#ifdef FREERDP_HAVE_VALGRIND_MEMCHECK_H 
   37#include <valgrind/memcheck.h> 
   42#include "../credssp_auth.h" 
   43#include "ncacn_http.h" 
   46#include "rpc_client.h" 
   51#define TAG FREERDP_TAG("core.gateway.rpc") 
   53static const char* PTYPE_STRINGS[] = { 
"PTYPE_REQUEST",       
"PTYPE_PING",
 
   54                                     "PTYPE_RESPONSE",      
"PTYPE_FAULT",
 
   55                                     "PTYPE_WORKING",       
"PTYPE_NOCALL",
 
   56                                     "PTYPE_REJECT",        
"PTYPE_ACK",
 
   57                                     "PTYPE_CL_CANCEL",     
"PTYPE_FACK",
 
   58                                     "PTYPE_CANCEL_ACK",    
"PTYPE_BIND",
 
   59                                     "PTYPE_BIND_ACK",      
"PTYPE_BIND_NAK",
 
   60                                     "PTYPE_ALTER_CONTEXT", 
"PTYPE_ALTER_CONTEXT_RESP",
 
   61                                     "PTYPE_RPC_AUTH_3",    
"PTYPE_SHUTDOWN",
 
   62                                     "PTYPE_CO_CANCEL",     
"PTYPE_ORPHANED",
 
   65static const char* client_in_state_str(CLIENT_IN_CHANNEL_STATE state)
 
   68  const char* str = 
"CLIENT_IN_CHANNEL_STATE_UNKNOWN";
 
   72    case CLIENT_IN_CHANNEL_STATE_INITIAL:
 
   73      str = 
"CLIENT_IN_CHANNEL_STATE_INITIAL";
 
   76    case CLIENT_IN_CHANNEL_STATE_CONNECTED:
 
   77      str = 
"CLIENT_IN_CHANNEL_STATE_CONNECTED";
 
   80    case CLIENT_IN_CHANNEL_STATE_SECURITY:
 
   81      str = 
"CLIENT_IN_CHANNEL_STATE_SECURITY";
 
   84    case CLIENT_IN_CHANNEL_STATE_NEGOTIATED:
 
   85      str = 
"CLIENT_IN_CHANNEL_STATE_NEGOTIATED";
 
   88    case CLIENT_IN_CHANNEL_STATE_OPENED:
 
   89      str = 
"CLIENT_IN_CHANNEL_STATE_OPENED";
 
   92    case CLIENT_IN_CHANNEL_STATE_OPENED_A4W:
 
   93      str = 
"CLIENT_IN_CHANNEL_STATE_OPENED_A4W";
 
   96    case CLIENT_IN_CHANNEL_STATE_FINAL:
 
   97      str = 
"CLIENT_IN_CHANNEL_STATE_FINAL";
 
  105static const char* client_out_state_str(CLIENT_OUT_CHANNEL_STATE state)
 
  108  const char* str = 
"CLIENT_OUT_CHANNEL_STATE_UNKNOWN";
 
  112    case CLIENT_OUT_CHANNEL_STATE_INITIAL:
 
  113      str = 
"CLIENT_OUT_CHANNEL_STATE_INITIAL";
 
  116    case CLIENT_OUT_CHANNEL_STATE_CONNECTED:
 
  117      str = 
"CLIENT_OUT_CHANNEL_STATE_CONNECTED";
 
  120    case CLIENT_OUT_CHANNEL_STATE_SECURITY:
 
  121      str = 
"CLIENT_OUT_CHANNEL_STATE_SECURITY";
 
  124    case CLIENT_OUT_CHANNEL_STATE_NEGOTIATED:
 
  125      str = 
"CLIENT_OUT_CHANNEL_STATE_NEGOTIATED";
 
  128    case CLIENT_OUT_CHANNEL_STATE_OPENED:
 
  129      str = 
"CLIENT_OUT_CHANNEL_STATE_OPENED";
 
  132    case CLIENT_OUT_CHANNEL_STATE_OPENED_A6W:
 
  133      str = 
"CLIENT_OUT_CHANNEL_STATE_OPENED_A6W";
 
  136    case CLIENT_OUT_CHANNEL_STATE_OPENED_A10W:
 
  137      str = 
"CLIENT_OUT_CHANNEL_STATE_OPENED_A10W";
 
  140    case CLIENT_OUT_CHANNEL_STATE_OPENED_B3W:
 
  141      str = 
"CLIENT_OUT_CHANNEL_STATE_OPENED_B3W";
 
  144    case CLIENT_OUT_CHANNEL_STATE_RECYCLED:
 
  145      str = 
"CLIENT_OUT_CHANNEL_STATE_RECYCLED";
 
  148    case CLIENT_OUT_CHANNEL_STATE_FINAL:
 
  149      str = 
"CLIENT_OUT_CHANNEL_STATE_FINAL";
 
  157const char* rpc_vc_state_str(VIRTUAL_CONNECTION_STATE state)
 
  160  const char* str = 
"VIRTUAL_CONNECTION_STATE_UNKNOWN";
 
  164    case VIRTUAL_CONNECTION_STATE_INITIAL:
 
  165      str = 
"VIRTUAL_CONNECTION_STATE_INITIAL";
 
  168    case VIRTUAL_CONNECTION_STATE_OUT_CHANNEL_WAIT:
 
  169      str = 
"VIRTUAL_CONNECTION_STATE_OUT_CHANNEL_WAIT";
 
  172    case VIRTUAL_CONNECTION_STATE_WAIT_A3W:
 
  173      str = 
"VIRTUAL_CONNECTION_STATE_WAIT_A3W";
 
  176    case VIRTUAL_CONNECTION_STATE_WAIT_C2:
 
  177      str = 
"VIRTUAL_CONNECTION_STATE_WAIT_C2";
 
  180    case VIRTUAL_CONNECTION_STATE_OPENED:
 
  181      str = 
"VIRTUAL_CONNECTION_STATE_OPENED";
 
  184    case VIRTUAL_CONNECTION_STATE_FINAL:
 
  185      str = 
"VIRTUAL_CONNECTION_STATE_FINAL";
 
  220void rpc_pdu_header_print(wLog* log, 
const rpcconn_hdr_t* header)
 
  222  WINPR_ASSERT(header);
 
  224  WLog_Print(log, WLOG_INFO, 
"rpc_vers: %" PRIu8 
"", header->common.rpc_vers);
 
  225  WLog_Print(log, WLOG_INFO, 
"rpc_vers_minor: %" PRIu8 
"", header->common.rpc_vers_minor);
 
  227  if (header->common.ptype > PTYPE_RTS)
 
  228    WLog_Print(log, WLOG_INFO, 
"ptype: %s (%" PRIu8 
")", 
"PTYPE_UNKNOWN", header->common.ptype);
 
  230    WLog_Print(log, WLOG_INFO, 
"ptype: %s (%" PRIu8 
")", PTYPE_STRINGS[header->common.ptype],
 
  231               header->common.ptype);
 
  233  WLog_Print(log, WLOG_INFO, 
"pfc_flags (0x%02" PRIX8 
") = {", header->common.pfc_flags);
 
  235  if (header->common.pfc_flags & PFC_FIRST_FRAG)
 
  236    WLog_Print(log, WLOG_INFO, 
" PFC_FIRST_FRAG");
 
  238  if (header->common.pfc_flags & PFC_LAST_FRAG)
 
  239    WLog_Print(log, WLOG_INFO, 
" PFC_LAST_FRAG");
 
  241  if (header->common.pfc_flags & PFC_PENDING_CANCEL)
 
  242    WLog_Print(log, WLOG_INFO, 
" PFC_PENDING_CANCEL");
 
  244  if (header->common.pfc_flags & PFC_RESERVED_1)
 
  245    WLog_Print(log, WLOG_INFO, 
" PFC_RESERVED_1");
 
  247  if (header->common.pfc_flags & PFC_CONC_MPX)
 
  248    WLog_Print(log, WLOG_INFO, 
" PFC_CONC_MPX");
 
  250  if (header->common.pfc_flags & PFC_DID_NOT_EXECUTE)
 
  251    WLog_Print(log, WLOG_INFO, 
" PFC_DID_NOT_EXECUTE");
 
  253  if (header->common.pfc_flags & PFC_OBJECT_UUID)
 
  254    WLog_Print(log, WLOG_INFO, 
" PFC_OBJECT_UUID");
 
  256  WLog_Print(log, WLOG_INFO, 
" }");
 
  257  WLog_Print(log, WLOG_INFO,
 
  258             "packed_drep[4]: %02" PRIX8 
" %02" PRIX8 
" %02" PRIX8 
" %02" PRIX8 
"",
 
  259             header->common.packed_drep[0], header->common.packed_drep[1],
 
  260             header->common.packed_drep[2], header->common.packed_drep[3]);
 
  261  WLog_Print(log, WLOG_INFO, 
"frag_length: %" PRIu16 
"", header->common.frag_length);
 
  262  WLog_Print(log, WLOG_INFO, 
"auth_length: %" PRIu16 
"", header->common.auth_length);
 
  263  WLog_Print(log, WLOG_INFO, 
"call_id: %" PRIu32 
"", header->common.call_id);
 
  265  if (header->common.ptype == PTYPE_RESPONSE)
 
  267    WLog_Print(log, WLOG_INFO, 
"alloc_hint: %" PRIu32 
"", header->response.alloc_hint);
 
  268    WLog_Print(log, WLOG_INFO, 
"p_cont_id: %" PRIu16 
"", header->response.p_cont_id);
 
  269    WLog_Print(log, WLOG_INFO, 
"cancel_count: %" PRIu8 
"", header->response.cancel_count);
 
  270    WLog_Print(log, WLOG_INFO, 
"reserved: %" PRIu8 
"", header->response.reserved);
 
  279  header.rpc_vers = rpc->rpc_vers;
 
  280  header.rpc_vers_minor = rpc->rpc_vers_minor;
 
  281  header.packed_drep[0] = rpc->packed_drep[0];
 
  282  header.packed_drep[1] = rpc->packed_drep[1];
 
  283  header.packed_drep[2] = rpc->packed_drep[2];
 
  284  header.packed_drep[3] = rpc->packed_drep[3];
 
  288size_t rpc_offset_align(
size_t* offset, 
size_t alignment)
 
  292  *offset = (*offset + alignment - 1) & ~(alignment - 1);
 
  297size_t rpc_offset_pad(
size_t* offset, 
size_t pad)
 
  378BOOL rpc_get_stub_data_info(rdpRpc* rpc, 
const rpcconn_hdr_t* header, 
size_t* poffset,
 
  384  UINT32 frag_length = 0;
 
  385  UINT32 auth_length = 0;
 
  386  UINT32 auth_pad_length = 0;
 
  387  UINT32 sec_trailer_offset = 0;
 
  388  const rpc_sec_trailer* sec_trailer = NULL;
 
  391  WINPR_ASSERT(header);
 
  392  WINPR_ASSERT(poffset);
 
  393  WINPR_ASSERT(length);
 
  395  offset = RPC_COMMON_FIELDS_LENGTH;
 
  397  switch (header->common.ptype)
 
  401      rpc_offset_align(&offset, 8);
 
  402      sec_trailer = &header->response.auth_verifier;
 
  407      rpc_offset_align(&offset, 8);
 
  408      sec_trailer = &header->request.auth_verifier;
 
  416      WLog_Print(rpc->log, WLOG_ERROR, 
"Unknown PTYPE: 0x%02" PRIX8 
"", header->common.ptype);
 
  420  frag_length = header->common.frag_length;
 
  421  auth_length = header->common.auth_length;
 
  427  used = offset + auth_length + 8ull;
 
  430    auth_pad_length = sec_trailer->auth_pad_length;
 
  431    used += sec_trailer->auth_pad_length;
 
  434  if (frag_length < used)
 
  440  sec_trailer_offset = frag_length - auth_length - 8;
 
  448  if ((frag_length - (sec_trailer_offset + 8)) != auth_length)
 
  450    WLog_Print(rpc->log, WLOG_ERROR,
 
  451               "invalid auth_length: actual: %" PRIu32 
", expected: %" PRIu32 
"", auth_length,
 
  452               (frag_length - (sec_trailer_offset + 8)));
 
  455  *length = sec_trailer_offset - auth_pad_length - offset;
 
  466  if (!channel || (length > INT32_MAX))
 
  470  status = BIO_read(channel->tls->bio, Stream_Pointer(s), (INT32)length);
 
  474    Stream_Seek(s, (
size_t)status);
 
  478  if (BIO_should_retry(channel->tls->bio))
 
  481  WLog_Print(channel->rpc->log, WLOG_ERROR, 
"rpc_channel_read: Out of retries");
 
  485SSIZE_T rpc_channel_write_int(
RpcChannel* channel, 
const BYTE* data, 
size_t length,
 
  486                              const char* file, 
size_t line, 
const char* fkt)
 
  488  WINPR_ASSERT(channel);
 
  489  WINPR_ASSERT(channel->rpc);
 
  491  const DWORD level = WLOG_TRACE;
 
  492  if (WLog_IsLevelActive(channel->rpc->log, level))
 
  494    WLog_PrintTextMessage(channel->rpc->log, level, line, file, fkt,
 
  495                          "Sending [%s] %" PRIuz 
" bytes", fkt, length);
 
  498  return freerdp_tls_write_all(channel->tls, data, length);
 
  501BOOL rpc_in_channel_transition_to_state(
RpcInChannel* inChannel, CLIENT_IN_CHANNEL_STATE state)
 
  506  inChannel->State = state;
 
  507  WLog_Print(inChannel->common.rpc->log, WLOG_DEBUG, 
"%s", client_in_state_str(state));
 
  514  HttpContext* http = NULL;
 
  515  rdpSettings* settings = NULL;
 
  518  if (!client || !channel || !inout || !client->context || !client->context->settings)
 
  521  settings = client->context->settings;
 
  522  channel->auth = credssp_auth_new(client->context);
 
  523  rts_generate_cookie((BYTE*)&channel->Cookie);
 
  524  channel->client = client;
 
  529  channel->http = http_context_new();
 
  534  http = channel->http;
 
  537    if (!http_context_set_pragma(http, 
"ResourceTypeUuid=44e265dd-7daf-42cd-8560-3cdb6e7a2729"))
 
  542      char* strguid = NULL;
 
  543      RPC_STATUS rpcStatus = UuidToStringA(guid, &strguid);
 
  545      if (rpcStatus != RPC_S_OK)
 
  548      const BOOL rc = http_context_append_pragma(http, 
"SessionId=%s", strguid);
 
  549      RpcStringFreeA(&strguid);
 
  555      if (!http_context_append_pragma(http, 
"MinConnTimeout=%" PRIu32, timeout))
 
  559    if (!http_context_set_rdg_correlation_id(http, guid) ||
 
  560        !http_context_set_rdg_connection_id(http, guid))
 
  565  if (!http_context_set_method(http, inout) ||
 
  566      !http_context_set_uri(http, 
"/rpc/rpcproxy.dll?localhost:3388") ||
 
  567      !http_context_set_accept(http, 
"application/rpc") ||
 
  568      !http_context_set_cache_control(http, 
"no-cache") ||
 
  569      !http_context_set_connection(http, 
"Keep-Alive") ||
 
  570      !http_context_set_user_agent(http, 
"MSRPC") ||
 
  571      !http_context_set_host(http, settings->GatewayHostname))
 
  577static int rpc_in_channel_init(rdpRpc* rpc, 
RpcInChannel* inChannel, 
const GUID* guid)
 
  580  WINPR_ASSERT(inChannel);
 
  582  inChannel->common.rpc = rpc;
 
  583  inChannel->State = CLIENT_IN_CHANNEL_STATE_INITIAL;
 
  584  inChannel->BytesSent = 0;
 
  585  inChannel->SenderAvailableWindow = rpc->ReceiveWindow;
 
  586  inChannel->PingOriginator.ConnectionTimeout = 30;
 
  587  inChannel->PingOriginator.KeepAliveInterval = 0;
 
  589  if (rpc_channel_rpch_init(rpc->client, &inChannel->common, 
"RPC_IN_DATA", guid) < 0)
 
  595static RpcInChannel* rpc_in_channel_new(rdpRpc* rpc, 
const GUID* guid)
 
  601    rpc_in_channel_init(rpc, inChannel, guid);
 
  612  credssp_auth_free(channel->auth);
 
  613  http_context_free(channel->http);
 
  614  freerdp_tls_free(channel->tls);
 
  618BOOL rpc_out_channel_transition_to_state(
RpcOutChannel* outChannel, CLIENT_OUT_CHANNEL_STATE state)
 
  623  outChannel->State = state;
 
  624  WLog_Print(outChannel->common.rpc->log, WLOG_DEBUG, 
"%s", client_out_state_str(state));
 
  628static int rpc_out_channel_init(rdpRpc* rpc, 
RpcOutChannel* outChannel, 
const GUID* guid)
 
  631  WINPR_ASSERT(outChannel);
 
  633  outChannel->common.rpc = rpc;
 
  634  outChannel->State = CLIENT_OUT_CHANNEL_STATE_INITIAL;
 
  635  outChannel->BytesReceived = 0;
 
  636  outChannel->ReceiverAvailableWindow = rpc->ReceiveWindow;
 
  637  outChannel->ReceiveWindow = rpc->ReceiveWindow;
 
  638  outChannel->ReceiveWindowSize = rpc->ReceiveWindow;
 
  639  outChannel->AvailableWindowAdvertised = rpc->ReceiveWindow;
 
  641  if (rpc_channel_rpch_init(rpc->client, &outChannel->common, 
"RPC_OUT_DATA", guid) < 0)
 
  647RpcOutChannel* rpc_out_channel_new(rdpRpc* rpc, 
const GUID* guid)
 
  653    rpc_out_channel_init(rpc, outChannel, guid);
 
  660                                                VIRTUAL_CONNECTION_STATE state)
 
  666  connection->State = state;
 
  667  WLog_Print(rpc->log, WLOG_DEBUG, 
"%s", rpc_vc_state_str(state));
 
  676  if (connection->DefaultInChannel)
 
  677    rpc_channel_free(&connection->DefaultInChannel->common);
 
  678  if (connection->NonDefaultInChannel)
 
  679    rpc_channel_free(&connection->NonDefaultInChannel->common);
 
  680  if (connection->DefaultOutChannel)
 
  681    rpc_channel_free(&connection->DefaultOutChannel->common);
 
  682  if (connection->NonDefaultOutChannel)
 
  683    rpc_channel_free(&connection->NonDefaultOutChannel->common);
 
  697  rts_generate_cookie((BYTE*)&(connection->Cookie));
 
  698  rts_generate_cookie((BYTE*)&(connection->AssociationGroupId));
 
  699  connection->State = VIRTUAL_CONNECTION_STATE_INITIAL;
 
  701  connection->DefaultInChannel = rpc_in_channel_new(rpc, &connection->Cookie);
 
  703  if (!connection->DefaultInChannel)
 
  706  connection->DefaultOutChannel = rpc_out_channel_new(rpc, &connection->Cookie);
 
  708  if (!connection->DefaultOutChannel)
 
  713  rpc_virtual_connection_free(connection);
 
  717static BOOL rpc_channel_tls_connect(
RpcChannel* channel, UINT32 timeout)
 
  719  if (!channel || !channel->client || !channel->client->context ||
 
  720      !channel->client->context->settings)
 
  723  rdpContext* context = channel->client->context;
 
  724  WINPR_ASSERT(context);
 
  726  rdpSettings* settings = context->settings;
 
  727  WINPR_ASSERT(settings);
 
  732  rdpTransport* transport = freerdp_get_transport(context);
 
  734      transport_connect_layer(transport, channel->client->host, channel->client->port, timeout);
 
  739  BIO* layerBio = BIO_new(BIO_s_transport_layer());
 
  742    transport_layer_free(layer);
 
  745  BIO_set_data(layerBio, layer);
 
  747  BIO* bufferedBio = BIO_new(BIO_s_buffered_socket());
 
  750    BIO_free_all(layerBio);
 
  754  bufferedBio = BIO_push(bufferedBio, layerBio);
 
  756  if (!BIO_set_nonblock(bufferedBio, TRUE))
 
  758    BIO_free_all(bufferedBio);
 
  762  if (channel->client->isProxy)
 
  764    WINPR_ASSERT(settings->GatewayPort <= UINT16_MAX);
 
  765    if (!proxy_connect(context, bufferedBio, proxyUsername, proxyPassword,
 
  766                       settings->GatewayHostname, (UINT16)settings->GatewayPort))
 
  768      BIO_free_all(bufferedBio);
 
  773  channel->bio = bufferedBio;
 
  774  rdpTls* tls = channel->tls = freerdp_tls_new(context);
 
  779  tls->hostname = settings->GatewayHostname;
 
  780  tls->port = WINPR_ASSERTING_INT_CAST(int32_t, MIN(UINT16_MAX, settings->GatewayPort));
 
  781  tls->isGatewayTransport = TRUE;
 
  782  int tlsStatus = freerdp_tls_connect(tls, bufferedBio);
 
  788      freerdp_set_last_error_if_not(context, FREERDP_ERROR_TLS_CONNECT_FAILED);
 
  792      freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_CANCELLED);
 
  801static int rpc_in_channel_connect(
RpcInChannel* inChannel, UINT32 timeout)
 
  803  rdpContext* context = NULL;
 
  805  if (!inChannel || !inChannel->common.client || !inChannel->common.client->context)
 
  808  context = inChannel->common.client->context;
 
  812  if (!rpc_channel_tls_connect(&inChannel->common, timeout))
 
  815  rpc_in_channel_transition_to_state(inChannel, CLIENT_IN_CHANNEL_STATE_CONNECTED);
 
  817  if (!rpc_ncacn_http_auth_init(context, &inChannel->common))
 
  822  if (!rpc_ncacn_http_send_in_channel_request(&inChannel->common))
 
  824    WLog_Print(inChannel->common.rpc->log, WLOG_ERROR,
 
  825               "rpc_ncacn_http_send_in_channel_request failure");
 
  829  if (!rpc_in_channel_transition_to_state(inChannel, CLIENT_IN_CHANNEL_STATE_SECURITY))
 
  835static int rpc_out_channel_connect(
RpcOutChannel* outChannel, UINT32 timeout)
 
  837  rdpContext* context = NULL;
 
  839  if (!outChannel || !outChannel->common.client || !outChannel->common.client->context)
 
  842  context = outChannel->common.client->context;
 
  846  if (!rpc_channel_tls_connect(&outChannel->common, timeout))
 
  849  rpc_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_CONNECTED);
 
  851  if (!rpc_ncacn_http_auth_init(context, &outChannel->common))
 
  856  if (!rpc_ncacn_http_send_out_channel_request(&outChannel->common, FALSE))
 
  858    WLog_Print(outChannel->common.rpc->log, WLOG_ERROR,
 
  859               "rpc_ncacn_http_send_out_channel_request failure");
 
  863  rpc_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_SECURITY);
 
  867int rpc_out_channel_replacement_connect(
RpcOutChannel* outChannel, uint32_t timeout)
 
  869  rdpContext* context = NULL;
 
  871  if (!outChannel || !outChannel->common.client || !outChannel->common.client->context)
 
  874  context = outChannel->common.client->context;
 
  878  if (!rpc_channel_tls_connect(&outChannel->common, timeout))
 
  881  rpc_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_CONNECTED);
 
  883  if (!rpc_ncacn_http_auth_init(context, (
RpcChannel*)outChannel))
 
  888  if (!rpc_ncacn_http_send_out_channel_request(&outChannel->common, TRUE))
 
  890    WLog_Print(outChannel->common.rpc->log, WLOG_ERROR,
 
  891               "rpc_ncacn_http_send_out_channel_request failure");
 
  895  rpc_out_channel_transition_to_state(outChannel, CLIENT_OUT_CHANNEL_STATE_SECURITY);
 
  899BOOL rpc_connect(rdpRpc* rpc, UINT32 timeout)
 
  904  rpc->VirtualConnection = rpc_virtual_connection_new(rpc);
 
  906  if (!rpc->VirtualConnection)
 
  909  connection = rpc->VirtualConnection;
 
  910  inChannel = connection->DefaultInChannel;
 
  911  outChannel = connection->DefaultOutChannel;
 
  912  rpc_virtual_connection_transition_to_state(rpc, connection, VIRTUAL_CONNECTION_STATE_INITIAL);
 
  914  if (rpc_in_channel_connect(inChannel, timeout) < 0)
 
  917  if (rpc_out_channel_connect(outChannel, timeout) < 0)
 
  923rdpRpc* rpc_new(rdpTransport* transport)
 
  925  rdpContext* context = transport_get_context(transport);
 
  928  WINPR_ASSERT(context);
 
  930  rpc = (rdpRpc*)calloc(1, 
sizeof(rdpRpc));
 
  935  rpc->log = WLog_Get(TAG);
 
  936  rpc->State = RPC_CLIENT_STATE_INITIAL;
 
  937  rpc->transport = transport;
 
  939  rpc->auth = credssp_auth_new(context);
 
  946  rpc->StubFragCount = 0;
 
  948  rpc->rpc_vers_minor = 0;
 
  950  rpc->packed_drep[0] = 0x10;
 
  951  rpc->packed_drep[1] = 0x00;
 
  952  rpc->packed_drep[2] = 0x00;
 
  953  rpc->packed_drep[3] = 0x00;
 
  954  rpc->max_xmit_frag = 0x0FF8;
 
  955  rpc->max_recv_frag = 0x0FF8;
 
  956  rpc->ReceiveWindow = 0x00010000;
 
  957  rpc->ChannelLifetime = 0x40000000;
 
  958  rpc->KeepAliveInterval = 300000;
 
  959  rpc->CurrentKeepAliveInterval = rpc->KeepAliveInterval;
 
  960  rpc->CurrentKeepAliveTime = 0;
 
  962  rpc->client = rpc_client_new(context, rpc->max_recv_frag);
 
  969  WINPR_PRAGMA_DIAG_PUSH
 
  970  WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
 
  972  WINPR_PRAGMA_DIAG_POP
 
  976void rpc_free(rdpRpc* rpc)
 
  980    rpc_client_free(rpc->client);
 
  981    credssp_auth_free(rpc->auth);
 
  982    rpc_virtual_connection_free(rpc->VirtualConnection);
 
FREERDP_API const char * freerdp_settings_get_string(const rdpSettings *settings, FreeRDP_Settings_Keys_String id)
Returns a immutable string settings value.