20#include <freerdp/config.h>
24#include <winpr/assert.h>
25#include <winpr/cast.h>
27#include "activation.h"
30#define TAG FREERDP_TAG("core.activation")
32static BOOL rdp_recv_client_font_list_pdu(
wStream* s);
33static BOOL rdp_recv_client_persistent_key_list_pdu(
wStream* s);
34static BOOL rdp_send_server_font_map_pdu(rdpRdp* rdp);
36static BOOL rdp_write_synchronize_pdu(
wStream* s,
const rdpSettings* settings)
40 if (!Stream_CheckAndLogRequiredCapacity(TAG, (s), 4))
42 Stream_Write_UINT16(s, SYNCMSGTYPE_SYNC);
43 Stream_Write_UINT16(s,
44 WINPR_ASSERTING_INT_CAST(uint16_t, PduSource));
48static BOOL rdp_recv_sync_pdu(rdpRdp* rdp,
wStream* s,
const char* what)
51 UINT16 targetUser = 0;
54 if (!Stream_CheckAndLogRequiredLengthEx(TAG, WLOG_WARN, s, 4, 1,
"%s(%s:%" PRIuz
") %s",
55 __func__, __FILE__, (
size_t)__LINE__, what))
57 Stream_Read_UINT16(s, msgType);
58 if (msgType != SYNCMSGTYPE_SYNC)
60 WLog_WARN(TAG,
"%s: Invalid messageType=0x%04" PRIx16
", expected 0x%04" PRIx16, what,
61 msgType, SYNCMSGTYPE_SYNC);
64 Stream_Read_UINT16(s, targetUser);
65 WLog_VRB(TAG,
"%s: targetUser=0x%04" PRIx16, what, targetUser);
69BOOL rdp_recv_server_synchronize_pdu(rdpRdp* rdp,
wStream* s)
71 if (!rdp_recv_sync_pdu(rdp, s,
"[MS-RDPBCGR] 2.2.1.19 Server Synchronize PDU"))
73 return rdp_finalize_set_flag(rdp, FINALIZE_SC_SYNCHRONIZE_PDU);
76BOOL rdp_send_server_synchronize_pdu(rdpRdp* rdp)
79 wStream* s = rdp_data_pdu_init(rdp, &sec_flags);
84 if (!rdp_write_synchronize_pdu(s, rdp->settings))
90 WINPR_ASSERT(rdp->mcs);
91 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SYNCHRONIZE, rdp->mcs->userId, sec_flags);
94BOOL rdp_recv_client_synchronize_pdu(rdpRdp* rdp,
wStream* s)
96 if (!rdp_recv_sync_pdu(rdp, s,
"[MS-RDPBCGR] 2.2.1.14 Client Synchronize PDU"))
98 return rdp_finalize_set_flag(rdp, FINALIZE_CS_SYNCHRONIZE_PDU);
101BOOL rdp_send_client_synchronize_pdu(rdpRdp* rdp)
103 UINT16 sec_flags = 0;
104 wStream* s = rdp_data_pdu_init(rdp, &sec_flags);
109 if (!rdp_write_synchronize_pdu(s, rdp->settings))
111 Stream_Free(s, TRUE);
115 WINPR_ASSERT(rdp->mcs);
116 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SYNCHRONIZE, rdp->mcs->userId, sec_flags);
119static BOOL rdp_recv_control_pdu(
wStream* s, UINT16* action, UINT16* grantId, UINT32* controlId)
122 WINPR_ASSERT(action);
123 WINPR_ASSERT(grantId);
124 WINPR_ASSERT(controlId);
126 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
129 Stream_Read_UINT16(s, *action);
130 Stream_Read_UINT16(s, *grantId);
131 Stream_Read_UINT32(s, *controlId);
135static BOOL rdp_write_client_control_pdu(
wStream* s, UINT16 action, UINT16 grantId,
139 if (!Stream_CheckAndLogRequiredCapacity(TAG, (s), 8))
141 Stream_Write_UINT16(s, action);
142 Stream_Write_UINT16(s, grantId);
143 Stream_Write_UINT32(s, controlId);
147BOOL rdp_recv_server_control_pdu(rdpRdp* rdp,
wStream* s)
151 UINT32 controlId = 0;
156 if (!rdp_recv_control_pdu(s, &action, &grantId, &controlId))
161 case CTRLACTION_COOPERATE:
162 return rdp_finalize_set_flag(rdp, FINALIZE_SC_CONTROL_COOPERATE_PDU);
164 case CTRLACTION_GRANTED_CONTROL:
165 rdp->resendFocus = TRUE;
166 return rdp_finalize_set_flag(rdp, FINALIZE_SC_CONTROL_GRANTED_PDU);
169 char buffer[128] = { 0 };
170 WLog_WARN(TAG,
"Unexpected control PDU %s",
171 rdp_ctrlaction_string(action, buffer,
sizeof(buffer)));
178BOOL rdp_send_server_control_cooperate_pdu(rdpRdp* rdp)
180 UINT16 sec_flags = 0;
181 wStream* s = rdp_data_pdu_init(rdp, &sec_flags);
184 if (!Stream_CheckAndLogRequiredCapacity(TAG, (s), 8))
186 Stream_Free(s, TRUE);
189 Stream_Write_UINT16(s, CTRLACTION_COOPERATE);
190 Stream_Write_UINT16(s, 0);
191 Stream_Write_UINT32(s, 0);
193 WINPR_ASSERT(rdp->mcs);
194 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->userId, sec_flags);
197BOOL rdp_send_server_control_granted_pdu(rdpRdp* rdp)
199 UINT16 sec_flags = 0;
200 wStream* s = rdp_data_pdu_init(rdp, &sec_flags);
203 if (!Stream_CheckAndLogRequiredCapacity(TAG, (s), 8))
205 Stream_Free(s, TRUE);
209 WINPR_ASSERT(rdp->mcs);
210 Stream_Write_UINT16(s, CTRLACTION_GRANTED_CONTROL);
211 Stream_Write_UINT16(s, rdp->mcs->userId);
212 Stream_Write_UINT32(s, 0x03EA);
213 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->userId, sec_flags);
216BOOL rdp_send_client_control_pdu(rdpRdp* rdp, UINT16 action)
219 UINT16 ControlId = 0;
223 case CTRLACTION_COOPERATE:
224 case CTRLACTION_REQUEST_CONTROL:
228 "Invalid client control PDU::action 0x%04" PRIx16
", not allowed by client",
233 UINT16 sec_flags = 0;
234 wStream* s = rdp_data_pdu_init(rdp, &sec_flags);
237 if (!rdp_write_client_control_pdu(s, action, GrantId, ControlId))
239 Stream_Free(s, TRUE);
243 WINPR_ASSERT(rdp->mcs);
244 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->userId, sec_flags);
247static BOOL rdp_write_client_persistent_key_list_pdu(
wStream* s,
253 if (!Stream_EnsureRemainingCapacity(s, 24))
256 Stream_Write_UINT16(s, info->numEntriesCache0);
257 Stream_Write_UINT16(s, info->numEntriesCache1);
258 Stream_Write_UINT16(s, info->numEntriesCache2);
259 Stream_Write_UINT16(s, info->numEntriesCache3);
260 Stream_Write_UINT16(s, info->numEntriesCache4);
261 Stream_Write_UINT16(s, info->totalEntriesCache0);
262 Stream_Write_UINT16(s, info->totalEntriesCache1);
263 Stream_Write_UINT16(s, info->totalEntriesCache2);
264 Stream_Write_UINT16(s, info->totalEntriesCache3);
265 Stream_Write_UINT16(s, info->totalEntriesCache4);
266 Stream_Write_UINT8(s, PERSIST_FIRST_PDU | PERSIST_LAST_PDU);
267 Stream_Write_UINT8(s, 0);
268 Stream_Write_UINT16(s, 0);
271 if (!Stream_EnsureRemainingCapacity(s, info->keyCount * 8ull))
274 for (UINT32 index = 0; index < info->keyCount; index++)
276 const UINT64 val = info->keyList[index];
277 Stream_Write_UINT64(s, val);
283static UINT16 rdp_load_persistent_key_list(rdpRdp* rdp, UINT64** pKeyList)
286 UINT64* keyList = NULL;
287 rdpPersistentCache* persistent = NULL;
288 rdpSettings* settings = rdp->settings;
295 if (!settings->BitmapCachePersistFile)
298 persistent = persistent_cache_new();
304 persistent_cache_open(persistent, settings->BitmapCachePersistFile, FALSE, 0);
310 const int count = persistent_cache_get_count(persistent);
311 if ((count < 0) || (count > UINT16_MAX))
314 keyCount = (UINT16)count;
315 keyList = (UINT64*)calloc(keyCount,
sizeof(UINT64));
320 for (
int index = 0; index < count; index++)
324 if (persistent_cache_read_entry(persistent, &cacheEntry) < 1)
327 keyList[index] = cacheEntry.key64;
333 persistent_cache_free(persistent);
336 persistent_cache_free(persistent);
341BOOL rdp_send_client_persistent_key_list_pdu(rdpRdp* rdp)
343 UINT16 keyMaxFrag = 2042;
344 UINT64* keyList = NULL;
347 rdpSettings* settings = rdp->settings;
348 UINT16 keyCount = rdp_load_persistent_key_list(rdp, &keyList);
350 WLog_DBG(TAG,
"Persistent Key List: TotalKeyCount: %" PRIu16
" MaxKeyFrag: %" PRIu16, keyCount,
359 if (keyCount > keyMaxFrag)
360 keyCount = keyMaxFrag;
362 WINPR_ASSERT(settings->BitmapCacheV2CellInfo[0].numEntries <= UINT16_MAX);
363 info.totalEntriesCache0 = (UINT16)settings->BitmapCacheV2CellInfo[0].numEntries;
365 WINPR_ASSERT(settings->BitmapCacheV2CellInfo[1].numEntries <= UINT16_MAX);
366 info.totalEntriesCache1 = (UINT16)settings->BitmapCacheV2CellInfo[1].numEntries;
368 WINPR_ASSERT(settings->BitmapCacheV2CellInfo[2].numEntries <= UINT16_MAX);
369 info.totalEntriesCache2 = (UINT16)settings->BitmapCacheV2CellInfo[2].numEntries;
371 WINPR_ASSERT(settings->BitmapCacheV2CellInfo[3].numEntries <= UINT16_MAX);
372 info.totalEntriesCache3 = (UINT16)settings->BitmapCacheV2CellInfo[3].numEntries;
374 WINPR_ASSERT(settings->BitmapCacheV2CellInfo[4].numEntries <= UINT16_MAX);
375 info.totalEntriesCache4 = (UINT16)settings->BitmapCacheV2CellInfo[4].numEntries;
377 info.numEntriesCache0 = MIN(keyCount, info.totalEntriesCache0);
378 keyCount -= info.numEntriesCache0;
379 info.numEntriesCache1 = MIN(keyCount, info.totalEntriesCache1);
380 keyCount -= info.numEntriesCache1;
381 info.numEntriesCache2 = MIN(keyCount, info.totalEntriesCache2);
382 keyCount -= info.numEntriesCache2;
383 info.numEntriesCache3 = MIN(keyCount, info.totalEntriesCache3);
384 keyCount -= info.numEntriesCache3;
385 info.numEntriesCache4 = MIN(keyCount, info.totalEntriesCache4);
387 info.totalEntriesCache0 = info.numEntriesCache0;
388 info.totalEntriesCache1 = info.numEntriesCache1;
389 info.totalEntriesCache2 = info.numEntriesCache2;
390 info.totalEntriesCache3 = info.numEntriesCache3;
391 info.totalEntriesCache4 = info.numEntriesCache4;
393 keyCount = info.totalEntriesCache0 + info.totalEntriesCache1 + info.totalEntriesCache2 +
394 info.totalEntriesCache3 + info.totalEntriesCache4;
396 info.keyCount = keyCount;
397 info.keyList = keyList;
399 WLog_DBG(TAG,
"persistentKeyList count: %" PRIu32, info.keyCount);
402 "numEntriesCache: [0]: %" PRIu16
" [1]: %" PRIu16
" [2]: %" PRIu16
" [3]: %" PRIu16
404 info.numEntriesCache0, info.numEntriesCache1, info.numEntriesCache2,
405 info.numEntriesCache3, info.numEntriesCache4);
408 "totalEntriesCache: [0]: %" PRIu16
" [1]: %" PRIu16
" [2]: %" PRIu16
" [3]: %" PRIu16
410 info.totalEntriesCache0, info.totalEntriesCache1, info.totalEntriesCache2,
411 info.totalEntriesCache3, info.totalEntriesCache4);
413 UINT16 sec_flags = 0;
414 wStream* s = rdp_data_pdu_init(rdp, &sec_flags);
422 if (!rdp_write_client_persistent_key_list_pdu(s, &info))
424 Stream_Free(s, TRUE);
429 WINPR_ASSERT(rdp->mcs);
432 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_BITMAP_CACHE_PERSISTENT_LIST, rdp->mcs->userId,
436BOOL rdp_recv_client_font_list_pdu(
wStream* s)
440 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
443 return Stream_SafeSeek(s, 8);
446BOOL rdp_recv_client_persistent_key_list_pdu(
wStream* s)
456 if (!Stream_CheckAndLogRequiredLength(TAG, s, 21))
458 WLog_ERR(TAG,
"short TS_BITMAPCACHE_PERSISTENT_LIST_PDU, need 21 bytes, got %" PRIuz,
459 Stream_GetRemainingLength(s));
463 for (
size_t x = 0; x < 5; x++)
465 Stream_Read_UINT16(s, cache);
470 for (
size_t x = 0; x < 5; x++)
473 Stream_Read_UINT16(s, tmp);
480 "TS_BITMAPCACHE_PERSISTENT_LIST_PDU::totalEntriesCacheX exceeds 262144 entries");
484 Stream_Read_UINT8(s, flags);
485 if ((flags & ~(PERSIST_LAST_PDU | PERSIST_FIRST_PDU)) != 0)
488 "TS_BITMAPCACHE_PERSISTENT_LIST_PDU::bBitMask has an invalid value of 0x%02" PRIx8,
494 if (!Stream_SafeSeek(s, 3))
496 WLog_ERR(TAG,
"short TS_BITMAPCACHE_PERSISTENT_LIST_PDU, need 3 bytes, got %" PRIuz,
497 Stream_GetRemainingLength(s));
501 if (!Stream_SafeSeek(s, count *
sizeof(UINT64)))
504 "short TS_BITMAPCACHE_PERSISTENT_LIST_PDU, need %" PRIuz
" bytes, got %" PRIuz,
505 count *
sizeof(UINT64), Stream_GetRemainingLength(s));
511static BOOL rdp_write_client_font_list_pdu(
wStream* s, UINT16 flags)
515 if (!Stream_CheckAndLogRequiredCapacity(TAG, (s), 8))
517 Stream_Write_UINT16(s, 0);
518 Stream_Write_UINT16(s, 0);
519 Stream_Write_UINT16(s, flags);
520 Stream_Write_UINT16(s, 50);
524BOOL rdp_send_client_font_list_pdu(rdpRdp* rdp, UINT16 flags)
526 UINT16 sec_flags = 0;
527 wStream* s = rdp_data_pdu_init(rdp, &sec_flags);
530 if (!rdp_write_client_font_list_pdu(s, flags))
532 Stream_Free(s, TRUE);
536 WINPR_ASSERT(rdp->mcs);
537 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_FONT_LIST, rdp->mcs->userId, sec_flags);
540BOOL rdp_recv_font_map_pdu(rdpRdp* rdp,
wStream* s)
542 UINT16 numberEntries = 0;
543 UINT16 totalNumEntries = 0;
545 UINT16 entrySize = 0;
548 WINPR_ASSERT(rdp->settings);
553 if (Stream_CheckAndLogRequiredLength(TAG, s, 8))
555 Stream_Read_UINT16(s, numberEntries);
556 if (numberEntries != 0)
559 "[MS-RDPBCGR] 2.2.1.22.1 Font Map PDU Data (TS_FONT_MAP_PDU)::numberEntries != 0 "
562 Stream_Read_UINT16(s, totalNumEntries);
563 if (totalNumEntries != 0)
566 "[MS-RDPBCGR] 2.2.1.22.1 Font Map PDU Data (TS_FONT_MAP_PDU)::totalNumEntries != "
569 Stream_Read_UINT16(s, mapFlags);
570 if (mapFlags != (FONTLIST_FIRST | FONTLIST_LAST))
573 "[MS-RDPBCGR] 2.2.1.22.1 Font Map PDU Data (TS_FONT_MAP_PDU)::mapFlags != 0x0003 "
574 "(FONTLIST_FIRST | FONTLIST_LAST) "
577 Stream_Read_UINT16(s, entrySize);
580 "[MS-RDPBCGR] 2.2.1.22.1 Font Map PDU Data (TS_FONT_MAP_PDU)::entrySize != 4 "
586 "[MS-RDPBCGR] 2.2.1.22.1 Font Map PDU Data (TS_FONT_MAP_PDU) paylaod size is "
589 return rdp_finalize_set_flag(rdp, FINALIZE_SC_FONT_MAP_PDU);
592BOOL rdp_send_server_font_map_pdu(rdpRdp* rdp)
594 UINT16 sec_flags = 0;
595 wStream* s = rdp_data_pdu_init(rdp, &sec_flags);
598 if (!Stream_CheckAndLogRequiredCapacity(TAG, (s), 8))
600 Stream_Free(s, TRUE);
603 Stream_Write_UINT16(s, 0);
604 Stream_Write_UINT16(s, 0);
605 Stream_Write_UINT16(s, FONTLIST_FIRST | FONTLIST_LAST);
606 Stream_Write_UINT16(s, 4);
608 WINPR_ASSERT(rdp->mcs);
609 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_FONT_MAP, rdp->mcs->userId, sec_flags);
612BOOL rdp_recv_deactivate_all(rdpRdp* rdp,
wStream* s)
614 UINT16 lengthSourceDescriptor = 0;
619 if (rdp_get_state(rdp) == CONNECTION_STATE_ACTIVE)
621 if (!rdp_finalize_set_flag(rdp, FINALIZE_DEACTIVATE_REACTIVATE))
624 rdp->was_deactivated = TRUE;
634 WINPR_ASSERT(rdp->settings);
635 if (Stream_GetRemainingLength(s) > 0)
640 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
643 Stream_Read_UINT32(s, ShareId);
647 if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
650 Stream_Read_UINT16(s, lengthSourceDescriptor);
652 if (!Stream_CheckAndLogRequiredLength(TAG, s, lengthSourceDescriptor))
655 Stream_Seek(s, lengthSourceDescriptor);
659 return rdp_client_transition_to_state(rdp,
660 CONNECTION_STATE_CAPABILITIES_EXCHANGE_DEMAND_ACTIVE);
663BOOL rdp_send_deactivate_all(rdpRdp* rdp)
666 WINPR_ASSERT(rdp->mcs);
668 if (rdp->mcs->userId == 0)
670 WLog_Print(rdp->log, WLOG_WARN,
671 "rdpMcs::userId == 0, skip sending PDU_TYPE_DEACTIVATE_ALL");
675 UINT16 sec_flags = 0;
676 wStream* s = rdp_send_stream_pdu_init(rdp, &sec_flags);
682 if (!Stream_CheckAndLogRequiredCapacityWLog(rdp->log, (s), 7))
685 WINPR_ASSERT(rdp->settings);
688 Stream_Write_UINT32(s, ShareId);
690 Stream_Write_UINT16(s, 1);
691 Stream_Write_UINT8(s, 0);
693 WINPR_ASSERT(rdp->mcs);
694 status = rdp_send_pdu(rdp, s, PDU_TYPE_DEACTIVATE_ALL, rdp->mcs->userId, sec_flags);
700BOOL rdp_server_accept_client_control_pdu(rdpRdp* rdp,
wStream* s)
704 UINT32 ControlId = 0;
705 const CONNECTION_STATE state = rdp_get_state(rdp);
710 if (!rdp_recv_control_pdu(s, &action, &GrantId, &ControlId))
716 case CTRLACTION_REQUEST_CONTROL:
717 if (!rdp_finalize_is_flag_set(rdp, FINALIZE_CS_CONTROL_COOPERATE_PDU))
719 char abuffer[128] = { 0 };
720 char buffer[1024] = { 0 };
722 "Received action=%s with GrantId=0x%04" PRIx16
", ControlId=0x%08" PRIx32
723 " in unexpected state %s [missing %s]",
724 rdp_ctrlaction_string(action, abuffer,
sizeof(abuffer)), GrantId,
725 ControlId, rdp_state_string(state),
726 rdp_finalize_flags_to_str(FINALIZE_CS_CONTROL_COOPERATE_PDU, buffer,
730 if ((GrantId != 0) || (ControlId != 0))
733 "Received CTRLACTION_COOPERATE with GrantId=0x%04" PRIx16
734 " != 0x00, ControlId=0x%08" PRIx32
" != 0x00",
738 return rdp_finalize_set_flag(rdp, FINALIZE_CS_CONTROL_REQUEST_PDU);
739 case CTRLACTION_COOPERATE:
740 if (!rdp_finalize_is_flag_set(rdp, FINALIZE_CS_SYNCHRONIZE_PDU))
742 char abuffer[128] = { 0 };
743 char buffer[1024] = { 0 };
746 "Received action=%s with GrantId=0x%04" PRIx16
", ControlId=0x%08" PRIx32
747 " in unexpected state %s [missing %s]",
748 rdp_ctrlaction_string(action, abuffer,
sizeof(abuffer)), GrantId, ControlId,
749 rdp_state_string(state),
750 rdp_finalize_flags_to_str(FINALIZE_CS_SYNCHRONIZE_PDU, buffer,
sizeof(buffer)));
753 if ((GrantId != 0) || (ControlId != 0))
756 "Received CTRLACTION_COOPERATE with GrantId=0x%04" PRIx16
757 " != 0x00, ControlId=0x%08" PRIx32
" != 0x00",
761 return rdp_finalize_set_flag(rdp, FINALIZE_CS_CONTROL_COOPERATE_PDU);
764 char abuffer[128] = { 0 };
766 "Received unexpected action=%s with GrantId=0x%04" PRIx16
767 ", ControlId=0x%08" PRIx32,
768 rdp_ctrlaction_string(action, abuffer,
sizeof(abuffer)), GrantId, ControlId);
776BOOL rdp_server_accept_client_font_list_pdu(rdpRdp* rdp,
wStream* s)
781 if (!rdp_recv_client_font_list_pdu(s))
783 rdp_finalize_set_flag(rdp, FINALIZE_CS_FONT_LIST_PDU);
785 if (!rdp_server_transition_to_state(rdp, CONNECTION_STATE_FINALIZATION_CLIENT_FONT_MAP))
788 if (!rdp_send_server_font_map_pdu(rdp))
791 if (!rdp_server_transition_to_state(rdp, CONNECTION_STATE_ACTIVE))
797BOOL rdp_server_accept_client_persistent_key_list_pdu(rdpRdp* rdp,
wStream* s)
802 if (!rdp_recv_client_persistent_key_list_pdu(s))
805 rdp_finalize_set_flag(rdp, FINALIZE_CS_PERSISTENT_KEY_LIST_PDU);
810const char* rdp_ctrlaction_string(UINT16 action,
char* buffer,
size_t size)
812 const char* actstr = NULL;
815 case CTRLACTION_COOPERATE:
816 actstr =
"CTRLACTION_COOPERATE";
818 case CTRLACTION_DETACH:
819 actstr =
"CTRLACTION_DETACH";
821 case CTRLACTION_GRANTED_CONTROL:
822 actstr =
"CTRLACTION_GRANTED_CONTROL";
824 case CTRLACTION_REQUEST_CONTROL:
825 actstr =
"CTRLACTION_REQUEST_CONTROL";
828 actstr =
"CTRLACTION_UNKNOWN";
832 (void)_snprintf(buffer, size,
"%s [0x%04" PRIx16
"]", actstr, action);
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_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.
FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 param)
Sets a UINT32 settings value.