diff --git a/client/X11/xfreerdp.c b/client/X11/xfreerdp.c index c15a501af..d9e5b792d 100644 --- a/client/X11/xfreerdp.c +++ b/client/X11/xfreerdp.c @@ -948,7 +948,7 @@ int xfreerdp_run(freerdp* instance) xfi = ((xfContext*) instance->context)->xfi; channels = instance->context->channels; - while (!xfi->disconnect) + while (!xfi->disconnect && !freerdp_shall_disconnect(instance)) { rcount = 0; wcount = 0; diff --git a/include/freerdp/freerdp.h b/include/freerdp/freerdp.h index 2613d570b..dd993c49a 100644 --- a/include/freerdp/freerdp.h +++ b/include/freerdp/freerdp.h @@ -103,6 +103,7 @@ FREERDP_API void freerdp_context_new(freerdp* instance); FREERDP_API void freerdp_context_free(freerdp* instance); FREERDP_API boolean freerdp_connect(freerdp* instance); +FREERDP_API boolean freerdp_shall_disconnect(freerdp* instance); FREERDP_API boolean freerdp_disconnect(freerdp* instance); FREERDP_API boolean freerdp_get_fds(freerdp* instance, void** rfds, int* rcount, void** wfds, int* wcount); diff --git a/libfreerdp-core/activation.c b/libfreerdp-core/activation.c index de3b7f979..f93e75d10 100644 --- a/libfreerdp-core/activation.c +++ b/libfreerdp-core/activation.c @@ -294,6 +294,8 @@ boolean rdp_recv_deactivate_all(rdpRdp* rdp, STREAM* s) { if (rdp_check_fds(rdp) < 0) return false; + if (rdp->disconnect) + break; } return true; diff --git a/libfreerdp-core/capabilities.c b/libfreerdp-core/capabilities.c index 7c3891ce3..6db2411af 100644 --- a/libfreerdp-core/capabilities.c +++ b/libfreerdp-core/capabilities.c @@ -1798,6 +1798,9 @@ boolean rdp_recv_demand_active(rdpRdp* rdp, STREAM* s) if (!rdp_read_header(rdp, s, &length, &channelId)) return false; + if (rdp->disconnect) + return true; + if (rdp->settings->encryption) { rdp_read_security_header(s, &securityFlags); diff --git a/libfreerdp-core/connection.c b/libfreerdp-core/connection.c index 5de0a5d91..fb4fde3f2 100644 --- a/libfreerdp-core/connection.c +++ b/libfreerdp-core/connection.c @@ -450,6 +450,9 @@ boolean rdp_client_connect_demand_active(rdpRdp* rdp, STREAM* s) return true; } + if (rdp->disconnect) + return true; + if (!rdp_send_confirm_active(rdp)) return false; diff --git a/libfreerdp-core/freerdp.c b/libfreerdp-core/freerdp.c index fbf2494e4..310982240 100644 --- a/libfreerdp-core/freerdp.c +++ b/libfreerdp-core/freerdp.c @@ -147,6 +147,12 @@ boolean freerdp_disconnect(freerdp* instance) return true; } +boolean freerdp_shall_disconnect(freerdp* instance) +{ + + return instance->context->rdp->disconnect; +} + void freerdp_get_version(int* major, int* minor, int* revision) { if (major != NULL) diff --git a/libfreerdp-core/rdp.c b/libfreerdp-core/rdp.c index 702fb9440..8d499e854 100644 --- a/libfreerdp-core/rdp.c +++ b/libfreerdp-core/rdp.c @@ -237,6 +237,17 @@ boolean rdp_read_header(rdpRdp* rdp, STREAM* s, uint16* length, uint16* channel_ if (*length - 8 > stream_get_left(s)) return false; + if (MCSPDU == DomainMCSPDU_DisconnectProviderUltimatum) + { + uint8 reason; + + (void) per_read_enumerated(s, &reason, 0); + + rdp->disconnect = true; + + return true; + } + per_read_integer16(s, &initiator, MCS_BASE_CHANNEL_ID); /* initiator (UserId) */ per_read_integer16(s, channel_id, 0); /* channelId */ stream_seek(s, 1); /* dataPriority + Segmentation (0x70) */ diff --git a/libfreerdp-core/rdp.h b/libfreerdp-core/rdp.h index fb7c5c912..4a295f1f6 100644 --- a/libfreerdp-core/rdp.h +++ b/libfreerdp-core/rdp.h @@ -155,6 +155,7 @@ struct rdp_rdp uint8 fips_decrypt_key[24]; uint32 errorInfo; uint32 finalize_sc_pdus; + boolean disconnect; }; void rdp_read_security_header(STREAM* s, uint16* flags);