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)
124 WINPR_ASSERT(mcs->context);
126 return mcs->context->settings;
129static const rdpSettings* mcs_get_const_settings(
const rdpMcs* mcs)
132 WINPR_ASSERT(mcs->context);
134 return mcs->context->settings;
137static char* rdp_early_server_caps_string(UINT32 flags,
char* buffer,
size_t size)
139 char msg[32] = WINPR_C_ARRAY_INIT;
140 const UINT32 mask = RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V1 | RNS_UD_SC_DYNAMIC_DST_SUPPORTED |
141 RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V2 | RNS_UD_SC_SKIP_CHANNELJOIN_SUPPORTED;
142 const UINT32 unknown = flags & (~mask);
144 if (flags & RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V1)
145 winpr_str_append(
"RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V1", buffer, size,
"|");
146 if (flags & RNS_UD_SC_DYNAMIC_DST_SUPPORTED)
147 winpr_str_append(
"RNS_UD_SC_DYNAMIC_DST_SUPPORTED", buffer, size,
"|");
148 if (flags & RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V2)
149 winpr_str_append(
"RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V2", buffer, size,
"|");
150 if (flags & RNS_UD_SC_SKIP_CHANNELJOIN_SUPPORTED)
151 winpr_str_append(
"RNS_UD_SC_SKIP_CHANNELJOIN_SUPPORTED", buffer, size,
"|");
155 (void)_snprintf(msg,
sizeof(msg),
"RNS_UD_SC_UNKNOWN[0x%08" PRIx32
"]", unknown);
156 winpr_str_append(msg, buffer, size,
"|");
158 (void)_snprintf(msg,
sizeof(msg),
"[0x%08" PRIx32
"]", flags);
159 winpr_str_append(msg, buffer, size,
"|");
163static const char* rdp_early_client_caps_string(UINT32 flags,
char* buffer,
size_t size)
165 char msg[32] = WINPR_C_ARRAY_INIT;
166 const UINT32 mask = RNS_UD_CS_SUPPORT_ERRINFO_PDU | RNS_UD_CS_WANT_32BPP_SESSION |
167 RNS_UD_CS_SUPPORT_STATUSINFO_PDU | RNS_UD_CS_STRONG_ASYMMETRIC_KEYS |
168 RNS_UD_CS_RELATIVE_MOUSE_INPUT | RNS_UD_CS_VALID_CONNECTION_TYPE |
169 RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU |
170 RNS_UD_CS_SUPPORT_NETCHAR_AUTODETECT |
171 RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL | RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE |
172 RNS_UD_CS_SUPPORT_HEARTBEAT_PDU | RNS_UD_CS_SUPPORT_SKIP_CHANNELJOIN;
173 const UINT32 unknown = flags & (~mask);
175 if (flags & RNS_UD_CS_SUPPORT_ERRINFO_PDU)
176 winpr_str_append(
"RNS_UD_CS_SUPPORT_ERRINFO_PDU", buffer, size,
"|");
177 if (flags & RNS_UD_CS_WANT_32BPP_SESSION)
178 winpr_str_append(
"RNS_UD_CS_WANT_32BPP_SESSION", buffer, size,
"|");
179 if (flags & RNS_UD_CS_SUPPORT_STATUSINFO_PDU)
180 winpr_str_append(
"RNS_UD_CS_SUPPORT_STATUSINFO_PDU", buffer, size,
"|");
181 if (flags & RNS_UD_CS_STRONG_ASYMMETRIC_KEYS)
182 winpr_str_append(
"RNS_UD_CS_STRONG_ASYMMETRIC_KEYS", buffer, size,
"|");
183 if (flags & RNS_UD_CS_RELATIVE_MOUSE_INPUT)
184 winpr_str_append(
"RNS_UD_CS_RELATIVE_MOUSE_INPUT", buffer, size,
"|");
185 if (flags & RNS_UD_CS_VALID_CONNECTION_TYPE)
186 winpr_str_append(
"RNS_UD_CS_VALID_CONNECTION_TYPE", buffer, size,
"|");
187 if (flags & RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU)
188 winpr_str_append(
"RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU", buffer, size,
"|");
189 if (flags & RNS_UD_CS_SUPPORT_NETCHAR_AUTODETECT)
190 winpr_str_append(
"RNS_UD_CS_SUPPORT_NETCHAR_AUTODETECT", buffer, size,
"|");
191 if (flags & RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL)
192 winpr_str_append(
"RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL", buffer, size,
"|");
193 if (flags & RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE)
194 winpr_str_append(
"RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE", buffer, size,
"|");
195 if (flags & RNS_UD_CS_SUPPORT_HEARTBEAT_PDU)
196 winpr_str_append(
"RNS_UD_CS_SUPPORT_HEARTBEAT_PDU", buffer, size,
"|");
197 if (flags & RNS_UD_CS_SUPPORT_SKIP_CHANNELJOIN)
198 winpr_str_append(
"RNS_UD_CS_SUPPORT_SKIP_CHANNELJOIN", buffer, size,
"|");
202 (void)_snprintf(msg,
sizeof(msg),
"RNS_UD_CS_UNKNOWN[0x%08" PRIx32
"]", unknown);
203 winpr_str_append(msg, buffer, size,
"|");
205 (void)_snprintf(msg,
sizeof(msg),
"[0x%08" PRIx32
"]", flags);
206 winpr_str_append(msg, buffer, size,
"|");
210static DWORD rdp_version_common(wLog* log, DWORD serverVersion, DWORD clientVersion)
212 DWORD version = MIN(serverVersion, clientVersion);
217 case RDP_VERSION_5_PLUS:
218 case RDP_VERSION_10_0:
219 case RDP_VERSION_10_1:
220 case RDP_VERSION_10_2:
221 case RDP_VERSION_10_3:
222 case RDP_VERSION_10_4:
223 case RDP_VERSION_10_5:
224 case RDP_VERSION_10_6:
225 case RDP_VERSION_10_7:
226 case RDP_VERSION_10_8:
227 case RDP_VERSION_10_9:
228 case RDP_VERSION_10_10:
229 case RDP_VERSION_10_11:
230 case RDP_VERSION_10_12:
234 WLog_Print(log, WLOG_ERROR,
235 "Invalid client [%" PRIu32
"] and server [%" PRIu32
"] versions",
236 serverVersion, clientVersion);
340static const BYTE t124_02_98_oid[6] = { 0, 0, 20, 124, 0, 1 };
342static const BYTE h221_cs_key[4] = {
'D',
'u',
'c',
'a' };
343static const BYTE h221_sc_key[4] = {
'M',
'c',
'D',
'n' };
355BOOL gcc_read_conference_create_request(
wStream* s, rdpMcs* mcs)
365 if (!per_read_choice(s, &choice))
368 if (!per_read_object_identifier(s, t124_02_98_oid))
372 if (!per_read_length(s, &length))
376 if (!per_read_choice(s, &choice))
379 if (!per_read_selection(s, &selection))
383 if (!per_read_numeric_string(s, 1))
386 if (!per_read_padding(s, 1))
390 if (!per_read_number_of_sets(s, &number) || number != 1)
393 if (!per_read_choice(s, &choice) ||
398 if (!per_read_octet_string(s, h221_cs_key, 4,
403 if (!per_read_length(s, &length))
406 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, length))
409 if (!gcc_read_client_data_blocks(s, mcs, length))
425BOOL gcc_write_conference_create_request(
wStream* s,
wStream* userData)
428 WINPR_ASSERT(userData);
430 if (!per_write_choice(s, 0))
432 if (!per_write_object_identifier(s, t124_02_98_oid))
435 const size_t pos = Stream_GetPosition(userData);
436 WINPR_ASSERT(pos <= UINT16_MAX - 14);
437 if (!per_write_length(s, (UINT16)pos + 14))
440 if (!per_write_choice(s, 0))
443 if (!per_write_selection(s, 0x08))
446 if (!per_write_numeric_string(s, (BYTE*)
"1", 1, 1))
448 if (!per_write_padding(s, 1))
451 if (!per_write_number_of_sets(s, 1))
453 if (!per_write_choice(s, 0xC0))
456 if (!per_write_octet_string(s, h221_cs_key, 4,
460 const size_t upos = Stream_GetPosition(userData);
461 WINPR_ASSERT(upos <= UINT16_MAX);
462 return per_write_octet_string(s, Stream_Buffer(userData), (UINT16)upos,
466BOOL gcc_read_conference_create_response(
wStream* s, rdpMcs* mcs)
477 if (!per_read_choice(s, &choice) || !per_read_object_identifier(s, t124_02_98_oid))
481 if (!per_read_length(s, &length))
485 if (!per_read_choice(s, &choice))
489 if (!per_read_integer16(s, &nodeID, 1001))
493 if (!per_read_integer(s, &tag))
497 if (!per_read_enumerated(s, &result, MCS_Result_enum_length))
501 if (!per_read_number_of_sets(s, &number))
505 if (!per_read_choice(s, &choice))
509 if (!per_read_octet_string(s, h221_sc_key, 4,
514 if (!per_read_length(s, &length))
517 if (!gcc_read_server_data_blocks(s, mcs, length))
519 WLog_Print(mcs->log, WLOG_ERROR,
520 "gcc_read_conference_create_response: gcc_read_server_data_blocks failed");
527BOOL gcc_write_conference_create_response(
wStream* s,
wStream* userData)
530 WINPR_ASSERT(userData);
532 if (!per_write_choice(s, 0))
534 if (!per_write_object_identifier(s, t124_02_98_oid))
538 if (!per_write_length(s, 0x2A))
541 if (!per_write_choice(s, 0x14))
544 if (!per_write_integer16(s, 0x79F3, 1001))
547 if (!per_write_integer(s, 1))
550 if (!per_write_enumerated(s, 0, MCS_Result_enum_length))
553 if (!per_write_number_of_sets(s, 1))
556 if (!per_write_choice(s, 0xC0))
559 if (!per_write_octet_string(s, h221_sc_key, 4,
563 const size_t pos = Stream_GetPosition(userData);
564 WINPR_ASSERT(pos <= UINT16_MAX);
565 return per_write_octet_string(s, Stream_Buffer(userData), (UINT16)pos,
569static BOOL gcc_read_client_unused1_data(
wStream* s)
571 return Stream_SafeSeek(s, 2);
574BOOL gcc_read_client_data_blocks(
wStream* s, rdpMcs* mcs, UINT16 length)
579 BOOL gotMultitransport = FALSE;
583 wStream sbuffer = WINPR_C_ARRAY_INIT;
585 UINT16 blockLength = 0;
587 if (!gcc_read_user_data_header(mcs->log, s, &type, &blockLength))
590 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, (
size_t)(blockLength - 4)))
593 wStream* sub = Stream_StaticConstInit(&sbuffer, Stream_Pointer(s), blockLength - 4);
596 Stream_Seek(s, blockLength - 4);
599 char buffer[64] = WINPR_C_ARRAY_INIT;
600 WLog_Print(mcs->log, WLOG_TRACE,
"Processing block %s",
601 gcc_block_type_string(type, buffer,
sizeof(buffer)));
606 if (!gcc_read_client_core_data(sub, mcs))
612 if (!gcc_read_client_security_data(sub, mcs))
618 if (!gcc_read_client_network_data(sub, mcs))
624 if (!gcc_read_client_cluster_data(sub, mcs))
630 if (!gcc_read_client_monitor_data(sub, mcs))
635 case CS_MCS_MSGCHANNEL:
636 if (!gcc_read_client_message_channel_data(sub, mcs))
642 if (!gcc_read_client_monitor_extended_data(sub, mcs))
648 if (!gcc_read_client_unused1_data(sub))
654 case CS_MULTITRANSPORT:
655 gotMultitransport = TRUE;
656 if (!gcc_read_client_multitransport_channel_data(sub, mcs))
662 WLog_Print(mcs->log, WLOG_ERROR,
"Unknown GCC client data block: 0x%04" PRIX16
"",
664 winpr_HexLogDump(mcs->log, WLOG_TRACE, Stream_Pointer(sub),
665 Stream_GetRemainingLength(sub));
669 const size_t rem = Stream_GetRemainingLength(sub);
672 char buffer[128] = WINPR_C_ARRAY_INIT;
673 const size_t total = Stream_Length(sub);
674 WLog_Print(mcs->log, WLOG_ERROR,
675 "Error parsing GCC client data block %s: Actual Offset: %" PRIuz
676 " Expected Offset: %" PRIuz,
677 gcc_block_type_string(type, buffer,
sizeof(buffer)), total - rem, total);
680 if (blockLength > length)
682 char buffer[128] = WINPR_C_ARRAY_INIT;
683 WLog_Print(mcs->log, WLOG_ERROR,
684 "Error parsing GCC client data block %s: got blockLength 0x%04" PRIx16
685 ", but only 0x%04" PRIx16
"remaining",
686 gcc_block_type_string(type, buffer,
sizeof(buffer)), blockLength, length);
690 length -= blockLength;
693 if (!gotMultitransport)
695 rdpSettings* settings = mcs_get_settings(mcs);
704BOOL gcc_write_client_data_blocks(
wStream* s,
const rdpMcs* mcs)
706 const rdpSettings* settings = mcs_get_const_settings(mcs);
709 WINPR_ASSERT(settings);
711 if (!gcc_write_client_core_data(s, mcs) || !gcc_write_client_cluster_data(s, mcs) ||
712 !gcc_write_client_security_data(s, mcs) || !gcc_write_client_network_data(s, mcs))
717 if (settings->NegotiationFlags & EXTENDED_CLIENT_DATA_SUPPORTED)
719 if (settings->UseMultimon && !settings->SpanMonitors)
721 if (!gcc_write_client_monitor_data(s, mcs) ||
722 !gcc_write_client_monitor_extended_data(s, mcs))
726 if (!gcc_write_client_message_channel_data(s, mcs) ||
727 !gcc_write_client_multitransport_channel_data(s, mcs))
732 if (settings->UseMultimon && !settings->SpanMonitors)
734 WLog_Print(mcs->log, WLOG_ERROR,
735 "WARNING: true multi monitor support was not advertised by server!");
737 if (settings->ForceMultimon)
739 WLog_Print(mcs->log, WLOG_ERROR,
740 "Sending multi monitor information anyway (may break connectivity!)");
741 if (!gcc_write_client_monitor_data(s, mcs) ||
742 !gcc_write_client_monitor_extended_data(s, mcs))
747 WLog_Print(mcs->log, WLOG_ERROR,
748 "Use /multimon:force to force sending multi monitor information");
755char* gcc_block_type_string(UINT16 type,
char* buffer,
size_t size)
760 (void)_snprintf(buffer, size,
"CS_CORE [0x%04" PRIx16
"]", type);
763 (void)_snprintf(buffer, size,
"CS_SECURITY [0x%04" PRIx16
"]", type);
766 (void)_snprintf(buffer, size,
"CS_NET [0x%04" PRIx16
"]", type);
769 (void)_snprintf(buffer, size,
"CS_CLUSTER [0x%04" PRIx16
"]", type);
772 (void)_snprintf(buffer, size,
"CS_MONITOR [0x%04" PRIx16
"]", type);
774 case CS_MCS_MSGCHANNEL:
775 (void)_snprintf(buffer, size,
"CS_MONITOR [0x%04" PRIx16
"]", type);
778 (void)_snprintf(buffer, size,
"CS_MONITOR_EX [0x%04" PRIx16
"]", type);
781 (void)_snprintf(buffer, size,
"CS_UNUSED1 [0x%04" PRIx16
"]", type);
783 case CS_MULTITRANSPORT:
784 (void)_snprintf(buffer, size,
"CS_MONITOR_EX [0x%04" PRIx16
"]", type);
787 (void)_snprintf(buffer, size,
"SC_CORE [0x%04" PRIx16
"]", type);
790 (void)_snprintf(buffer, size,
"SC_SECURITY [0x%04" PRIx16
"]", type);
793 (void)_snprintf(buffer, size,
"SC_NET [0x%04" PRIx16
"]", type);
795 case SC_MCS_MSGCHANNEL:
796 (void)_snprintf(buffer, size,
"SC_MCS_MSGCHANNEL [0x%04" PRIx16
"]", type);
798 case SC_MULTITRANSPORT:
799 (void)_snprintf(buffer, size,
"SC_MULTITRANSPORT [0x%04" PRIx16
"]", type);
802 (void)_snprintf(buffer, size,
"UNKNOWN [0x%04" PRIx16
"]", type);
808BOOL gcc_read_server_data_blocks(
wStream* s, rdpMcs* mcs, UINT16 length)
812 UINT16 blockLength = 0;
813 BYTE* holdp =
nullptr;
818 while (offset < length)
820 char buffer[64] = WINPR_C_ARRAY_INIT;
825 if (!gcc_read_user_data_header(mcs->log, s, &type, &blockLength))
827 WLog_Print(mcs->log, WLOG_ERROR,
828 "gcc_read_server_data_blocks: gcc_read_user_data_header failed");
831 holdp = Stream_Pointer(s);
832 sub = Stream_StaticInit(&subbuffer, holdp, blockLength - 4);
833 if (!Stream_SafeSeek(s, blockLength - 4))
835 WLog_Print(mcs->log, WLOG_ERROR,
"gcc_read_server_data_blocks: stream too short");
838 offset += blockLength;
843 if (!gcc_read_server_core_data(sub, mcs))
845 WLog_Print(mcs->log, WLOG_ERROR,
846 "gcc_read_server_data_blocks: gcc_read_server_core_data failed");
853 if (!gcc_read_server_security_data(sub, mcs))
858 if (!gcc_read_server_network_data(sub, mcs))
860 WLog_Print(mcs->log, WLOG_ERROR,
861 "gcc_read_server_data_blocks: gcc_read_server_network_data failed");
867 case SC_MCS_MSGCHANNEL:
868 if (!gcc_read_server_message_channel_data(sub, mcs))
871 mcs->log, WLOG_ERROR,
872 "gcc_read_server_data_blocks: gcc_read_server_message_channel_data failed");
878 case SC_MULTITRANSPORT:
879 if (!gcc_read_server_multitransport_channel_data(sub, mcs))
881 WLog_Print(mcs->log, WLOG_ERROR,
882 "gcc_read_server_data_blocks: "
883 "gcc_read_server_multitransport_channel_data failed");
890 WLog_Print(mcs->log, WLOG_ERROR,
"gcc_read_server_data_blocks: ignoring type=%s",
891 gcc_block_type_string(type, buffer,
sizeof(buffer)));
892 winpr_HexLogDump(mcs->log, WLOG_TRACE, Stream_Pointer(sub),
893 Stream_GetRemainingLength(sub));
897 rest = Stream_GetRemainingLength(sub);
900 WLog_Print(mcs->log, WLOG_WARN,
901 "gcc_read_server_data_blocks: ignoring %" PRIuz
" bytes with type=%s", rest,
902 gcc_block_type_string(type, buffer,
sizeof(buffer)));
909BOOL gcc_write_server_data_blocks(
wStream* s, rdpMcs* mcs)
914 if (!gcc_write_server_core_data(s, mcs) ||
915 !gcc_write_server_network_data(s, mcs) ||
916 !gcc_write_server_security_data(s, mcs) ||
917 !gcc_write_server_message_channel_data(s, mcs))
920 const rdpSettings* settings = mcs_get_const_settings(mcs);
921 WINPR_ASSERT(settings);
923 if (settings->SupportMultitransport && (settings->MultitransportFlags != 0))
925 return gcc_write_server_multitransport_channel_data(s, mcs);
930BOOL gcc_read_user_data_header(wLog* log,
wStream* s, UINT16* type, UINT16* length)
933 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
936 Stream_Read_UINT16(s, *type);
937 Stream_Read_UINT16(s, *length);
939 return !((*length < 4) ||
940 (!Stream_CheckAndLogRequiredLengthWLog(log, s, (
size_t)(*length - 4))));
954BOOL gcc_write_user_data_header(
wStream* s, UINT16 type, UINT16 length)
958 if (!Stream_EnsureRemainingCapacity(s, 4 + length))
960 Stream_Write_UINT16(s, type);
961 Stream_Write_UINT16(s, length);
965static UINT32 filterAndLogEarlyServerCapabilityFlags(wLog* log, UINT32 flags)
968 (RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V1 | RNS_UD_SC_DYNAMIC_DST_SUPPORTED |
969 RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V2 | RNS_UD_SC_SKIP_CHANNELJOIN_SUPPORTED);
970 const UINT32 filtered = flags & mask;
971 const UINT32 unknown = flags & (~mask);
974 char buffer[256] = WINPR_C_ARRAY_INIT;
975 WLog_Print(log, WLOG_WARN,
976 "TS_UD_SC_CORE::EarlyCapabilityFlags [0x%08" PRIx32
" & 0x%08" PRIx32
977 " --> 0x%08" PRIx32
"] filtering %s, feature not implemented",
978 flags, ~mask, unknown,
979 rdp_early_server_caps_string(unknown, buffer,
sizeof(buffer)));
984static UINT32 earlyServerCapsFromSettings(wLog* log,
const rdpSettings* settings)
986 UINT32 EarlyCapabilityFlags = 0;
988 if (settings->SupportEdgeActionV1)
989 EarlyCapabilityFlags |= RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V1;
990 if (settings->SupportDynamicTimeZone)
991 EarlyCapabilityFlags |= RNS_UD_SC_DYNAMIC_DST_SUPPORTED;
992 if (settings->SupportEdgeActionV2)
993 EarlyCapabilityFlags |= RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V2;
994 if (settings->SupportSkipChannelJoin)
995 EarlyCapabilityFlags |= RNS_UD_SC_SKIP_CHANNELJOIN_SUPPORTED;
997 return filterAndLogEarlyServerCapabilityFlags(log, EarlyCapabilityFlags);
1000static UINT16 filterAndLogEarlyClientCapabilityFlags(wLog* log, UINT32 flags)
1003 (RNS_UD_CS_SUPPORT_ERRINFO_PDU | RNS_UD_CS_WANT_32BPP_SESSION |
1004 RNS_UD_CS_SUPPORT_STATUSINFO_PDU | RNS_UD_CS_STRONG_ASYMMETRIC_KEYS |
1005 RNS_UD_CS_RELATIVE_MOUSE_INPUT | RNS_UD_CS_VALID_CONNECTION_TYPE |
1006 RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU | RNS_UD_CS_SUPPORT_NETCHAR_AUTODETECT |
1007 RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL | RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE |
1008 RNS_UD_CS_SUPPORT_HEARTBEAT_PDU | RNS_UD_CS_SUPPORT_SKIP_CHANNELJOIN);
1009 const UINT32 filtered = flags & mask;
1010 const UINT32 unknown = flags & ~mask;
1013 char buffer[256] = WINPR_C_ARRAY_INIT;
1014 WLog_Print(log, WLOG_WARN,
1015 "(TS_UD_CS_CORE)::EarlyCapabilityFlags [0x%08" PRIx32
" & 0x%08" PRIx32
1016 " --> 0x%08" PRIx32
"] filtering %s, feature not implemented",
1017 flags, ~mask, unknown,
1018 rdp_early_client_caps_string(unknown, buffer,
sizeof(buffer)));
1021 WINPR_ASSERT(filtered <= UINT16_MAX);
1022 return (UINT16)filtered;
1025static UINT16 earlyClientCapsFromSettings(wLog* log,
const rdpSettings* settings)
1027 UINT32 earlyCapabilityFlags = 0;
1029 WINPR_ASSERT(settings);
1030 if (settings->SupportErrorInfoPdu)
1031 earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_ERRINFO_PDU;
1034 earlyCapabilityFlags |= RNS_UD_CS_WANT_32BPP_SESSION;
1036 if (settings->SupportStatusInfoPdu)
1037 earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_STATUSINFO_PDU;
1039 if (settings->ConnectionType)
1040 earlyCapabilityFlags |= RNS_UD_CS_VALID_CONNECTION_TYPE;
1042 if (settings->SupportMonitorLayoutPdu)
1043 earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU;
1046 earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_NETCHAR_AUTODETECT;
1048 if (settings->SupportGraphicsPipeline)
1049 earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL;
1051 if (settings->SupportDynamicTimeZone)
1052 earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE;
1054 if (settings->SupportHeartbeatPdu)
1055 earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_HEARTBEAT_PDU;
1057 if (settings->SupportAsymetricKeys)
1058 earlyCapabilityFlags |= RNS_UD_CS_STRONG_ASYMMETRIC_KEYS;
1060 if (settings->HasRelativeMouseEvent)
1061 earlyCapabilityFlags |= RNS_UD_CS_RELATIVE_MOUSE_INPUT;
1063 if (settings->SupportSkipChannelJoin)
1064 earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_SKIP_CHANNELJOIN;
1066 return filterAndLogEarlyClientCapabilityFlags(log, earlyCapabilityFlags);
1069static BOOL updateEarlyClientCaps(wLog* log, rdpSettings* settings, UINT32 earlyCapabilityFlags,
1070 UINT32 connectionType)
1072 WINPR_ASSERT(settings);
1074 if (settings->SupportErrorInfoPdu)
1075 settings->SupportErrorInfoPdu = (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_ERRINFO_PDU) != 0;
1083 if (settings->SupportStatusInfoPdu)
1084 settings->SupportStatusInfoPdu =
1085 (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_STATUSINFO_PDU) != 0;
1087 if (settings->SupportAsymetricKeys)
1088 settings->SupportAsymetricKeys =
1089 (earlyCapabilityFlags & RNS_UD_CS_STRONG_ASYMMETRIC_KEYS) != 0;
1091 if (settings->HasRelativeMouseEvent)
1095 if (settings->RdpVersion >= RDP_VERSION_10_12)
1097 settings->HasRelativeMouseEvent =
1098 (earlyCapabilityFlags & RNS_UD_CS_RELATIVE_MOUSE_INPUT) != 0;
1101 settings->HasRelativeMouseEvent = FALSE;
1104 if (settings->NetworkAutoDetect)
1105 settings->NetworkAutoDetect =
1106 (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_NETCHAR_AUTODETECT) != 0;
1108 if (settings->SupportSkipChannelJoin)
1109 settings->SupportSkipChannelJoin =
1110 (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_SKIP_CHANNELJOIN) != 0;
1112 if (settings->SupportMonitorLayoutPdu)
1113 settings->SupportMonitorLayoutPdu =
1114 (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU) != 0;
1116 if (settings->SupportHeartbeatPdu)
1117 settings->SupportHeartbeatPdu =
1118 (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_HEARTBEAT_PDU) != 0;
1120 if (settings->SupportGraphicsPipeline)
1121 settings->SupportGraphicsPipeline =
1122 (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL) != 0;
1124 if (settings->SupportDynamicTimeZone)
1125 settings->SupportDynamicTimeZone =
1126 (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE) != 0;
1128 if ((earlyCapabilityFlags & RNS_UD_CS_VALID_CONNECTION_TYPE) == 0)
1130 settings->ConnectionType = connectionType;
1132 filterAndLogEarlyClientCapabilityFlags(log, earlyCapabilityFlags);
1136static BOOL updateEarlyServerCaps(wLog* log, rdpSettings* settings, UINT32 earlyCapabilityFlags,
1137 WINPR_ATTR_UNUSED UINT32 connectionType)
1139 WINPR_ASSERT(settings);
1141 settings->SupportEdgeActionV1 = (settings->SupportEdgeActionV1 &&
1142 (earlyCapabilityFlags & RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V1));
1143 settings->SupportDynamicTimeZone = (settings->SupportDynamicTimeZone &&
1144 (earlyCapabilityFlags & RNS_UD_SC_DYNAMIC_DST_SUPPORTED));
1145 settings->SupportEdgeActionV2 = (settings->SupportEdgeActionV2 &&
1146 (earlyCapabilityFlags & RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V2));
1147 settings->SupportSkipChannelJoin =
1148 (settings->SupportSkipChannelJoin &&
1149 (earlyCapabilityFlags & RNS_UD_SC_SKIP_CHANNELJOIN_SUPPORTED));
1151 filterAndLogEarlyServerCapabilityFlags(log, earlyCapabilityFlags);
1164BOOL gcc_read_client_core_data(
wStream* s, rdpMcs* mcs)
1166 char buffer[2048] = WINPR_C_ARRAY_INIT;
1167 char strbuffer[130] = WINPR_C_ARRAY_INIT;
1169 BYTE connectionType = 0;
1170 UINT32 clientColorDepth = 0;
1171 UINT16 colorDepth = 0;
1172 UINT16 postBeta2ColorDepth = 0;
1173 UINT16 highColorDepth = 0;
1174 UINT32 serverSelectedProtocol = 0;
1175 rdpSettings* settings = mcs_get_settings(mcs);
1178 WINPR_ASSERT(settings);
1181 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 128))
1184 Stream_Read_UINT32(s, version);
1185 settings->RdpVersion = rdp_version_common(mcs->log, version, settings->RdpVersion);
1186 Stream_Read_UINT16(s, settings->DesktopWidth);
1187 Stream_Read_UINT16(s, settings->DesktopHeight);
1188 Stream_Read_UINT16(s, colorDepth);
1189 Stream_Seek_UINT16(s);
1190 Stream_Read_UINT32(s, settings->KeyboardLayout);
1191 Stream_Read_UINT32(s, settings->ClientBuild);
1194 if (Stream_Read_UTF16_String_As_UTF8_Buffer(s, 32 /
sizeof(WCHAR), strbuffer,
1195 ARRAYSIZE(strbuffer)) < 0)
1197 WLog_Print(mcs->log, WLOG_ERROR,
"failed to convert client host name");
1204 Stream_Read_UINT32(s, settings->KeyboardType);
1205 Stream_Read_UINT32(s, settings->KeyboardSubType);
1206 Stream_Read_UINT32(s, settings->KeyboardFunctionKey);
1218 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 2))
1221 Stream_Read_UINT16(s, postBeta2ColorDepth);
1223 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 2))
1226 const UINT16 clientProductId = Stream_Get_UINT16(s);
1231 if (clientProductId != 1)
1233 WLog_Print(mcs->log, WLOG_WARN,
1234 "[MS-RDPBCGR] 2.2.1.3.2 Client Core Data (TS_UD_CS_CORE)::clientProductId "
1235 "(optional) expected 1, got %" PRIu32,
1239 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 4))
1242 const UINT32 serialNumber = Stream_Get_UINT32(s);
1247 if (serialNumber != 0)
1249 WLog_Print(mcs->log, WLOG_WARN,
1250 "[MS-RDPBCGR] 2.2.1.3.2 Client Core Data (TS_UD_CS_CORE)::serialNumber "
1251 "(optional) expected 0, got %" PRIu32,
1255 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 2))
1258 Stream_Read_UINT16(s, highColorDepth);
1260 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 2))
1263 Stream_Read_UINT16(s, settings->SupportedColorDepths);
1265 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 2))
1268 Stream_Read_UINT16(s, settings->EarlyCapabilityFlags);
1271 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 64))
1274 if (Stream_Read_UTF16_String_As_UTF8_Buffer(s, 64 /
sizeof(WCHAR), strbuffer,
1275 ARRAYSIZE(strbuffer)) < 0)
1277 WLog_Print(mcs->log, WLOG_ERROR,
"failed to convert the client product identifier");
1284 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 1))
1287 Stream_Read_UINT8(s, connectionType);
1289 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 1))
1292 Stream_Seek_UINT8(s);
1294 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 4))
1297 Stream_Read_UINT32(s, serverSelectedProtocol);
1299 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 4))
1302 Stream_Read_UINT32(s, settings->DesktopPhysicalWidth);
1304 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 4))
1307 Stream_Read_UINT32(s,
1308 settings->DesktopPhysicalHeight);
1310 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 2))
1313 Stream_Read_UINT16(s, settings->DesktopOrientation);
1315 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 4))
1318 Stream_Read_UINT32(s, settings->DesktopScaleFactor);
1320 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 4))
1323 Stream_Read_UINT32(s, settings->DeviceScaleFactor);
1326 settings->SelectedProtocol = serverSelectedProtocol;
1327 else if (settings->SelectedProtocol != serverSelectedProtocol)
1331 if (highColorDepth > 0)
1333 if (settings->EarlyCapabilityFlags & RNS_UD_CS_WANT_32BPP_SESSION)
1334 clientColorDepth = 32;
1336 clientColorDepth = highColorDepth;
1338 else if (postBeta2ColorDepth > 0)
1340 switch (postBeta2ColorDepth)
1342 case RNS_UD_COLOR_4BPP:
1343 clientColorDepth = 4;
1346 case RNS_UD_COLOR_8BPP:
1347 clientColorDepth = 8;
1350 case RNS_UD_COLOR_16BPP_555:
1351 clientColorDepth = 15;
1354 case RNS_UD_COLOR_16BPP_565:
1355 clientColorDepth = 16;
1358 case RNS_UD_COLOR_24BPP:
1359 clientColorDepth = 24;
1370 case RNS_UD_COLOR_4BPP:
1371 clientColorDepth = 4;
1374 case RNS_UD_COLOR_8BPP:
1375 clientColorDepth = 8;
1388 !settings->ServerMode)
1395 mcs->log, WLOG_DEBUG,
"Received EarlyCapabilityFlags=%s",
1396 rdp_early_client_caps_string(settings->EarlyCapabilityFlags, buffer,
sizeof(buffer)));
1398 return updateEarlyClientCaps(mcs->log, settings, settings->EarlyCapabilityFlags,
1411BOOL gcc_write_client_core_data(
wStream* s,
const rdpMcs* mcs)
1413 char buffer[2048] = WINPR_C_ARRAY_INIT;
1414 char dbuffer[2048] = WINPR_C_ARRAY_INIT;
1415 BYTE connectionType = 0;
1416 HIGH_COLOR_DEPTH highColorDepth = HIGH_COLOR_4BPP;
1418 UINT16 earlyCapabilityFlags = 0;
1419 const rdpSettings* settings = mcs_get_const_settings(mcs);
1422 WINPR_ASSERT(settings);
1424 const UINT16 SupportedColorDepths =
1428 if (!gcc_write_user_data_header(s, CS_CORE, 234))
1431 Stream_Write_UINT32(s, settings->RdpVersion);
1432 Stream_Write_UINT16(
1433 s, WINPR_ASSERTING_INT_CAST(uint16_t, settings->DesktopWidth));
1434 Stream_Write_UINT16(
1435 s, WINPR_ASSERTING_INT_CAST(uint16_t, settings->DesktopHeight));
1436 Stream_Write_UINT16(s,
1438 Stream_Write_UINT16(s, RNS_UD_SAS_DEL);
1439 Stream_Write_UINT32(s, settings->KeyboardLayout);
1440 Stream_Write_UINT32(s, settings->ClientBuild);
1442 if (!Stream_EnsureRemainingCapacity(s, 32 + 12 + 64 + 8))
1446 size_t clientNameLength = 0;
1447 WCHAR* clientName = ConvertUtf8ToWCharAlloc(settings->ClientHostname, &clientNameLength);
1448 if (clientNameLength >= 16)
1450 clientNameLength = 16;
1451 clientName[clientNameLength - 1] = 0;
1454 Stream_Write(s, clientName, (clientNameLength * 2));
1455 Stream_Zero(s, 32 - (clientNameLength * 2));
1457 Stream_Write_UINT32(s, settings->KeyboardType);
1458 Stream_Write_UINT32(s, settings->KeyboardSubType);
1459 Stream_Write_UINT32(s, settings->KeyboardFunctionKey);
1461 Stream_Write_UINT16(s, RNS_UD_COLOR_8BPP);
1462 Stream_Write_UINT16(s, 1);
1463 Stream_Write_UINT32(s, 0);
1464 highColorDepth = ColorDepthToHighColor(ColorDepth);
1465 earlyCapabilityFlags = earlyClientCapsFromSettings(mcs->log, settings);
1467 WINPR_ASSERT(settings->ConnectionType <= UINT8_MAX);
1468 connectionType = (UINT8)settings->ConnectionType;
1470 if (!Stream_EnsureRemainingCapacity(s, 6))
1474 mcs->log, WLOG_DEBUG,
1475 "Sending highColorDepth=%s, supportedColorDepths=%s, earlyCapabilityFlags=%s",
1476 HighColorToString(highColorDepth),
1478 rdp_early_client_caps_string(earlyCapabilityFlags, buffer,
sizeof(buffer)));
1479 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, highColorDepth));
1480 Stream_Write_UINT16(s, SupportedColorDepths);
1481 Stream_Write_UINT16(s, earlyCapabilityFlags);
1483 if (!Stream_EnsureRemainingCapacity(s, 64 + 24))
1490 if (Stream_Write_UTF16_String_From_UTF8(s, 32, str, strnlen(str, 32), TRUE) < 0)
1494 Stream_Zero(s, 32 *
sizeof(WCHAR));
1496 Stream_Write_UINT8(s, connectionType);
1497 Stream_Write_UINT8(s, 0);
1498 Stream_Write_UINT32(s, settings->SelectedProtocol);
1499 Stream_Write_UINT32(s, settings->DesktopPhysicalWidth);
1500 Stream_Write_UINT32(s, settings->DesktopPhysicalHeight);
1501 Stream_Write_UINT16(s, settings->DesktopOrientation);
1502 Stream_Write_UINT32(s, settings->DesktopScaleFactor);
1503 Stream_Write_UINT32(s, settings->DeviceScaleFactor);
1507BOOL gcc_read_server_core_data(
wStream* s, rdpMcs* mcs)
1509 UINT32 serverVersion = 0;
1510 rdpSettings* settings = mcs_get_settings(mcs);
1513 WINPR_ASSERT(settings);
1515 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 4))
1518 Stream_Read_UINT32(s, serverVersion);
1519 settings->RdpVersion = rdp_version_common(mcs->log, serverVersion, settings->RdpVersion);
1521 if (Stream_GetRemainingLength(s) >= 4)
1523 Stream_Read_UINT32(s, settings->RequestedProtocols);
1526 if (Stream_GetRemainingLength(s) >= 4)
1528 char buffer[2048] = WINPR_C_ARRAY_INIT;
1530 Stream_Read_UINT32(s, settings->EarlyCapabilityFlags);
1532 mcs->log, WLOG_DEBUG,
"Received EarlyCapabilityFlags=%s",
1533 rdp_early_client_caps_string(settings->EarlyCapabilityFlags, buffer,
sizeof(buffer)));
1536 return updateEarlyServerCaps(mcs->log, settings, settings->EarlyCapabilityFlags,
1537 settings->ConnectionType);
1543BOOL gcc_write_server_core_data(
wStream* s, rdpMcs* mcs)
1545 const rdpSettings* settings = mcs_get_const_settings(mcs);
1548 WINPR_ASSERT(settings);
1550 if (!gcc_write_user_data_header(s, SC_CORE, 16))
1553 const UINT32 EarlyCapabilityFlags = earlyServerCapsFromSettings(mcs->log, settings);
1554 Stream_Write_UINT32(s, settings->RdpVersion);
1555 Stream_Write_UINT32(s, settings->RequestedProtocols);
1556 Stream_Write_UINT32(s, EarlyCapabilityFlags);
1569BOOL gcc_read_client_security_data(
wStream* s, rdpMcs* mcs)
1571 rdpSettings* settings = mcs_get_settings(mcs);
1574 WINPR_ASSERT(settings);
1576 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 8))
1579 if (settings->UseRdpSecurityLayer)
1581 Stream_Read_UINT32(s, settings->EncryptionMethods);
1583 if (settings->EncryptionMethods == ENCRYPTION_METHOD_NONE)
1584 Stream_Read_UINT32(s, settings->EncryptionMethods);
1605BOOL gcc_write_client_security_data(
wStream* s,
const rdpMcs* mcs)
1607 const rdpSettings* settings = mcs_get_const_settings(mcs);
1610 WINPR_ASSERT(settings);
1612 if (!gcc_write_user_data_header(s, CS_SECURITY, 12))
1615 if (settings->UseRdpSecurityLayer)
1617 Stream_Write_UINT32(s, settings->EncryptionMethods);
1618 Stream_Write_UINT32(s, 0);
1623 Stream_Write_UINT32(s, 0);
1624 Stream_Write_UINT32(s, settings->EncryptionMethods);
1629BOOL gcc_read_server_security_data(
wStream* s, rdpMcs* mcs)
1631 BOOL validCryptoConfig = FALSE;
1632 UINT32 EncryptionMethod = 0;
1633 UINT32 EncryptionLevel = 0;
1634 rdpSettings* settings = mcs_get_settings(mcs);
1637 WINPR_ASSERT(settings);
1639 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 8))
1642 Stream_Read_UINT32(s, EncryptionMethod);
1643 Stream_Read_UINT32(s, EncryptionLevel);
1646 switch (EncryptionMethod)
1648 case ENCRYPTION_METHOD_NONE:
1649 WLog_Print(mcs->log, WLOG_DEBUG,
"Server rdp encryption method: NONE");
1652 case ENCRYPTION_METHOD_40BIT:
1653 WLog_Print(mcs->log, WLOG_DEBUG,
"Server rdp encryption method: 40BIT");
1656 case ENCRYPTION_METHOD_56BIT:
1657 WLog_Print(mcs->log, WLOG_DEBUG,
"Server rdp encryption method: 56BIT");
1660 case ENCRYPTION_METHOD_128BIT:
1661 WLog_Print(mcs->log, WLOG_DEBUG,
"Server rdp encryption method: 128BIT");
1664 case ENCRYPTION_METHOD_FIPS:
1665 WLog_Print(mcs->log, WLOG_DEBUG,
"Server rdp encryption method: FIPS");
1669 WLog_Print(mcs->log, WLOG_ERROR,
"Received unknown encryption method %08" PRIX32
"",
1674 if (settings->UseRdpSecurityLayer && !(settings->EncryptionMethods & EncryptionMethod))
1676 WLog_Print(mcs->log, WLOG_WARN,
1677 "Server uses non-advertised encryption method 0x%08" PRIX32
"",
1682 settings->EncryptionMethods = EncryptionMethod;
1683 settings->EncryptionLevel = EncryptionLevel;
1685 switch (settings->EncryptionLevel)
1687 case ENCRYPTION_LEVEL_NONE:
1688 if (settings->EncryptionMethods == ENCRYPTION_METHOD_NONE)
1690 validCryptoConfig = TRUE;
1695 case ENCRYPTION_LEVEL_FIPS:
1696 if (settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS)
1698 validCryptoConfig = TRUE;
1703 case ENCRYPTION_LEVEL_LOW:
1704 case ENCRYPTION_LEVEL_HIGH:
1705 case ENCRYPTION_LEVEL_CLIENT_COMPATIBLE:
1706 if (settings->EncryptionMethods == ENCRYPTION_METHOD_40BIT ||
1707 settings->EncryptionMethods == ENCRYPTION_METHOD_56BIT ||
1708 settings->EncryptionMethods == ENCRYPTION_METHOD_128BIT ||
1709 settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS)
1711 validCryptoConfig = TRUE;
1717 WLog_Print(mcs->log, WLOG_ERROR,
"Received unknown encryption level 0x%08" PRIX32
"",
1718 settings->EncryptionLevel);
1721 if (!validCryptoConfig)
1723 WLog_Print(mcs->log, WLOG_ERROR,
1724 "Received invalid cryptographic configuration (level=0x%08" PRIX32
1725 " method=0x%08" PRIX32
")",
1726 settings->EncryptionLevel, settings->EncryptionMethods);
1730 if (settings->EncryptionLevel == ENCRYPTION_LEVEL_NONE)
1733 settings->UseRdpSecurityLayer = FALSE;
1737 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 8))
1740 Stream_Read_UINT32(s, settings->ServerRandomLength);
1741 Stream_Read_UINT32(s, settings->ServerCertificateLength);
1743 if ((settings->ServerRandomLength == 0) || (settings->ServerCertificateLength == 0))
1745 WLog_Print(mcs->log, WLOG_ERROR,
1746 "Invalid ServerRandom (length=%" PRIu32
") or ServerCertificate (length=%" PRIu32
1748 settings->ServerRandomLength, settings->ServerCertificateLength);
1752 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, settings->ServerRandomLength))
1757 settings->ServerRandomLength))
1760 Stream_Read(s, settings->ServerRandom, settings->ServerRandomLength);
1762 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, settings->ServerCertificateLength))
1767 settings->ServerCertificateLength))
1770 Stream_Read(s, settings->ServerCertificate, settings->ServerCertificateLength);
1773 const BYTE* data = settings->ServerCertificate;
1774 const uint32_t length = settings->ServerCertificateLength;
1776 if (!freerdp_certificate_read_server_cert(settings->RdpServerCertificate, data, length))
1786static BOOL gcc_update_server_random(rdpSettings* settings)
1788 const size_t length = 32;
1789 WINPR_ASSERT(settings);
1795 return winpr_RAND(data, length) >= 0;
1801BOOL gcc_write_server_security_data(
wStream* s, rdpMcs* mcs)
1803 if (!gcc_update_server_random(mcs_get_settings(mcs)))
1806 const rdpSettings* settings = mcs_get_const_settings(mcs);
1809 WINPR_ASSERT(settings);
1811 const size_t posHeader = Stream_GetPosition(s);
1812 if (!gcc_write_user_data_header(s, SC_SECURITY, 12))
1815 Stream_Write_UINT32(s, settings->EncryptionMethods);
1816 Stream_Write_UINT32(s, settings->EncryptionLevel);
1818 if (settings->EncryptionMethods == ENCRYPTION_METHOD_NONE)
1821 if (!Stream_EnsureRemainingCapacity(s,
sizeof(UINT32) + settings->ServerRandomLength))
1823 Stream_Write_UINT32(s, settings->ServerRandomLength);
1824 const size_t posCertLen = Stream_GetPosition(s);
1825 Stream_Seek_UINT32(s);
1826 Stream_Write(s, settings->ServerRandom, settings->ServerRandomLength);
1828 const SSIZE_T len = freerdp_certificate_write_server_cert(
1829 settings->RdpServerCertificate, CERT_TEMPORARILY_ISSUED | CERT_CHAIN_VERSION_1, s);
1832 const size_t end = Stream_GetPosition(s);
1834 WINPR_ASSERT(end >= posHeader);
1835 const size_t diff = end - posHeader;
1836 WINPR_ASSERT(diff <= UINT16_MAX);
1837 if (!Stream_SetPosition(s, posHeader))
1839 if (!gcc_write_user_data_header(s, SC_SECURITY, (UINT16)diff))
1841 if (!Stream_SetPosition(s, posCertLen))
1843 WINPR_ASSERT(len <= UINT32_MAX);
1844 Stream_Write_UINT32(s, (UINT32)len);
1845 return Stream_SetPosition(s, end);
1858BOOL gcc_read_client_network_data(
wStream* s, rdpMcs* mcs)
1863 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 4))
1866 Stream_Read_UINT32(s, mcs->channelCount);
1868 if (!Stream_CheckAndLogRequiredLengthOfSizeWLog(mcs->log, s, mcs->channelCount, 12ull))
1871 if (mcs->channelCount > CHANNEL_MAX_COUNT)
1873 WLog_Print(mcs->log, WLOG_ERROR,
"rdpMcs::channelCount %" PRIu32
" > maximum %d",
1874 mcs->channelCount, CHANNEL_MAX_COUNT);
1879 for (UINT32 i = 0; i < mcs->channelCount; i++)
1887 rdpMcsChannel* channel = &mcs->channels[i];
1888 Stream_Read(s, channel->Name, CHANNEL_NAME_LEN + 1);
1890 if (!memchr(channel->Name, 0, CHANNEL_NAME_LEN + 1))
1893 mcs->log, WLOG_ERROR,
1894 "protocol violation: received a static channel name with missing null-termination");
1898 Stream_Read_UINT32(s, channel->options);
1899 channel->ChannelId = mcs->baseChannelId++;
1914BOOL gcc_write_client_network_data(
wStream* s,
const rdpMcs* mcs)
1918 if (mcs->channelCount > 0)
1920 const size_t length = mcs->channelCount * 12 + 8;
1921 WINPR_ASSERT(length <= UINT16_MAX);
1922 if (!gcc_write_user_data_header(s, CS_NET, (UINT16)length))
1924 Stream_Write_UINT32(s, mcs->channelCount);
1927 for (UINT32 i = 0; i < mcs->channelCount; i++)
1930 rdpMcsChannel* channel = &mcs->channels[i];
1931 Stream_Write(s, channel->Name, CHANNEL_NAME_LEN + 1);
1932 Stream_Write_UINT32(s, channel->options);
1938BOOL gcc_read_server_network_data(
wStream* s, rdpMcs* mcs)
1940 UINT16 channelId = 0;
1941 UINT32 parsedChannelCount = 0;
1944 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 4))
1947 mcs->IOChannelId = Stream_Get_UINT16(s);
1948 const uint16_t channelCount = Stream_Get_UINT16(s);
1949 parsedChannelCount = channelCount;
1951 if (channelCount != mcs->channelCount)
1953 WLog_Print(mcs->log, WLOG_ERROR,
"requested %" PRIu32
" channels, got %" PRIu16
" instead",
1954 mcs->channelCount, channelCount);
1958 mcs->channelCount = channelCount;
1961 if (!Stream_CheckAndLogRequiredLengthOfSizeWLog(mcs->log, s, channelCount, 2ull))
1964 if (mcs->channelMaxCount < parsedChannelCount)
1966 WLog_Print(mcs->log, WLOG_ERROR,
1967 "requested %" PRIu32
" channels > channelMaxCount %" PRIu16, mcs->channelCount,
1968 mcs->channelMaxCount);
1972 for (UINT32 i = 0; i < parsedChannelCount; i++)
1974 rdpMcsChannel* channel = &mcs->channels[i];
1975 Stream_Read_UINT16(s, channelId);
1976 channel->ChannelId = channelId;
1979 if (channelCount % 2 == 1)
1980 return Stream_SafeSeek(s, 2);
1985BOOL gcc_write_server_network_data(
wStream* s,
const rdpMcs* mcs)
1989 const size_t payloadLen =
1990 8ull + mcs->channelCount * 2ull + (mcs->channelCount % 2 == 1 ? 2ull : 0ull);
1992 WINPR_ASSERT(payloadLen <= UINT16_MAX);
1993 if (!gcc_write_user_data_header(s, SC_NET, (UINT16)payloadLen))
1996 Stream_Write_UINT16(s, MCS_GLOBAL_CHANNEL_ID);
1997 Stream_Write_UINT16(s,
1998 WINPR_ASSERTING_INT_CAST(uint16_t, mcs->channelCount));
2000 for (UINT32 i = 0; i < mcs->channelCount; i++)
2002 const rdpMcsChannel* channel = &mcs->channels[i];
2003 Stream_Write_UINT16(s, channel->ChannelId);
2006 if (mcs->channelCount % 2 == 1)
2007 Stream_Write_UINT16(s, 0);
2021BOOL gcc_read_client_cluster_data(
wStream* s, rdpMcs* mcs)
2023 char buffer[128] = WINPR_C_ARRAY_INIT;
2024 UINT32 redirectedSessionId = 0;
2025 rdpSettings* settings = mcs_get_settings(mcs);
2028 WINPR_ASSERT(settings);
2030 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 8))
2033 Stream_Read_UINT32(s, settings->ClusterInfoFlags);
2034 Stream_Read_UINT32(s, redirectedSessionId);
2036 WLog_Print(mcs->log, WLOG_TRACE,
"read ClusterInfoFlags=%s, RedirectedSessionId=0x%08" PRIx32,
2037 rdp_cluster_info_flags_to_string(settings->ClusterInfoFlags, buffer,
sizeof(buffer)),
2038 redirectedSessionId);
2039 if (settings->ClusterInfoFlags & REDIRECTED_SESSIONID_FIELD_VALID)
2040 settings->RedirectedSessionId = redirectedSessionId;
2042 settings->ConsoleSession = (settings->ClusterInfoFlags & REDIRECTED_SESSIONID_FIELD_VALID) != 0;
2043 settings->RedirectSmartCards = (settings->ClusterInfoFlags & REDIRECTED_SMARTCARD) != 0;
2045 if (Stream_GetRemainingLength(s) > 0)
2048 Stream_Seek(s, Stream_GetRemainingLength(s));
2063BOOL gcc_write_client_cluster_data(
wStream* s,
const rdpMcs* mcs)
2065 char buffer[128] = WINPR_C_ARRAY_INIT;
2067 const rdpSettings* settings = mcs_get_const_settings(mcs);
2070 WINPR_ASSERT(settings);
2072 if (!gcc_write_user_data_header(s, CS_CLUSTER, 12))
2074 flags = settings->ClusterInfoFlags;
2076 if (settings->ConsoleSession || settings->RedirectedSessionId)
2077 flags |= REDIRECTED_SESSIONID_FIELD_VALID;
2079 if (settings->RedirectSmartCards && settings->SmartcardLogon)
2080 flags |= REDIRECTED_SMARTCARD;
2082 if (flags & REDIRECTION_SUPPORTED)
2087 flags |= (REDIRECTION_VERSION6 << 2);
2089 flags |= (REDIRECTION_VERSION5 << 2);
2092 WLog_Print(mcs->log, WLOG_TRACE,
"write ClusterInfoFlags=%s, RedirectedSessionId=0x%08" PRIx32,
2093 rdp_cluster_info_flags_to_string(flags, buffer,
sizeof(buffer)),
2094 settings->RedirectedSessionId);
2095 Stream_Write_UINT32(s, flags);
2096 Stream_Write_UINT32(s, settings->RedirectedSessionId);
2109BOOL gcc_read_client_monitor_data(
wStream* s, rdpMcs* mcs)
2111 UINT32 monitorCount = 0;
2112 rdpSettings* settings = mcs_get_settings(mcs);
2115 WINPR_ASSERT(settings);
2117 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 8))
2120 Stream_Read_UINT32(s, settings->MonitorFlags);
2121 Stream_Read_UINT32(s, monitorCount);
2127 if (monitorCount > 16)
2129 WLog_Print(mcs->log, WLOG_ERROR,
"announced monitors(%" PRIu32
") exceed the 16 limit",
2134 if (monitorCount > settings->MonitorDefArraySize)
2136 WLog_Print(mcs->log, WLOG_ERROR,
2137 "too many announced monitors(%" PRIu32
"), clamping to %" PRIu32
"",
2138 monitorCount, settings->MonitorDefArraySize);
2139 monitorCount = settings->MonitorDefArraySize;
2142 if (!Stream_CheckAndLogRequiredLengthOfSizeWLog(mcs->log, s, monitorCount, 20))
2145 settings->MonitorCount = monitorCount;
2147 for (UINT32 index = 0; index < monitorCount; index++)
2149 rdpMonitor* current = &settings->MonitorDefArray[index];
2151 const INT32 left = Stream_Get_INT32(s);
2152 const INT32 top = Stream_Get_INT32(s);
2153 const INT32 right = Stream_Get_INT32(s);
2154 const INT32 bottom = Stream_Get_INT32(s);
2155 const UINT32 flags = Stream_Get_UINT32(s);
2157 if ((1ll * left > right) || (1ll * top > bottom))
2159 WLog_Print(mcs->log, WLOG_ERROR,
"rdpMonitor::rect %dx%d-%dx%d invalid", left, top,
2164 const INT64 w = 1ll * right - left;
2165 const INT64 h = 1ll * bottom - top;
2166 if ((w >= INT32_MAX) || (h >= INT32_MAX) || (w < 0) || (h < 0))
2168 WLog_Print(mcs->log, WLOG_ERROR,
2169 "rdpMonitor::width/height %" PRId64
"/%" PRId64
" invalid", w, h);
2175 current->width = WINPR_ASSERTING_INT_CAST(int32_t, w + 1);
2176 current->height = WINPR_ASSERTING_INT_CAST(int32_t, h + 1);
2177 current->is_primary = (flags & MONITOR_PRIMARY) != 0;
2192BOOL gcc_write_client_monitor_data(
wStream* s,
const rdpMcs* mcs)
2196 const rdpSettings* settings = mcs_get_const_settings(mcs);
2199 WINPR_ASSERT(settings);
2201 WLog_Print(mcs->log, WLOG_DEBUG,
"MonitorCount=%" PRIu32, settings->MonitorCount);
2202 if (settings->MonitorCount > 1)
2204 const size_t len = (20 * settings->MonitorCount) + 12;
2205 WINPR_ASSERT(len <= UINT16_MAX);
2206 const UINT16 length = (UINT16)len;
2207 if (!gcc_write_user_data_header(s, CS_MONITOR, length))
2209 Stream_Write_UINT32(s, settings->MonitorFlags);
2210 Stream_Write_UINT32(s, settings->MonitorCount);
2214 for (UINT32 i = 0; i < settings->MonitorCount; i++)
2216 const rdpMonitor* current = &settings->MonitorDefArray[i];
2217 if (current->is_primary)
2225 for (UINT32 i = 0; i < settings->MonitorCount; i++)
2227 const rdpMonitor* current = &settings->MonitorDefArray[i];
2228 const INT32 left = current->x - baseX;
2229 const INT32 top = current->y - baseY;
2230 const INT32 right = left + current->width - 1;
2231 const INT32 bottom = top + current->height - 1;
2232 const UINT32 flags = current->is_primary ? MONITOR_PRIMARY : 0;
2233 WLog_Print(mcs->log, WLOG_DEBUG,
2234 "Monitor[%" PRIu32
"]: top=%" PRId32
", left=%" PRId32
", bottom=%" PRId32
2235 ", right=%" PRId32
", flags=%" PRIu32,
2236 i, top, left, bottom, right, flags);
2237 Stream_Write_INT32(s, left);
2238 Stream_Write_INT32(s, top);
2239 Stream_Write_INT32(s, right);
2240 Stream_Write_INT32(s, bottom);
2241 Stream_Write_UINT32(s, flags);
2244 WLog_Print(mcs->log, WLOG_DEBUG,
"FINISHED");
2248BOOL gcc_read_client_monitor_extended_data(
wStream* s, rdpMcs* mcs)
2250 UINT32 monitorCount = 0;
2251 UINT32 monitorAttributeSize = 0;
2252 rdpSettings* settings = mcs_get_settings(mcs);
2255 WINPR_ASSERT(settings);
2257 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 12))
2260 Stream_Read_UINT32(s, settings->MonitorAttributeFlags);
2261 Stream_Read_UINT32(s, monitorAttributeSize);
2262 Stream_Read_UINT32(s, monitorCount);
2264 if (monitorAttributeSize != 20)
2266 WLog_Print(mcs->log, WLOG_ERROR,
2267 "TS_UD_CS_MONITOR_EX::monitorAttributeSize %" PRIu32
" != 20",
2268 monitorAttributeSize);
2272 if (!Stream_CheckAndLogRequiredCapacityOfSizeWLog(mcs->log, s, monitorCount,
2273 monitorAttributeSize))
2276 if (settings->MonitorCount != monitorCount)
2278 WLog_Print(mcs->log, WLOG_ERROR,
2279 "(TS_UD_CS_MONITOR_EX)::monitorCount %" PRIu32
" != expected %" PRIu32,
2280 monitorCount, settings->MonitorCount);
2284 settings->HasMonitorAttributes = TRUE;
2286 for (UINT32 index = 0; index < monitorCount; index++)
2288 rdpMonitor* current = &settings->MonitorDefArray[index];
2289 Stream_Read_UINT32(s, current->attributes.physicalWidth);
2290 Stream_Read_UINT32(s, current->attributes.physicalHeight);
2291 Stream_Read_UINT32(s, current->attributes.orientation);
2292 Stream_Read_UINT32(s, current->attributes.desktopScaleFactor);
2293 Stream_Read_UINT32(s, current->attributes.deviceScaleFactor);
2299BOOL gcc_write_client_monitor_extended_data(
wStream* s,
const rdpMcs* mcs)
2301 const rdpSettings* settings = mcs_get_const_settings(mcs);
2304 WINPR_ASSERT(settings);
2306 if (settings->HasMonitorAttributes)
2308 const size_t length = (20 * settings->MonitorCount) + 16;
2309 WINPR_ASSERT(length <= UINT16_MAX);
2310 if (!gcc_write_user_data_header(s, CS_MONITOR_EX, (UINT16)length))
2312 Stream_Write_UINT32(s, settings->MonitorAttributeFlags);
2313 Stream_Write_UINT32(s, 20);
2314 Stream_Write_UINT32(s, settings->MonitorCount);
2316 for (UINT32 i = 0; i < settings->MonitorCount; i++)
2318 const rdpMonitor* current = &settings->MonitorDefArray[i];
2319 Stream_Write_UINT32(s, current->attributes.physicalWidth);
2320 Stream_Write_UINT32(s, current->attributes.physicalHeight);
2321 Stream_Write_UINT32(s, current->attributes.orientation);
2322 Stream_Write_UINT32(s, current->attributes.desktopScaleFactor);
2323 Stream_Write_UINT32(s, current->attributes.deviceScaleFactor);
2338BOOL gcc_read_client_message_channel_data(
wStream* s, rdpMcs* mcs)
2343 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 4))
2346 Stream_Read_UINT32(s, mcs->flags);
2347 mcs->messageChannelId = mcs->baseChannelId++;
2360BOOL gcc_write_client_message_channel_data(
wStream* s,
const rdpMcs* mcs)
2362 const rdpSettings* settings = mcs_get_const_settings(mcs);
2366 WINPR_ASSERT(settings);
2368 settings->SupportHeartbeatPdu || settings->SupportMultitransport)
2370 if (!gcc_write_user_data_header(s, CS_MCS_MSGCHANNEL, 8))
2372 Stream_Write_UINT32(s, mcs->flags);
2377BOOL gcc_read_server_message_channel_data(
wStream* s, rdpMcs* mcs)
2379 UINT16 MCSChannelId = 0;
2382 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 2))
2385 Stream_Read_UINT16(s, MCSChannelId);
2387 mcs->messageChannelId = MCSChannelId;
2391BOOL gcc_write_server_message_channel_data(
wStream* s,
const rdpMcs* mcs)
2395 if (mcs->messageChannelId == 0)
2398 if (!gcc_write_user_data_header(s, SC_MCS_MSGCHANNEL, 6))
2401 Stream_Write_UINT16(s, mcs->messageChannelId);
2414BOOL gcc_read_client_multitransport_channel_data(
wStream* s, rdpMcs* mcs)
2416 rdpSettings* settings = mcs_get_settings(mcs);
2419 WINPR_ASSERT(settings);
2421 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 4))
2424 UINT32 remoteFlags = 0;
2425 Stream_Read_UINT32(s, remoteFlags);
2426 settings->MultitransportFlags &= remoteFlags;
2440BOOL gcc_write_client_multitransport_channel_data(
wStream* s,
const rdpMcs* mcs)
2442 const rdpSettings* settings = mcs_get_const_settings(mcs);
2445 WINPR_ASSERT(settings);
2446 if (!gcc_write_user_data_header(s, CS_MULTITRANSPORT, 8))
2448 Stream_Write_UINT32(s, settings->MultitransportFlags);
2452BOOL gcc_read_server_multitransport_channel_data(
wStream* s, rdpMcs* mcs)
2454 rdpSettings* settings = mcs_get_settings(mcs);
2455 UINT32 remoteFlags = 0;
2458 WINPR_ASSERT(settings);
2459 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 4))
2462 Stream_Read_UINT32(s, remoteFlags);
2463 settings->MultitransportFlags &= remoteFlags;
2467BOOL gcc_write_server_multitransport_channel_data(
wStream* s,
const rdpMcs* mcs)
2469 const rdpSettings* settings = mcs_get_const_settings(mcs);
2472 WINPR_ASSERT(settings);
2474 if (!gcc_write_user_data_header(s, SC_MULTITRANSPORT, 8))
2477 Stream_Write_UINT32(s, settings->MultitransportFlags);
FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 val)
Sets a UINT32 settings value.
FREERDP_API BOOL freerdp_settings_set_bool(rdpSettings *settings, FreeRDP_Settings_Keys_Bool id, BOOL val)
Sets a BOOL settings value.
WINPR_ATTR_NODISCARD 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.
WINPR_ATTR_NODISCARD FREERDP_API void * freerdp_settings_get_pointer_writable(rdpSettings *settings, FreeRDP_Settings_Keys_Pointer id)
Returns a mutable pointer settings value.
WINPR_ATTR_NODISCARD FREERDP_API UINT16 freerdp_settings_get_uint16(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt16 id)
Returns a UINT16 settings value.
WINPR_ATTR_NODISCARD FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
WINPR_ATTR_NODISCARD 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
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.
FREERDP_API BOOL freerdp_settings_set_string(rdpSettings *settings, FreeRDP_Settings_Keys_String id, const char *val)
Sets a string settings value. The param is copied.