24#include <freerdp/config.h>
29#include <winpr/crypto.h>
30#include <winpr/assert.h>
31#include <winpr/cast.h>
33#include <freerdp/log.h>
34#include <freerdp/utils/string.h>
35#include <freerdp/crypto/certificate.h>
41#include "../crypto/certificate.h"
45 HIGH_COLOR_4BPP = 0x04,
46 HIGH_COLOR_8BPP = 0x08,
47 HIGH_COLOR_15BPP = 0x0F,
48 HIGH_COLOR_16BPP = 0x10,
49 HIGH_COLOR_24BPP = 0x18,
52static const char* HighColorToString(HIGH_COLOR_DEPTH color)
57 return "HIGH_COLOR_4BPP";
59 return "HIGH_COLOR_8BPP";
60 case HIGH_COLOR_15BPP:
61 return "HIGH_COLOR_15BPP";
62 case HIGH_COLOR_16BPP:
63 return "HIGH_COLOR_16BPP";
64 case HIGH_COLOR_24BPP:
65 return "HIGH_COLOR_24BPP";
67 return "HIGH_COLOR_UNKNOWN";
71static HIGH_COLOR_DEPTH ColorDepthToHighColor(UINT32 bpp)
76 return HIGH_COLOR_4BPP;
78 return HIGH_COLOR_8BPP;
80 return HIGH_COLOR_15BPP;
82 return HIGH_COLOR_16BPP;
84 return HIGH_COLOR_24BPP;
88static char* gcc_block_type_string(UINT16 type,
char* buffer,
size_t size);
89static BOOL gcc_read_client_cluster_data(
wStream* s, rdpMcs* mcs);
90static BOOL gcc_read_client_core_data(
wStream* s, rdpMcs* mcs);
91static BOOL gcc_read_client_data_blocks(
wStream* s, rdpMcs* mcs, UINT16 length);
92static BOOL gcc_read_server_data_blocks(
wStream* s, rdpMcs* mcs, UINT16 length);
93static BOOL gcc_read_user_data_header(wLog* log,
wStream* s, UINT16* type, UINT16* length);
94static BOOL gcc_write_user_data_header(
wStream* s, UINT16 type, UINT16 length);
96static BOOL gcc_write_client_core_data(
wStream* s,
const rdpMcs* mcs);
97static BOOL gcc_read_server_core_data(
wStream* s, rdpMcs* mcs);
98static BOOL gcc_write_server_core_data(
wStream* s, rdpMcs* mcs);
99static BOOL gcc_read_client_security_data(
wStream* s, rdpMcs* mcs);
100static BOOL gcc_write_client_security_data(
wStream* s,
const rdpMcs* mcs);
101static BOOL gcc_read_server_security_data(
wStream* s, rdpMcs* mcs);
102static BOOL gcc_write_server_security_data(
wStream* s, rdpMcs* mcs);
103static BOOL gcc_read_client_network_data(
wStream* s, rdpMcs* mcs);
104static BOOL gcc_write_client_network_data(
wStream* s,
const rdpMcs* mcs);
105static BOOL gcc_read_server_network_data(
wStream* s, rdpMcs* mcs);
106static BOOL gcc_write_server_network_data(
wStream* s,
const rdpMcs* mcs);
107static BOOL gcc_write_client_cluster_data(
wStream* s,
const rdpMcs* mcs);
108static BOOL gcc_read_client_monitor_data(
wStream* s, rdpMcs* mcs);
109static BOOL gcc_write_client_monitor_data(
wStream* s,
const rdpMcs* mcs);
110static BOOL gcc_read_client_monitor_extended_data(
wStream* s, rdpMcs* mcs);
111static BOOL gcc_write_client_monitor_extended_data(
wStream* s,
const rdpMcs* mcs);
112static BOOL gcc_read_client_message_channel_data(
wStream* s, rdpMcs* mcs);
113static BOOL gcc_write_client_message_channel_data(
wStream* s,
const rdpMcs* mcs);
114static BOOL gcc_read_server_message_channel_data(
wStream* s, rdpMcs* mcs);
115static BOOL gcc_write_server_message_channel_data(
wStream* s,
const rdpMcs* mcs);
116static BOOL gcc_read_client_multitransport_channel_data(
wStream* s, rdpMcs* mcs);
117static BOOL gcc_write_client_multitransport_channel_data(
wStream* s,
const rdpMcs* mcs);
118static BOOL gcc_read_server_multitransport_channel_data(
wStream* s, rdpMcs* mcs);
119static BOOL gcc_write_server_multitransport_channel_data(
wStream* s,
const rdpMcs* mcs);
121static rdpSettings* mcs_get_settings(rdpMcs* mcs)
125 rdpContext* context = transport_get_context(mcs->transport);
126 WINPR_ASSERT(context);
128 return context->settings;
131static const rdpSettings* mcs_get_const_settings(
const rdpMcs* mcs)
135 const rdpContext* context = transport_get_context(mcs->transport);
136 WINPR_ASSERT(context);
138 return context->settings;
141static char* rdp_early_server_caps_string(UINT32 flags,
char* buffer,
size_t size)
143 char msg[32] = { 0 };
144 const UINT32 mask = RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V1 | RNS_UD_SC_DYNAMIC_DST_SUPPORTED |
145 RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V2 | RNS_UD_SC_SKIP_CHANNELJOIN_SUPPORTED;
146 const UINT32 unknown = flags & (~mask);
148 if (flags & RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V1)
149 winpr_str_append(
"RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V1", buffer, size,
"|");
150 if (flags & RNS_UD_SC_DYNAMIC_DST_SUPPORTED)
151 winpr_str_append(
"RNS_UD_SC_DYNAMIC_DST_SUPPORTED", buffer, size,
"|");
152 if (flags & RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V2)
153 winpr_str_append(
"RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V2", buffer, size,
"|");
154 if (flags & RNS_UD_SC_SKIP_CHANNELJOIN_SUPPORTED)
155 winpr_str_append(
"RNS_UD_SC_SKIP_CHANNELJOIN_SUPPORTED", buffer, size,
"|");
159 (void)_snprintf(msg,
sizeof(msg),
"RNS_UD_SC_UNKNOWN[0x%08" PRIx32
"]", unknown);
160 winpr_str_append(msg, buffer, size,
"|");
162 (void)_snprintf(msg,
sizeof(msg),
"[0x%08" PRIx32
"]", flags);
163 winpr_str_append(msg, buffer, size,
"|");
167static const char* rdp_early_client_caps_string(UINT32 flags,
char* buffer,
size_t size)
169 char msg[32] = { 0 };
170 const UINT32 mask = RNS_UD_CS_SUPPORT_ERRINFO_PDU | RNS_UD_CS_WANT_32BPP_SESSION |
171 RNS_UD_CS_SUPPORT_STATUSINFO_PDU | RNS_UD_CS_STRONG_ASYMMETRIC_KEYS |
172 RNS_UD_CS_RELATIVE_MOUSE_INPUT | RNS_UD_CS_VALID_CONNECTION_TYPE |
173 RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU |
174 RNS_UD_CS_SUPPORT_NETCHAR_AUTODETECT |
175 RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL | RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE |
176 RNS_UD_CS_SUPPORT_HEARTBEAT_PDU | RNS_UD_CS_SUPPORT_SKIP_CHANNELJOIN;
177 const UINT32 unknown = flags & (~mask);
179 if (flags & RNS_UD_CS_SUPPORT_ERRINFO_PDU)
180 winpr_str_append(
"RNS_UD_CS_SUPPORT_ERRINFO_PDU", buffer, size,
"|");
181 if (flags & RNS_UD_CS_WANT_32BPP_SESSION)
182 winpr_str_append(
"RNS_UD_CS_WANT_32BPP_SESSION", buffer, size,
"|");
183 if (flags & RNS_UD_CS_SUPPORT_STATUSINFO_PDU)
184 winpr_str_append(
"RNS_UD_CS_SUPPORT_STATUSINFO_PDU", buffer, size,
"|");
185 if (flags & RNS_UD_CS_STRONG_ASYMMETRIC_KEYS)
186 winpr_str_append(
"RNS_UD_CS_STRONG_ASYMMETRIC_KEYS", buffer, size,
"|");
187 if (flags & RNS_UD_CS_RELATIVE_MOUSE_INPUT)
188 winpr_str_append(
"RNS_UD_CS_RELATIVE_MOUSE_INPUT", buffer, size,
"|");
189 if (flags & RNS_UD_CS_VALID_CONNECTION_TYPE)
190 winpr_str_append(
"RNS_UD_CS_VALID_CONNECTION_TYPE", buffer, size,
"|");
191 if (flags & RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU)
192 winpr_str_append(
"RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU", buffer, size,
"|");
193 if (flags & RNS_UD_CS_SUPPORT_NETCHAR_AUTODETECT)
194 winpr_str_append(
"RNS_UD_CS_SUPPORT_NETCHAR_AUTODETECT", buffer, size,
"|");
195 if (flags & RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL)
196 winpr_str_append(
"RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL", buffer, size,
"|");
197 if (flags & RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE)
198 winpr_str_append(
"RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE", buffer, size,
"|");
199 if (flags & RNS_UD_CS_SUPPORT_HEARTBEAT_PDU)
200 winpr_str_append(
"RNS_UD_CS_SUPPORT_HEARTBEAT_PDU", buffer, size,
"|");
201 if (flags & RNS_UD_CS_SUPPORT_SKIP_CHANNELJOIN)
202 winpr_str_append(
"RNS_UD_CS_SUPPORT_SKIP_CHANNELJOIN", buffer, size,
"|");
206 (void)_snprintf(msg,
sizeof(msg),
"RNS_UD_CS_UNKNOWN[0x%08" PRIx32
"]", unknown);
207 winpr_str_append(msg, buffer, size,
"|");
209 (void)_snprintf(msg,
sizeof(msg),
"[0x%08" PRIx32
"]", flags);
210 winpr_str_append(msg, buffer, size,
"|");
214static DWORD rdp_version_common(wLog* log, DWORD serverVersion, DWORD clientVersion)
216 DWORD version = MIN(serverVersion, clientVersion);
221 case RDP_VERSION_5_PLUS:
222 case RDP_VERSION_10_0:
223 case RDP_VERSION_10_1:
224 case RDP_VERSION_10_2:
225 case RDP_VERSION_10_3:
226 case RDP_VERSION_10_4:
227 case RDP_VERSION_10_5:
228 case RDP_VERSION_10_6:
229 case RDP_VERSION_10_7:
230 case RDP_VERSION_10_8:
231 case RDP_VERSION_10_9:
232 case RDP_VERSION_10_10:
233 case RDP_VERSION_10_11:
234 case RDP_VERSION_10_12:
238 WLog_Print(log, WLOG_ERROR,
239 "Invalid client [%" PRId32
"] and server [%" PRId32
"] versions",
240 serverVersion, clientVersion);
344static const BYTE t124_02_98_oid[6] = { 0, 0, 20, 124, 0, 1 };
346static const BYTE h221_cs_key[4] =
"Duca";
347static const BYTE h221_sc_key[4] =
"McDn";
359BOOL gcc_read_conference_create_request(
wStream* s, rdpMcs* mcs)
369 if (!per_read_choice(s, &choice))
372 if (!per_read_object_identifier(s, t124_02_98_oid))
376 if (!per_read_length(s, &length))
380 if (!per_read_choice(s, &choice))
383 if (!per_read_selection(s, &selection))
387 if (!per_read_numeric_string(s, 1))
390 if (!per_read_padding(s, 1))
394 if (!per_read_number_of_sets(s, &number) || number != 1)
397 if (!per_read_choice(s, &choice) ||
402 if (!per_read_octet_string(s, h221_cs_key, 4,
407 if (!per_read_length(s, &length))
410 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, length))
413 if (!gcc_read_client_data_blocks(s, mcs, length))
429BOOL gcc_write_conference_create_request(
wStream* s,
wStream* userData)
432 WINPR_ASSERT(userData);
434 if (!per_write_choice(s, 0))
436 if (!per_write_object_identifier(s, t124_02_98_oid))
439 const size_t pos = Stream_GetPosition(userData);
440 WINPR_ASSERT(pos <= UINT16_MAX - 14);
441 if (!per_write_length(s, (UINT16)pos + 14))
444 if (!per_write_choice(s, 0))
447 if (!per_write_selection(s, 0x08))
450 if (!per_write_numeric_string(s, (BYTE*)
"1", 1, 1))
452 if (!per_write_padding(s, 1))
455 if (!per_write_number_of_sets(s, 1))
457 if (!per_write_choice(s, 0xC0))
460 if (!per_write_octet_string(s, h221_cs_key, 4,
464 const size_t upos = Stream_GetPosition(userData);
465 WINPR_ASSERT(upos <= UINT16_MAX);
466 return per_write_octet_string(s, Stream_Buffer(userData), (UINT16)upos,
470BOOL gcc_read_conference_create_response(
wStream* s, rdpMcs* mcs)
481 if (!per_read_choice(s, &choice) || !per_read_object_identifier(s, t124_02_98_oid))
485 if (!per_read_length(s, &length))
489 if (!per_read_choice(s, &choice))
493 if (!per_read_integer16(s, &nodeID, 1001))
497 if (!per_read_integer(s, &tag))
501 if (!per_read_enumerated(s, &result, MCS_Result_enum_length))
505 if (!per_read_number_of_sets(s, &number))
509 if (!per_read_choice(s, &choice))
513 if (!per_read_octet_string(s, h221_sc_key, 4,
518 if (!per_read_length(s, &length))
521 if (!gcc_read_server_data_blocks(s, mcs, length))
523 WLog_Print(mcs->log, WLOG_ERROR,
524 "gcc_read_conference_create_response: gcc_read_server_data_blocks failed");
531BOOL gcc_write_conference_create_response(
wStream* s,
wStream* userData)
534 WINPR_ASSERT(userData);
536 if (!per_write_choice(s, 0))
538 if (!per_write_object_identifier(s, t124_02_98_oid))
542 if (!per_write_length(s, 0x2A))
545 if (!per_write_choice(s, 0x14))
548 if (!per_write_integer16(s, 0x79F3, 1001))
551 if (!per_write_integer(s, 1))
554 if (!per_write_enumerated(s, 0, MCS_Result_enum_length))
557 if (!per_write_number_of_sets(s, 1))
560 if (!per_write_choice(s, 0xC0))
563 if (!per_write_octet_string(s, h221_sc_key, 4,
567 const size_t pos = Stream_GetPosition(userData);
568 WINPR_ASSERT(pos <= UINT16_MAX);
569 return per_write_octet_string(s, Stream_Buffer(userData), (UINT16)pos,
573static BOOL gcc_read_client_unused1_data(
wStream* s)
575 return Stream_SafeSeek(s, 2);
578BOOL gcc_read_client_data_blocks(
wStream* s, rdpMcs* mcs, UINT16 length)
583 BOOL gotMultitransport = FALSE;
589 UINT16 blockLength = 0;
591 if (!gcc_read_user_data_header(mcs->log, s, &type, &blockLength))
594 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, (
size_t)(blockLength - 4)))
597 wStream* sub = Stream_StaticConstInit(&sbuffer, Stream_Pointer(s), blockLength - 4);
600 Stream_Seek(s, blockLength - 4);
603 char buffer[64] = { 0 };
604 WLog_Print(mcs->log, WLOG_TRACE,
"Processing block %s",
605 gcc_block_type_string(type, buffer,
sizeof(buffer)));
610 if (!gcc_read_client_core_data(sub, mcs))
616 if (!gcc_read_client_security_data(sub, mcs))
622 if (!gcc_read_client_network_data(sub, mcs))
628 if (!gcc_read_client_cluster_data(sub, mcs))
634 if (!gcc_read_client_monitor_data(sub, mcs))
639 case CS_MCS_MSGCHANNEL:
640 if (!gcc_read_client_message_channel_data(sub, mcs))
646 if (!gcc_read_client_monitor_extended_data(sub, mcs))
652 if (!gcc_read_client_unused1_data(sub))
658 case CS_MULTITRANSPORT:
659 gotMultitransport = TRUE;
660 if (!gcc_read_client_multitransport_channel_data(sub, mcs))
666 WLog_Print(mcs->log, WLOG_ERROR,
"Unknown GCC client data block: 0x%04" PRIX16
"",
668 winpr_HexLogDump(mcs->log, WLOG_TRACE, Stream_Pointer(sub),
669 Stream_GetRemainingLength(sub));
673 const size_t rem = Stream_GetRemainingLength(sub);
676 char buffer[128] = { 0 };
677 const size_t total = Stream_Length(sub);
678 WLog_Print(mcs->log, WLOG_ERROR,
679 "Error parsing GCC client data block %s: Actual Offset: %" PRIuz
680 " Expected Offset: %" PRIuz,
681 gcc_block_type_string(type, buffer,
sizeof(buffer)), total - rem, total);
684 if (blockLength > length)
686 char buffer[128] = { 0 };
687 WLog_Print(mcs->log, WLOG_ERROR,
688 "Error parsing GCC client data block %s: got blockLength 0x%04" PRIx16
689 ", but only 0x%04" PRIx16
"remaining",
690 gcc_block_type_string(type, buffer,
sizeof(buffer)), blockLength, length);
694 length -= blockLength;
697 if (!gotMultitransport)
699 rdpSettings* settings = mcs_get_settings(mcs);
708BOOL gcc_write_client_data_blocks(
wStream* s,
const rdpMcs* mcs)
710 const rdpSettings* settings = mcs_get_const_settings(mcs);
713 WINPR_ASSERT(settings);
715 if (!gcc_write_client_core_data(s, mcs) || !gcc_write_client_cluster_data(s, mcs) ||
716 !gcc_write_client_security_data(s, mcs) || !gcc_write_client_network_data(s, mcs))
721 if (settings->NegotiationFlags & EXTENDED_CLIENT_DATA_SUPPORTED)
723 if (settings->UseMultimon && !settings->SpanMonitors)
725 if (!gcc_write_client_monitor_data(s, mcs) ||
726 !gcc_write_client_monitor_extended_data(s, mcs))
730 if (!gcc_write_client_message_channel_data(s, mcs) ||
731 !gcc_write_client_multitransport_channel_data(s, mcs))
736 if (settings->UseMultimon && !settings->SpanMonitors)
738 WLog_Print(mcs->log, WLOG_ERROR,
739 "WARNING: true multi monitor support was not advertised by server!");
741 if (settings->ForceMultimon)
743 WLog_Print(mcs->log, WLOG_ERROR,
744 "Sending multi monitor information anyway (may break connectivity!)");
745 if (!gcc_write_client_monitor_data(s, mcs) ||
746 !gcc_write_client_monitor_extended_data(s, mcs))
751 WLog_Print(mcs->log, WLOG_ERROR,
752 "Use /multimon:force to force sending multi monitor information");
759char* gcc_block_type_string(UINT16 type,
char* buffer,
size_t size)
764 (void)_snprintf(buffer, size,
"CS_CORE [0x%04" PRIx16
"]", type);
767 (void)_snprintf(buffer, size,
"CS_SECURITY [0x%04" PRIx16
"]", type);
770 (void)_snprintf(buffer, size,
"CS_NET [0x%04" PRIx16
"]", type);
773 (void)_snprintf(buffer, size,
"CS_CLUSTER [0x%04" PRIx16
"]", type);
776 (void)_snprintf(buffer, size,
"CS_MONITOR [0x%04" PRIx16
"]", type);
778 case CS_MCS_MSGCHANNEL:
779 (void)_snprintf(buffer, size,
"CS_MONITOR [0x%04" PRIx16
"]", type);
782 (void)_snprintf(buffer, size,
"CS_MONITOR_EX [0x%04" PRIx16
"]", type);
785 (void)_snprintf(buffer, size,
"CS_UNUSED1 [0x%04" PRIx16
"]", type);
787 case CS_MULTITRANSPORT:
788 (void)_snprintf(buffer, size,
"CS_MONITOR_EX [0x%04" PRIx16
"]", type);
791 (void)_snprintf(buffer, size,
"SC_CORE [0x%04" PRIx16
"]", type);
794 (void)_snprintf(buffer, size,
"SC_SECURITY [0x%04" PRIx16
"]", type);
797 (void)_snprintf(buffer, size,
"SC_NET [0x%04" PRIx16
"]", type);
799 case SC_MCS_MSGCHANNEL:
800 (void)_snprintf(buffer, size,
"SC_MCS_MSGCHANNEL [0x%04" PRIx16
"]", type);
802 case SC_MULTITRANSPORT:
803 (void)_snprintf(buffer, size,
"SC_MULTITRANSPORT [0x%04" PRIx16
"]", type);
806 (void)_snprintf(buffer, size,
"UNKNOWN [0x%04" PRIx16
"]", type);
812BOOL gcc_read_server_data_blocks(
wStream* s, rdpMcs* mcs, UINT16 length)
816 UINT16 blockLength = 0;
822 while (offset < length)
824 char buffer[64] = { 0 };
829 if (!gcc_read_user_data_header(mcs->log, s, &type, &blockLength))
831 WLog_Print(mcs->log, WLOG_ERROR,
832 "gcc_read_server_data_blocks: gcc_read_user_data_header failed");
835 holdp = Stream_Pointer(s);
836 sub = Stream_StaticInit(&subbuffer, holdp, blockLength - 4);
837 if (!Stream_SafeSeek(s, blockLength - 4))
839 WLog_Print(mcs->log, WLOG_ERROR,
"gcc_read_server_data_blocks: stream too short");
842 offset += blockLength;
847 if (!gcc_read_server_core_data(sub, mcs))
849 WLog_Print(mcs->log, WLOG_ERROR,
850 "gcc_read_server_data_blocks: gcc_read_server_core_data failed");
857 if (!gcc_read_server_security_data(sub, mcs))
862 if (!gcc_read_server_network_data(sub, mcs))
864 WLog_Print(mcs->log, WLOG_ERROR,
865 "gcc_read_server_data_blocks: gcc_read_server_network_data failed");
871 case SC_MCS_MSGCHANNEL:
872 if (!gcc_read_server_message_channel_data(sub, mcs))
875 mcs->log, WLOG_ERROR,
876 "gcc_read_server_data_blocks: gcc_read_server_message_channel_data failed");
882 case SC_MULTITRANSPORT:
883 if (!gcc_read_server_multitransport_channel_data(sub, mcs))
885 WLog_Print(mcs->log, WLOG_ERROR,
886 "gcc_read_server_data_blocks: "
887 "gcc_read_server_multitransport_channel_data failed");
894 WLog_Print(mcs->log, WLOG_ERROR,
"gcc_read_server_data_blocks: ignoring type=%s",
895 gcc_block_type_string(type, buffer,
sizeof(buffer)));
896 winpr_HexLogDump(mcs->log, WLOG_TRACE, Stream_Pointer(sub),
897 Stream_GetRemainingLength(sub));
901 rest = Stream_GetRemainingLength(sub);
904 WLog_Print(mcs->log, WLOG_WARN,
905 "gcc_read_server_data_blocks: ignoring %" PRIuz
" bytes with type=%s", rest,
906 gcc_block_type_string(type, buffer,
sizeof(buffer)));
913BOOL gcc_write_server_data_blocks(
wStream* s, rdpMcs* mcs)
918 if (!gcc_write_server_core_data(s, mcs) ||
919 !gcc_write_server_network_data(s, mcs) ||
920 !gcc_write_server_security_data(s, mcs) ||
921 !gcc_write_server_message_channel_data(s, mcs))
924 const rdpSettings* settings = mcs_get_const_settings(mcs);
925 WINPR_ASSERT(settings);
927 if (settings->SupportMultitransport && (settings->MultitransportFlags != 0))
929 return gcc_write_server_multitransport_channel_data(s, mcs);
934BOOL gcc_read_user_data_header(wLog* log,
wStream* s, UINT16* type, UINT16* length)
937 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
940 Stream_Read_UINT16(s, *type);
941 Stream_Read_UINT16(s, *length);
943 if ((*length < 4) || (!Stream_CheckAndLogRequiredLengthWLog(log, s, (
size_t)(*length - 4))))
960BOOL gcc_write_user_data_header(
wStream* s, UINT16 type, UINT16 length)
964 if (!Stream_EnsureRemainingCapacity(s, 4 + length))
966 Stream_Write_UINT16(s, type);
967 Stream_Write_UINT16(s, length);
971static UINT32 filterAndLogEarlyServerCapabilityFlags(wLog* log, UINT32 flags)
974 (RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V1 | RNS_UD_SC_DYNAMIC_DST_SUPPORTED |
975 RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V2 | RNS_UD_SC_SKIP_CHANNELJOIN_SUPPORTED);
976 const UINT32 filtered = flags & mask;
977 const UINT32 unknown = flags & (~mask);
980 char buffer[256] = { 0 };
981 WLog_Print(log, WLOG_WARN,
982 "TS_UD_SC_CORE::EarlyCapabilityFlags [0x%08" PRIx32
" & 0x%08" PRIx32
983 " --> 0x%08" PRIx32
"] filtering %s, feature not implemented",
984 flags, ~mask, unknown,
985 rdp_early_server_caps_string(unknown, buffer,
sizeof(buffer)));
990static UINT32 earlyServerCapsFromSettings(wLog* log,
const rdpSettings* settings)
992 UINT32 EarlyCapabilityFlags = 0;
994 if (settings->SupportEdgeActionV1)
995 EarlyCapabilityFlags |= RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V1;
996 if (settings->SupportDynamicTimeZone)
997 EarlyCapabilityFlags |= RNS_UD_SC_DYNAMIC_DST_SUPPORTED;
998 if (settings->SupportEdgeActionV2)
999 EarlyCapabilityFlags |= RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V2;
1000 if (settings->SupportSkipChannelJoin)
1001 EarlyCapabilityFlags |= RNS_UD_SC_SKIP_CHANNELJOIN_SUPPORTED;
1003 return filterAndLogEarlyServerCapabilityFlags(log, EarlyCapabilityFlags);
1006static UINT16 filterAndLogEarlyClientCapabilityFlags(wLog* log, UINT32 flags)
1009 (RNS_UD_CS_SUPPORT_ERRINFO_PDU | RNS_UD_CS_WANT_32BPP_SESSION |
1010 RNS_UD_CS_SUPPORT_STATUSINFO_PDU | RNS_UD_CS_STRONG_ASYMMETRIC_KEYS |
1011 RNS_UD_CS_RELATIVE_MOUSE_INPUT | RNS_UD_CS_VALID_CONNECTION_TYPE |
1012 RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU | RNS_UD_CS_SUPPORT_NETCHAR_AUTODETECT |
1013 RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL | RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE |
1014 RNS_UD_CS_SUPPORT_HEARTBEAT_PDU | RNS_UD_CS_SUPPORT_SKIP_CHANNELJOIN);
1015 const UINT32 filtered = flags & mask;
1016 const UINT32 unknown = flags & ~mask;
1019 char buffer[256] = { 0 };
1020 WLog_Print(log, WLOG_WARN,
1021 "(TS_UD_CS_CORE)::EarlyCapabilityFlags [0x%08" PRIx32
" & 0x%08" PRIx32
1022 " --> 0x%08" PRIx32
"] filtering %s, feature not implemented",
1023 flags, ~mask, unknown,
1024 rdp_early_client_caps_string(unknown, buffer,
sizeof(buffer)));
1027 WINPR_ASSERT(filtered <= UINT16_MAX);
1028 return (UINT16)filtered;
1031static UINT16 earlyClientCapsFromSettings(wLog* log,
const rdpSettings* settings)
1033 UINT32 earlyCapabilityFlags = 0;
1035 WINPR_ASSERT(settings);
1036 if (settings->SupportErrorInfoPdu)
1037 earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_ERRINFO_PDU;
1040 earlyCapabilityFlags |= RNS_UD_CS_WANT_32BPP_SESSION;
1042 if (settings->SupportStatusInfoPdu)
1043 earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_STATUSINFO_PDU;
1045 if (settings->ConnectionType)
1046 earlyCapabilityFlags |= RNS_UD_CS_VALID_CONNECTION_TYPE;
1048 if (settings->SupportMonitorLayoutPdu)
1049 earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU;
1052 earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_NETCHAR_AUTODETECT;
1054 if (settings->SupportGraphicsPipeline)
1055 earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL;
1057 if (settings->SupportDynamicTimeZone)
1058 earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE;
1060 if (settings->SupportHeartbeatPdu)
1061 earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_HEARTBEAT_PDU;
1063 if (settings->SupportAsymetricKeys)
1064 earlyCapabilityFlags |= RNS_UD_CS_STRONG_ASYMMETRIC_KEYS;
1066 if (settings->HasRelativeMouseEvent)
1067 earlyCapabilityFlags |= RNS_UD_CS_RELATIVE_MOUSE_INPUT;
1069 if (settings->SupportSkipChannelJoin)
1070 earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_SKIP_CHANNELJOIN;
1072 return filterAndLogEarlyClientCapabilityFlags(log, earlyCapabilityFlags);
1075static BOOL updateEarlyClientCaps(wLog* log, rdpSettings* settings, UINT32 earlyCapabilityFlags,
1076 UINT32 connectionType)
1078 WINPR_ASSERT(settings);
1080 if (settings->SupportErrorInfoPdu)
1081 settings->SupportErrorInfoPdu =
1082 (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_ERRINFO_PDU) ? TRUE : FALSE;
1090 if (settings->SupportStatusInfoPdu)
1091 settings->SupportStatusInfoPdu =
1092 (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_STATUSINFO_PDU) ? TRUE : FALSE;
1094 if (settings->SupportAsymetricKeys)
1095 settings->SupportAsymetricKeys =
1096 (earlyCapabilityFlags & RNS_UD_CS_STRONG_ASYMMETRIC_KEYS) ? TRUE : FALSE;
1098 if (settings->HasRelativeMouseEvent)
1102 if (settings->RdpVersion >= RDP_VERSION_10_12)
1104 settings->HasRelativeMouseEvent =
1105 (earlyCapabilityFlags & RNS_UD_CS_RELATIVE_MOUSE_INPUT) ? TRUE : FALSE;
1108 settings->HasRelativeMouseEvent = FALSE;
1111 if (settings->NetworkAutoDetect)
1112 settings->NetworkAutoDetect =
1113 (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_NETCHAR_AUTODETECT) ? TRUE : FALSE;
1115 if (settings->SupportSkipChannelJoin)
1116 settings->SupportSkipChannelJoin =
1117 (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_SKIP_CHANNELJOIN) ? TRUE : FALSE;
1119 if (settings->SupportMonitorLayoutPdu)
1120 settings->SupportMonitorLayoutPdu =
1121 (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU) ? TRUE : FALSE;
1123 if (settings->SupportHeartbeatPdu)
1124 settings->SupportHeartbeatPdu =
1125 (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_HEARTBEAT_PDU) ? TRUE : FALSE;
1127 if (settings->SupportGraphicsPipeline)
1128 settings->SupportGraphicsPipeline =
1129 (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL) ? TRUE : FALSE;
1131 if (settings->SupportDynamicTimeZone)
1132 settings->SupportDynamicTimeZone =
1133 (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE) ? TRUE : FALSE;
1135 if ((earlyCapabilityFlags & RNS_UD_CS_VALID_CONNECTION_TYPE) == 0)
1137 settings->ConnectionType = connectionType;
1139 filterAndLogEarlyClientCapabilityFlags(log, earlyCapabilityFlags);
1143static BOOL updateEarlyServerCaps(wLog* log, rdpSettings* settings, UINT32 earlyCapabilityFlags,
1144 WINPR_ATTR_UNUSED UINT32 connectionType)
1146 WINPR_ASSERT(settings);
1148 settings->SupportEdgeActionV1 =
1149 settings->SupportEdgeActionV1 &&
1150 (earlyCapabilityFlags & RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V1)
1153 settings->SupportDynamicTimeZone =
1154 settings->SupportDynamicTimeZone && (earlyCapabilityFlags & RNS_UD_SC_DYNAMIC_DST_SUPPORTED)
1157 settings->SupportEdgeActionV2 =
1158 settings->SupportEdgeActionV2 &&
1159 (earlyCapabilityFlags & RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V2)
1162 settings->SupportSkipChannelJoin =
1163 settings->SupportSkipChannelJoin &&
1164 (earlyCapabilityFlags & RNS_UD_SC_SKIP_CHANNELJOIN_SUPPORTED)
1168 filterAndLogEarlyServerCapabilityFlags(log, earlyCapabilityFlags);
1181BOOL gcc_read_client_core_data(
wStream* s, rdpMcs* mcs)
1183 char buffer[2048] = { 0 };
1184 char strbuffer[130] = { 0 };
1186 BYTE connectionType = 0;
1187 UINT32 clientColorDepth = 0;
1188 UINT16 colorDepth = 0;
1189 UINT16 postBeta2ColorDepth = 0;
1190 UINT16 highColorDepth = 0;
1191 UINT32 serverSelectedProtocol = 0;
1192 rdpSettings* settings = mcs_get_settings(mcs);
1195 WINPR_ASSERT(settings);
1198 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 128))
1201 Stream_Read_UINT32(s, version);
1202 settings->RdpVersion = rdp_version_common(mcs->log, version, settings->RdpVersion);
1203 Stream_Read_UINT16(s, settings->DesktopWidth);
1204 Stream_Read_UINT16(s, settings->DesktopHeight);
1205 Stream_Read_UINT16(s, colorDepth);
1206 Stream_Seek_UINT16(s);
1207 Stream_Read_UINT32(s, settings->KeyboardLayout);
1208 Stream_Read_UINT32(s, settings->ClientBuild);
1211 if (Stream_Read_UTF16_String_As_UTF8_Buffer(s, 32 /
sizeof(WCHAR), strbuffer,
1212 ARRAYSIZE(strbuffer)) < 0)
1214 WLog_Print(mcs->log, WLOG_ERROR,
"failed to convert client host name");
1221 Stream_Read_UINT32(s, settings->KeyboardType);
1222 Stream_Read_UINT32(s, settings->KeyboardSubType);
1223 Stream_Read_UINT32(s, settings->KeyboardFunctionKey);
1235 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 2))
1238 Stream_Read_UINT16(s, postBeta2ColorDepth);
1240 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 2))
1243 const UINT16 clientProductId = Stream_Get_UINT16(s);
1248 if (clientProductId != 1)
1250 WLog_Print(mcs->log, WLOG_WARN,
1251 "[MS-RDPBCGR] 2.2.1.3.2 Client Core Data (TS_UD_CS_CORE)::clientProductId "
1252 "(optional) expected 1, got %" PRIu32,
1256 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 4))
1259 const UINT32 serialNumber = Stream_Get_UINT32(s);
1264 if (serialNumber != 0)
1266 WLog_Print(mcs->log, WLOG_WARN,
1267 "[MS-RDPBCGR] 2.2.1.3.2 Client Core Data (TS_UD_CS_CORE)::serialNumber "
1268 "(optional) expected 0, got %" PRIu32,
1272 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 2))
1275 Stream_Read_UINT16(s, highColorDepth);
1277 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 2))
1280 Stream_Read_UINT16(s, settings->SupportedColorDepths);
1282 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 2))
1285 Stream_Read_UINT16(s, settings->EarlyCapabilityFlags);
1288 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 64))
1291 if (Stream_Read_UTF16_String_As_UTF8_Buffer(s, 64 /
sizeof(WCHAR), strbuffer,
1292 ARRAYSIZE(strbuffer)) < 0)
1294 WLog_Print(mcs->log, WLOG_ERROR,
"failed to convert the client product identifier");
1301 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 1))
1304 Stream_Read_UINT8(s, connectionType);
1306 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 1))
1309 Stream_Seek_UINT8(s);
1311 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 4))
1314 Stream_Read_UINT32(s, serverSelectedProtocol);
1316 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 4))
1319 Stream_Read_UINT32(s, settings->DesktopPhysicalWidth);
1321 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 4))
1324 Stream_Read_UINT32(s,
1325 settings->DesktopPhysicalHeight);
1327 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 2))
1330 Stream_Read_UINT16(s, settings->DesktopOrientation);
1332 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 4))
1335 Stream_Read_UINT32(s, settings->DesktopScaleFactor);
1337 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 4))
1340 Stream_Read_UINT32(s, settings->DeviceScaleFactor);
1343 settings->SelectedProtocol = serverSelectedProtocol;
1344 else if (settings->SelectedProtocol != serverSelectedProtocol)
1348 if (highColorDepth > 0)
1350 if (settings->EarlyCapabilityFlags & RNS_UD_CS_WANT_32BPP_SESSION)
1351 clientColorDepth = 32;
1353 clientColorDepth = highColorDepth;
1355 else if (postBeta2ColorDepth > 0)
1357 switch (postBeta2ColorDepth)
1359 case RNS_UD_COLOR_4BPP:
1360 clientColorDepth = 4;
1363 case RNS_UD_COLOR_8BPP:
1364 clientColorDepth = 8;
1367 case RNS_UD_COLOR_16BPP_555:
1368 clientColorDepth = 15;
1371 case RNS_UD_COLOR_16BPP_565:
1372 clientColorDepth = 16;
1375 case RNS_UD_COLOR_24BPP:
1376 clientColorDepth = 24;
1387 case RNS_UD_COLOR_4BPP:
1388 clientColorDepth = 4;
1391 case RNS_UD_COLOR_8BPP:
1392 clientColorDepth = 8;
1405 !settings->ServerMode)
1412 mcs->log, WLOG_DEBUG,
"Received EarlyCapabilityFlags=%s",
1413 rdp_early_client_caps_string(settings->EarlyCapabilityFlags, buffer,
sizeof(buffer)));
1415 return updateEarlyClientCaps(mcs->log, settings, settings->EarlyCapabilityFlags,
1428BOOL gcc_write_client_core_data(
wStream* s,
const rdpMcs* mcs)
1430 char buffer[2048] = { 0 };
1431 char dbuffer[2048] = { 0 };
1432 BYTE connectionType = 0;
1433 HIGH_COLOR_DEPTH highColorDepth = HIGH_COLOR_4BPP;
1435 UINT16 earlyCapabilityFlags = 0;
1436 const rdpSettings* settings = mcs_get_const_settings(mcs);
1439 WINPR_ASSERT(settings);
1441 const UINT16 SupportedColorDepths =
1445 if (!gcc_write_user_data_header(s, CS_CORE, 234))
1448 Stream_Write_UINT32(s, settings->RdpVersion);
1449 Stream_Write_UINT16(
1450 s, WINPR_ASSERTING_INT_CAST(uint16_t, settings->DesktopWidth));
1451 Stream_Write_UINT16(
1452 s, WINPR_ASSERTING_INT_CAST(uint16_t, settings->DesktopHeight));
1453 Stream_Write_UINT16(s,
1455 Stream_Write_UINT16(s, RNS_UD_SAS_DEL);
1456 Stream_Write_UINT32(s, settings->KeyboardLayout);
1457 Stream_Write_UINT32(s, settings->ClientBuild);
1459 if (!Stream_EnsureRemainingCapacity(s, 32 + 12 + 64 + 8))
1463 size_t clientNameLength = 0;
1464 WCHAR* clientName = ConvertUtf8ToWCharAlloc(settings->ClientHostname, &clientNameLength);
1465 if (clientNameLength >= 16)
1467 clientNameLength = 16;
1468 clientName[clientNameLength - 1] = 0;
1471 Stream_Write(s, clientName, (clientNameLength * 2));
1472 Stream_Zero(s, 32 - (clientNameLength * 2));
1474 Stream_Write_UINT32(s, settings->KeyboardType);
1475 Stream_Write_UINT32(s, settings->KeyboardSubType);
1476 Stream_Write_UINT32(s, settings->KeyboardFunctionKey);
1478 Stream_Write_UINT16(s, RNS_UD_COLOR_8BPP);
1479 Stream_Write_UINT16(s, 1);
1480 Stream_Write_UINT32(s, 0);
1481 highColorDepth = ColorDepthToHighColor(ColorDepth);
1482 earlyCapabilityFlags = earlyClientCapsFromSettings(mcs->log, settings);
1484 WINPR_ASSERT(settings->ConnectionType <= UINT8_MAX);
1485 connectionType = (UINT8)settings->ConnectionType;
1487 if (!Stream_EnsureRemainingCapacity(s, 6))
1491 mcs->log, WLOG_DEBUG,
1492 "Sending highColorDepth=%s, supportedColorDepths=%s, earlyCapabilityFlags=%s",
1493 HighColorToString(highColorDepth),
1495 rdp_early_client_caps_string(earlyCapabilityFlags, buffer,
sizeof(buffer)));
1496 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, highColorDepth));
1497 Stream_Write_UINT16(s, SupportedColorDepths);
1498 Stream_Write_UINT16(s, earlyCapabilityFlags);
1500 if (!Stream_EnsureRemainingCapacity(s, 64 + 24))
1507 if (Stream_Write_UTF16_String_From_UTF8(s, 32, str, strnlen(str, 32), TRUE) < 0)
1511 Stream_Zero(s, 32 *
sizeof(WCHAR));
1513 Stream_Write_UINT8(s, connectionType);
1514 Stream_Write_UINT8(s, 0);
1515 Stream_Write_UINT32(s, settings->SelectedProtocol);
1516 Stream_Write_UINT32(s, settings->DesktopPhysicalWidth);
1517 Stream_Write_UINT32(s, settings->DesktopPhysicalHeight);
1518 Stream_Write_UINT16(s, settings->DesktopOrientation);
1519 Stream_Write_UINT32(s, settings->DesktopScaleFactor);
1520 Stream_Write_UINT32(s, settings->DeviceScaleFactor);
1524BOOL gcc_read_server_core_data(
wStream* s, rdpMcs* mcs)
1526 UINT32 serverVersion = 0;
1527 rdpSettings* settings = mcs_get_settings(mcs);
1530 WINPR_ASSERT(settings);
1532 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 4))
1535 Stream_Read_UINT32(s, serverVersion);
1536 settings->RdpVersion = rdp_version_common(mcs->log, serverVersion, settings->RdpVersion);
1538 if (Stream_GetRemainingLength(s) >= 4)
1540 Stream_Read_UINT32(s, settings->RequestedProtocols);
1543 if (Stream_GetRemainingLength(s) >= 4)
1545 char buffer[2048] = { 0 };
1547 Stream_Read_UINT32(s, settings->EarlyCapabilityFlags);
1549 mcs->log, WLOG_DEBUG,
"Received EarlyCapabilityFlags=%s",
1550 rdp_early_client_caps_string(settings->EarlyCapabilityFlags, buffer,
sizeof(buffer)));
1553 return updateEarlyServerCaps(mcs->log, settings, settings->EarlyCapabilityFlags,
1554 settings->ConnectionType);
1560BOOL gcc_write_server_core_data(
wStream* s, rdpMcs* mcs)
1562 const rdpSettings* settings = mcs_get_const_settings(mcs);
1565 WINPR_ASSERT(settings);
1567 if (!gcc_write_user_data_header(s, SC_CORE, 16))
1570 const UINT32 EarlyCapabilityFlags = earlyServerCapsFromSettings(mcs->log, settings);
1571 Stream_Write_UINT32(s, settings->RdpVersion);
1572 Stream_Write_UINT32(s, settings->RequestedProtocols);
1573 Stream_Write_UINT32(s, EarlyCapabilityFlags);
1586BOOL gcc_read_client_security_data(
wStream* s, rdpMcs* mcs)
1588 rdpSettings* settings = mcs_get_settings(mcs);
1591 WINPR_ASSERT(settings);
1593 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 8))
1596 if (settings->UseRdpSecurityLayer)
1598 Stream_Read_UINT32(s, settings->EncryptionMethods);
1600 if (settings->EncryptionMethods == ENCRYPTION_METHOD_NONE)
1601 Stream_Read_UINT32(s, settings->EncryptionMethods);
1622BOOL gcc_write_client_security_data(
wStream* s,
const rdpMcs* mcs)
1624 const rdpSettings* settings = mcs_get_const_settings(mcs);
1627 WINPR_ASSERT(settings);
1629 if (!gcc_write_user_data_header(s, CS_SECURITY, 12))
1632 if (settings->UseRdpSecurityLayer)
1634 Stream_Write_UINT32(s, settings->EncryptionMethods);
1635 Stream_Write_UINT32(s, 0);
1640 Stream_Write_UINT32(s, 0);
1641 Stream_Write_UINT32(s, settings->EncryptionMethods);
1646BOOL gcc_read_server_security_data(
wStream* s, rdpMcs* mcs)
1648 BOOL validCryptoConfig = FALSE;
1649 UINT32 EncryptionMethod = 0;
1650 UINT32 EncryptionLevel = 0;
1651 rdpSettings* settings = mcs_get_settings(mcs);
1654 WINPR_ASSERT(settings);
1656 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 8))
1659 Stream_Read_UINT32(s, EncryptionMethod);
1660 Stream_Read_UINT32(s, EncryptionLevel);
1663 switch (EncryptionMethod)
1665 case ENCRYPTION_METHOD_NONE:
1666 WLog_Print(mcs->log, WLOG_DEBUG,
"Server rdp encryption method: NONE");
1669 case ENCRYPTION_METHOD_40BIT:
1670 WLog_Print(mcs->log, WLOG_DEBUG,
"Server rdp encryption method: 40BIT");
1673 case ENCRYPTION_METHOD_56BIT:
1674 WLog_Print(mcs->log, WLOG_DEBUG,
"Server rdp encryption method: 56BIT");
1677 case ENCRYPTION_METHOD_128BIT:
1678 WLog_Print(mcs->log, WLOG_DEBUG,
"Server rdp encryption method: 128BIT");
1681 case ENCRYPTION_METHOD_FIPS:
1682 WLog_Print(mcs->log, WLOG_DEBUG,
"Server rdp encryption method: FIPS");
1686 WLog_Print(mcs->log, WLOG_ERROR,
"Received unknown encryption method %08" PRIX32
"",
1691 if (settings->UseRdpSecurityLayer && !(settings->EncryptionMethods & EncryptionMethod))
1693 WLog_Print(mcs->log, WLOG_WARN,
1694 "Server uses non-advertised encryption method 0x%08" PRIX32
"",
1699 settings->EncryptionMethods = EncryptionMethod;
1700 settings->EncryptionLevel = EncryptionLevel;
1702 switch (settings->EncryptionLevel)
1704 case ENCRYPTION_LEVEL_NONE:
1705 if (settings->EncryptionMethods == ENCRYPTION_METHOD_NONE)
1707 validCryptoConfig = TRUE;
1712 case ENCRYPTION_LEVEL_FIPS:
1713 if (settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS)
1715 validCryptoConfig = TRUE;
1720 case ENCRYPTION_LEVEL_LOW:
1721 case ENCRYPTION_LEVEL_HIGH:
1722 case ENCRYPTION_LEVEL_CLIENT_COMPATIBLE:
1723 if (settings->EncryptionMethods == ENCRYPTION_METHOD_40BIT ||
1724 settings->EncryptionMethods == ENCRYPTION_METHOD_56BIT ||
1725 settings->EncryptionMethods == ENCRYPTION_METHOD_128BIT ||
1726 settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS)
1728 validCryptoConfig = TRUE;
1734 WLog_Print(mcs->log, WLOG_ERROR,
"Received unknown encryption level 0x%08" PRIX32
"",
1735 settings->EncryptionLevel);
1738 if (!validCryptoConfig)
1740 WLog_Print(mcs->log, WLOG_ERROR,
1741 "Received invalid cryptographic configuration (level=0x%08" PRIX32
1742 " method=0x%08" PRIX32
")",
1743 settings->EncryptionLevel, settings->EncryptionMethods);
1747 if (settings->EncryptionLevel == ENCRYPTION_LEVEL_NONE)
1750 settings->UseRdpSecurityLayer = FALSE;
1754 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 8))
1757 Stream_Read_UINT32(s, settings->ServerRandomLength);
1758 Stream_Read_UINT32(s, settings->ServerCertificateLength);
1760 if ((settings->ServerRandomLength == 0) || (settings->ServerCertificateLength == 0))
1762 WLog_Print(mcs->log, WLOG_ERROR,
1763 "Invalid ServerRandom (length=%" PRIu32
") or ServerCertificate (length=%" PRIu32
1765 settings->ServerRandomLength, settings->ServerCertificateLength);
1769 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, settings->ServerRandomLength))
1774 settings->ServerRandomLength))
1777 Stream_Read(s, settings->ServerRandom, settings->ServerRandomLength);
1779 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, settings->ServerCertificateLength))
1784 settings->ServerCertificateLength))
1787 Stream_Read(s, settings->ServerCertificate, settings->ServerCertificateLength);
1789 const BYTE* data = settings->ServerCertificate;
1790 const uint32_t length = settings->ServerCertificateLength;
1792 if (!freerdp_certificate_read_server_cert(settings->RdpServerCertificate, data, length))
1802static BOOL gcc_update_server_random(rdpSettings* settings)
1804 const size_t length = 32;
1805 WINPR_ASSERT(settings);
1811 winpr_RAND(data, length);
1818BOOL gcc_write_server_security_data(
wStream* s, rdpMcs* mcs)
1820 if (!gcc_update_server_random(mcs_get_settings(mcs)))
1823 const rdpSettings* settings = mcs_get_const_settings(mcs);
1826 WINPR_ASSERT(settings);
1828 const size_t posHeader = Stream_GetPosition(s);
1829 if (!gcc_write_user_data_header(s, SC_SECURITY, 12))
1832 Stream_Write_UINT32(s, settings->EncryptionMethods);
1833 Stream_Write_UINT32(s, settings->EncryptionLevel);
1835 if (settings->EncryptionMethods == ENCRYPTION_METHOD_NONE)
1838 if (!Stream_EnsureRemainingCapacity(s,
sizeof(UINT32) + settings->ServerRandomLength))
1840 Stream_Write_UINT32(s, settings->ServerRandomLength);
1841 const size_t posCertLen = Stream_GetPosition(s);
1842 Stream_Seek_UINT32(s);
1843 Stream_Write(s, settings->ServerRandom, settings->ServerRandomLength);
1845 const SSIZE_T len = freerdp_certificate_write_server_cert(
1846 settings->RdpServerCertificate, CERT_TEMPORARILY_ISSUED | CERT_CHAIN_VERSION_1, s);
1849 const size_t end = Stream_GetPosition(s);
1851 WINPR_ASSERT(end >= posHeader);
1852 const size_t diff = end - posHeader;
1853 WINPR_ASSERT(diff <= UINT16_MAX);
1854 Stream_SetPosition(s, posHeader);
1855 if (!gcc_write_user_data_header(s, SC_SECURITY, (UINT16)diff))
1857 Stream_SetPosition(s, posCertLen);
1858 WINPR_ASSERT(len <= UINT32_MAX);
1859 Stream_Write_UINT32(s, (UINT32)len);
1860 Stream_SetPosition(s, end);
1874BOOL gcc_read_client_network_data(
wStream* s, rdpMcs* mcs)
1879 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 4))
1882 Stream_Read_UINT32(s, mcs->channelCount);
1884 if (!Stream_CheckAndLogRequiredLengthOfSizeWLog(mcs->log, s, mcs->channelCount, 12ull))
1887 if (mcs->channelCount > CHANNEL_MAX_COUNT)
1889 WLog_Print(mcs->log, WLOG_ERROR,
"rdpMcs::channelCount %" PRIu32
" > maximum %" PRIu32,
1890 mcs->channelCount, CHANNEL_MAX_COUNT);
1895 for (UINT32 i = 0; i < mcs->channelCount; i++)
1903 rdpMcsChannel* channel = &mcs->channels[i];
1904 Stream_Read(s, channel->Name, CHANNEL_NAME_LEN + 1);
1906 if (!memchr(channel->Name, 0, CHANNEL_NAME_LEN + 1))
1909 mcs->log, WLOG_ERROR,
1910 "protocol violation: received a static channel name with missing null-termination");
1914 Stream_Read_UINT32(s, channel->options);
1915 channel->ChannelId = mcs->baseChannelId++;
1930BOOL gcc_write_client_network_data(
wStream* s,
const rdpMcs* mcs)
1934 if (mcs->channelCount > 0)
1936 const size_t length = mcs->channelCount * 12 + 8;
1937 WINPR_ASSERT(length <= UINT16_MAX);
1938 if (!gcc_write_user_data_header(s, CS_NET, (UINT16)length))
1940 Stream_Write_UINT32(s, mcs->channelCount);
1943 for (UINT32 i = 0; i < mcs->channelCount; i++)
1946 rdpMcsChannel* channel = &mcs->channels[i];
1947 Stream_Write(s, channel->Name, CHANNEL_NAME_LEN + 1);
1948 Stream_Write_UINT32(s, channel->options);
1954BOOL gcc_read_server_network_data(
wStream* s, rdpMcs* mcs)
1956 UINT16 channelId = 0;
1957 UINT32 parsedChannelCount = 0;
1960 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 4))
1963 mcs->IOChannelId = Stream_Get_UINT16(s);
1964 const uint16_t channelCount = Stream_Get_UINT16(s);
1965 parsedChannelCount = channelCount;
1967 if (channelCount != mcs->channelCount)
1969 WLog_Print(mcs->log, WLOG_ERROR,
"requested %" PRIu32
" channels, got %" PRIu16
" instead",
1970 mcs->channelCount, channelCount);
1974 mcs->channelCount = channelCount;
1977 if (!Stream_CheckAndLogRequiredLengthOfSizeWLog(mcs->log, s, channelCount, 2ull))
1980 if (mcs->channelMaxCount < parsedChannelCount)
1982 WLog_Print(mcs->log, WLOG_ERROR,
1983 "requested %" PRIu32
" channels > channelMaxCount %" PRIu16, mcs->channelCount,
1984 mcs->channelMaxCount);
1988 for (UINT32 i = 0; i < parsedChannelCount; i++)
1990 rdpMcsChannel* channel = &mcs->channels[i];
1991 Stream_Read_UINT16(s, channelId);
1992 channel->ChannelId = channelId;
1995 if (channelCount % 2 == 1)
1996 return Stream_SafeSeek(s, 2);
2001BOOL gcc_write_server_network_data(
wStream* s,
const rdpMcs* mcs)
2005 const size_t payloadLen = 8 + mcs->channelCount * 2 + (mcs->channelCount % 2 == 1 ? 2 : 0);
2007 WINPR_ASSERT(payloadLen <= UINT16_MAX);
2008 if (!gcc_write_user_data_header(s, SC_NET, (UINT16)payloadLen))
2011 Stream_Write_UINT16(s, MCS_GLOBAL_CHANNEL_ID);
2012 Stream_Write_UINT16(s,
2013 WINPR_ASSERTING_INT_CAST(uint16_t, mcs->channelCount));
2015 for (UINT32 i = 0; i < mcs->channelCount; i++)
2017 const rdpMcsChannel* channel = &mcs->channels[i];
2018 Stream_Write_UINT16(s, channel->ChannelId);
2021 if (mcs->channelCount % 2 == 1)
2022 Stream_Write_UINT16(s, 0);
2036BOOL gcc_read_client_cluster_data(
wStream* s, rdpMcs* mcs)
2038 char buffer[128] = { 0 };
2039 UINT32 redirectedSessionId = 0;
2040 rdpSettings* settings = mcs_get_settings(mcs);
2043 WINPR_ASSERT(settings);
2045 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 8))
2048 Stream_Read_UINT32(s, settings->ClusterInfoFlags);
2049 Stream_Read_UINT32(s, redirectedSessionId);
2051 WLog_Print(mcs->log, WLOG_TRACE,
"read ClusterInfoFlags=%s, RedirectedSessionId=0x%08" PRIx32,
2052 rdp_cluster_info_flags_to_string(settings->ClusterInfoFlags, buffer,
sizeof(buffer)),
2053 redirectedSessionId);
2054 if (settings->ClusterInfoFlags & REDIRECTED_SESSIONID_FIELD_VALID)
2055 settings->RedirectedSessionId = redirectedSessionId;
2057 settings->ConsoleSession =
2058 (settings->ClusterInfoFlags & REDIRECTED_SESSIONID_FIELD_VALID) ? TRUE : FALSE;
2059 settings->RedirectSmartCards =
2060 (settings->ClusterInfoFlags & REDIRECTED_SMARTCARD) ? TRUE : FALSE;
2062 if (Stream_GetRemainingLength(s) > 0)
2065 Stream_Seek(s, Stream_GetRemainingLength(s));
2080BOOL gcc_write_client_cluster_data(
wStream* s,
const rdpMcs* mcs)
2082 char buffer[128] = { 0 };
2084 const rdpSettings* settings = mcs_get_const_settings(mcs);
2087 WINPR_ASSERT(settings);
2089 if (!gcc_write_user_data_header(s, CS_CLUSTER, 12))
2091 flags = settings->ClusterInfoFlags;
2093 if (settings->ConsoleSession || settings->RedirectedSessionId)
2094 flags |= REDIRECTED_SESSIONID_FIELD_VALID;
2096 if (settings->RedirectSmartCards && settings->SmartcardLogon)
2097 flags |= REDIRECTED_SMARTCARD;
2099 if (flags & REDIRECTION_SUPPORTED)
2104 flags |= (REDIRECTION_VERSION6 << 2);
2106 flags |= (REDIRECTION_VERSION5 << 2);
2109 WLog_Print(mcs->log, WLOG_TRACE,
"write ClusterInfoFlags=%s, RedirectedSessionId=0x%08" PRIx32,
2110 rdp_cluster_info_flags_to_string(flags, buffer,
sizeof(buffer)),
2111 settings->RedirectedSessionId);
2112 Stream_Write_UINT32(s, flags);
2113 Stream_Write_UINT32(s, settings->RedirectedSessionId);
2126BOOL gcc_read_client_monitor_data(
wStream* s, rdpMcs* mcs)
2128 UINT32 monitorCount = 0;
2129 rdpSettings* settings = mcs_get_settings(mcs);
2132 WINPR_ASSERT(settings);
2134 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 8))
2137 Stream_Read_UINT32(s, settings->MonitorFlags);
2138 Stream_Read_UINT32(s, monitorCount);
2144 if (monitorCount > 16)
2146 WLog_Print(mcs->log, WLOG_ERROR,
"announced monitors(%" PRIu32
") exceed the 16 limit",
2151 if (monitorCount > settings->MonitorDefArraySize)
2153 WLog_Print(mcs->log, WLOG_ERROR,
2154 "too many announced monitors(%" PRIu32
"), clamping to %" PRIu32
"",
2155 monitorCount, settings->MonitorDefArraySize);
2156 monitorCount = settings->MonitorDefArraySize;
2159 if (!Stream_CheckAndLogRequiredLengthOfSizeWLog(mcs->log, s, monitorCount, 20))
2162 settings->MonitorCount = monitorCount;
2164 for (UINT32 index = 0; index < monitorCount; index++)
2166 rdpMonitor* current = &settings->MonitorDefArray[index];
2168 const INT32 left = Stream_Get_INT32(s);
2169 const INT32 top = Stream_Get_INT32(s);
2170 const INT32 right = Stream_Get_INT32(s);
2171 const INT32 bottom = Stream_Get_INT32(s);
2172 const UINT32 flags = Stream_Get_UINT32(s);
2174 if ((left > right) || (top > bottom))
2176 WLog_Print(mcs->log, WLOG_ERROR,
"rdpMonitor::rect %dx%d-%dx%d invalid", left, top,
2181 const INT64 w = right - left;
2182 const INT64 h = bottom - top;
2183 if ((w >= INT32_MAX) || (h >= INT32_MAX) || (w < 0) || (h < 0))
2185 WLog_Print(mcs->log, WLOG_ERROR,
2186 "rdpMonitor::width/height %" PRId64
"/%" PRId64
" invalid", w, h);
2192 current->width = WINPR_ASSERTING_INT_CAST(int32_t, w + 1);
2193 current->height = WINPR_ASSERTING_INT_CAST(int32_t, h + 1);
2194 current->is_primary = (flags & MONITOR_PRIMARY) ? TRUE : FALSE;
2209BOOL gcc_write_client_monitor_data(
wStream* s,
const rdpMcs* mcs)
2213 const rdpSettings* settings = mcs_get_const_settings(mcs);
2216 WINPR_ASSERT(settings);
2218 WLog_Print(mcs->log, WLOG_DEBUG,
"MonitorCount=%" PRIu32, settings->MonitorCount);
2219 if (settings->MonitorCount > 1)
2221 const size_t len = (20 * settings->MonitorCount) + 12;
2222 WINPR_ASSERT(len <= UINT16_MAX);
2223 const UINT16 length = (UINT16)len;
2224 if (!gcc_write_user_data_header(s, CS_MONITOR, length))
2226 Stream_Write_UINT32(s, settings->MonitorFlags);
2227 Stream_Write_UINT32(s, settings->MonitorCount);
2231 for (UINT32 i = 0; i < settings->MonitorCount; i++)
2233 const rdpMonitor* current = &settings->MonitorDefArray[i];
2234 if (current->is_primary)
2242 for (UINT32 i = 0; i < settings->MonitorCount; i++)
2244 const rdpMonitor* current = &settings->MonitorDefArray[i];
2245 const INT32 left = current->x - baseX;
2246 const INT32 top = current->y - baseY;
2247 const INT32 right = left + current->width - 1;
2248 const INT32 bottom = top + current->height - 1;
2249 const UINT32 flags = current->is_primary ? MONITOR_PRIMARY : 0;
2250 WLog_Print(mcs->log, WLOG_DEBUG,
2251 "Monitor[%" PRIu32
"]: top=%" PRId32
", left=%" PRId32
", bottom=%" PRId32
2252 ", right=%" PRId32
", flags=%" PRIu32,
2253 i, top, left, bottom, right, flags);
2254 Stream_Write_INT32(s, left);
2255 Stream_Write_INT32(s, top);
2256 Stream_Write_INT32(s, right);
2257 Stream_Write_INT32(s, bottom);
2258 Stream_Write_UINT32(s, flags);
2261 WLog_Print(mcs->log, WLOG_DEBUG,
"FINISHED");
2265BOOL gcc_read_client_monitor_extended_data(
wStream* s, rdpMcs* mcs)
2267 UINT32 monitorCount = 0;
2268 UINT32 monitorAttributeSize = 0;
2269 rdpSettings* settings = mcs_get_settings(mcs);
2272 WINPR_ASSERT(settings);
2274 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 12))
2277 Stream_Read_UINT32(s, settings->MonitorAttributeFlags);
2278 Stream_Read_UINT32(s, monitorAttributeSize);
2279 Stream_Read_UINT32(s, monitorCount);
2281 if (monitorAttributeSize != 20)
2283 WLog_Print(mcs->log, WLOG_ERROR,
2284 "TS_UD_CS_MONITOR_EX::monitorAttributeSize %" PRIu32
" != 20",
2285 monitorAttributeSize);
2289 if (!Stream_CheckAndLogRequiredCapacityOfSizeWLog(mcs->log, s, monitorCount,
2290 monitorAttributeSize))
2293 if (settings->MonitorCount != monitorCount)
2295 WLog_Print(mcs->log, WLOG_ERROR,
2296 "(TS_UD_CS_MONITOR_EX)::monitorCount %" PRIu32
" != expected %" PRIu32,
2297 monitorCount, settings->MonitorCount);
2301 settings->HasMonitorAttributes = TRUE;
2303 for (UINT32 index = 0; index < monitorCount; index++)
2305 rdpMonitor* current = &settings->MonitorDefArray[index];
2306 Stream_Read_UINT32(s, current->attributes.physicalWidth);
2307 Stream_Read_UINT32(s, current->attributes.physicalHeight);
2308 Stream_Read_UINT32(s, current->attributes.orientation);
2309 Stream_Read_UINT32(s, current->attributes.desktopScaleFactor);
2310 Stream_Read_UINT32(s, current->attributes.deviceScaleFactor);
2316BOOL gcc_write_client_monitor_extended_data(
wStream* s,
const rdpMcs* mcs)
2318 const rdpSettings* settings = mcs_get_const_settings(mcs);
2321 WINPR_ASSERT(settings);
2323 if (settings->HasMonitorAttributes)
2325 const size_t length = (20 * settings->MonitorCount) + 16;
2326 WINPR_ASSERT(length <= UINT16_MAX);
2327 if (!gcc_write_user_data_header(s, CS_MONITOR_EX, (UINT16)length))
2329 Stream_Write_UINT32(s, settings->MonitorAttributeFlags);
2330 Stream_Write_UINT32(s, 20);
2331 Stream_Write_UINT32(s, settings->MonitorCount);
2333 for (UINT32 i = 0; i < settings->MonitorCount; i++)
2335 const rdpMonitor* current = &settings->MonitorDefArray[i];
2336 Stream_Write_UINT32(s, current->attributes.physicalWidth);
2337 Stream_Write_UINT32(s, current->attributes.physicalHeight);
2338 Stream_Write_UINT32(s, current->attributes.orientation);
2339 Stream_Write_UINT32(s, current->attributes.desktopScaleFactor);
2340 Stream_Write_UINT32(s, current->attributes.deviceScaleFactor);
2355BOOL gcc_read_client_message_channel_data(
wStream* s, rdpMcs* mcs)
2360 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 4))
2363 Stream_Read_UINT32(s, mcs->flags);
2364 mcs->messageChannelId = mcs->baseChannelId++;
2377BOOL gcc_write_client_message_channel_data(
wStream* s,
const rdpMcs* mcs)
2379 const rdpSettings* settings = mcs_get_const_settings(mcs);
2383 WINPR_ASSERT(settings);
2385 settings->SupportHeartbeatPdu || settings->SupportMultitransport)
2387 if (!gcc_write_user_data_header(s, CS_MCS_MSGCHANNEL, 8))
2389 Stream_Write_UINT32(s, mcs->flags);
2394BOOL gcc_read_server_message_channel_data(
wStream* s, rdpMcs* mcs)
2396 UINT16 MCSChannelId = 0;
2399 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 2))
2402 Stream_Read_UINT16(s, MCSChannelId);
2404 mcs->messageChannelId = MCSChannelId;
2408BOOL gcc_write_server_message_channel_data(
wStream* s,
const rdpMcs* mcs)
2412 if (mcs->messageChannelId == 0)
2415 if (!gcc_write_user_data_header(s, SC_MCS_MSGCHANNEL, 6))
2418 Stream_Write_UINT16(s, mcs->messageChannelId);
2431BOOL gcc_read_client_multitransport_channel_data(
wStream* s, rdpMcs* mcs)
2433 rdpSettings* settings = mcs_get_settings(mcs);
2436 WINPR_ASSERT(settings);
2438 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 4))
2441 UINT32 remoteFlags = 0;
2442 Stream_Read_UINT32(s, remoteFlags);
2443 settings->MultitransportFlags &= remoteFlags;
2457BOOL gcc_write_client_multitransport_channel_data(
wStream* s,
const rdpMcs* mcs)
2459 const rdpSettings* settings = mcs_get_const_settings(mcs);
2462 WINPR_ASSERT(settings);
2463 if (!gcc_write_user_data_header(s, CS_MULTITRANSPORT, 8))
2465 Stream_Write_UINT32(s, settings->MultitransportFlags);
2469BOOL gcc_read_server_multitransport_channel_data(
wStream* s, rdpMcs* mcs)
2471 rdpSettings* settings = mcs_get_settings(mcs);
2472 UINT32 remoteFlags = 0;
2475 WINPR_ASSERT(settings);
2476 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 4))
2479 Stream_Read_UINT32(s, remoteFlags);
2480 settings->MultitransportFlags &= remoteFlags;
2484BOOL gcc_write_server_multitransport_channel_data(
wStream* s,
const rdpMcs* mcs)
2486 const rdpSettings* settings = mcs_get_const_settings(mcs);
2489 WINPR_ASSERT(settings);
2491 if (!gcc_write_user_data_header(s, SC_MULTITRANSPORT, 8))
2494 Stream_Write_UINT32(s, settings->MultitransportFlags);
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 BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.
FREERDP_API const char * freerdp_supported_color_depths_string(UINT16 mask, char *buffer, size_t size)
returns a string representation of RNS_UD_XXBPP_SUPPORT values
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 UINT16 freerdp_settings_get_uint16(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt16 id)
Returns a UINT16 settings value.
FREERDP_API void * freerdp_settings_get_pointer_writable(rdpSettings *settings, FreeRDP_Settings_Keys_Pointer id)
Returns a mutable pointer settings value.
FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 param)
Sets a UINT32 settings value.
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_bool(rdpSettings *settings, FreeRDP_Settings_Keys_Bool id, BOOL param)
Sets a BOOL settings value.