diff --git a/libfreerdp/core/client.c b/libfreerdp/core/client.c index 02f44ac85..4650604b7 100644 --- a/libfreerdp/core/client.c +++ b/libfreerdp/core/client.c @@ -303,7 +303,7 @@ UINT freerdp_channels_attach(freerdp* instance) WINPR_ASSERT(instance->context->settings); channels = instance->context->channels; - hostname = instance->context->settings->ServerHostname; + hostname = freerdp_settings_get_string(instance->context->settings, FreeRDP_ServerHostname); hostnameLength = strlen(hostname); for (index = 0; index < channels->clientDataCount; index++) @@ -366,7 +366,7 @@ UINT freerdp_channels_detach(freerdp* instance) WINPR_ASSERT(channels); WINPR_ASSERT(context->settings); - hostname = context->settings->ServerHostname; + hostname = freerdp_settings_get_string(context->settings, FreeRDP_ServerHostname); hostnameLength = strlen(hostname); for (index = 0; index < channels->clientDataCount; index++) @@ -429,7 +429,7 @@ UINT freerdp_channels_post_connect(rdpChannels* channels, freerdp* instance) WINPR_ASSERT(instance->context->settings); channels->connected = TRUE; - hostname = instance->context->settings->ServerHostname; + hostname = freerdp_settings_get_string(instance->context->settings, FreeRDP_ServerHostname); hostnameLength = strlen(hostname); for (index = 0; index < channels->clientDataCount; index++) @@ -575,7 +575,7 @@ const char* freerdp_channels_get_name_by_id(freerdp* instance, UINT16 channelId) if (!mcsChannel) return NULL; - return (const char*)mcsChannel->Name; + return mcsChannel->Name; } BOOL freerdp_channels_process_message_free(wMessage* message, DWORD type) @@ -913,6 +913,8 @@ static UINT VCAPITYPE FreeRDP_VirtualChannelInitEx( { CHANNEL_DEF* channel = freerdp_settings_get_pointer_array_writable( settings, FreeRDP_ChannelDefArray, settings->ChannelCount); + if (!channel) + continue; strncpy(channel->name, pChannelDef->name, CHANNEL_NAME_LEN); channel->options = pChannelDef->options; settings->ChannelCount++; @@ -990,6 +992,8 @@ static UINT VCAPITYPE FreeRDP_VirtualChannelInit(LPVOID* ppInitHandle, PCHANNEL_ for (index = 0; index < channelCount; index++) { + UINT32 ChannelCount = freerdp_settings_get_uint32(settings, FreeRDP_ChannelCount); + pChannelDef = &pChannel[index]; pChannelOpenData = &channels->openDataList[channels->openDataCount]; pChannelOpenData->OpenHandle = InterlockedIncrement(&g_OpenHandleSeq); @@ -1001,13 +1005,14 @@ static UINT VCAPITYPE FreeRDP_VirtualChannelInit(LPVOID* ppInitHandle, PCHANNEL_ strncpy(pChannelOpenData->name, pChannelDef->name, CHANNEL_NAME_LEN); pChannelOpenData->options = pChannelDef->options; - if (settings->ChannelCount < CHANNEL_MAX_COUNT) + if (ChannelCount < CHANNEL_MAX_COUNT) { channel = freerdp_settings_get_pointer_array_writable(settings, FreeRDP_ChannelDefArray, - settings->ChannelCount); + ChannelCount++); strncpy(channel->name, pChannelDef->name, CHANNEL_NAME_LEN); channel->options = pChannelDef->options; - settings->ChannelCount++; + if (!freerdp_settings_set_uint32(settings, FreeRDP_ChannelCount, ChannelCount)) + return ERROR_INTERNAL_ERROR; } channels->openDataCount++; @@ -1273,6 +1278,11 @@ int freerdp_channels_client_load(rdpChannels* channels, rdpSettings* settings, CHANNEL_ENTRY_POINTS_FREERDP EntryPoints = { 0 }; CHANNEL_CLIENT_DATA* pChannelClientData; + WINPR_ASSERT(channels); + WINPR_ASSERT(channels->instance); + WINPR_ASSERT(channels->instance->context); + WINPR_ASSERT(entry); + if (channels->clientDataCount + 1 > CHANNEL_MAX_COUNT) { WLog_ERR(TAG, "error: too many channels"); @@ -1296,7 +1306,7 @@ int freerdp_channels_client_load(rdpChannels* channels, rdpSettings* settings, EntryPoints.pVirtualChannelWrite = FreeRDP_VirtualChannelWrite; EntryPoints.MagicNumber = FREERDP_CHANNEL_MAGIC_NUMBER; EntryPoints.pExtendedData = data; - EntryPoints.context = ((freerdp*)settings->instance)->context; + EntryPoints.context = channels->instance->context; /* enable VirtualChannelInit */ channels->can_call_init = TRUE; EnterCriticalSection(&channels->channelsLock); @@ -1323,6 +1333,11 @@ int freerdp_channels_client_load_ex(rdpChannels* channels, rdpSettings* settings CHANNEL_INIT_DATA* pChannelInitData = NULL; CHANNEL_CLIENT_DATA* pChannelClientData = NULL; + WINPR_ASSERT(channels); + WINPR_ASSERT(channels->instance); + WINPR_ASSERT(channels->instance->context); + WINPR_ASSERT(entryEx); + if (channels->clientDataCount + 1 > CHANNEL_MAX_COUNT) { WLog_ERR(TAG, "error: too many channels"); @@ -1348,7 +1363,7 @@ int freerdp_channels_client_load_ex(rdpChannels* channels, rdpSettings* settings EntryPointsEx.pVirtualChannelWriteEx = FreeRDP_VirtualChannelWriteEx; EntryPointsEx.MagicNumber = FREERDP_CHANNEL_MAGIC_NUMBER; EntryPointsEx.pExtendedData = data; - EntryPointsEx.context = ((freerdp*)settings->instance)->context; + EntryPointsEx.context = channels->instance->context; /* enable VirtualChannelInit */ channels->can_call_init = TRUE; EnterCriticalSection(&channels->channelsLock); diff --git a/libfreerdp/core/connection.c b/libfreerdp/core/connection.c index db5a5e4e0..72384c589 100644 --- a/libfreerdp/core/connection.c +++ b/libfreerdp/core/connection.c @@ -549,6 +549,12 @@ BOOL rdp_client_redirect(rdpRdp* rdp) if (!rdp_client_disconnect_and_clear(rdp)) return FALSE; + freerdp_channels_disconnect(rdp->context->channels, rdp->context->instance); + freerdp_channels_close(rdp->context->channels, rdp->context->instance); + freerdp_channels_free(rdp->context->channels); + rdp->context->channels = freerdp_channels_new(rdp->context->instance); + WINPR_ASSERT(rdp->context->channels); + if (rdp_redirection_apply_settings(rdp) != 0) return FALSE; @@ -611,6 +617,14 @@ BOOL rdp_client_redirect(rdpRdp* rdp) if (!IFCALLRESULT(TRUE, rdp->context->instance->Redirect, rdp->context->instance)) return FALSE; + BOOL ok = IFCALLRESULT(TRUE, rdp->context->instance->LoadChannels, rdp->context->instance); + if (!ok) + return FALSE; + + if (CHANNEL_RC_OK != + freerdp_channels_pre_connect(rdp->context->channels, rdp->context->instance)) + return FALSE; + status = rdp_client_connect(rdp); if (status) diff --git a/libfreerdp/core/freerdp.c b/libfreerdp/core/freerdp.c index a87c04dcf..5487f801d 100644 --- a/libfreerdp/core/freerdp.c +++ b/libfreerdp/core/freerdp.c @@ -103,7 +103,18 @@ BOOL freerdp_connect(freerdp* instance) instance->ConnectionCallbackState = CLIENT_STATE_PRECONNECT_PASSED; if (status) + { + freerdp_settings_free(rdp->originalSettings); + rdp->originalSettings = freerdp_settings_clone(settings); + if (!rdp->originalSettings) + return 0; + + BOOL ok = IFCALLRESULT(TRUE, instance->LoadChannels, instance); + if (!ok) + return 0; + status2 = freerdp_channels_pre_connect(instance->context->channels, instance); + } if (settings->KeyboardLayout == KBD_JAPANESE || settings->KeyboardLayout == KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002) diff --git a/libfreerdp/core/rdp.c b/libfreerdp/core/rdp.c index e00e063a5..dad84f2a6 100644 --- a/libfreerdp/core/rdp.c +++ b/libfreerdp/core/rdp.c @@ -1890,6 +1890,13 @@ rdpRdp* rdp_new(rdpContext* context) } else rdp->settings = context->settings; + + /* Keep a backup copy of settings for later comparisons */ + freerdp_settings_free(rdp->originalSettings); + rdp->originalSettings = freerdp_settings_clone(rdp->settings); + if (!rdp->originalSettings) + return FALSE; + rdp->settings->instance = context->instance; context->settings = rdp->settings; @@ -2092,6 +2099,7 @@ void rdp_free(rdpRdp* rdp) rdp_reset_free(rdp); freerdp_settings_free(rdp->settings); + freerdp_settings_free(rdp->originalSettings); input_free(rdp->input); update_free(rdp->update); diff --git a/libfreerdp/core/rdp.h b/libfreerdp/core/rdp.h index f813079b6..603ee2bec 100644 --- a/libfreerdp/core/rdp.h +++ b/libfreerdp/core/rdp.h @@ -163,6 +163,7 @@ struct rdp_rdp rdpLicense* license; rdpRedirection* redirection; rdpSettings* settings; + rdpSettings* originalSettings; rdpTransport* transport; rdpAutoDetect* autodetect; rdpHeartbeat* heartbeat;