diff --git a/libfreerdp/core/activation.c b/libfreerdp/core/activation.c index b21d05f5d..f33449782 100644 --- a/libfreerdp/core/activation.c +++ b/libfreerdp/core/activation.c @@ -26,16 +26,6 @@ #define TAG FREERDP_TAG("core.activation") -/* -static const char* const CTRLACTION_STRINGS[] = -{ - "", - "CTRLACTION_REQUEST_CONTROL", - "CTRLACTION_GRANTED_CONTROL", - "CTRLACTION_DETACH", - "CTRLACTION_COOPERATE" -}; -*/ static BOOL rdp_recv_server_synchronize_pdu(rdpRdp* rdp, wStream* s); static BOOL rdp_recv_client_font_list_pdu(wStream* s); static BOOL rdp_recv_client_persistent_key_list_pdu(wStream* s); @@ -72,8 +62,7 @@ BOOL rdp_recv_server_synchronize_pdu(rdpRdp* rdp, wStream* s) WINPR_ASSERT(rdp); WINPR_ASSERT(s); - rdp->finalize_sc_pdus |= FINALIZE_SC_SYNCHRONIZE_PDU; - return TRUE; + return rdp_finalize_set_flag(rdp, FINALIZE_SC_SYNCHRONIZE_PDU); } BOOL rdp_send_server_synchronize_pdu(rdpRdp* rdp) @@ -100,7 +89,8 @@ BOOL rdp_recv_client_synchronize_pdu(rdpRdp* rdp, wStream* s) WINPR_ASSERT(rdp); WINPR_ASSERT(s); - rdp->finalize_sc_pdus |= FINALIZE_SC_SYNCHRONIZE_PDU; + if (!rdp_finalize_set_flag(rdp, FINALIZE_SC_SYNCHRONIZE_PDU)) + return FALSE; if (!Stream_CheckAndLogRequiredLength(TAG, s, 4)) return FALSE; @@ -173,16 +163,19 @@ BOOL rdp_recv_server_control_pdu(rdpRdp* rdp, wStream* s) switch (action) { case CTRLACTION_COOPERATE: - rdp->finalize_sc_pdus |= FINALIZE_SC_CONTROL_COOPERATE_PDU; - break; + return rdp_finalize_set_flag(rdp, FINALIZE_SC_CONTROL_COOPERATE_PDU); case CTRLACTION_GRANTED_CONTROL: - rdp->finalize_sc_pdus |= FINALIZE_SC_CONTROL_GRANTED_PDU; rdp->resendFocus = TRUE; - break; + return rdp_finalize_set_flag(rdp, FINALIZE_SC_CONTROL_GRANTED_PDU); + default: + { + char buffer[128] = { 0 }; + WLog_WARN(TAG, "Unexpected control PDU %s", + rdp_ctrlaction_string(action, buffer, sizeof(buffer))); + return TRUE; + } } - - return TRUE; } BOOL rdp_send_server_control_cooperate_pdu(rdpRdp* rdp) @@ -526,8 +519,7 @@ BOOL rdp_recv_server_font_map_pdu(rdpRdp* rdp, wStream* s) WINPR_ASSERT(s); WLog_WARN(TAG, "Invalid PDU received: FONT_MAP only allowed client -> server"); - rdp->finalize_sc_pdus |= FINALIZE_SC_FONT_MAP_PDU; - return FALSE; + return rdp_finalize_set_flag(rdp, FINALIZE_SC_FONT_MAP_PDU); } BOOL rdp_recv_client_font_map_pdu(rdpRdp* rdp, wStream* s) @@ -535,7 +527,8 @@ BOOL rdp_recv_client_font_map_pdu(rdpRdp* rdp, wStream* s) WINPR_ASSERT(rdp); WINPR_ASSERT(s); - rdp->finalize_sc_pdus |= FINALIZE_SC_FONT_MAP_PDU; + if (!rdp_finalize_set_flag(rdp, FINALIZE_SC_FONT_MAP_PDU)) + return FALSE; if (Stream_GetRemainingLength(s) >= 8) { @@ -576,9 +569,10 @@ BOOL rdp_recv_deactivate_all(rdpRdp* rdp, wStream* s) WINPR_ASSERT(s); if (rdp_get_state(rdp) == CONNECTION_STATE_ACTIVE) - rdp->deactivation_reactivation = TRUE; - else - rdp->deactivation_reactivation = FALSE; + { + if (!rdp_finalize_set_flag(rdp, FINALIZE_DEACTIVATE_REACTIVATE)) + return FALSE; + } /* * Windows XP can send short DEACTIVATE_ALL PDU that doesn't contain @@ -729,3 +723,29 @@ BOOL rdp_server_accept_client_persistent_key_list_pdu(rdpRdp* rdp, wStream* s) // TODO: Actually do something with this return TRUE; } + +const char* rdp_ctrlaction_string(UINT16 action, char* buffer, size_t size) +{ + const char* actstr; + switch (action) + { + case CTRLACTION_COOPERATE: + actstr = "CTRLACTION_COOPERATE"; + break; + case CTRLACTION_DETACH: + actstr = "CTRLACTION_DETACH"; + break; + case CTRLACTION_GRANTED_CONTROL: + actstr = "CTRLACTION_GRANTED_CONTROL"; + break; + case CTRLACTION_REQUEST_CONTROL: + actstr = "CTRLACTION_REQUEST_CONTROL"; + break; + default: + actstr = "CTRLACTION_UNKNOWN"; + break; + } + + _snprintf(buffer, size, "%s [0x%04" PRIx16 "]", actstr, action); + return buffer; +} diff --git a/libfreerdp/core/activation.h b/libfreerdp/core/activation.h index c795819a2..9f114d1f5 100644 --- a/libfreerdp/core/activation.h +++ b/libfreerdp/core/activation.h @@ -28,10 +28,13 @@ #define SYNCMSGTYPE_SYNC 0x0001 -#define CTRLACTION_REQUEST_CONTROL 0x0001 -#define CTRLACTION_GRANTED_CONTROL 0x0002 -#define CTRLACTION_DETACH 0x0003 -#define CTRLACTION_COOPERATE 0x0004 +typedef enum +{ + CTRLACTION_REQUEST_CONTROL = 0x0001, + CTRLACTION_GRANTED_CONTROL = 0x0002, + CTRLACTION_DETACH = 0x0003, + CTRLACTION_COOPERATE = 0x0004 +} CTRLACTION; struct _RDP_BITMAP_PERSISTENT_INFO { @@ -56,6 +59,7 @@ typedef struct _RDP_BITMAP_PERSISTENT_INFO RDP_BITMAP_PERSISTENT_INFO; #define FONTLIST_FIRST 0x0001 #define FONTLIST_LAST 0x0002 +FREERDP_LOCAL const char* rdp_ctrlaction_string(UINT16 action, char* buffer, size_t size); FREERDP_LOCAL BOOL rdp_recv_deactivate_all(rdpRdp* rdp, wStream* s); FREERDP_LOCAL BOOL rdp_send_deactivate_all(rdpRdp* rdp); diff --git a/libfreerdp/core/connection.c b/libfreerdp/core/connection.c index f36b26521..db5a5e4e0 100644 --- a/libfreerdp/core/connection.c +++ b/libfreerdp/core/connection.c @@ -1143,7 +1143,8 @@ int rdp_client_connect_finalize(rdpRdp* rdp) * host cache and a deactivation reactivation sequence is *not* in progress. */ - if (!rdp->deactivation_reactivation && rdp->settings->BitmapCachePersistEnabled) + if (!rdp_finalize_is_flag_set(rdp, FINALIZE_DEACTIVATE_REACTIVATE) && + rdp->settings->BitmapCachePersistEnabled) { if (!rdp_send_client_persistent_key_list_pdu(rdp)) return -1; @@ -1166,7 +1167,7 @@ int rdp_client_transition_to_state(rdpRdp* rdp, CONNECTION_STATE state) { case CONNECTION_STATE_FINALIZATION: update_reset_state(rdp->update); - rdp->finalize_sc_pdus = 0; + rdp_finalize_reset_flags(rdp, FALSE); break; case CONNECTION_STATE_ACTIVE: @@ -1174,7 +1175,8 @@ int rdp_client_transition_to_state(rdpRdp* rdp, CONNECTION_STATE state) ActivatedEventArgs activatedEvent; rdpContext* context = rdp->context; EventArgsInit(&activatedEvent, "libfreerdp"); - activatedEvent.firstActivation = !rdp->deactivation_reactivation; + activatedEvent.firstActivation = + !rdp_finalize_is_flag_set(rdp, FINALIZE_DEACTIVATE_REACTIVATE); PubSub_OnActivated(context->pubSub, context, &activatedEvent); } @@ -1458,7 +1460,8 @@ BOOL rdp_server_transition_to_state(rdpRdp* rdp, CONNECTION_STATE state) break; case CONNECTION_STATE_FINALIZATION: - rdp->finalize_sc_pdus = 0; + if (!rdp_finalize_reset_flags(rdp, FALSE)) + goto fail; break; case CONNECTION_STATE_ACTIVE: diff --git a/libfreerdp/core/rdp.c b/libfreerdp/core/rdp.c index 335446339..e00e063a5 100644 --- a/libfreerdp/core/rdp.c +++ b/libfreerdp/core/rdp.c @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -1745,7 +1746,7 @@ int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra) case CONNECTION_STATE_FINALIZATION: status = rdp_recv_pdu(rdp, s); - if ((status >= 0) && (rdp->finalize_sc_pdus == FINALIZE_SC_COMPLETE)) + if ((status >= 0) && rdp_finalize_is_flag_set(rdp, FINALIZE_SC_COMPLETE)) { rdp_client_transition_to_state(rdp, CONNECTION_STATE_ACTIVE); return 2; @@ -2070,8 +2071,7 @@ BOOL rdp_reset(rdpRdp* rdp) goto fail; rdp->errorInfo = 0; - rdp->deactivation_reactivation = FALSE; - rdp->finalize_sc_pdus = 0; + rdp_finalize_reset_flags(rdp, TRUE); rc = TRUE; @@ -2144,3 +2144,70 @@ void* rdp_get_io_callback_context(rdpRdp* rdp) WINPR_ASSERT(rdp); return rdp->ioContext; } + +const char* rdp_finalize_flags_to_str(UINT32 flags, char* buffer, size_t size) +{ + char number[32] = { 0 }; + const UINT32 mask = ~(FINALIZE_SC_SYNCHRONIZE_PDU | FINALIZE_SC_CONTROL_COOPERATE_PDU | + FINALIZE_SC_CONTROL_GRANTED_PDU | FINALIZE_SC_FONT_MAP_PDU | + FINALIZE_CS_SYNCHRONIZE_PDU | FINALIZE_CS_CONTROL_COOPERATE_PDU | + FINALIZE_CS_CONTROL_REQUEST_PDU | FINALIZE_CS_PERSISTENT_KEY_LIST_PDU | + FINALIZE_CS_FONT_LIST_PDU | FINALIZE_DEACTIVATE_REACTIVATE); + + if (flags & FINALIZE_SC_SYNCHRONIZE_PDU) + winpr_str_append("FINALIZE_SC_SYNCHRONIZE_PDU", buffer, size, "|"); + if (flags & FINALIZE_SC_CONTROL_COOPERATE_PDU) + winpr_str_append("FINALIZE_SC_CONTROL_COOPERATE_PDU", buffer, size, "|"); + if (flags & FINALIZE_SC_CONTROL_GRANTED_PDU) + winpr_str_append("FINALIZE_SC_CONTROL_GRANTED_PDU", buffer, size, "|"); + if (flags & FINALIZE_SC_FONT_MAP_PDU) + winpr_str_append("FINALIZE_SC_FONT_MAP_PDU", buffer, size, "|"); + if (flags & FINALIZE_CS_SYNCHRONIZE_PDU) + winpr_str_append("FINALIZE_CS_SYNCHRONIZE_PDU", buffer, size, "|"); + if (flags & FINALIZE_CS_CONTROL_COOPERATE_PDU) + winpr_str_append("FINALIZE_CS_CONTROL_COOPERATE_PDU", buffer, size, "|"); + if (flags & FINALIZE_CS_CONTROL_REQUEST_PDU) + winpr_str_append("FINALIZE_CS_CONTROL_REQUEST_PDU", buffer, size, "|"); + if (flags & FINALIZE_CS_PERSISTENT_KEY_LIST_PDU) + winpr_str_append("FINALIZE_CS_PERSISTENT_KEY_LIST_PDU", buffer, size, "|"); + if (flags & FINALIZE_CS_FONT_LIST_PDU) + winpr_str_append("FINALIZE_CS_FONT_LIST_PDU", buffer, size, "|"); + if (flags & FINALIZE_DEACTIVATE_REACTIVATE) + winpr_str_append("FINALIZE_DEACTIVATE_REACTIVATE", buffer, size, "|"); + if (flags & mask) + winpr_str_append("UNKNOWN_FLAG", buffer, size, "|"); + if (flags == 0) + winpr_str_append("NO_FLAG_SET", buffer, size, "|"); + _snprintf(number, sizeof(number), " [0x%04" PRIx16 "]", flags); + winpr_str_append(number, buffer, size, "|"); + return buffer; +} + +BOOL rdp_finalize_reset_flags(rdpRdp* rdp, BOOL clearAll) +{ + WINPR_ASSERT(rdp); + WLog_DBG(TAG, "[%s] reset finalize_sc_pdus", rdp_get_state_string(rdp)); + if (clearAll) + rdp->finalize_sc_pdus = 0; + else + rdp->finalize_sc_pdus &= FINALIZE_DEACTIVATE_REACTIVATE; + return TRUE; +} + +BOOL rdp_finalize_set_flag(rdpRdp* rdp, UINT32 flag) +{ + char buffer[1024] = { 0 }; + + WINPR_ASSERT(rdp); + + WLog_DBG(TAG, "[%s] received flag %s", rdp_get_state_string(rdp), + rdp_finalize_flags_to_str(flag, buffer, sizeof(buffer))); + rdp->finalize_sc_pdus |= flag; + return TRUE; +} + +BOOL rdp_finalize_is_flag_set(rdpRdp* rdp, UINT32 flag) +{ + WINPR_ASSERT(rdp); + return (rdp->finalize_sc_pdus & flag) == flag; +} diff --git a/libfreerdp/core/rdp.h b/libfreerdp/core/rdp.h index 46b138296..f813079b6 100644 --- a/libfreerdp/core/rdp.h +++ b/libfreerdp/core/rdp.h @@ -89,11 +89,29 @@ #define PDU_TYPE_FLOW_RESPONSE 0x42 #define PDU_TYPE_FLOW_STOP 0x43 -#define FINALIZE_SC_SYNCHRONIZE_PDU 0x01 -#define FINALIZE_SC_CONTROL_COOPERATE_PDU 0x02 -#define FINALIZE_SC_CONTROL_GRANTED_PDU 0x04 -#define FINALIZE_SC_FONT_MAP_PDU 0x08 -#define FINALIZE_SC_COMPLETE 0x0F +typedef enum +{ + FINALIZE_SC_SYNCHRONIZE_PDU = 0x01, + FINALIZE_SC_CONTROL_COOPERATE_PDU = 0x02, + FINALIZE_SC_CONTROL_GRANTED_PDU = 0x04, + FINALIZE_SC_FONT_MAP_PDU = 0x08, + + FINALIZE_CS_SYNCHRONIZE_PDU = 0x10, + FINALIZE_CS_CONTROL_COOPERATE_PDU = 0x20, + FINALIZE_CS_CONTROL_REQUEST_PDU = 0x40, + FINALIZE_CS_PERSISTENT_KEY_LIST_PDU = 0x80, + FINALIZE_CS_FONT_LIST_PDU = 0x100, + + FINALIZE_DEACTIVATE_REACTIVATE = 0x200 +} rdpFinalizePduType; + +#define FINALIZE_SC_COMPLETE \ + (FINALIZE_SC_SYNCHRONIZE_PDU | FINALIZE_SC_CONTROL_COOPERATE_PDU | \ + FINALIZE_SC_CONTROL_GRANTED_PDU | FINALIZE_SC_FONT_MAP_PDU) +#define FINALIZE_CS_COMPLETE \ + (FINALIZE_CS_SYNCHRONIZE_PDU | FINALIZE_CS_CONTROL_COOPERATE_PDU | \ + FINALIZE_CS_CONTROL_REQUEST_PDU | FINALIZE_CS_PERSISTENT_KEY_LIST_PDU | \ + FINALIZE_CS_FONT_LIST_PDU) /* Data PDU Types */ typedef enum @@ -173,7 +191,6 @@ struct rdp_rdp UINT32 errorInfo; UINT32 finalize_sc_pdus; BOOL resendFocus; - BOOL deactivation_reactivation; BOOL AwaitCapabilities; UINT64 inBytes; UINT64 inPackets; @@ -248,6 +265,11 @@ FREERDP_LOCAL void* rdp_get_io_callback_context(rdpRdp* rdp); const char* data_pdu_type_to_string(UINT8 type); const char* pdu_type_to_str(UINT16 pduType); +BOOL rdp_finalize_reset_flags(rdpRdp* rdp, BOOL clearAll); +BOOL rdp_finalize_set_flag(rdpRdp* rdp, UINT32 flag); +BOOL rdp_finalize_is_flag_set(rdpRdp* rdp, UINT32 flag); +const char* rdp_finalize_flags_to_str(UINT32 flags, char* buffer, size_t size); + BOOL rdp_decrypt(rdpRdp* rdp, wStream* s, UINT16* pLength, UINT16 securityFlags); BOOL rdp_set_error_info(rdpRdp* rdp, UINT32 errorInfo);