diff --git a/server/proxy/CMakeLists.txt b/server/proxy/CMakeLists.txt index ec212168e..710c5328b 100644 --- a/server/proxy/CMakeLists.txt +++ b/server/proxy/CMakeLists.txt @@ -32,6 +32,8 @@ set(${MODULE_PREFIX}_SRCS pf_input.h pf_update.c pf_update.h + pf_rail.c + pf_rail.h pf_rdpgfx.c pf_rdpgfx.h pf_disp.c diff --git a/server/proxy/config.ini b/server/proxy/config.ini index 34fc6d84b..5ec72e487 100644 --- a/server/proxy/config.ini +++ b/server/proxy/config.ini @@ -33,6 +33,7 @@ GFX = TRUE DisplayControl = TRUE Clipboard = TRUE AudioOutput = TRUE +RemoteApp = TRUE [Clipboard] TextOnly = FALSE diff --git a/server/proxy/pf_channels.c b/server/proxy/pf_channels.c index 75e719eda..fd184536d 100644 --- a/server/proxy/pf_channels.c +++ b/server/proxy/pf_channels.c @@ -35,6 +35,7 @@ #include "pf_channels.h" #include "pf_client.h" #include "pf_context.h" +#include "pf_rail.h" #include "pf_rdpgfx.h" #include "pf_cliprdr.h" #include "pf_disp.h" @@ -55,13 +56,24 @@ void pf_OnChannelConnectedEventHandler(void* data, ChannelConnectedEventArgs* e) { pClientContext* pc = (pClientContext*)data; pServerContext* ps = pc->pdata->ps; - WLog_INFO(TAG, "Channel connected: %s", e->name); if (strcmp(e->name, RDPEI_DVC_CHANNEL_NAME) == 0) { pc->rdpei = (RdpeiClientContext*)e->pInterface; } + else if (strcmp(e->name, RAIL_SVC_CHANNEL_NAME) == 0) + { + pc->rail = (RailClientContext*)e->pInterface; + + if (ps->rail->Start(ps->rail) != CHANNEL_RC_OK) + { + WLog_ERR(TAG, "failed to start RAIL server"); + return; + } + + pf_rail_pipeline_init(pc->rail, ps->rail, pc->pdata); + } else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0) { pf_channels_wait_for_server_dynvc(ps); @@ -132,7 +144,6 @@ void pf_OnChannelDisconnectedEventHandler(void* data, ChannelDisconnectedEventAr rdpContext* context = (rdpContext*)data; pClientContext* pc = (pClientContext*)context; pServerContext* ps = pc->pdata->ps; - WLog_INFO(TAG, "Channel disconnected: %s", e->name); if (strcmp(e->name, RDPEI_DVC_CHANNEL_NAME) == 0) @@ -147,6 +158,13 @@ void pf_OnChannelDisconnectedEventHandler(void* data, ChannelDisconnectedEventAr gdi_graphics_pipeline_uninit(context->gdi, pc->gfx_decoder); rdpgfx_client_context_free(pc->gfx_decoder); } + else if (strcmp(e->name, RAIL_SVC_CHANNEL_NAME) == 0) + { + if (!ps->rail->Stop(ps->rail)) + WLog_ERR(TAG, "failed to close rail server"); + + pc->rail = NULL; + } else if (strcmp(e->name, DISP_DVC_CHANNEL_NAME) == 0) { if (ps->disp->Close(ps->disp) != CHANNEL_RC_OK) @@ -205,6 +223,13 @@ BOOL pf_server_channels_init(pServerContext* ps) return FALSE; } + if (config->RemoteApp && + WTSVirtualChannelManagerIsChannelJoined(ps->vcm, RAIL_SVC_CHANNEL_NAME)) + { + if (!pf_rail_context_init(ps)) + return FALSE; + } + return pf_modules_run_hook(HOOK_TYPE_SERVER_CHANNELS_INIT, context); } @@ -234,5 +259,11 @@ void pf_server_channels_free(pServerContext* ps) ps->rdpsnd = NULL; } + if (ps->rail) + { + rail_server_context_free(ps->rail); + ps->rail = NULL; + } + pf_modules_run_hook(HOOK_TYPE_SERVER_CHANNELS_FREE, (rdpContext*)ps); } diff --git a/server/proxy/pf_config.c b/server/proxy/pf_config.c index a2a9b1209..469cb979e 100644 --- a/server/proxy/pf_config.c +++ b/server/proxy/pf_config.c @@ -152,6 +152,7 @@ static BOOL pf_config_load_channels(wIniFile* ini, proxyConfig* config) config->DisplayControl = pf_config_get_bool(ini, "Channels", "DisplayControl"); config->Clipboard = pf_config_get_bool(ini, "Channels", "Clipboard"); config->AudioOutput = pf_config_get_bool(ini, "Channels", "AudioOutput"); + config->RemoteApp = pf_config_get_bool(ini, "Channels", "RemoteApp"); return TRUE; } @@ -324,6 +325,7 @@ void pf_server_config_print(proxyConfig* config) CONFIG_PRINT_BOOL(config, DisplayControl); CONFIG_PRINT_BOOL(config, Clipboard); CONFIG_PRINT_BOOL(config, AudioOutput); + CONFIG_PRINT_BOOL(config, RemoteApp); CONFIG_PRINT_SECTION("Clipboard"); CONFIG_PRINT_BOOL(config, TextOnly); diff --git a/server/proxy/pf_config.h b/server/proxy/pf_config.h index 36b536d08..b943e2c1a 100644 --- a/server/proxy/pf_config.h +++ b/server/proxy/pf_config.h @@ -56,6 +56,7 @@ struct proxy_config BOOL DisplayControl; BOOL Clipboard; BOOL AudioOutput; + BOOL RemoteApp; /* clipboard specific settings */ BOOL TextOnly; diff --git a/server/proxy/pf_context.c b/server/proxy/pf_context.c index ab140a7d0..b31836df1 100644 --- a/server/proxy/pf_context.c +++ b/server/proxy/pf_context.c @@ -92,6 +92,7 @@ BOOL pf_context_init_server_context(freerdp_peer* client) BOOL pf_context_copy_settings(rdpSettings* dst, const rdpSettings* src) { rdpSettings* before_copy = freerdp_settings_clone(dst); + if (!before_copy) return FALSE; @@ -127,7 +128,6 @@ BOOL pf_context_copy_settings(rdpSettings* dst, const rdpSettings* src) { /* adjust instance pointer for client's context */ dst->instance = before_copy->instance; - /* RdpServerRsaKey must be set to NULL if `dst` is client's context */ dst->RdpServerRsaKey = NULL; } diff --git a/server/proxy/pf_context.h b/server/proxy/pf_context.h index af10cfcfe..c4c92067b 100644 --- a/server/proxy/pf_context.h +++ b/server/proxy/pf_context.h @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include #include #include @@ -49,6 +51,7 @@ struct p_server_context HANDLE vcm; HANDLE dynvcReady; + RailServerContext* rail; RdpgfxServerContext* gfx; DispServerContext* disp; CliprdrServerContext* cliprdr; @@ -73,6 +76,7 @@ struct p_client_context RdpgfxClientContext* gfx_decoder; DispClientContext* disp; CliprdrClientContext* cliprdr; + RailClientContext* rail; /* * In a case when freerdp_connect fails, diff --git a/server/proxy/pf_rail.c b/server/proxy/pf_rail.c new file mode 100644 index 000000000..6aabe1419 --- /dev/null +++ b/server/proxy/pf_rail.c @@ -0,0 +1,336 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * FreeRDP Proxy Server + * + * Copyright 2019 Mati Shabtay + * Copyright 2019 Kobi Mizrachi + * Copyright 2019 Idan Freiberg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "pf_rail.h" +#include "pf_context.h" +#include "pf_log.h" + +#define TAG PROXY_TAG("rail") + +BOOL pf_rail_context_init(pServerContext* ps) +{ + RailServerContext* rail; + rail = ps->rail = rail_server_context_new(ps->vcm); + + if (!rail) + { + return FALSE; + } + + rail->rdpContext = (rdpContext*)ps; + return TRUE; +} + +static UINT pf_rail_client_on_open(RailClientContext* context, BOOL* sendHandshake) +{ + if (NULL != sendHandshake) + *sendHandshake = FALSE; + + return CHANNEL_RC_OK; +} + +/* Callbacks from client side */ +static UINT pf_rail_server_handshake(RailClientContext* client, + const RAIL_HANDSHAKE_ORDER* handshake) +{ + proxyData* pdata = (proxyData*)client->custom; + RailServerContext* server = (RailServerContext*)pdata->ps->rail; + WLog_DBG(TAG, __FUNCTION__); + return server->ServerHandshake(server, handshake); +} + +static UINT pf_rail_server_handshake_ex(RailClientContext* client, + const RAIL_HANDSHAKE_EX_ORDER* handshakeEx) +{ + proxyData* pdata = (proxyData*)client->custom; + RailServerContext* server = (RailServerContext*)pdata->ps->rail; + WLog_DBG(TAG, __FUNCTION__); + return server->ServerHandshakeEx(server, handshakeEx); +} + +static UINT pf_rail_server_sysparam(RailClientContext* client, const RAIL_SYSPARAM_ORDER* sysparam) +{ + proxyData* pdata = (proxyData*)client->custom; + RailServerContext* server = (RailServerContext*)pdata->ps->rail; + WLog_DBG(TAG, __FUNCTION__); + return server->ServerSysparam(server, sysparam); +} + +static UINT pf_rail_server_local_move_size(RailClientContext* client, + const RAIL_LOCALMOVESIZE_ORDER* localMoveSize) +{ + proxyData* pdata = (proxyData*)client->custom; + RailServerContext* server = (RailServerContext*)pdata->ps->rail; + WLog_DBG(TAG, __FUNCTION__); + return server->ServerLocalMoveSize(server, localMoveSize); +} + +static UINT pf_rail_server_min_max_info(RailClientContext* client, + const RAIL_MINMAXINFO_ORDER* minMaxInfo) +{ + proxyData* pdata = (proxyData*)client->custom; + RailServerContext* server = (RailServerContext*)pdata->ps->rail; + WLog_DBG(TAG, __FUNCTION__); + return server->ServerMinMaxInfo(server, minMaxInfo); +} + +static UINT pf_rail_server_taskbar_info(RailClientContext* client, + const RAIL_TASKBAR_INFO_ORDER* taskbarInfo) +{ + proxyData* pdata = (proxyData*)client->custom; + RailServerContext* server = (RailServerContext*)pdata->ps->rail; + WLog_DBG(TAG, __FUNCTION__); + return server->ServerTaskbarInfo(server, taskbarInfo); +} + +static UINT pf_rail_server_langbar_info(RailClientContext* client, + const RAIL_LANGBAR_INFO_ORDER* langbarInfo) +{ + proxyData* pdata = (proxyData*)client->custom; + RailServerContext* server = (RailServerContext*)pdata->ps->rail; + WLog_DBG(TAG, __FUNCTION__); + return server->ServerLangbarInfo(server, langbarInfo); +} + +static UINT pf_rail_server_exec_result(RailClientContext* client, + const RAIL_EXEC_RESULT_ORDER* execResult) +{ + proxyData* pdata = (proxyData*)client->custom; + RailServerContext* server = (RailServerContext*)pdata->ps->rail; + WLog_DBG(TAG, __FUNCTION__); + return server->ServerExecResult(server, execResult); +} + +static UINT pf_rail_server_z_order_sync(RailClientContext* client, + const RAIL_ZORDER_SYNC* zOrderSync) +{ + proxyData* pdata = (proxyData*)client->custom; + RailServerContext* server = (RailServerContext*)pdata->ps->rail; + WLog_DBG(TAG, __FUNCTION__); + return server->ServerZOrderSync(server, zOrderSync); +} + +static UINT pf_rail_server_cloak(RailClientContext* client, const RAIL_CLOAK* cloak) +{ + proxyData* pdata = (proxyData*)client->custom; + RailServerContext* server = (RailServerContext*)pdata->ps->rail; + WLog_DBG(TAG, __FUNCTION__); + return server->ServerCloak(server, cloak); +} + +static UINT +pf_rail_server_power_display_request(RailClientContext* client, + const RAIL_POWER_DISPLAY_REQUEST* powerDisplayRequest) +{ + proxyData* pdata = (proxyData*)client->custom; + RailServerContext* server = (RailServerContext*)pdata->ps->rail; + WLog_DBG(TAG, __FUNCTION__); + return server->ServerPowerDisplayRequest(server, powerDisplayRequest); +} + +static UINT pf_rail_server_get_appid_resp(RailClientContext* client, + const RAIL_GET_APPID_RESP_ORDER* getAppidResp) +{ + proxyData* pdata = (proxyData*)client->custom; + RailServerContext* server = (RailServerContext*)pdata->ps->rail; + WLog_DBG(TAG, __FUNCTION__); + return server->ServerGetAppidResp(server, getAppidResp); +} + +static UINT pf_rail_server_get_appid_resp_ex(RailClientContext* client, + const RAIL_GET_APPID_RESP_EX* getAppidRespEx) +{ + proxyData* pdata = (proxyData*)client->custom; + RailServerContext* server = (RailServerContext*)pdata->ps->rail; + WLog_DBG(TAG, __FUNCTION__); + return server->ServerGetAppidRespEx(server, getAppidRespEx); +} + +/* Callbacks from server side */ + +static UINT pf_rail_client_handshake(RailServerContext* server, + const RAIL_HANDSHAKE_ORDER* handshake) +{ + proxyData* pdata = (proxyData*)server->custom; + RailClientContext* client = (RailClientContext*)pdata->pc->rail; + WLog_DBG(TAG, __FUNCTION__); + return client->ClientHandshake(client, handshake); +} + +static UINT pf_rail_client_client_status(RailServerContext* server, + const RAIL_CLIENT_STATUS_ORDER* clientStatus) +{ + proxyData* pdata = (proxyData*)server->custom; + RailClientContext* client = (RailClientContext*)pdata->pc->rail; + WLog_DBG(TAG, __FUNCTION__); + return client->ClientInformation(client, clientStatus); +} + +static UINT pf_rail_client_exec(RailServerContext* server, const RAIL_EXEC_ORDER* exec) +{ + proxyData* pdata = (proxyData*)server->custom; + RailClientContext* client = (RailClientContext*)pdata->pc->rail; + WLog_DBG(TAG, __FUNCTION__); + return client->ClientExecute(client, exec); +} + +static UINT pf_rail_client_sysparam(RailServerContext* server, const RAIL_SYSPARAM_ORDER* sysparam) +{ + proxyData* pdata = (proxyData*)server->custom; + RailClientContext* client = (RailClientContext*)pdata->pc->rail; + WLog_DBG(TAG, __FUNCTION__); + return client->ClientSystemParam(client, sysparam); +} + +static UINT pf_rail_client_activate(RailServerContext* server, const RAIL_ACTIVATE_ORDER* activate) +{ + proxyData* pdata = (proxyData*)server->custom; + RailClientContext* client = (RailClientContext*)pdata->pc->rail; + WLog_DBG(TAG, __FUNCTION__); + return client->ClientActivate(client, activate); +} + +static UINT pf_rail_client_sysmenu(RailServerContext* server, const RAIL_SYSMENU_ORDER* sysmenu) +{ + proxyData* pdata = (proxyData*)server->custom; + RailClientContext* client = (RailClientContext*)pdata->pc->rail; + WLog_DBG(TAG, __FUNCTION__); + return client->ClientSystemMenu(client, sysmenu); +} + +static UINT pf_rail_client_syscommand(RailServerContext* server, + const RAIL_SYSCOMMAND_ORDER* syscommand) +{ + proxyData* pdata = (proxyData*)server->custom; + RailClientContext* client = (RailClientContext*)pdata->pc->rail; + WLog_DBG(TAG, __FUNCTION__); + return client->ClientSystemCommand(client, syscommand); +} + +static UINT pf_rail_client_notify_event(RailServerContext* server, + const RAIL_NOTIFY_EVENT_ORDER* notifyEvent) +{ + proxyData* pdata = (proxyData*)server->custom; + RailClientContext* client = (RailClientContext*)pdata->pc->rail; + WLog_DBG(TAG, __FUNCTION__); + return client->ClientNotifyEvent(client, notifyEvent); +} + +static UINT pf_rail_client_window_move(RailServerContext* server, + const RAIL_WINDOW_MOVE_ORDER* windowMove) +{ + proxyData* pdata = (proxyData*)server->custom; + RailClientContext* client = (RailClientContext*)pdata->pc->rail; + WLog_DBG(TAG, __FUNCTION__); + return client->ClientWindowMove(client, windowMove); +} + +static UINT pf_rail_client_snap_arrange(RailServerContext* server, + const RAIL_SNAP_ARRANGE* snapArrange) +{ + proxyData* pdata = (proxyData*)server->custom; + RailClientContext* client = (RailClientContext*)pdata->pc->rail; + WLog_DBG(TAG, __FUNCTION__); + return client->ClientSnapArrange(client, snapArrange); +} + +static UINT pf_rail_client_get_appid_req(RailServerContext* server, + const RAIL_GET_APPID_REQ_ORDER* getAppidReq) +{ + proxyData* pdata = (proxyData*)server->custom; + RailClientContext* client = (RailClientContext*)pdata->pc->rail; + WLog_DBG(TAG, __FUNCTION__); + return client->ClientGetAppIdRequest(client, getAppidReq); +} + +static UINT pf_rail_client_langbar_info(RailServerContext* server, + const RAIL_LANGBAR_INFO_ORDER* langbarInfo) +{ + proxyData* pdata = (proxyData*)server->custom; + RailClientContext* client = (RailClientContext*)pdata->pc->rail; + WLog_DBG(TAG, __FUNCTION__); + return client->ClientLanguageBarInfo(client, langbarInfo); +} + +static UINT pf_rail_client_language_ime_info(RailServerContext* server, + const RAIL_LANGUAGEIME_INFO_ORDER* languageImeInfo) +{ + proxyData* pdata = (proxyData*)server->custom; + RailClientContext* client = (RailClientContext*)pdata->pc->rail; + WLog_DBG(TAG, __FUNCTION__); + return client->ClientLanguageIMEInfo(client, languageImeInfo); +} + +static UINT pf_rail_client_compartment_info(RailServerContext* server, + const RAIL_COMPARTMENT_INFO_ORDER* compartmentInfo) +{ + WLog_DBG(TAG, __FUNCTION__); + return 0; +} + +static UINT pf_rail_client_cloak(RailServerContext* server, const RAIL_CLOAK* cloak) +{ + proxyData* pdata = (proxyData*)server->custom; + RailClientContext* client = (RailClientContext*)pdata->pc->rail; + WLog_DBG(TAG, __FUNCTION__); + return client->ClientCloak(client, cloak); +} + +void pf_rail_pipeline_init(RailClientContext* client, RailServerContext* server, proxyData* pdata) +{ + /* Set server and client side references to proxy data */ + client->custom = (void*)pdata; + server->custom = (void*)pdata; + /* Set client callbacks */ + client->OnOpen = pf_rail_client_on_open; + client->ServerHandshake = pf_rail_server_handshake; + client->ServerHandshakeEx = pf_rail_server_handshake_ex; + client->ServerSystemParam = pf_rail_server_sysparam; + client->ServerLocalMoveSize = pf_rail_server_local_move_size; + client->ServerMinMaxInfo = pf_rail_server_min_max_info; + client->ServerTaskBarInfo = pf_rail_server_taskbar_info; + client->ServerLanguageBarInfo = pf_rail_server_langbar_info; + client->ServerExecuteResult = pf_rail_server_exec_result; + client->ServerZOrderSync = pf_rail_server_z_order_sync; + client->ServerCloak = pf_rail_server_cloak; + client->ServerPowerDisplayRequest = pf_rail_server_power_display_request; + client->ServerGetAppIdResponse = pf_rail_server_get_appid_resp; + client->ServerGetAppidResponseExtended = pf_rail_server_get_appid_resp_ex; + /* Set server callbacks */ + server->ClientHandshake = pf_rail_client_handshake; + server->ClientClientStatus = pf_rail_client_client_status; + server->ClientExec = pf_rail_client_exec; + server->ClientSysparam = pf_rail_client_sysparam; + server->ClientActivate = pf_rail_client_activate; + server->ClientSysmenu = pf_rail_client_sysmenu; + server->ClientSyscommand = pf_rail_client_syscommand; + server->ClientNotifyEvent = pf_rail_client_notify_event; + server->ClientGetAppidReq = pf_rail_client_get_appid_req; + server->ClientWindowMove = pf_rail_client_window_move; + server->ClientSnapArrange = pf_rail_client_snap_arrange; + server->ClientLangbarInfo = pf_rail_client_langbar_info; + server->ClientLanguageImeInfo = pf_rail_client_language_ime_info; + server->ClientCompartmentInfo = pf_rail_client_compartment_info; + server->ClientCloak = pf_rail_client_cloak; +} diff --git a/server/proxy/pf_rail.h b/server/proxy/pf_rail.h new file mode 100644 index 000000000..6d99bab20 --- /dev/null +++ b/server/proxy/pf_rail.h @@ -0,0 +1,33 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * FreeRDP Proxy Server + * + * Copyright 2019 Mati Shabtay + * Copyright 2019 Kobi Mizrachi + * Copyright 2019 Idan Freiberg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FREERDP_SERVER_PROXY_PFRAIL_H +#define FREERDP_SERVER_PROXY_PFRAIL_H + +#include +#include + +#include "pf_context.h" + +BOOL pf_rail_context_init(pServerContext* ps); +void pf_rail_pipeline_init(RailClientContext* client, RailServerContext* server, proxyData* pdata); + +#endif /*FREERDP_SERVER_PROXY_PFRAIL_H*/ diff --git a/server/proxy/pf_rdpgfx.c b/server/proxy/pf_rdpgfx.c index 968c25102..f2ea38ee0 100644 --- a/server/proxy/pf_rdpgfx.c +++ b/server/proxy/pf_rdpgfx.c @@ -492,7 +492,6 @@ void pf_rdpgfx_pipeline_init(RdpgfxClientContext* gfx, RdpgfxServerContext* serv gfx->MapSurfaceToWindow = pf_rdpgfx_map_surface_to_window; gfx->MapSurfaceToScaledOutput = pf_rdpgfx_map_surface_to_scaled_output; gfx->MapSurfaceToScaledWindow = pf_rdpgfx_map_surface_to_scaled_window; - /* No need to register to OnClose callback. GFX termination is handled in pf_server */ gfx->OnOpen = pf_rdpgfx_on_open; gfx->CapsConfirm = pf_rdpgfx_caps_confirm; diff --git a/server/proxy/pf_server.c b/server/proxy/pf_server.c index a7ee7f2fe..a7fdf545b 100644 --- a/server/proxy/pf_server.c +++ b/server/proxy/pf_server.c @@ -47,9 +47,9 @@ #include "pf_context.h" #include "pf_input.h" #include "pf_update.h" -#include "pf_channels.h" #include "pf_rdpgfx.h" #include "pf_disp.h" +#include "pf_rail.h" #include "pf_channels.h" #define TAG PROXY_TAG("server") @@ -247,6 +247,17 @@ static DWORD WINAPI pf_server_handle_client(LPVOID arg) client->settings->PrivateKeyFile = _strdup("server.key"); client->settings->RdpKeyFile = _strdup("server.key"); + if (config->RemoteApp) + { + client->settings->RemoteApplicationSupportLevel = + RAIL_LEVEL_SUPPORTED | RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED | + RAIL_LEVEL_SHELL_INTEGRATION_SUPPORTED | RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED | + RAIL_LEVEL_SERVER_TO_CLIENT_IME_SYNC_SUPPORTED | + RAIL_LEVEL_HIDE_MINIMIZED_APPS_SUPPORTED | RAIL_LEVEL_WINDOW_CLOAKING_SUPPORTED | + RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED; + client->settings->RemoteAppLanguageBarSupported = TRUE; + } + if (!client->settings->CertificateFile || !client->settings->PrivateKeyFile || !client->settings->RdpKeyFile) { diff --git a/server/proxy/pf_update.c b/server/proxy/pf_update.c index 180dc087e..4b0c9b5bc 100644 --- a/server/proxy/pf_update.c +++ b/server/proxy/pf_update.c @@ -30,8 +30,6 @@ #define TAG PROXY_TAG("update") -/* server callbacks */ - static BOOL pf_server_refresh_rect(rdpContext* context, BYTE count, const RECTANGLE_16* areas) { pServerContext* ps = (pServerContext*)context; @@ -46,7 +44,7 @@ static BOOL pf_server_suppress_output(rdpContext* context, BYTE allow, const REC return pc->update->SuppressOutput(pc, allow, area); } -/* client callbacks */ +/* Proxy from PC to PS */ /** * This function is called whenever a new frame starts. @@ -57,6 +55,7 @@ static BOOL pf_client_begin_paint(rdpContext* context) pClientContext* pc = (pClientContext*)context; proxyData* pdata = pc->pdata; rdpContext* ps = (rdpContext*)pdata->ps; + WLog_DBG(TAG, __FUNCTION__); return ps->update->BeginPaint(ps); } @@ -98,6 +97,7 @@ static BOOL pf_client_bitmap_update(rdpContext* context, const BITMAP_UPDATE* bi pClientContext* pc = (pClientContext*)context; proxyData* pdata = pc->pdata; rdpContext* ps = (rdpContext*)pdata->ps; + WLog_DBG(TAG, __FUNCTION__); return ps->update->BitmapUpdate(ps, bitmap); } @@ -106,6 +106,7 @@ static BOOL pf_client_desktop_resize(rdpContext* context) pClientContext* pc = (pClientContext*)context; proxyData* pdata = pc->pdata; rdpContext* ps = (rdpContext*)pdata->ps; + WLog_DBG(TAG, __FUNCTION__); ps->settings->DesktopWidth = context->settings->DesktopWidth; ps->settings->DesktopHeight = context->settings->DesktopHeight; return ps->update->DesktopResize(ps); @@ -117,6 +118,7 @@ static BOOL pf_client_remote_monitors(rdpContext* context, UINT32 count, pClientContext* pc = (pClientContext*)context; proxyData* pdata = pc->pdata; rdpContext* ps = (rdpContext*)pdata->ps; + WLog_DBG(TAG, __FUNCTION__); return freerdp_display_send_monitor_layout(ps, count, monitors); } @@ -126,6 +128,7 @@ static BOOL pf_client_send_pointer_system(rdpContext* context, pClientContext* pc = (pClientContext*)context; proxyData* pdata = pc->pdata; rdpContext* ps = (rdpContext*)pdata->ps; + WLog_DBG(TAG, __FUNCTION__); return ps->update->pointer->PointerSystem(ps, pointer_system); } @@ -135,6 +138,7 @@ static BOOL pf_client_send_pointer_position(rdpContext* context, pClientContext* pc = (pClientContext*)context; proxyData* pdata = pc->pdata; rdpContext* ps = (rdpContext*)pdata->ps; + WLog_DBG(TAG, __FUNCTION__); return ps->update->pointer->PointerPosition(ps, pointerPosition); } @@ -144,6 +148,7 @@ static BOOL pf_client_send_pointer_color(rdpContext* context, pClientContext* pc = (pClientContext*)context; proxyData* pdata = pc->pdata; rdpContext* ps = (rdpContext*)pdata->ps; + WLog_DBG(TAG, __FUNCTION__); return ps->update->pointer->PointerColor(ps, pointer_color); } @@ -152,6 +157,7 @@ static BOOL pf_client_send_pointer_new(rdpContext* context, const POINTER_NEW_UP pClientContext* pc = (pClientContext*)context; proxyData* pdata = pc->pdata; rdpContext* ps = (rdpContext*)pdata->ps; + WLog_DBG(TAG, __FUNCTION__); return ps->update->pointer->PointerNew(ps, pointer_new); } @@ -161,6 +167,7 @@ static BOOL pf_client_send_pointer_cached(rdpContext* context, pClientContext* pc = (pClientContext*)context; proxyData* pdata = pc->pdata; rdpContext* ps = (rdpContext*)pdata->ps; + WLog_DBG(TAG, __FUNCTION__); return ps->update->pointer->PointerCached(ps, pointer_cached); } @@ -172,6 +179,107 @@ static BOOL pf_client_save_session_info(rdpContext* context, UINT32 type, void* return ps->update->SaveSessionInfo(ps, type, data); } +static BOOL pf_client_server_status_info(rdpContext* context, UINT32 status) +{ + pClientContext* pc = (pClientContext*)context; + rdpContext* ps = (rdpContext*)pc->pdata->ps; + WLog_DBG(TAG, __FUNCTION__); + return ps->update->ServerStatusInfo(ps, status); +} + +static BOOL pf_client_window_create(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo, + const WINDOW_STATE_ORDER* windowState) +{ + pClientContext* pc = (pClientContext*)context; + rdpContext* ps = (rdpContext*)pc->pdata->ps; + WLog_DBG(TAG, __FUNCTION__); + return ps->update->window->WindowCreate(ps, orderInfo, windowState); +} + +static BOOL pf_client_window_update(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo, + const WINDOW_STATE_ORDER* windowState) +{ + pClientContext* pc = (pClientContext*)context; + rdpContext* ps = (rdpContext*)pc->pdata->ps; + WLog_DBG(TAG, __FUNCTION__); + return ps->update->window->WindowUpdate(ps, orderInfo, windowState); +} + +static BOOL pf_client_window_icon(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo, + const WINDOW_ICON_ORDER* windowIcon) +{ + pClientContext* pc = (pClientContext*)context; + rdpContext* ps = (rdpContext*)pc->pdata->ps; + WLog_DBG(TAG, __FUNCTION__); + return ps->update->window->WindowIcon(ps, orderInfo, windowIcon); +} + +static BOOL pf_client_window_cached_icon(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo, + const WINDOW_CACHED_ICON_ORDER* windowCachedIcon) +{ + pClientContext* pc = (pClientContext*)context; + rdpContext* ps = (rdpContext*)pc->pdata->ps; + WLog_DBG(TAG, __FUNCTION__); + return ps->update->window->WindowCachedIcon(ps, orderInfo, windowCachedIcon); +} + +static BOOL pf_client_window_delete(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo) +{ + pClientContext* pc = (pClientContext*)context; + rdpContext* ps = (rdpContext*)pc->pdata->ps; + WLog_DBG(TAG, __FUNCTION__); + return ps->update->window->WindowDelete(ps, orderInfo); +} + +static BOOL pf_client_notify_icon_create(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo, + const NOTIFY_ICON_STATE_ORDER* notifyIconState) +{ + pClientContext* pc = (pClientContext*)context; + rdpContext* ps = (rdpContext*)pc->pdata->ps; + WLog_DBG(TAG, __FUNCTION__); + return ps->update->window->NotifyIconCreate(ps, orderInfo, notifyIconState); +} + +static BOOL pf_client_notify_icon_update(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo, + const NOTIFY_ICON_STATE_ORDER* notifyIconState) +{ + pClientContext* pc = (pClientContext*)context; + rdpContext* ps = (rdpContext*)pc->pdata->ps; + WLog_DBG(TAG, __FUNCTION__); + return ps->update->window->NotifyIconUpdate(ps, orderInfo, notifyIconState); +} + +static BOOL pf_client_notify_icon_delete(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo) +{ + pClientContext* pc = (pClientContext*)context; + rdpContext* ps = (rdpContext*)pc->pdata->ps; + WLog_DBG(TAG, __FUNCTION__); + return ps->update->window->NotifyIconDelete(ps, orderInfo); +} + +static BOOL pf_client_monitored_desktop(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo, + const MONITORED_DESKTOP_ORDER* monitoredDesktop) +{ + pClientContext* pc = (pClientContext*)context; + rdpContext* ps = (rdpContext*)pc->pdata->ps; + WLog_DBG(TAG, __FUNCTION__); + return ps->update->window->MonitoredDesktop(ps, orderInfo, monitoredDesktop); +} + +static BOOL pf_client_non_monitored_desktop(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo) +{ + pClientContext* pc = (pClientContext*)context; + rdpContext* ps = (rdpContext*)pc->pdata->ps; + WLog_DBG(TAG, __FUNCTION__); + return ps->update->window->NonMonitoredDesktop(ps, orderInfo); +} + +void pf_server_register_update_callbacks(rdpUpdate* update) +{ + update->RefreshRect = pf_server_refresh_rect; + update->SuppressOutput = pf_server_suppress_output; +} + void pf_client_register_update_callbacks(rdpUpdate* update) { update->BeginPaint = pf_client_begin_paint; @@ -180,16 +288,22 @@ void pf_client_register_update_callbacks(rdpUpdate* update) update->DesktopResize = pf_client_desktop_resize; update->RemoteMonitors = pf_client_remote_monitors; update->SaveSessionInfo = pf_client_save_session_info; - + update->ServerStatusInfo = pf_client_server_status_info; + /* Rail window updates */ + update->window->WindowCreate = pf_client_window_create; + update->window->WindowUpdate = pf_client_window_update; + update->window->WindowIcon = pf_client_window_icon; + update->window->WindowCachedIcon = pf_client_window_cached_icon; + update->window->WindowDelete = pf_client_window_delete; + update->window->NotifyIconCreate = pf_client_notify_icon_create; + update->window->NotifyIconUpdate = pf_client_notify_icon_update; + update->window->NotifyIconDelete = pf_client_notify_icon_delete; + update->window->MonitoredDesktop = pf_client_monitored_desktop; + update->window->NonMonitoredDesktop = pf_client_non_monitored_desktop; + /* Pointer updates */ update->pointer->PointerSystem = pf_client_send_pointer_system; update->pointer->PointerPosition = pf_client_send_pointer_position; update->pointer->PointerColor = pf_client_send_pointer_color; update->pointer->PointerNew = pf_client_send_pointer_new; update->pointer->PointerCached = pf_client_send_pointer_cached; } - -void pf_server_register_update_callbacks(rdpUpdate* update) -{ - update->RefreshRect = pf_server_refresh_rect; - update->SuppressOutput = pf_server_suppress_output; -}