24 #include <freerdp/config.h>
26 #include <winpr/crt.h>
27 #include <winpr/ssl.h>
28 #include <winpr/path.h>
29 #include <winpr/synch.h>
30 #include <winpr/string.h>
31 #include <winpr/winsock.h>
32 #include <winpr/thread.h>
35 #include <freerdp/freerdp.h>
36 #include <freerdp/streamdump.h>
37 #include <freerdp/channels/wtsvc.h>
38 #include <freerdp/channels/channels.h>
39 #include <freerdp/channels/drdynvc.h>
40 #include <freerdp/build-config.h>
42 #include <freerdp/channels/rdpdr.h>
44 #include <freerdp/server/proxy/proxy_server.h>
45 #include <freerdp/server/proxy/proxy_log.h>
47 #include "pf_server.h"
48 #include "pf_channel.h"
49 #include <freerdp/server/proxy/proxy_config.h>
50 #include "pf_client.h"
51 #include <freerdp/server/proxy/proxy_context.h>
52 #include "pf_update.h"
53 #include "proxy_modules.h"
55 #include "channels/pf_channel_drdynvc.h"
56 #include "channels/pf_channel_rdpdr.h"
58 #define TAG PROXY_TAG("server")
66 static BOOL pf_server_parse_target_from_routing_token(rdpContext* context, rdpSettings* settings,
67 FreeRDP_Settings_Keys_String targetID,
68 FreeRDP_Settings_Keys_UInt32 portID)
70 #define TARGET_MAX (100)
71 #define ROUTING_TOKEN_PREFIX "Cookie: msts="
74 DWORD routing_token_length = 0;
75 const size_t prefix_len = strnlen(ROUTING_TOKEN_PREFIX,
sizeof(ROUTING_TOKEN_PREFIX));
76 const char* routing_token = freerdp_nego_get_routing_token(context, &routing_token_length);
77 pServerContext* ps = (pServerContext*)context;
82 if ((routing_token_length <= prefix_len) || (routing_token_length >= TARGET_MAX))
84 PROXY_LOG_ERR(TAG, ps,
"invalid routing token length: %" PRIu32
"", routing_token_length);
88 len = routing_token_length - prefix_len;
94 colon = strchr(target,
':');
99 unsigned long p = strtoul(colon + 1, NULL, 10);
111 static BOOL pf_server_get_target_info(rdpContext* context, rdpSettings* settings,
112 const proxyConfig* config)
114 pServerContext* ps = (pServerContext*)context;
117 WINPR_ASSERT(settings);
119 WINPR_ASSERT(ps->pdata);
121 ev.fetch_method = config->FixedTarget ? PROXY_FETCH_TARGET_METHOD_CONFIG
122 : PROXY_FETCH_TARGET_METHOD_LOAD_BALANCE_INFO;
124 if (!pf_modules_run_filter(ps->pdata->module, FILTER_TYPE_SERVER_FETCH_TARGET_ADDR, ps->pdata,
128 switch (ev.fetch_method)
130 case PROXY_FETCH_TARGET_METHOD_DEFAULT:
131 case PROXY_FETCH_TARGET_METHOD_LOAD_BALANCE_INFO:
132 return pf_server_parse_target_from_routing_token(
133 context, settings, FreeRDP_ServerHostname, FreeRDP_ServerPort);
135 case PROXY_FETCH_TARGET_METHOD_CONFIG:
137 WINPR_ASSERT(config);
139 if (config->TargetPort > 0)
151 config->TargetTlsSecLevel))
156 PROXY_LOG_ERR(TAG, ps,
"strdup failed!");
160 if (config->TargetUser)
166 if (config->TargetDomain)
172 if (config->TargetPassword)
175 config->TargetPassword))
181 case PROXY_FETCH_TARGET_USE_CUSTOM_ADDR:
183 if (!ev.target_address)
185 PROXY_LOG_ERR(TAG, ps,
186 "router: using CUSTOM_ADDR fetch method, but target_address == NULL");
192 PROXY_LOG_ERR(TAG, ps,
"strdup failed!");
196 free(ev.target_address);
200 PROXY_LOG_ERR(TAG, ps,
"unknown target fetch method: %d", ev.fetch_method);
207 static BOOL pf_server_setup_channels(freerdp_peer* peer)
210 char** accepted_channels = NULL;
211 size_t accepted_channels_count = 0;
212 pServerContext* ps = (pServerContext*)peer->context;
214 accepted_channels = WTSGetAcceptedChannelNames(peer, &accepted_channels_count);
215 if (!accepted_channels)
218 for (
size_t i = 0; i < accepted_channels_count; i++)
220 pServerStaticChannelContext* channelContext = NULL;
221 const char* cname = accepted_channels[i];
222 UINT16 channelId = WTSChannelGetId(peer, cname);
224 PROXY_LOG_INFO(TAG, ps,
"Accepted channel: %s (%" PRIu16
")", cname, channelId);
225 channelContext = StaticChannelContext_new(ps, cname, channelId);
228 PROXY_LOG_ERR(TAG, ps,
"error seting up channelContext for '%s'", cname);
232 if ((strcmp(cname, DRDYNVC_SVC_CHANNEL_NAME) == 0) &&
233 (channelContext->channelMode == PF_UTILS_CHANNEL_INTERCEPT))
235 if (!pf_channel_setup_drdynvc(ps->pdata, channelContext))
237 PROXY_LOG_ERR(TAG, ps,
"error while setting up dynamic channel");
238 StaticChannelContext_free(channelContext);
242 else if (strcmp(cname, RDPDR_SVC_CHANNEL_NAME) == 0 &&
243 (channelContext->channelMode == PF_UTILS_CHANNEL_INTERCEPT))
245 if (!pf_channel_setup_rdpdr(ps, channelContext))
247 PROXY_LOG_ERR(TAG, ps,
"error while setting up redirection channel");
248 StaticChannelContext_free(channelContext);
254 if (!pf_channel_setup_generic(channelContext))
256 PROXY_LOG_ERR(TAG, ps,
"error while setting up generic channel");
257 StaticChannelContext_free(channelContext);
262 if (!HashTable_Insert(ps->channelsByFrontId, &channelContext->front_channel_id,
265 StaticChannelContext_free(channelContext);
266 PROXY_LOG_ERR(TAG, ps,
"error inserting channelContext in byId table for '%s'", cname);
273 free(accepted_channels);
286 static BOOL pf_server_post_connect(freerdp_peer* peer)
288 pServerContext* ps = NULL;
289 pClientContext* pc = NULL;
290 rdpSettings* client_settings = NULL;
291 proxyData* pdata = NULL;
292 rdpSettings* frontSettings = NULL;
296 ps = (pServerContext*)peer->context;
299 frontSettings = peer->context->settings;
300 WINPR_ASSERT(frontSettings);
306 PROXY_LOG_INFO(TAG, ps,
"Accepted client: %s", ClientHostname);
307 if (!pf_server_setup_channels(peer))
309 PROXY_LOG_ERR(TAG, ps,
"error setting up channels");
313 pc = pf_context_create_client_context(frontSettings);
316 PROXY_LOG_ERR(TAG, ps,
"failed to create client context!");
320 client_settings = pc->context.settings;
323 proxy_data_set_client_context(pdata, pc);
325 if (!pf_server_get_target_info(peer->context, client_settings, pdata->config))
327 PROXY_LOG_INFO(TAG, ps,
"pf_server_get_target_info failed!");
331 PROXY_LOG_INFO(TAG, ps,
"remote target is %s:%" PRIu32
"",
335 if (!pf_modules_run_hook(pdata->module, HOOK_TYPE_SERVER_POST_CONNECT, pdata, peer))
339 if (!(pdata->client_thread = CreateThread(NULL, 0, pf_client_start, pc, 0, NULL)))
341 PROXY_LOG_ERR(TAG, ps,
"failed to create client thread");
348 static BOOL pf_server_activate(freerdp_peer* peer)
350 pServerContext* ps = NULL;
351 proxyData* pdata = NULL;
352 rdpSettings* settings = NULL;
356 ps = (pServerContext*)peer->context;
362 settings = peer->context->settings;
366 if (!pf_modules_run_hook(pdata->module, HOOK_TYPE_SERVER_ACTIVATE, pdata, peer))
372 static BOOL pf_server_logon(freerdp_peer* peer,
const SEC_WINNT_AUTH_IDENTITY* identity,
375 pServerContext* ps = NULL;
376 proxyData* pdata = NULL;
381 ps = (pServerContext*)peer->context;
386 WINPR_ASSERT(identity);
388 info.identity = identity;
389 info.automatic = automatic;
390 if (!pf_modules_run_filter(pdata->module, FILTER_TYPE_SERVER_PEER_LOGON, pdata, &info))
395 static BOOL pf_server_adjust_monitor_layout(freerdp_peer* peer)
402 static BOOL pf_server_receive_channel_data_hook(freerdp_peer* peer, UINT16 channelId,
403 const BYTE* data,
size_t size, UINT32 flags,
406 pServerContext* ps = NULL;
407 pClientContext* pc = NULL;
408 proxyData* pdata = NULL;
409 const proxyConfig* config = NULL;
410 const pServerStaticChannelContext* channel = NULL;
411 UINT64 channelId64 = channelId;
415 ps = (pServerContext*)peer->context;
422 config = pdata->config;
423 WINPR_ASSERT(config);
432 channel = HashTable_GetItemValue(ps->channelsByFrontId, &channelId64);
435 PROXY_LOG_ERR(TAG, ps,
"channel id=%" PRIu64
" not registered here, dropping", channelId64);
439 WINPR_ASSERT(channel->onFrontData);
440 switch (channel->onFrontData(pdata, channel, data, size, flags, totalSize))
442 case PF_CHANNEL_RESULT_PASS:
446 ev.channel_id = channelId;
447 ev.channel_name = channel->channel_name;
451 ev.total_size = totalSize;
452 return IFCALLRESULT(TRUE, pc->sendChannelData, pc, &ev);
454 case PF_CHANNEL_RESULT_DROP:
456 case PF_CHANNEL_RESULT_ERROR:
462 WINPR_ASSERT(pdata->server_receive_channel_data_original);
463 return pdata->server_receive_channel_data_original(peer, channelId, data, size, flags,
467 static BOOL pf_server_initialize_peer_connection(freerdp_peer* peer)
471 pServerContext* ps = (pServerContext*)peer->context;
475 rdpSettings* settings = peer->context->settings;
476 WINPR_ASSERT(settings);
478 proxyData* pdata = proxy_data_new();
481 proxyServer* server = (proxyServer*)peer->ContextExtra;
482 WINPR_ASSERT(server);
483 proxy_data_set_server_context(pdata, ps);
485 pdata->module = server->module;
486 const proxyConfig* config = pdata->config = server->config;
488 rdpPrivateKey* key = freerdp_key_new_from_pem(config->PrivateKeyPEM);
495 rdpCertificate* cert = freerdp_certificate_new_from_pem(config->CertificatePEM);
505 ZeroMemory(OrderSupport, 32);
508 WINPR_ASSERT(peer->context->update);
509 peer->context->update->autoCalculateBitmapData = FALSE;
516 if (pf_utils_is_passthrough(config))
522 if (config->RemoteApp)
525 RAIL_LEVEL_SUPPORTED | RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED |
526 RAIL_LEVEL_SHELL_INTEGRATION_SUPPORTED | RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED |
527 RAIL_LEVEL_SERVER_TO_CLIENT_IME_SYNC_SUPPORTED |
528 RAIL_LEVEL_HIDE_MINIMIZED_APPS_SUPPORTED | RAIL_LEVEL_WINDOW_CLOAKING_SUPPORTED |
529 RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED;
544 ENCRYPTION_LEVEL_CLIENT_COMPATIBLE))
559 peer->PostConnect = pf_server_post_connect;
560 peer->Activate = pf_server_activate;
561 peer->Logon = pf_server_logon;
562 peer->AdjustMonitorsLayout = pf_server_adjust_monitor_layout;
565 pdata->server_receive_channel_data_original = peer->ReceiveChannelData;
566 peer->ReceiveChannelData = pf_server_receive_channel_data_hook;
568 if (!stream_dump_register_handlers(peer->context, CONNECTION_STATE_NEGO, TRUE))
578 static DWORD WINAPI pf_server_handle_peer(LPVOID arg)
580 HANDLE eventHandles[MAXIMUM_WAIT_OBJECTS] = { 0 };
581 pServerContext* ps = NULL;
582 proxyData* pdata = NULL;
583 peer_thread_args* args = arg;
587 freerdp_peer* client = args->client;
588 WINPR_ASSERT(client);
590 proxyServer* server = (proxyServer*)client->ContextExtra;
591 WINPR_ASSERT(server);
593 size_t count = ArrayList_Count(server->peer_list);
595 if (!pf_context_init_server_context(client))
598 if (!pf_server_initialize_peer_connection(client))
601 ps = (pServerContext*)client->context;
603 PROXY_LOG_DBG(TAG, ps,
"Added peer, %" PRIuz
" connected", count);
608 if (!pf_modules_run_hook(pdata->module, HOOK_TYPE_SERVER_SESSION_INITIALIZE, pdata, client))
611 WINPR_ASSERT(client->Initialize);
612 client->Initialize(client);
614 PROXY_LOG_INFO(TAG, ps,
"new connection: proxy address: %s, client address: %s",
615 pdata->config->Host, client->hostname);
617 if (!pf_modules_run_hook(pdata->module, HOOK_TYPE_SERVER_SESSION_STARTED, pdata, client))
622 HANDLE ChannelEvent = INVALID_HANDLE_VALUE;
623 DWORD eventCount = 0;
625 WINPR_ASSERT(client->GetEventHandles);
626 const DWORD tmp = client->GetEventHandles(client, &eventHandles[eventCount],
627 ARRAYSIZE(eventHandles) - eventCount);
631 PROXY_LOG_ERR(TAG, ps,
"Failed to get FreeRDP transport event handles");
638 ChannelEvent = WTSVirtualChannelManagerGetEventHandle(ps->vcm);
640 WINPR_ASSERT(ChannelEvent && (ChannelEvent != INVALID_HANDLE_VALUE));
641 WINPR_ASSERT(pdata->abort_event && (pdata->abort_event != INVALID_HANDLE_VALUE));
642 eventHandles[eventCount++] = ChannelEvent;
643 eventHandles[eventCount++] = pdata->abort_event;
644 eventHandles[eventCount++] = server->stopEvent;
646 const DWORD status = WaitForMultipleObjects(
647 eventCount, eventHandles, FALSE, 1000);
649 if (status == WAIT_FAILED)
651 PROXY_LOG_ERR(TAG, ps,
"WaitForMultipleObjects failed (status: %" PRIu32
")", status);
655 WINPR_ASSERT(client->CheckFileDescriptor);
656 if (client->CheckFileDescriptor(client) != TRUE)
659 if (WaitForSingleObject(ChannelEvent, 0) == WAIT_OBJECT_0)
661 if (!WTSVirtualChannelManagerCheckFileDescriptor(ps->vcm))
663 PROXY_LOG_ERR(TAG, ps,
"WTSVirtualChannelManagerCheckFileDescriptor failure");
669 if (proxy_data_shall_disconnect(pdata))
671 PROXY_LOG_INFO(TAG, ps,
"abort event is set, closing connection with peer %s",
676 if (WaitForSingleObject(server->stopEvent, 0) == WAIT_OBJECT_0)
678 PROXY_LOG_INFO(TAG, ps,
"Server shutting down, terminating peer");
682 switch (WTSVirtualChannelManagerGetDrdynvcState(ps->vcm))
685 case DRDYNVC_STATE_NONE:
688 if (!WTSVirtualChannelManagerCheckFileDescriptor(ps->vcm))
690 PROXY_LOG_ERR(TAG, ps,
"Failed to initialize drdynvc channel");
696 case DRDYNVC_STATE_READY:
697 if (WaitForSingleObject(ps->dynvcReady, 0) == WAIT_TIMEOUT)
699 (void)SetEvent(ps->dynvcReady);
711 PROXY_LOG_INFO(TAG, ps,
"starting shutdown of connection");
712 PROXY_LOG_INFO(TAG, ps,
"stopping proxy's client");
715 proxy_data_abort_connect(pdata);
717 pf_modules_run_hook(pdata->module, HOOK_TYPE_SERVER_SESSION_END, pdata, client);
719 PROXY_LOG_INFO(TAG, ps,
"freeing server's channels");
721 WINPR_ASSERT(client->Close);
722 client->Close(client);
724 WINPR_ASSERT(client->Disconnect);
725 client->Disconnect(client);
728 PROXY_LOG_INFO(TAG, ps,
"freeing proxy data");
730 if (pdata && pdata->client_thread)
732 proxy_data_abort_connect(pdata);
733 (void)WaitForSingleObject(pdata->client_thread, INFINITE);
737 ArrayList_Lock(server->peer_list);
738 ArrayList_Remove(server->peer_list, args->thread);
739 count = ArrayList_Count(server->peer_list);
740 ArrayList_Unlock(server->peer_list);
742 PROXY_LOG_DBG(TAG, ps,
"Removed peer, %" PRIuz
" connected", count);
743 freerdp_peer_context_free(client);
744 freerdp_peer_free(client);
745 proxy_data_free(pdata);
747 #if defined(WITH_DEBUG_EVENTS)
755 static BOOL pf_server_start_peer(freerdp_peer* client)
757 HANDLE hThread = NULL;
758 proxyServer* server = NULL;
759 peer_thread_args* args = calloc(1,
sizeof(peer_thread_args));
763 WINPR_ASSERT(client);
764 args->client = client;
766 server = (proxyServer*)client->ContextExtra;
767 WINPR_ASSERT(server);
769 hThread = CreateThread(NULL, 0, pf_server_handle_peer, args, CREATE_SUSPENDED, NULL);
773 args->thread = hThread;
774 if (!ArrayList_Append(server->peer_list, hThread))
776 (void)CloseHandle(hThread);
780 return ResumeThread(hThread) != (DWORD)-1;
783 static BOOL pf_server_peer_accepted(freerdp_listener* listener, freerdp_peer* client)
785 WINPR_ASSERT(listener);
786 WINPR_ASSERT(client);
788 client->ContextExtra = listener->info;
790 return pf_server_start_peer(client);
793 BOOL pf_server_start(proxyServer* server)
797 WINPR_ASSERT(server);
799 WTSRegisterWtsApiFunctionTable(FreeRDP_InitWtsApi());
800 winpr_InitializeSSL(WINPR_SSL_INIT_DEFAULT);
802 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
805 WINPR_ASSERT(server->config);
806 WINPR_ASSERT(server->listener);
807 WINPR_ASSERT(server->listener->Open);
808 if (!server->listener->Open(server->listener, server->config->Host, server->config->Port))
813 WLog_ERR(TAG,
"failed to start listener: address already in use!");
816 WLog_ERR(TAG,
"failed to start listener: insufficent permissions!");
819 WLog_ERR(TAG,
"failed to start listener: errno=%d", errno);
833 BOOL pf_server_start_from_socket(proxyServer* server,
int socket)
837 WINPR_ASSERT(server);
839 WTSRegisterWtsApiFunctionTable(FreeRDP_InitWtsApi());
840 winpr_InitializeSSL(WINPR_SSL_INIT_DEFAULT);
842 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
845 WINPR_ASSERT(server->listener);
846 WINPR_ASSERT(server->listener->OpenFromSocket);
847 if (!server->listener->OpenFromSocket(server->listener, socket))
852 WLog_ERR(TAG,
"failed to start listener: address already in use!");
855 WLog_ERR(TAG,
"failed to start listener: insufficent permissions!");
858 WLog_ERR(TAG,
"failed to start listener: errno=%d", errno);
872 BOOL pf_server_start_with_peer_socket(proxyServer* server,
int peer_fd)
874 struct sockaddr_storage peer_addr;
875 socklen_t len =
sizeof(peer_addr);
876 freerdp_peer* client = NULL;
878 WINPR_ASSERT(server);
880 if (WaitForSingleObject(server->stopEvent, 0) == WAIT_OBJECT_0)
883 client = freerdp_peer_new(peer_fd);
887 if (getpeername(peer_fd, (
struct sockaddr*)&peer_addr, &len) != 0)
890 if (!freerdp_peer_set_local_and_hostname(client, &peer_addr))
893 client->ContextExtra = server;
895 if (!pf_server_start_peer(client))
901 WLog_ERR(TAG,
"PeerAccepted callback failed");
902 freerdp_peer_free(client);
906 static BOOL are_all_required_modules_loaded(proxyModule* module,
const proxyConfig* config)
912 if (!pf_modules_is_plugin_loaded(module, plugin_name))
914 WLog_ERR(TAG,
"Required plugin '%s' is not loaded. stopping.", plugin_name);
922 static void peer_free(
void* obj)
924 HANDLE hdl = (HANDLE)obj;
925 (void)CloseHandle(hdl);
928 proxyServer* pf_server_new(
const proxyConfig* config)
931 proxyServer* server = NULL;
933 WINPR_ASSERT(config);
935 server = calloc(1,
sizeof(proxyServer));
942 server->module = pf_modules_new(FREERDP_PROXY_PLUGINDIR,
pf_config_modules(server->config),
946 WLog_ERR(TAG,
"failed to initialize proxy modules!");
950 pf_modules_list_loaded_plugins(server->module);
951 if (!are_all_required_modules_loaded(server->module, server->config))
954 server->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
955 if (!server->stopEvent)
958 server->listener = freerdp_listener_new();
959 if (!server->listener)
962 server->peer_list = ArrayList_New(FALSE);
963 if (!server->peer_list)
966 obj = ArrayList_Object(server->peer_list);
969 obj->fnObjectFree = peer_free;
971 server->listener->info = server;
972 server->listener->PeerAccepted = pf_server_peer_accepted;
974 if (!pf_modules_add(server->module,
pf_config_plugin, (
void*)server->config))
980 WINPR_PRAGMA_DIAG_PUSH
981 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
982 pf_server_free(server);
983 WINPR_PRAGMA_DIAG_POP
987 BOOL pf_server_run(proxyServer* server)
990 HANDLE eventHandles[MAXIMUM_WAIT_OBJECTS] = { 0 };
991 DWORD eventCount = 0;
993 freerdp_listener* listener = NULL;
995 WINPR_ASSERT(server);
997 listener = server->listener;
998 WINPR_ASSERT(listener);
1002 WINPR_ASSERT(listener->GetEventHandles);
1003 eventCount = listener->GetEventHandles(listener, eventHandles, ARRAYSIZE(eventHandles));
1005 if ((0 == eventCount) || (eventCount >= ARRAYSIZE(eventHandles)))
1007 WLog_ERR(TAG,
"Failed to get FreeRDP event handles");
1011 WINPR_ASSERT(server->stopEvent);
1012 eventHandles[eventCount++] = server->stopEvent;
1013 status = WaitForMultipleObjects(eventCount, eventHandles, FALSE, 1000);
1015 if (WAIT_FAILED == status)
1018 if (WaitForSingleObject(server->stopEvent, 0) == WAIT_OBJECT_0)
1021 if (WAIT_FAILED == status)
1023 WLog_ERR(TAG,
"select failed");
1028 WINPR_ASSERT(listener->CheckFileDescriptor);
1029 if (listener->CheckFileDescriptor(listener) != TRUE)
1031 WLog_ERR(TAG,
"Failed to accept new peer");
1037 WINPR_ASSERT(listener->Close);
1038 listener->Close(listener);
1042 void pf_server_stop(proxyServer* server)
1049 (void)SetEvent(server->stopEvent);
1052 void pf_server_free(proxyServer* server)
1057 pf_server_stop(server);
1059 if (server->peer_list)
1061 while (ArrayList_Count(server->peer_list) > 0)
1073 ArrayList_Free(server->peer_list);
1074 freerdp_listener_free(server->listener);
1076 if (server->stopEvent)
1077 (void)CloseHandle(server->stopEvent);
1080 pf_modules_free(server->module);
1083 #if defined(WITH_DEBUG_EVENTS)
1088 BOOL pf_server_add_module(proxyServer* server, proxyModuleEntryPoint ep,
void* userdata)
1090 WINPR_ASSERT(server);
1093 return pf_modules_add(server->module, ep, userdata);
FREERDP_API void pf_server_config_free(proxyConfig *config)
pf_server_config_free Releases all resources associated with proxyConfig
FREERDP_API const char ** pf_config_modules(const proxyConfig *config)
pf_config_modules
FREERDP_API BOOL pf_config_clone(proxyConfig **dst, const proxyConfig *config)
pf_config_clone Create a copy of the configuration
FREERDP_API size_t pf_config_required_plugins_count(const proxyConfig *config)
pf_config_required_plugins_count
FREERDP_API BOOL pf_config_plugin(proxyPluginsManager *plugins_manager, void *userdata)
pf_config_plugin Register a proxy plugin handling event filtering defined in the configuration.
FREERDP_API const char * pf_config_required_plugin(const proxyConfig *config, size_t index)
pf_config_required_plugin
FREERDP_API size_t pf_config_modules_count(const proxyConfig *config)
pf_config_modules_count
FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
FREERDP_API BOOL freerdp_settings_set_string(rdpSettings *settings, FreeRDP_Settings_Keys_String id, const char *param)
Sets a string settings value. The param is copied.
FREERDP_API const char * freerdp_settings_get_string(const rdpSettings *settings, FreeRDP_Settings_Keys_String id)
Returns a immutable string settings value.
FREERDP_API BOOL freerdp_settings_set_pointer_len(rdpSettings *settings, FreeRDP_Settings_Keys_Pointer id, const void *data, size_t len)
Set a pointer to value data.
FREERDP_API BOOL freerdp_settings_set_string_len(rdpSettings *settings, FreeRDP_Settings_Keys_String id, const char *param, size_t len)
Sets a string settings value. The param is copied.
FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 param)
Sets a UINT32 settings value.
FREERDP_API BOOL freerdp_settings_set_bool(rdpSettings *settings, FreeRDP_Settings_Keys_Bool id, BOOL param)
Sets a BOOL settings value.
FREERDP_API void * freerdp_settings_get_pointer_writable(rdpSettings *settings, FreeRDP_Settings_Keys_Pointer id)
Returns a mutable pointer settings value.
This struct contains function pointer to initialize/free objects.