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")
33static BOOL rdp_recv_client_font_list_pdu(
wStream* s);
36static BOOL rdp_recv_client_persistent_key_list_pdu(
wStream* s);
39static BOOL rdp_send_server_font_map_pdu(rdpRdp* rdp);
42static BOOL rdp_write_synchronize_pdu(
wStream* s,
const rdpSettings* settings)
46 if (!Stream_CheckAndLogRequiredCapacity(TAG, (s), 4))
48 Stream_Write_UINT16(s, SYNCMSGTYPE_SYNC);
49 Stream_Write_UINT16(s,
50 WINPR_ASSERTING_INT_CAST(uint16_t, PduSource));
55static BOOL rdp_recv_sync_pdu(rdpRdp* rdp,
wStream* s,
const char* what)
58 UINT16 targetUser = 0;
61 if (!Stream_CheckAndLogRequiredLengthEx(TAG, WLOG_WARN, s, 4, 1,
"%s(%s:%" PRIuz
") %s",
62 __func__, __FILE__, (
size_t)__LINE__, what))
64 Stream_Read_UINT16(s, msgType);
65 if (msgType != SYNCMSGTYPE_SYNC)
67 WLog_WARN(TAG,
"%s: Invalid messageType=0x%04" PRIx16
", expected 0x%04" PRIx16, what,
68 msgType, WINPR_CXX_COMPAT_CAST(uint16_t, SYNCMSGTYPE_SYNC));
71 Stream_Read_UINT16(s, targetUser);
72 WLog_VRB(TAG,
"%s: targetUser=0x%04" PRIx16, what, targetUser);
76BOOL rdp_recv_server_synchronize_pdu(rdpRdp* rdp,
wStream* s)
78 if (!rdp_recv_sync_pdu(rdp, s,
"[MS-RDPBCGR] 2.2.1.19 Server Synchronize PDU"))
80 return rdp_finalize_set_flag(rdp, FINALIZE_SC_SYNCHRONIZE_PDU);
83BOOL rdp_send_server_synchronize_pdu(rdpRdp* rdp)
86 wStream* s = rdp_data_pdu_init(rdp, &sec_flags);
91 if (!rdp_write_synchronize_pdu(s, rdp->settings))
97 WINPR_ASSERT(rdp->mcs);
98 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SYNCHRONIZE, rdp->mcs->userId, sec_flags);
101BOOL rdp_recv_client_synchronize_pdu(rdpRdp* rdp,
wStream* s)
103 if (!rdp_recv_sync_pdu(rdp, s,
"[MS-RDPBCGR] 2.2.1.14 Client Synchronize PDU"))
105 return rdp_finalize_set_flag(rdp, FINALIZE_CS_SYNCHRONIZE_PDU);
108BOOL rdp_send_client_synchronize_pdu(rdpRdp* rdp)
110 UINT16 sec_flags = 0;
111 wStream* s = rdp_data_pdu_init(rdp, &sec_flags);
116 if (!rdp_write_synchronize_pdu(s, rdp->settings))
118 Stream_Free(s, TRUE);
122 WINPR_ASSERT(rdp->mcs);
123 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SYNCHRONIZE, rdp->mcs->userId, sec_flags);
127static BOOL rdp_recv_control_pdu(
wStream* s, UINT16* action, UINT16* grantId, UINT32* controlId)
130 WINPR_ASSERT(action);
131 WINPR_ASSERT(grantId);
132 WINPR_ASSERT(controlId);
134 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
137 Stream_Read_UINT16(s, *action);
138 Stream_Read_UINT16(s, *grantId);
139 Stream_Read_UINT32(s, *controlId);
144static BOOL rdp_write_client_control_pdu(
wStream* s, UINT16 action, UINT16 grantId,
148 if (!Stream_CheckAndLogRequiredCapacity(TAG, (s), 8))
150 Stream_Write_UINT16(s, action);
151 Stream_Write_UINT16(s, grantId);
152 Stream_Write_UINT32(s, controlId);
156BOOL rdp_recv_server_control_pdu(rdpRdp* rdp,
wStream* s)
160 UINT32 controlId = 0;
165 if (!rdp_recv_control_pdu(s, &action, &grantId, &controlId))
170 case CTRLACTION_COOPERATE:
171 return rdp_finalize_set_flag(rdp, FINALIZE_SC_CONTROL_COOPERATE_PDU);
173 case CTRLACTION_GRANTED_CONTROL:
174 rdp->resendFocus = TRUE;
175 return rdp_finalize_set_flag(rdp, FINALIZE_SC_CONTROL_GRANTED_PDU);
178 char buffer[128] = WINPR_C_ARRAY_INIT;
179 WLog_WARN(TAG,
"Unexpected control PDU %s",
180 rdp_ctrlaction_string(action, buffer,
sizeof(buffer)));
187BOOL rdp_send_server_control_cooperate_pdu(rdpRdp* rdp)
189 UINT16 sec_flags = 0;
190 wStream* s = rdp_data_pdu_init(rdp, &sec_flags);
193 if (!Stream_CheckAndLogRequiredCapacity(TAG, (s), 8))
195 Stream_Free(s, TRUE);
198 Stream_Write_UINT16(s, CTRLACTION_COOPERATE);
199 Stream_Write_UINT16(s, 0);
200 Stream_Write_UINT32(s, 0);
202 WINPR_ASSERT(rdp->mcs);
203 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->userId, sec_flags);
206BOOL rdp_send_server_control_granted_pdu(rdpRdp* rdp)
208 UINT16 sec_flags = 0;
209 wStream* s = rdp_data_pdu_init(rdp, &sec_flags);
212 if (!Stream_CheckAndLogRequiredCapacity(TAG, (s), 8))
214 Stream_Free(s, TRUE);
218 WINPR_ASSERT(rdp->mcs);
219 Stream_Write_UINT16(s, CTRLACTION_GRANTED_CONTROL);
220 Stream_Write_UINT16(s, rdp->mcs->userId);
221 Stream_Write_UINT32(s, 0x03EA);
222 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->userId, sec_flags);
225BOOL rdp_send_client_control_pdu(rdpRdp* rdp, UINT16 action)
228 UINT16 ControlId = 0;
232 case CTRLACTION_COOPERATE:
233 case CTRLACTION_REQUEST_CONTROL:
237 "Invalid client control PDU::action 0x%04" PRIx16
", not allowed by client",
242 UINT16 sec_flags = 0;
243 wStream* s = rdp_data_pdu_init(rdp, &sec_flags);
246 if (!rdp_write_client_control_pdu(s, action, GrantId, ControlId))
248 Stream_Free(s, TRUE);
252 WINPR_ASSERT(rdp->mcs);
253 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->userId, sec_flags);
257static BOOL rdp_write_client_persistent_key_list_pdu(
wStream* s, UINT8 flags,
263 if (!Stream_EnsureRemainingCapacity(s, 24))
266 Stream_Write_UINT16(s, info->numEntriesCache0);
267 Stream_Write_UINT16(s, info->numEntriesCache1);
268 Stream_Write_UINT16(s, info->numEntriesCache2);
269 Stream_Write_UINT16(s, info->numEntriesCache3);
270 Stream_Write_UINT16(s, info->numEntriesCache4);
271 Stream_Write_UINT16(s, info->totalEntriesCache0);
272 Stream_Write_UINT16(s, info->totalEntriesCache1);
273 Stream_Write_UINT16(s, info->totalEntriesCache2);
274 Stream_Write_UINT16(s, info->totalEntriesCache3);
275 Stream_Write_UINT16(s, info->totalEntriesCache4);
276 Stream_Write_UINT8(s, flags);
277 Stream_Write_UINT8(s, 0);
278 Stream_Write_UINT16(s, 0);
281 if (!Stream_CheckAndLogRequiredCapacityOfSize(TAG, s, info->keyCount,
sizeof(UINT64)))
284 for (UINT32 index = 0; index < info->keyCount; index++)
286 const UINT64 val = info->keyList[index];
287 Stream_Write_UINT64(s, val);
294static BOOL rdp_send_persistent_key_list_pdu(rdpRdp* rdp, UINT8 flags,
300 UINT16 sec_flags = 0;
301 wStream* s = rdp_data_pdu_init(rdp, &sec_flags);
306 if (!rdp_write_client_persistent_key_list_pdu(s, flags, info))
308 Stream_Free(s, TRUE);
312 WINPR_ASSERT(rdp->mcs);
314 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_BITMAP_CACHE_PERSISTENT_LIST, rdp->mcs->userId,
319static UINT16 rdp_load_persistent_key_list(rdpRdp* rdp, UINT64** pKeyList)
322 UINT64* keyList =
nullptr;
325 WINPR_ASSERT(pKeyList);
326 rdpSettings* settings = rdp->settings;
333 if (!settings->BitmapCachePersistFile)
336 rdpPersistentCache* persistent = persistent_cache_new();
342 persistent_cache_open(persistent, settings->BitmapCachePersistFile, FALSE, 0);
348 const int count = persistent_cache_get_count(persistent);
349 if ((count < 0) || (count > UINT16_MAX))
352 keyCount = (UINT16)count;
353 keyList = (UINT64*)calloc(keyCount,
sizeof(UINT64));
358 for (
int index = 0; index < count; index++)
362 if (persistent_cache_read_entry(persistent, &cacheEntry) < 1)
365 keyList[index] = cacheEntry.key64;
371 persistent_cache_free(persistent);
374 persistent_cache_free(persistent);
385 const UINT16 maxSlots = step;
387 copy.keyList = &info->keyList[offset];
389 if (offset < info->totalEntriesCache0)
391 copy.numEntriesCache0 =
392 MIN(step, WINPR_ASSERTING_INT_CAST(UINT16, (info->totalEntriesCache0 - offset)));
393 step -= copy.numEntriesCache0;
394 offset += copy.numEntriesCache0;
397 if (offset < 1ull * info->totalEntriesCache0 + info->totalEntriesCache1)
399 copy.numEntriesCache1 =
400 MIN(step, WINPR_ASSERTING_INT_CAST(UINT16, (info->totalEntriesCache1 - offset)));
401 step -= copy.numEntriesCache1;
402 offset += copy.numEntriesCache1;
405 1ull * info->totalEntriesCache0 + info->totalEntriesCache1 + info->totalEntriesCache2)
407 copy.numEntriesCache2 =
408 MIN(step, WINPR_ASSERTING_INT_CAST(UINT16, (info->totalEntriesCache2 - offset)));
409 step -= copy.numEntriesCache3;
411 if (offset < 1ull * info->totalEntriesCache0 + info->totalEntriesCache1 +
412 info->totalEntriesCache2 + info->totalEntriesCache3)
414 copy.numEntriesCache3 =
415 MIN(step, WINPR_ASSERTING_INT_CAST(UINT16, (info->totalEntriesCache3 - offset)));
416 step -= copy.numEntriesCache3;
418 if (offset < 1ull * info->totalEntriesCache0 + info->totalEntriesCache1 +
419 info->totalEntriesCache2 + info->totalEntriesCache3 + info->totalEntriesCache4)
421 copy.numEntriesCache4 =
422 MIN(step, WINPR_ASSERTING_INT_CAST(UINT16, (info->totalEntriesCache4 - offset)));
423 step -= copy.numEntriesCache4;
425 copy.keyCount = maxSlots - step;
429BOOL rdp_send_client_persistent_key_list_pdu(rdpRdp* rdp)
433 rdpSettings* settings = rdp->settings;
434 const UINT32 cellInfoCount =
436 if (cellInfoCount != 5)
438 WLog_ERR(TAG,
"BitmapCacheV2NumCells %" PRIu32
", but must be 5. Aborting.", cellInfoCount);
442 UINT64* keyList =
nullptr;
444 const UINT16 keyCount = rdp_load_persistent_key_list(rdp, &keyList);
446 WLog_DBG(TAG,
"Persistent Key List: TotalKeyCount: %" PRIu16, keyCount);
448 info.totalEntriesCache0 =
449 (UINT16)MIN(UINT16_MAX, settings->BitmapCacheV2CellInfo[0].numEntries);
450 info.totalEntriesCache1 =
451 (UINT16)MIN(UINT16_MAX, settings->BitmapCacheV2CellInfo[1].numEntries);
452 info.totalEntriesCache2 =
453 (UINT16)MIN(UINT16_MAX, settings->BitmapCacheV2CellInfo[2].numEntries);
454 info.totalEntriesCache3 =
455 (UINT16)MIN(UINT16_MAX, settings->BitmapCacheV2CellInfo[3].numEntries);
456 info.totalEntriesCache4 =
457 (UINT16)MIN(UINT16_MAX, settings->BitmapCacheV2CellInfo[4].numEntries);
459 info.keyCount = keyCount;
460 info.keyList = keyList;
462 WLog_DBG(TAG,
"persistentKeyList count: %" PRIu32, info.keyCount);
465 "numEntriesCache: [0]: %" PRIu16
" [1]: %" PRIu16
" [2]: %" PRIu16
" [3]: %" PRIu16
467 info.numEntriesCache0, info.numEntriesCache1, info.numEntriesCache2,
468 info.numEntriesCache3, info.numEntriesCache4);
471 "totalEntriesCache: [0]: %" PRIu16
" [1]: %" PRIu16
" [2]: %" PRIu16
" [3]: %" PRIu16
473 info.totalEntriesCache0, info.totalEntriesCache1, info.totalEntriesCache2,
474 info.totalEntriesCache3, info.totalEntriesCache4);
477 const UINT16 maxKeysPerPDU = 169;
478 for (UINT32 offset = 0; offset < info.keyCount; offset += maxKeysPerPDU)
480 const UINT16 curKeysPerPDU = (offset + maxKeysPerPDU) > info.keyCount
481 ? (UINT16)(info.keyCount - offset)
487 flags |= PERSIST_FIRST_PDU;
488 if (offset + curKeysPerPDU >= info.keyCount)
489 flags |= PERSIST_LAST_PDU;
490 res = rdp_send_persistent_key_list_pdu(rdp, flags, &cur);
498BOOL rdp_recv_client_font_list_pdu(
wStream* s)
502 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
505 return Stream_SafeSeek(s, 8);
508BOOL rdp_recv_client_persistent_key_list_pdu(
wStream* s)
518 if (!Stream_CheckAndLogRequiredLength(TAG, s, 21))
520 WLog_ERR(TAG,
"short TS_BITMAPCACHE_PERSISTENT_LIST_PDU, need 21 bytes, got %" PRIuz,
521 Stream_GetRemainingLength(s));
525 for (
size_t x = 0; x < 5; x++)
527 Stream_Read_UINT16(s, cache);
532 for (
size_t x = 0; x < 5; x++)
535 Stream_Read_UINT16(s, tmp);
542 "TS_BITMAPCACHE_PERSISTENT_LIST_PDU::totalEntriesCacheX exceeds 262144 entries");
546 Stream_Read_UINT8(s, flags);
547 if ((flags & ~(PERSIST_LAST_PDU | PERSIST_FIRST_PDU)) != 0)
550 "TS_BITMAPCACHE_PERSISTENT_LIST_PDU::bBitMask has an invalid value of 0x%02" PRIx8,
556 if (!Stream_SafeSeek(s, 3))
558 WLog_ERR(TAG,
"short TS_BITMAPCACHE_PERSISTENT_LIST_PDU, need 3 bytes, got %" PRIuz,
559 Stream_GetRemainingLength(s));
563 if (!Stream_SafeSeek(s, count *
sizeof(UINT64)))
566 "short TS_BITMAPCACHE_PERSISTENT_LIST_PDU, need %" PRIuz
" bytes, got %" PRIuz,
567 count *
sizeof(UINT64), Stream_GetRemainingLength(s));
574static BOOL rdp_write_client_font_list_pdu(
wStream* s, UINT16 flags)
578 if (!Stream_CheckAndLogRequiredCapacity(TAG, (s), 8))
580 Stream_Write_UINT16(s, 0);
581 Stream_Write_UINT16(s, 0);
582 Stream_Write_UINT16(s, flags);
583 Stream_Write_UINT16(s, 50);
587BOOL rdp_send_client_font_list_pdu(rdpRdp* rdp, UINT16 flags)
589 UINT16 sec_flags = 0;
590 wStream* s = rdp_data_pdu_init(rdp, &sec_flags);
593 if (!rdp_write_client_font_list_pdu(s, flags))
595 Stream_Free(s, TRUE);
599 WINPR_ASSERT(rdp->mcs);
600 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_FONT_LIST, rdp->mcs->userId, sec_flags);
603BOOL rdp_recv_font_map_pdu(rdpRdp* rdp,
wStream* s)
605 UINT16 numberEntries = 0;
606 UINT16 totalNumEntries = 0;
608 UINT16 entrySize = 0;
611 WINPR_ASSERT(rdp->settings);
615 if (!rdp_has_reached_state(rdp, CONNECTION_STATE_FINALIZATION_CLIENT_FONT_MAP))
619 if (Stream_CheckAndLogRequiredLength(TAG, s, 8))
621 Stream_Read_UINT16(s, numberEntries);
622 if (numberEntries != 0)
625 "[MS-RDPBCGR] 2.2.1.22.1 Font Map PDU Data (TS_FONT_MAP_PDU)::numberEntries != 0 "
628 Stream_Read_UINT16(s, totalNumEntries);
629 if (totalNumEntries != 0)
632 "[MS-RDPBCGR] 2.2.1.22.1 Font Map PDU Data (TS_FONT_MAP_PDU)::totalNumEntries != "
635 Stream_Read_UINT16(s, mapFlags);
636 if (mapFlags != (FONTLIST_FIRST | FONTLIST_LAST))
639 "[MS-RDPBCGR] 2.2.1.22.1 Font Map PDU Data (TS_FONT_MAP_PDU)::mapFlags != 0x0003 "
640 "(FONTLIST_FIRST | FONTLIST_LAST) "
643 Stream_Read_UINT16(s, entrySize);
646 "[MS-RDPBCGR] 2.2.1.22.1 Font Map PDU Data (TS_FONT_MAP_PDU)::entrySize != 4 "
652 "[MS-RDPBCGR] 2.2.1.22.1 Font Map PDU Data (TS_FONT_MAP_PDU) paylaod size is "
655 return rdp_finalize_set_flag(rdp, FINALIZE_SC_FONT_MAP_PDU);
658BOOL rdp_send_server_font_map_pdu(rdpRdp* rdp)
660 UINT16 sec_flags = 0;
661 wStream* s = rdp_data_pdu_init(rdp, &sec_flags);
664 if (!Stream_CheckAndLogRequiredCapacity(TAG, (s), 8))
666 Stream_Free(s, TRUE);
669 Stream_Write_UINT16(s, 0);
670 Stream_Write_UINT16(s, 0);
671 Stream_Write_UINT16(s, FONTLIST_FIRST | FONTLIST_LAST);
672 Stream_Write_UINT16(s, 4);
674 WINPR_ASSERT(rdp->mcs);
675 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_FONT_MAP, rdp->mcs->userId, sec_flags);
678BOOL rdp_recv_deactivate_all(rdpRdp* rdp,
wStream* s)
680 UINT16 lengthSourceDescriptor = 0;
685 if (rdp_get_state(rdp) == CONNECTION_STATE_ACTIVE)
687 if (!rdp_finalize_set_flag(rdp, FINALIZE_DEACTIVATE_REACTIVATE))
690 rdp->was_deactivated = TRUE;
700 WINPR_ASSERT(rdp->settings);
701 if (Stream_GetRemainingLength(s) > 0)
706 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
709 Stream_Read_UINT32(s, ShareId);
713 if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
716 Stream_Read_UINT16(s, lengthSourceDescriptor);
718 if (!Stream_CheckAndLogRequiredLength(TAG, s, lengthSourceDescriptor))
721 Stream_Seek(s, lengthSourceDescriptor);
725 return rdp_client_transition_to_state(rdp,
726 CONNECTION_STATE_CAPABILITIES_EXCHANGE_DEMAND_ACTIVE);
729BOOL rdp_send_deactivate_all(rdpRdp* rdp)
732 WINPR_ASSERT(rdp->mcs);
734 if (rdp->mcs->userId == 0)
736 WLog_Print(rdp->log, WLOG_WARN,
737 "rdpMcs::userId == 0, skip sending PDU_TYPE_DEACTIVATE_ALL");
741 UINT16 sec_flags = 0;
742 wStream* s = rdp_send_stream_pdu_init(rdp, &sec_flags);
748 if (!Stream_CheckAndLogRequiredCapacityWLog(rdp->log, (s), 7))
751 WINPR_ASSERT(rdp->settings);
754 Stream_Write_UINT32(s, ShareId);
756 Stream_Write_UINT16(s, 1);
757 Stream_Write_UINT8(s, 0);
759 WINPR_ASSERT(rdp->mcs);
760 status = rdp_send_pdu(rdp, s, PDU_TYPE_DEACTIVATE_ALL, rdp->mcs->userId, sec_flags);
766BOOL rdp_server_accept_client_control_pdu(rdpRdp* rdp,
wStream* s)
770 UINT32 ControlId = 0;
771 const CONNECTION_STATE state = rdp_get_state(rdp);
776 if (!rdp_recv_control_pdu(s, &action, &GrantId, &ControlId))
782 case CTRLACTION_REQUEST_CONTROL:
783 if (!rdp_finalize_is_flag_set(rdp, FINALIZE_CS_CONTROL_COOPERATE_PDU))
785 char abuffer[128] = WINPR_C_ARRAY_INIT;
786 char buffer[1024] = WINPR_C_ARRAY_INIT;
788 "Received action=%s with GrantId=0x%04" PRIx16
", ControlId=0x%08" PRIx32
789 " in unexpected state %s [missing %s]",
790 rdp_ctrlaction_string(action, abuffer,
sizeof(abuffer)), GrantId,
791 ControlId, rdp_state_string(state),
792 rdp_finalize_flags_to_str(FINALIZE_CS_CONTROL_COOPERATE_PDU, buffer,
796 if ((GrantId != 0) || (ControlId != 0))
799 "Received CTRLACTION_COOPERATE with GrantId=0x%04" PRIx16
800 " != 0x00, ControlId=0x%08" PRIx32
" != 0x00",
804 return rdp_finalize_set_flag(rdp, FINALIZE_CS_CONTROL_REQUEST_PDU);
805 case CTRLACTION_COOPERATE:
806 if (!rdp_finalize_is_flag_set(rdp, FINALIZE_CS_SYNCHRONIZE_PDU))
808 char abuffer[128] = WINPR_C_ARRAY_INIT;
809 char buffer[1024] = WINPR_C_ARRAY_INIT;
812 "Received action=%s with GrantId=0x%04" PRIx16
", ControlId=0x%08" PRIx32
813 " in unexpected state %s [missing %s]",
814 rdp_ctrlaction_string(action, abuffer,
sizeof(abuffer)), GrantId, ControlId,
815 rdp_state_string(state),
816 rdp_finalize_flags_to_str(FINALIZE_CS_SYNCHRONIZE_PDU, buffer,
sizeof(buffer)));
819 if ((GrantId != 0) || (ControlId != 0))
822 "Received CTRLACTION_COOPERATE with GrantId=0x%04" PRIx16
823 " != 0x00, ControlId=0x%08" PRIx32
" != 0x00",
827 return rdp_finalize_set_flag(rdp, FINALIZE_CS_CONTROL_COOPERATE_PDU);
830 char abuffer[128] = WINPR_C_ARRAY_INIT;
832 "Received unexpected action=%s with GrantId=0x%04" PRIx16
833 ", ControlId=0x%08" PRIx32,
834 rdp_ctrlaction_string(action, abuffer,
sizeof(abuffer)), GrantId, ControlId);
842BOOL rdp_server_accept_client_font_list_pdu(rdpRdp* rdp,
wStream* s)
847 if (!rdp_recv_client_font_list_pdu(s))
849 rdp_finalize_set_flag(rdp, FINALIZE_CS_FONT_LIST_PDU);
851 if (!rdp_server_transition_to_state(rdp, CONNECTION_STATE_FINALIZATION_CLIENT_FONT_MAP))
854 if (!rdp_send_server_font_map_pdu(rdp))
857 if (!rdp_server_transition_to_state(rdp, CONNECTION_STATE_ACTIVE))
863BOOL rdp_server_accept_client_persistent_key_list_pdu(rdpRdp* rdp,
wStream* s)
868 if (!rdp_recv_client_persistent_key_list_pdu(s))
871 rdp_finalize_set_flag(rdp, FINALIZE_CS_PERSISTENT_KEY_LIST_PDU);
876const char* rdp_ctrlaction_string(UINT16 action,
char* buffer,
size_t size)
878 const char* actstr =
nullptr;
881 case CTRLACTION_COOPERATE:
882 actstr =
"CTRLACTION_COOPERATE";
884 case CTRLACTION_DETACH:
885 actstr =
"CTRLACTION_DETACH";
887 case CTRLACTION_GRANTED_CONTROL:
888 actstr =
"CTRLACTION_GRANTED_CONTROL";
890 case CTRLACTION_REQUEST_CONTROL:
891 actstr =
"CTRLACTION_REQUEST_CONTROL";
894 actstr =
"CTRLACTION_UNKNOWN";
898 (void)_snprintf(buffer, size,
"%s [0x%04" PRIx16
"]", actstr, action);
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 val)
Sets a UINT32 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 BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.