diff --git a/channels/drdynvc/client/drdynvc_main.c b/channels/drdynvc/client/drdynvc_main.c index 086e02069..5ff06dab2 100644 --- a/channels/drdynvc/client/drdynvc_main.c +++ b/channels/drdynvc/client/drdynvc_main.c @@ -283,6 +283,8 @@ void dvcman_free(IWTSVirtualChannelManager* pChannelMgr) free(listener); } + dvcman->num_listeners = 0; + for (i = 0; i < dvcman->num_plugins; i++) { pPlugin = dvcman->plugins[i]; @@ -291,7 +293,10 @@ void dvcman_free(IWTSVirtualChannelManager* pChannelMgr) pPlugin->Terminated(pPlugin); } + dvcman->num_plugins = 0; + StreamPool_Free(dvcman->pool); + free(dvcman); } diff --git a/channels/rdpgfx/client/rdpgfx_main.c b/channels/rdpgfx/client/rdpgfx_main.c index e1ca84051..8e98a6f2c 100644 --- a/channels/rdpgfx/client/rdpgfx_main.c +++ b/channels/rdpgfx/client/rdpgfx_main.c @@ -955,9 +955,16 @@ static int rdpgfx_plugin_terminated(IWTSPlugin* pPlugin) WLog_Print(gfx->log, WLOG_DEBUG, "Terminated"); if (gfx->listener_callback) + { free(gfx->listener_callback); + gfx->listener_callback = NULL; + } - zgfx_context_free(gfx->zgfx); + if (gfx->zgfx) + { + zgfx_context_free(gfx->zgfx); + gfx->zgfx = NULL; + } count = HashTable_GetKeys(gfx->SurfaceTable, &pKeys); diff --git a/client/X11/cli/xfreerdp.c b/client/X11/cli/xfreerdp.c index 3006ad50f..1f46010d4 100644 --- a/client/X11/cli/xfreerdp.c +++ b/client/X11/cli/xfreerdp.c @@ -71,7 +71,6 @@ int main(int argc, char* argv[]) thread = freerdp_client_get_thread(context); WaitForSingleObject(thread, INFINITE); - GetExitCodeThread(thread, &dwExitCode); freerdp_client_stop(context); diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c index c404d424a..1aace96c7 100644 --- a/client/X11/xf_client.c +++ b/client/X11/xf_client.c @@ -203,7 +203,7 @@ void xf_draw_screen(xfContext* xfc, int x, int y, int w, int h) { if (w == 0 || h == 0) { - WLog_WARN(TAG, "invalid width and/or height specified: w=%d h=%d", w, h); + WLog_WARN(TAG, "invalid width and/or height specified: w=%d h=%d", w, h); return; } @@ -788,7 +788,6 @@ int _xf_error_handler(Display* d, XErrorEvent* ev) static void xf_post_disconnect(freerdp* instance) { xfContext* xfc; - rdpChannels* channels = channels = instance->context->channels; if (!instance || !instance->context || !instance->settings) return; @@ -895,7 +894,7 @@ BOOL xf_pre_connect(freerdp* instance) { if (!XInitThreads()) { - WLog_WARN(TAG, "XInitThreads() failure"); + WLog_WARN(TAG, "XInitThreads() failure"); xfc->UseXThreads = FALSE; } } @@ -911,7 +910,7 @@ BOOL xf_pre_connect(freerdp* instance) if (xfc->debug) { - WLog_INFO(TAG, "Enabling X11 debug mode."); + WLog_INFO(TAG, "Enabling X11 debug mode."); XSynchronize(xfc->display, TRUE); _def_error_handler = XSetErrorHandler(_xf_error_handler); } @@ -1127,6 +1126,7 @@ BOOL xf_post_connect(freerdp *instance) palette_cache_register_callbacks(instance->update); instance->update->BitmapUpdate = xf_gdi_bitmap_update; } + instance->update->PlaySound = xf_play_sound; instance->update->SetKeyboardIndicators = xf_keyboard_set_indicators; @@ -1360,39 +1360,44 @@ void* xf_input_thread(void *arg) BOOL xf_auto_reconnect(freerdp* instance) { + UINT32 maxRetries; + UINT32 numRetries = 0; xfContext* xfc = (xfContext*) instance->context; - UINT32 num_retries = 0; - UINT32 max_retries = instance->settings->AutoReconnectMaxRetries; + rdpSettings* settings = xfc->settings; + + maxRetries = settings->AutoReconnectMaxRetries; /* Only auto reconnect on network disconnects. */ if (freerdp_error_info(instance) != 0) return FALSE; /* A network disconnect was detected */ - WLog_INFO(TAG, "Network disconnect!"); + WLog_INFO(TAG, "Network disconnect!"); - if (!instance->settings->AutoReconnectionEnabled) + if (!settings->AutoReconnectionEnabled) { /* No auto-reconnect - just quit */ return FALSE; } /* Perform an auto-reconnect. */ - for (;;) + while (TRUE) { /* Quit retrying if max retries has been exceeded */ - if (num_retries++ >= max_retries) + if (numRetries++ >= maxRetries) { return FALSE; } /* Attempt the next reconnect */ - WLog_INFO(TAG, "Attempting reconnect (%u of %u)", num_retries, max_retries); + WLog_INFO(TAG, "Attempting reconnect (%u of %u)", numRetries, maxRetries); + if (freerdp_reconnect(instance)) { xfc->disconnect = FALSE; return TRUE; } + sleep(5); } @@ -1487,7 +1492,7 @@ void* xf_client_thread(void *param) nCount += freerdp_get_event_handles(context, &handles[nCount]); } - waitStatus = WaitForMultipleObjects(nCount, handles, FALSE, INFINITE); + waitStatus = WaitForMultipleObjects(nCount, handles, FALSE, 100); if (!settings->AsyncTransport) { @@ -1642,9 +1647,13 @@ static int xfreerdp_client_start(rdpContext* context) WLog_ERR(TAG, "error: server hostname was not specified with /v:[:port]"); return -1; } + xfc->disconnect = FALSE; - xfc->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) xf_client_thread, - context->instance, 0, NULL); + + xfc->thread = CreateThread(NULL, 0, + (LPTHREAD_START_ROUTINE) xf_client_thread, + context->instance, 0, NULL); + return 0; } @@ -1654,8 +1663,10 @@ static int xfreerdp_client_stop(rdpContext* context) if (context->settings->AsyncInput) { - wMessageQueue *queue; + wMessageQueue* queue; + queue = freerdp_get_message_queue(context->instance, FREERDP_INPUT_MESSAGE_QUEUE); + if (queue) MessageQueue_PostQuit(queue, 0); } @@ -1666,6 +1677,7 @@ static int xfreerdp_client_stop(rdpContext* context) if (xfc->thread) { + WaitForSingleObject(xfc->thread, INFINITE); CloseHandle(xfc->thread); xfc->thread = NULL; } @@ -1706,26 +1718,45 @@ static void xfreerdp_client_free(freerdp* instance, rdpContext* context) { xfContext* xfc = (xfContext*) context; - if (context) + if (!context) + return; + + xf_window_free(xfc); + + if (xfc->bitmap_buffer) { - xf_window_free(xfc); - - if (xfc->bitmap_buffer) - _aligned_free(xfc->bitmap_buffer); - - if (xfc->display) - XCloseDisplay(xfc->display); - - if (xfc->x11event) - CloseHandle(xfc->x11event); - - if (context->channels) - { - freerdp_channels_close(context->channels, instance); - freerdp_channels_free(context->channels); - context->channels = NULL; - } + _aligned_free(xfc->bitmap_buffer); + xfc->bitmap_buffer = NULL; } + + if (xfc->display) + { + XCloseDisplay(xfc->display); + xfc->display = NULL; + } + + if (xfc->x11event) + { + CloseHandle(xfc->x11event); + xfc->x11event = NULL; + } + + if (context->channels) + { + freerdp_channels_close(context->channels, instance); + freerdp_channels_free(context->channels); + context->channels = NULL; + } + + if (xfc->mutex) + { + WaitForSingleObject(xfc->mutex, INFINITE); + CloseHandle(xfc->mutex); + xfc->mutex = NULL; + } + + xf_monitors_free(xfc, instance->settings); + gdi_free(instance); } int RdpClientEntry(RDP_CLIENT_ENTRY_POINTS* pEntryPoints) diff --git a/client/X11/xf_gfx.c b/client/X11/xf_gfx.c index 673d046c1..7ac3874c2 100644 --- a/client/X11/xf_gfx.c +++ b/client/X11/xf_gfx.c @@ -890,7 +890,4 @@ void xf_graphics_pipeline_init(xfContext* xfc, RdpgfxClientContext* gfx) void xf_graphics_pipeline_uninit(xfContext* xfc, RdpgfxClientContext* gfx) { region16_uninit(&(xfc->invalidRegion)); - - gfx->custom = NULL; - xfc->gfx = NULL; } diff --git a/libfreerdp/core/freerdp.c b/libfreerdp/core/freerdp.c index 0ee563c7c..1e763dcda 100644 --- a/libfreerdp/core/freerdp.c +++ b/libfreerdp/core/freerdp.c @@ -62,8 +62,8 @@ BOOL freerdp_connect(freerdp* instance) { rdpRdp* rdp; + BOOL status = TRUE; rdpSettings* settings; - BOOL status = FALSE; ConnectionResultEventArgs e; /* We always set the return code to 0 before we start the connect sequence*/ @@ -73,7 +73,10 @@ BOOL freerdp_connect(freerdp* instance) rdp = instance->context->rdp; settings = instance->settings; - IFCALLRET(instance->PreConnect, status, instance); + if (!rdp->reconnect) + { + IFCALLRET(instance->PreConnect, status, instance); + } if (settings->KeyboardLayout == KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002) { @@ -116,7 +119,11 @@ BOOL freerdp_connect(freerdp* instance) instance->update->dump_rfx = TRUE; } - IFCALLRET(instance->PostConnect, status, instance); + if (!rdp->reconnect) + { + IFCALLRET(instance->PostConnect, status, instance); + } + update_post_connect(instance->update); if (!status) @@ -345,9 +352,14 @@ BOOL freerdp_disconnect(freerdp* instance) rdpRdp* rdp; rdp = instance->context->rdp; + rdp_client_disconnect(rdp); update_post_disconnect(instance->update); - IFCALL(instance->PostDisconnect, instance); + + if (!rdp->reconnect) + { + IFCALL(instance->PostDisconnect, instance); + } if (instance->update->pcap_rfx) { @@ -361,8 +373,19 @@ BOOL freerdp_disconnect(freerdp* instance) BOOL freerdp_reconnect(freerdp* instance) { - freerdp_disconnect(instance); - return freerdp_connect(instance); + BOOL status = TRUE; + rdpRdp* rdp = instance->context->rdp; + + rdp->reconnect = TRUE; + + status = freerdp_disconnect(instance); + + if (status) + status = freerdp_connect(instance); + + rdp->reconnect = FALSE; + + return status; } BOOL freerdp_shall_disconnect(freerdp* instance) diff --git a/libfreerdp/core/rdp.h b/libfreerdp/core/rdp.h index fb8531b01..5397f4176 100644 --- a/libfreerdp/core/rdp.h +++ b/libfreerdp/core/rdp.h @@ -169,6 +169,7 @@ struct rdp_rdp BYTE fips_decrypt_key[24]; UINT32 errorInfo; UINT32 finalize_sc_pdus; + BOOL reconnect; BOOL disconnect; BOOL resendFocus; BOOL deactivation_reactivation; diff --git a/libfreerdp/crypto/tls.c b/libfreerdp/crypto/tls.c index 613c185bc..6f8b15202 100644 --- a/libfreerdp/crypto/tls.c +++ b/libfreerdp/crypto/tls.c @@ -582,6 +582,7 @@ BOOL tls_prepare(rdpTls* tls, BIO *underlying, const SSL_METHOD *method, int opt #endif { tls->ctx = SSL_CTX_new(method); + if (!tls->ctx) { WLog_ERR(TAG, "SSL_CTX_new failed"); @@ -593,8 +594,10 @@ BOOL tls_prepare(rdpTls* tls, BIO *underlying, const SSL_METHOD *method, int opt SSL_CTX_set_options(tls->ctx, options); SSL_CTX_set_read_ahead(tls->ctx, 1); - if (tls->settings->PermittedTLSCiphers) { - if(!SSL_CTX_set_cipher_list(tls->ctx, tls->settings->PermittedTLSCiphers)) { + if (tls->settings->PermittedTLSCiphers) + { + if (!SSL_CTX_set_cipher_list(tls->ctx, tls->settings->PermittedTLSCiphers)) + { WLog_ERR(TAG, "SSL_CTX_set_cipher_list %s failed", tls->settings->PermittedTLSCiphers); return FALSE; } @@ -755,8 +758,6 @@ int tls_connect(rdpTls* tls, BIO *underlying) return tls_do_handshake(tls, TRUE); } - - BOOL tls_accept(rdpTls* tls, BIO *underlying, const char* cert_file, const char* privatekey_file) { long options = 0; @@ -1392,6 +1393,12 @@ void tls_free(rdpTls* tls) tls->ctx = NULL; } + if (tls->bio) + { + BIO_free(tls->bio); + tls->bio = NULL; + } + if (tls->PublicKey) { free(tls->PublicKey);