| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| 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_server_font_map_pdu(rdpRdp* rdp, wStream* s); |
| static BOOL rdp_recv_client_font_map_pdu(rdpRdp* rdp, wStream* s); |
| static BOOL rdp_send_server_font_map_pdu(rdpRdp* rdp); |
| |
| static void rdp_write_synchronize_pdu(wStream* s, rdpSettings* settings) |
| { |
| Stream_Write_UINT16(s, SYNCMSGTYPE_SYNC); |
| Stream_Write_UINT16(s, settings->PduSource); |
| } |
| |
| BOOL rdp_recv_synchronize_pdu(rdpRdp* rdp, wStream* s) |
| { |
| if (rdp->settings->ServerMode) |
| return rdp_recv_server_synchronize_pdu(rdp, s); |
| else |
| return rdp_recv_client_synchronize_pdu(rdp, s); |
| } |
| |
| BOOL rdp_recv_server_synchronize_pdu(rdpRdp* rdp, wStream* s) |
| { |
| rdp->finalize_sc_pdus |= FINALIZE_SC_SYNCHRONIZE_PDU; |
| return TRUE; |
| } |
| |
| BOOL rdp_send_server_synchronize_pdu(rdpRdp* rdp) |
| { |
| wStream* s = rdp_data_pdu_init(rdp); |
| rdp_write_synchronize_pdu(s, rdp->settings); |
| return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SYNCHRONIZE, rdp->mcs->userId); |
| } |
| |
| BOOL rdp_recv_client_synchronize_pdu(rdpRdp* rdp, wStream* s) |
| { |
| UINT16 messageType; |
| rdp->finalize_sc_pdus |= FINALIZE_SC_SYNCHRONIZE_PDU; |
| |
| if (Stream_GetRemainingLength(s) < 4) |
| return FALSE; |
| |
| Stream_Read_UINT16(s, messageType); |
| |
| if (messageType != SYNCMSGTYPE_SYNC) |
| return FALSE; |
| |
| |
| Stream_Seek_UINT16(s); |
| return TRUE; |
| } |
| |
| BOOL rdp_send_client_synchronize_pdu(rdpRdp* rdp) |
| { |
| wStream* s = rdp_data_pdu_init(rdp); |
| rdp_write_synchronize_pdu(s, rdp->settings); |
| return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SYNCHRONIZE, rdp->mcs->userId); |
| } |
| |
| static BOOL rdp_recv_control_pdu(wStream* s, UINT16* action) |
| { |
| if (Stream_GetRemainingLength(s) < 8) |
| return FALSE; |
| |
| Stream_Read_UINT16(s, *action); |
| Stream_Seek_UINT16(s); |
| Stream_Seek_UINT32(s); |
| return TRUE; |
| } |
| |
| static void rdp_write_client_control_pdu(wStream* s, UINT16 action) |
| { |
| Stream_Write_UINT16(s, action); |
| Stream_Write_UINT16(s, 0); |
| Stream_Write_UINT32(s, 0); |
| } |
| |
| BOOL rdp_recv_server_control_pdu(rdpRdp* rdp, wStream* s) |
| { |
| UINT16 action; |
| |
| if (rdp_recv_control_pdu(s, &action) == FALSE) |
| return FALSE; |
| |
| switch (action) |
| { |
| case CTRLACTION_COOPERATE: |
| rdp->finalize_sc_pdus |= FINALIZE_SC_CONTROL_COOPERATE_PDU; |
| break; |
| |
| case CTRLACTION_GRANTED_CONTROL: |
| rdp->finalize_sc_pdus |= FINALIZE_SC_CONTROL_GRANTED_PDU; |
| rdp->resendFocus = TRUE; |
| break; |
| } |
| |
| return TRUE; |
| } |
| |
| BOOL rdp_send_server_control_cooperate_pdu(rdpRdp* rdp) |
| { |
| wStream* s = rdp_data_pdu_init(rdp); |
| Stream_Write_UINT16(s, CTRLACTION_COOPERATE); |
| Stream_Write_UINT16(s, 0); |
| Stream_Write_UINT32(s, 0); |
| return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->userId); |
| } |
| |
| BOOL rdp_send_server_control_granted_pdu(rdpRdp* rdp) |
| { |
| wStream* s = rdp_data_pdu_init(rdp); |
| Stream_Write_UINT16(s, CTRLACTION_GRANTED_CONTROL); |
| Stream_Write_UINT16(s, rdp->mcs->userId); |
| Stream_Write_UINT32(s, 0x03EA); |
| return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->userId); |
| } |
| |
| BOOL rdp_send_client_control_pdu(rdpRdp* rdp, UINT16 action) |
| { |
| wStream* s = rdp_data_pdu_init(rdp); |
| rdp_write_client_control_pdu(s, action); |
| return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->userId); |
| } |
| |
| static void rdp_write_persistent_list_entry(wStream* s, UINT32 key1, UINT32 key2) |
| { |
| Stream_Write_UINT32(s, key1); |
| Stream_Write_UINT32(s, key2); |
| } |
| |
| static void rdp_write_client_persistent_key_list_pdu(wStream* s, rdpSettings* settings) |
| { |
| Stream_Write_UINT16(s, 0); |
| Stream_Write_UINT16(s, 0); |
| Stream_Write_UINT16(s, 0); |
| Stream_Write_UINT16(s, 0); |
| Stream_Write_UINT16(s, 0); |
| Stream_Write_UINT16(s, 0); |
| Stream_Write_UINT16(s, 0); |
| Stream_Write_UINT16(s, 0); |
| Stream_Write_UINT16(s, 0); |
| Stream_Write_UINT16(s, 0); |
| Stream_Write_UINT8(s, PERSIST_FIRST_PDU | PERSIST_LAST_PDU); |
| Stream_Write_UINT8(s, 0); |
| Stream_Write_UINT16(s, 0); |
| |
| } |
| |
| BOOL rdp_send_client_persistent_key_list_pdu(rdpRdp* rdp) |
| { |
| wStream* s; |
| s = rdp_data_pdu_init(rdp); |
| rdp_write_client_persistent_key_list_pdu(s, rdp->settings); |
| return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_BITMAP_CACHE_PERSISTENT_LIST, rdp->mcs->userId); |
| } |
| |
| BOOL rdp_recv_client_font_list_pdu(wStream* s) |
| { |
| if (Stream_GetRemainingLength(s) < 8) |
| return FALSE; |
| |
| |
| Stream_Seek(s, 8); |
| return TRUE; |
| } |
| |
| static void rdp_write_client_font_list_pdu(wStream* s, UINT16 flags) |
| { |
| Stream_Write_UINT16(s, 0); |
| Stream_Write_UINT16(s, 0); |
| Stream_Write_UINT16(s, flags); |
| Stream_Write_UINT16(s, 50); |
| } |
| |
| BOOL rdp_send_client_font_list_pdu(rdpRdp* rdp, UINT16 flags) |
| { |
| wStream* s = rdp_data_pdu_init(rdp); |
| rdp_write_client_font_list_pdu(s, flags); |
| return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_FONT_LIST, rdp->mcs->userId); |
| } |
| |
| BOOL rdp_recv_font_map_pdu(rdpRdp* rdp, wStream* s) |
| { |
| if (rdp->settings->ServerMode) |
| return rdp_recv_server_font_map_pdu(rdp, s); |
| else |
| return rdp_recv_client_font_map_pdu(rdp, s); |
| } |
| |
| BOOL rdp_recv_server_font_map_pdu(rdpRdp* rdp, wStream* s) |
| { |
| rdp->finalize_sc_pdus |= FINALIZE_SC_FONT_MAP_PDU; |
| return TRUE; |
| } |
| |
| BOOL rdp_recv_client_font_map_pdu(rdpRdp* rdp, wStream* s) |
| { |
| rdp->finalize_sc_pdus |= FINALIZE_SC_FONT_MAP_PDU; |
| |
| if (Stream_GetRemainingLength(s) >= 8) |
| { |
| Stream_Seek_UINT16(s); |
| Stream_Seek_UINT16(s); |
| Stream_Seek_UINT16(s); |
| Stream_Seek_UINT16(s); |
| } |
| |
| return TRUE; |
| } |
| |
| BOOL rdp_send_server_font_map_pdu(rdpRdp* rdp) |
| { |
| wStream* s; |
| s = rdp_data_pdu_init(rdp); |
| Stream_Write_UINT16(s, 0); |
| Stream_Write_UINT16(s, 0); |
| Stream_Write_UINT16(s, FONTLIST_FIRST | FONTLIST_LAST); |
| Stream_Write_UINT16(s, 4); |
| return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_FONT_MAP, rdp->mcs->userId); |
| } |
| |
| BOOL rdp_recv_deactivate_all(rdpRdp* rdp, wStream* s) |
| { |
| UINT16 lengthSourceDescriptor; |
| UINT32 timeout; |
| |
| if (rdp->state == CONNECTION_STATE_ACTIVE) |
| rdp->deactivation_reactivation = TRUE; |
| else |
| rdp->deactivation_reactivation = FALSE; |
| |
| |
| |
| |
| |
| if (Stream_GetRemainingLength(s) > 0) |
| { |
| do |
| { |
| if (Stream_GetRemainingLength(s) < 4) |
| break; |
| |
| Stream_Read_UINT32(s, rdp->settings->ShareId); |
| |
| if (Stream_GetRemainingLength(s) < 2) |
| break; |
| |
| Stream_Read_UINT16(s, lengthSourceDescriptor); |
| |
| if (Stream_GetRemainingLength(s) < lengthSourceDescriptor) |
| break; |
| |
| Stream_Seek(s, lengthSourceDescriptor); |
| } while (0); |
| } |
| |
| rdp_client_transition_to_state(rdp, CONNECTION_STATE_CAPABILITIES_EXCHANGE); |
| |
| for (timeout = 0; timeout < rdp->settings->TcpAckTimeout; timeout += 100) |
| { |
| if (rdp_check_fds(rdp) < 0) |
| return FALSE; |
| |
| if (freerdp_shall_disconnect(rdp->instance)) |
| return TRUE; |
| |
| if (rdp->state == CONNECTION_STATE_ACTIVE) |
| return TRUE; |
| |
| Sleep(100); |
| } |
| |
| WLog_ERR(TAG, "Timeout waiting for activation"); |
| return FALSE; |
| } |
| |
| BOOL rdp_send_deactivate_all(rdpRdp* rdp) |
| { |
| wStream* s = rdp_send_stream_pdu_init(rdp); |
| BOOL status; |
| |
| if (!s) |
| return FALSE; |
| |
| Stream_Write_UINT32(s, rdp->settings->ShareId); |
| Stream_Write_UINT16(s, 1); |
| Stream_Write_UINT8(s, 0); |
| status = rdp_send_pdu(rdp, s, PDU_TYPE_DEACTIVATE_ALL, rdp->mcs->userId); |
| Stream_Release(s); |
| return status; |
| } |
| |
| BOOL rdp_server_accept_client_control_pdu(rdpRdp* rdp, wStream* s) |
| { |
| UINT16 action; |
| |
| if (!rdp_recv_control_pdu(s, &action)) |
| return FALSE; |
| |
| if (action == CTRLACTION_REQUEST_CONTROL) |
| { |
| if (!rdp_send_server_control_granted_pdu(rdp)) |
| return FALSE; |
| } |
| |
| return TRUE; |
| } |
| |
| BOOL rdp_server_accept_client_font_list_pdu(rdpRdp* rdp, wStream* s) |
| { |
| rdpSettings* settings = rdp->settings; |
| freerdp_peer* peer = rdp->context->peer; |
| |
| if (!rdp_recv_client_font_list_pdu(s)) |
| return FALSE; |
| |
| if (settings->SupportMonitorLayoutPdu && settings->MonitorCount && peer->AdjustMonitorsLayout && |
| peer->AdjustMonitorsLayout(peer)) |
| { |
| |
| MONITOR_DEF* monitors = (MONITOR_DEF*)calloc(settings->MonitorCount, sizeof(MONITOR_DEF)); |
| |
| if (!monitors) |
| return FALSE; |
| |
| if (!display_convert_rdp_monitor_to_monitor_def(settings->MonitorCount, |
| settings->MonitorDefArray, &monitors)) |
| { |
| free(monitors); |
| return FALSE; |
| } |
| |
| if (!freerdp_display_send_monitor_layout(rdp->context, settings->MonitorCount, monitors)) |
| { |
| free(monitors); |
| return FALSE; |
| } |
| |
| free(monitors); |
| } |
| |
| if (!rdp_send_server_font_map_pdu(rdp)) |
| return FALSE; |
| |
| if (rdp_server_transition_to_state(rdp, CONNECTION_STATE_ACTIVE) < 0) |
| return FALSE; |
| |
| return TRUE; |
| } |