Merge pull request #5260 from akallabeth/rail_spec_update

Rail spec update
This commit is contained in:
Martin Fleisz 2019-04-29 11:27:26 +02:00 committed by GitHub
commit 25fc56a625
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 419 additions and 70 deletions

View File

@ -76,13 +76,15 @@ static UINT rail_send(railPlugin* rail, wStream* s)
* *
* @return 0 on success, otherwise a Win32 error code * @return 0 on success, otherwise a Win32 error code
*/ */
UINT rail_send_channel_data(railPlugin* rail, void* data, size_t length) UINT rail_send_channel_data(railPlugin* rail, wStream* src)
{ {
wStream* s = NULL; wStream* s;
size_t length;
if (!rail || !data) if (!rail || !src)
return ERROR_INVALID_PARAMETER; return ERROR_INVALID_PARAMETER;
length = Stream_GetPosition(src);
s = Stream_New(NULL, length); s = Stream_New(NULL, length);
if (!s) if (!s)
@ -91,7 +93,7 @@ UINT rail_send_channel_data(railPlugin* rail, void* data, size_t length)
return CHANNEL_RC_NO_MEMORY; return CHANNEL_RC_NO_MEMORY;
} }
Stream_Write(s, data, length); Stream_Write(s, Stream_Buffer(src), length);
return rail_send(rail, s); return rail_send(rail, s);
} }
@ -388,23 +390,6 @@ static UINT rail_server_handshake(RailClientContext* context,
return CHANNEL_RC_OK; /* stub - should be registered by client */ return CHANNEL_RC_OK; /* stub - should be registered by client */
} }
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT rail_client_handshake_ex(RailClientContext* context,
const RAIL_HANDSHAKE_EX_ORDER* handshakeEx)
{
railPlugin* rail;
if (!context || !handshakeEx)
return ERROR_INVALID_PARAMETER;
rail = (railPlugin*) context->handle;
return rail_send_handshake_ex_order(rail, handshakeEx);
}
/** /**
* Function description * Function description
* *
@ -577,6 +562,30 @@ static UINT rail_client_get_appid_request(RailClientContext* context,
return rail_send_client_get_appid_req_order(rail, getAppIdReq); return rail_send_client_get_appid_req_order(rail, getAppIdReq);
} }
static UINT rail_client_cloak(RailClientContext* context,
const RAIL_CLOAK* cloak)
{
railPlugin* rail;
if (!context || !cloak || !context->handle)
return ERROR_INVALID_PARAMETER;
rail = (railPlugin*) context->handle;
return rail_send_client_order_cloak_order(rail, cloak);
}
static UINT rail_client_snap_arrange(RailClientContext* context,
const RAIL_SNAP_ARRANGE* snap)
{
railPlugin* rail;
if (!context || !snap || !context->handle)
return ERROR_INVALID_PARAMETER;
rail = (railPlugin*) context->handle;
return rail_send_client_order_snap_arrange_order(rail, snap);
}
/** /**
* Function description * Function description
* *
@ -917,7 +926,6 @@ BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS pEntryPoints, PVOID p
context->ClientSystemCommand = rail_client_system_command; context->ClientSystemCommand = rail_client_system_command;
context->ClientHandshake = rail_client_handshake; context->ClientHandshake = rail_client_handshake;
context->ServerHandshake = rail_server_handshake; context->ServerHandshake = rail_server_handshake;
context->ClientHandshakeEx = rail_client_handshake_ex;
context->ServerHandshakeEx = rail_server_handshake_ex; context->ServerHandshakeEx = rail_server_handshake_ex;
context->ClientNotifyEvent = rail_client_notify_event; context->ClientNotifyEvent = rail_client_notify_event;
context->ClientWindowMove = rail_client_window_move; context->ClientWindowMove = rail_client_window_move;
@ -930,6 +938,8 @@ BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS pEntryPoints, PVOID p
context->ServerExecuteResult = rail_server_execute_result; context->ServerExecuteResult = rail_server_execute_result;
context->ClientGetAppIdRequest = rail_client_get_appid_request; context->ClientGetAppIdRequest = rail_client_get_appid_request;
context->ServerGetAppIdResponse = rail_server_get_appid_response; context->ServerGetAppIdResponse = rail_server_get_appid_response;
context->ClientSnapArrange = rail_client_snap_arrange;
context->ClientCloak = rail_client_cloak;
rail->rdpcontext = pEntryPointsEx->context; rail->rdpcontext = pEntryPointsEx->context;
rail->context = context; rail->context = context;
isFreerdp = TRUE; isFreerdp = TRUE;

View File

@ -54,6 +54,6 @@ struct rail_plugin
typedef struct rail_plugin railPlugin; typedef struct rail_plugin railPlugin;
RailClientContext* rail_get_client_interface(railPlugin* rail); RailClientContext* rail_get_client_interface(railPlugin* rail);
UINT rail_send_channel_data(railPlugin* rail, void* data, size_t length); UINT rail_send_channel_data(railPlugin* rail, wStream* s);
#endif /* FREERDP_CHANNEL_RAIL_CLIENT_MAIN_H */ #endif /* FREERDP_CHANNEL_RAIL_CLIENT_MAIN_H */

View File

@ -99,7 +99,7 @@ UINT rail_send_pdu(railPlugin* rail, wStream* s, UINT16 orderType)
Stream_SetPosition(s, orderLength); Stream_SetPosition(s, orderLength);
WLog_Print(rail->log, WLOG_DEBUG, "Sending %s PDU, length: %"PRIu16"", WLog_Print(rail->log, WLOG_DEBUG, "Sending %s PDU, length: %"PRIu16"",
RAIL_ORDER_TYPE_STRINGS[((orderType & 0xF0) >> 3) + (orderType & 0x0F)], orderLength); RAIL_ORDER_TYPE_STRINGS[((orderType & 0xF0) >> 3) + (orderType & 0x0F)], orderLength);
return rail_send_channel_data(rail, Stream_Buffer(s), orderLength); return rail_send_channel_data(rail, s);
} }
/** /**
@ -494,6 +494,7 @@ static UINT rail_write_langbar_info_order(wStream* s, const RAIL_LANGBAR_INFO_OR
static UINT rail_recv_handshake_order(railPlugin* rail, RAIL_HANDSHAKE_ORDER* handshake, wStream* s) static UINT rail_recv_handshake_order(railPlugin* rail, RAIL_HANDSHAKE_ORDER* handshake, wStream* s)
{ {
RailClientContext* context = rail_get_client_interface(rail); RailClientContext* context = rail_get_client_interface(rail);
RAIL_HANDSHAKE_ORDER clientHandshake = { 0 };
UINT error; UINT error;
if (!context || !handshake || !s) if (!context || !handshake || !s)
@ -505,6 +506,14 @@ static UINT rail_recv_handshake_order(railPlugin* rail, RAIL_HANDSHAKE_ORDER* ha
return error; return error;
} }
clientHandshake.buildNumber = 0x00001DB0;
/* 2.2.2.2.3 HandshakeEx PDU (TS_RAIL_ORDER_HANDSHAKE_EX)
* Client response is really a Handshake PDU */
error = context->ClientHandshake(context, &clientHandshake);
if (error != CHANNEL_RC_OK)
return error;
if (context->custom) if (context->custom)
{ {
IFCALLRET(context->ServerHandshake, error, context, handshake); IFCALLRET(context->ServerHandshake, error, context, handshake);
@ -525,6 +534,7 @@ static UINT rail_recv_handshake_ex_order(railPlugin* rail, RAIL_HANDSHAKE_EX_ORD
wStream* s) wStream* s)
{ {
RailClientContext* context = rail_get_client_interface(rail); RailClientContext* context = rail_get_client_interface(rail);
RAIL_HANDSHAKE_ORDER clientHandshake = { 0 };
UINT error; UINT error;
if (!context || !handshakeEx || !s) if (!context || !handshakeEx || !s)
@ -536,6 +546,14 @@ static UINT rail_recv_handshake_ex_order(railPlugin* rail, RAIL_HANDSHAKE_EX_ORD
return error; return error;
} }
clientHandshake.buildNumber = 0x00001DB0;
/* 2.2.2.2.3 HandshakeEx PDU (TS_RAIL_ORDER_HANDSHAKE_EX)
* Client response is really a Handshake PDU */
error = context->ClientHandshake(context, &clientHandshake);
if (error != CHANNEL_RC_OK)
return error;
if (context->custom) if (context->custom)
{ {
IFCALLRET(context->ServerHandshakeEx, error, context, handshakeEx); IFCALLRET(context->ServerHandshakeEx, error, context, handshakeEx);
@ -736,6 +754,155 @@ static UINT rail_recv_langbar_info_order(railPlugin* rail, RAIL_LANGBAR_INFO_ORD
return error; return error;
} }
static UINT rail_read_zorder_sync_order(wStream* s, RAIL_ZORDER_SYNC* zorder)
{
if (!s || !zorder)
return ERROR_INVALID_PARAMETER;
if (Stream_GetRemainingLength(s) < 4)
{
WLog_ERR(TAG, "Stream_GetRemainingLength failed!");
return ERROR_INVALID_DATA;
}
Stream_Read_UINT32(s, zorder->windowIdMarker);
return CHANNEL_RC_OK;
}
static UINT rail_recv_zorder_sync_order(railPlugin* rail, RAIL_ZORDER_SYNC* zorder,
wStream* s)
{
RailClientContext* context = rail_get_client_interface(rail);
UINT error;
if (!context || !zorder)
return ERROR_INVALID_PARAMETER;
if ((error = rail_read_zorder_sync_order(s, zorder)))
{
WLog_ERR(TAG, "rail_read_zorder_sync_order failed with error %"PRIu32"!", error);
return error;
}
if (context->custom)
{
IFCALLRET(context->ServerZOrderSync, error, context, zorder);
if (error)
WLog_ERR(TAG, "context.ServerZOrderSync failed with error %"PRIu32"", error);
}
return error;
}
static UINT rail_read_power_display_request_order(wStream* s, RAIL_POWER_DISPLAY_REQUEST* power)
{
if (!s || !power)
return ERROR_INVALID_PARAMETER;
if (Stream_GetRemainingLength(s) < 4)
{
WLog_ERR(TAG, "Stream_GetRemainingLength failed!");
return ERROR_INVALID_DATA;
}
Stream_Read_UINT32(s, power->active);
return CHANNEL_RC_OK;
}
static UINT rail_recv_power_display_request_order(railPlugin* rail,
RAIL_POWER_DISPLAY_REQUEST* power,
wStream* s)
{
RailClientContext* context = rail_get_client_interface(rail);
UINT error;
if (!context || !power)
return ERROR_INVALID_PARAMETER;
if ((error = rail_read_power_display_request_order(s, power)))
{
WLog_ERR(TAG, "rail_read_zorder_sync_order failed with error %"PRIu32"!", error);
return error;
}
if (context->custom)
{
IFCALLRET(context->ServerPowerDisplayRequest, error, context, power);
if (error)
WLog_ERR(TAG, "context.ServerPowerDisplayRequest failed with error %"PRIu32"", error);
}
return error;
}
static UINT rail_read_get_application_id_extended_response_order(wStream* s,
RAIL_GET_APPID_RESP_EX* id)
{
if (!s || !id)
return ERROR_INVALID_PARAMETER;
if (Stream_GetRemainingLength(s) < 4)
{
WLog_ERR(TAG, "Stream_GetRemainingLength failed!");
return ERROR_INVALID_DATA;
}
Stream_Read_UINT32(s, id->windowID);
if (!Stream_Read_UTF16_String(s, id->applicationID, ARRAYSIZE(id->applicationID)))
return ERROR_INVALID_DATA;
if (_wcsnlen(id->applicationID, ARRAYSIZE(id->applicationID)) >= ARRAYSIZE(id->applicationID))
return ERROR_INVALID_DATA;
if (Stream_GetRemainingLength(s) < 4)
{
WLog_ERR(TAG, "Stream_GetRemainingLength failed!");
return ERROR_INVALID_DATA;
}
Stream_Read_UINT32(s, id->processId);
if (!Stream_Read_UTF16_String(s, id->processImageName, ARRAYSIZE(id->processImageName)))
return ERROR_INVALID_DATA;
if (_wcsnlen(id->applicationID, ARRAYSIZE(id->processImageName)) >= ARRAYSIZE(id->processImageName))
return ERROR_INVALID_DATA;
return CHANNEL_RC_OK;
}
static UINT rail_recv_get_application_id_extended_response_order(railPlugin* rail,
RAIL_GET_APPID_RESP_EX* id,
wStream* s)
{
RailClientContext* context = rail_get_client_interface(rail);
UINT error;
if (!context || !id)
return ERROR_INVALID_PARAMETER;
if ((error = rail_read_get_application_id_extended_response_order(s, id)))
{
WLog_ERR(TAG, "rail_read_get_application_id_extended_response_order failed with error %"PRIu32"!",
error);
return error;
}
if (context->custom)
{
IFCALLRET(context->ServerGetAppidResponseExtended, error, context, id);
if (error)
WLog_ERR(TAG, "context.ServerGetAppidResponseExtended failed with error %"PRIu32"", error);
}
return error;
}
/** /**
* Function description * Function description
* *
@ -811,6 +978,24 @@ UINT rail_order_recv(railPlugin* rail, wStream* s)
return rail_recv_langbar_info_order(rail, &langBarInfo, s); return rail_recv_langbar_info_order(rail, &langBarInfo, s);
} }
case RDP_RAIL_ORDER_ZORDER_SYNC:
{
RAIL_ZORDER_SYNC val;
return rail_recv_zorder_sync_order(rail, &val, s);
}
case RDP_RAIL_ORDER_POWER_DISPLAY_REQUEST:
{
RAIL_POWER_DISPLAY_REQUEST val;
return rail_recv_power_display_request_order(rail, &val, s);
}
case RDP_RAIL_ORDER_GET_APPID_RESP_EX:
{
RAIL_GET_APPID_RESP_EX val;
return rail_recv_get_application_id_extended_response_order(rail, &val, s);
}
default: default:
WLog_ERR(TAG, "Unknown RAIL PDU order reveived."); WLog_ERR(TAG, "Unknown RAIL PDU order reveived.");
return ERROR_INVALID_DATA; return ERROR_INVALID_DATA;
@ -1315,3 +1500,52 @@ UINT rail_send_client_langbar_info_order(railPlugin* rail,
Stream_Free(s, TRUE); Stream_Free(s, TRUE);
return error; return error;
} }
UINT rail_send_client_order_cloak_order(railPlugin* rail, const RAIL_CLOAK* cloak)
{
wStream* s;
UINT error;
if (!rail || !cloak)
return ERROR_INVALID_PARAMETER;
s = rail_pdu_init(5);
if (!s)
{
WLog_ERR(TAG, "rail_pdu_init failed!");
return CHANNEL_RC_NO_MEMORY;
}
Stream_Write_UINT32(s, cloak->windowId);
Stream_Write_UINT8(s, cloak->cloak ? 1 : 0);
error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_CLOAK);
Stream_Free(s, TRUE);
return error;
}
UINT rail_send_client_order_snap_arrange_order(railPlugin* rail, const RAIL_SNAP_ARRANGE* snap)
{
wStream* s;
UINT error;
if (!rail)
return ERROR_INVALID_PARAMETER;
s = rail_pdu_init(12);
if (!s)
{
WLog_ERR(TAG, "rail_pdu_init failed!");
return CHANNEL_RC_NO_MEMORY;
}
Stream_Write_UINT32(s, snap->windowId);
Stream_Write_UINT16(s, snap->left);
Stream_Write_UINT16(s, snap->top);
Stream_Write_UINT16(s, snap->right);
Stream_Write_UINT16(s, snap->bottom);
error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_SNAP_ARRANGE);
Stream_Free(s, TRUE);
return error;
}

View File

@ -52,4 +52,7 @@ UINT rail_send_client_get_appid_req_order(railPlugin* rail,
UINT rail_send_client_langbar_info_order(railPlugin* rail, UINT rail_send_client_langbar_info_order(railPlugin* rail,
const RAIL_LANGBAR_INFO_ORDER* langBarInfo); const RAIL_LANGBAR_INFO_ORDER* langBarInfo);
UINT rail_send_client_order_cloak_order(railPlugin* rail, const RAIL_CLOAK* cloak);
UINT rail_send_client_order_snap_arrange_order(railPlugin* rail, const RAIL_SNAP_ARRANGE* snap);
#endif /* FREERDP_CHANNEL_RAIL_CLIENT_ORDERS_H */ #endif /* FREERDP_CHANNEL_RAIL_CLIENT_ORDERS_H */

View File

@ -242,6 +242,7 @@ static BOOL wl_post_connect(freerdp* instance)
w = (UINT32)gdi->width; w = (UINT32)gdi->width;
h = (UINT32)gdi->height; h = (UINT32)gdi->height;
if (settings->SmartSizing && !context->fullscreen) if (settings->SmartSizing && !context->fullscreen)
{ {
if (settings->SmartSizingWidth > 0) if (settings->SmartSizingWidth > 0)
@ -390,6 +391,22 @@ static BOOL handle_uwac_events(freerdp* instance, UwacDisplay* display)
return TRUE; return TRUE;
} }
static BOOL handle_window_events(freerdp* instance)
{
rdpSettings* settings;
if (!instance || !instance->settings)
return FALSE;
settings = instance->settings;
if (!settings->AsyncInput)
{
}
return TRUE;
}
static int wlfreerdp_run(freerdp* instance) static int wlfreerdp_run(freerdp* instance)
{ {
wlfContext* context; wlfContext* context;
@ -438,6 +455,18 @@ static int wlfreerdp_run(freerdp* instance)
if (freerdp_check_event_handles(instance->context) != TRUE) if (freerdp_check_event_handles(instance->context) != TRUE)
{ {
if (client_auto_reconnect_ex(instance, handle_window_events))
continue;
else
{
/*
* Indicate an unsuccessful connection attempt if reconnect
* did not succeed and no other error was specified.
*/
if (freerdp_error_info(instance) == 0)
status = 42;
}
if (freerdp_get_last_error(instance->context) == FREERDP_ERROR_SUCCESS) if (freerdp_get_last_error(instance->context) == FREERDP_ERROR_SUCCESS)
WLog_Print(context->log, WLOG_ERROR, "Failed to check FreeRDP file descriptor"); WLog_Print(context->log, WLOG_ERROR, "Failed to check FreeRDP file descriptor");

View File

@ -984,31 +984,23 @@ static UINT xf_rail_server_execute_result(RailClientContext* context,
static UINT xf_rail_server_system_param(RailClientContext* context, static UINT xf_rail_server_system_param(RailClientContext* context,
const RAIL_SYSPARAM_ORDER* sysparam) const RAIL_SYSPARAM_ORDER* sysparam)
{ {
// TODO: Actually apply param
return CHANNEL_RC_OK; return CHANNEL_RC_OK;
} }
/** static UINT xf_rail_server_start_cmd(RailClientContext* context)
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT xf_rail_server_handshake(RailClientContext* context,
const RAIL_HANDSHAKE_ORDER* handshake)
{ {
UINT status; UINT status;
RAIL_EXEC_ORDER exec = { 0 }; RAIL_EXEC_ORDER exec = { 0 };
RAIL_SYSPARAM_ORDER sysparam = { 0 }; RAIL_SYSPARAM_ORDER sysparam = { 0 };
RAIL_HANDSHAKE_ORDER clientHandshake;
RAIL_CLIENT_STATUS_ORDER clientStatus = { 0 }; RAIL_CLIENT_STATUS_ORDER clientStatus = { 0 };
xfContext* xfc = (xfContext*) context->custom; xfContext* xfc = (xfContext*) context->custom;
rdpSettings* settings = xfc->context.settings; rdpSettings* settings = xfc->context.settings;
clientHandshake.buildNumber = 0x00001DB0;
status = context->ClientHandshake(context, &clientHandshake);
if (status != CHANNEL_RC_OK)
return status;
clientStatus.flags = RAIL_CLIENTSTATUS_ALLOWLOCALMOVESIZE; clientStatus.flags = RAIL_CLIENTSTATUS_ALLOWLOCALMOVESIZE;
if (settings->AutoReconnectionEnabled)
clientStatus.flags |= RAIL_CLIENTSTATUS_AUTORECONNECT;
status = context->ClientInformation(context, &clientStatus); status = context->ClientInformation(context, &clientStatus);
if (status != CHANNEL_RC_OK) if (status != CHANNEL_RC_OK)
@ -1018,7 +1010,10 @@ static UINT xf_rail_server_handshake(RailClientContext* context,
{ {
RAIL_LANGBAR_INFO_ORDER langBarInfo; RAIL_LANGBAR_INFO_ORDER langBarInfo;
langBarInfo.languageBarStatus = 0x00000008; /* TF_SFT_HIDDEN */ langBarInfo.languageBarStatus = 0x00000008; /* TF_SFT_HIDDEN */
context->ClientLanguageBarInfo(context, &langBarInfo); status = context->ClientLanguageBarInfo(context, &langBarInfo);
if (status != CHANNEL_RC_OK)
return status;
} }
sysparam.params = 0; sysparam.params = 0;
@ -1050,6 +1045,16 @@ static UINT xf_rail_server_handshake(RailClientContext* context,
exec.RemoteApplicationArguments = settings->RemoteApplicationCmdLine; exec.RemoteApplicationArguments = settings->RemoteApplicationCmdLine;
return context->ClientExecute(context, &exec); return context->ClientExecute(context, &exec);
} }
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT xf_rail_server_handshake(RailClientContext* context,
const RAIL_HANDSHAKE_ORDER* handshake)
{
return xf_rail_server_start_cmd(context);
}
/** /**
* Function description * Function description
@ -1059,7 +1064,7 @@ static UINT xf_rail_server_handshake(RailClientContext* context,
static UINT xf_rail_server_handshake_ex(RailClientContext* context, static UINT xf_rail_server_handshake_ex(RailClientContext* context,
const RAIL_HANDSHAKE_EX_ORDER* handshakeEx) const RAIL_HANDSHAKE_EX_ORDER* handshakeEx)
{ {
return CHANNEL_RC_OK; return xf_rail_server_start_cmd(context);
} }
/** /**

View File

@ -48,8 +48,6 @@ typedef UINT(*pcRailClientHandshake)(RailClientContext* context,
const RAIL_HANDSHAKE_ORDER* handshake); const RAIL_HANDSHAKE_ORDER* handshake);
typedef UINT(*pcRailServerHandshake)(RailClientContext* context, typedef UINT(*pcRailServerHandshake)(RailClientContext* context,
const RAIL_HANDSHAKE_ORDER* handshake); const RAIL_HANDSHAKE_ORDER* handshake);
typedef UINT(*pcRailClientHandshakeEx)(RailClientContext* context,
const RAIL_HANDSHAKE_EX_ORDER* handshakeEx);
typedef UINT(*pcRailServerHandshakeEx)(RailClientContext* context, typedef UINT(*pcRailServerHandshakeEx)(RailClientContext* context,
const RAIL_HANDSHAKE_EX_ORDER* handshakeEx); const RAIL_HANDSHAKE_EX_ORDER* handshakeEx);
typedef UINT(*pcRailClientNotifyEvent)(RailClientContext* context, typedef UINT(*pcRailClientNotifyEvent)(RailClientContext* context,
@ -74,6 +72,16 @@ typedef UINT(*pcRailClientGetAppIdRequest)(RailClientContext* context,
const RAIL_GET_APPID_REQ_ORDER* getAppIdReq); const RAIL_GET_APPID_REQ_ORDER* getAppIdReq);
typedef UINT(*pcRailServerGetAppIdResponse)(RailClientContext* context, typedef UINT(*pcRailServerGetAppIdResponse)(RailClientContext* context,
const RAIL_GET_APPID_RESP_ORDER* getAppIdResp); const RAIL_GET_APPID_RESP_ORDER* getAppIdResp);
typedef UINT(*pcRailServerZOrderSync)(RailClientContext* context,
const RAIL_ZORDER_SYNC* zorder);
typedef UINT(*pcRailClientCloak)(RailClientContext* context,
const RAIL_CLOAK* cloak);
typedef UINT(*pcRailServerPowerDisplayRequest)(RailClientContext* context,
const RAIL_POWER_DISPLAY_REQUEST* power);
typedef UINT(*pcRailClientSnapArrange)(RailClientContext* context,
const RAIL_SNAP_ARRANGE* snap);
typedef UINT(*pcRailServerGetAppidResponseExtended)(RailClientContext* context,
const RAIL_GET_APPID_RESP_EX* id);
struct _rail_client_context struct _rail_client_context
{ {
@ -87,7 +95,6 @@ struct _rail_client_context
pcRailClientSystemCommand ClientSystemCommand; pcRailClientSystemCommand ClientSystemCommand;
pcRailClientHandshake ClientHandshake; pcRailClientHandshake ClientHandshake;
pcRailServerHandshake ServerHandshake; pcRailServerHandshake ServerHandshake;
pcRailClientHandshakeEx ClientHandshakeEx;
pcRailServerHandshakeEx ServerHandshakeEx; pcRailServerHandshakeEx ServerHandshakeEx;
pcRailClientNotifyEvent ClientNotifyEvent; pcRailClientNotifyEvent ClientNotifyEvent;
pcRailClientWindowMove ClientWindowMove; pcRailClientWindowMove ClientWindowMove;
@ -100,6 +107,11 @@ struct _rail_client_context
pcRailServerExecuteResult ServerExecuteResult; pcRailServerExecuteResult ServerExecuteResult;
pcRailClientGetAppIdRequest ClientGetAppIdRequest; pcRailClientGetAppIdRequest ClientGetAppIdRequest;
pcRailServerGetAppIdResponse ServerGetAppIdResponse; pcRailServerGetAppIdResponse ServerGetAppIdResponse;
pcRailServerZOrderSync ServerZOrderSync;
pcRailClientCloak ClientCloak;
pcRailServerPowerDisplayRequest ServerPowerDisplayRequest;
pcRailClientSnapArrange ClientSnapArrange;
pcRailServerGetAppidResponseExtended ServerGetAppidResponseExtended;
}; };
#endif /* FREERDP_CHANNEL_RAIL_CLIENT_RAIL_H */ #endif /* FREERDP_CHANNEL_RAIL_CLIENT_RAIL_H */

View File

@ -145,7 +145,9 @@ enum SPI_MASK
#define TF_SFT_DESKBAND 0x00000800 #define TF_SFT_DESKBAND 0x00000800
/* Extended Handshake Flags */ /* Extended Handshake Flags */
#define RAIL_ORDER_HANDSHAKEEX_FLAGS_HIDEF 0x00000001 #define RAIL_ORDER_HANDSHAKEEX_FLAGS_HIDEF 0x00000001
#define RAIL_ORDER_HANDSHAKE_EX_FLAGS_EXTENDED_SPI_SUPPORTED 0x00000002
#define RAIL_ORDER_HANDSHAKE_EX_FLAGS_SNAP_ARRANGE_SUPPORTED 0x00000004
/* Language Profile Information Flags */ /* Language Profile Information Flags */
#define TF_PROFILETYPE_INPUTPROCESSOR 0x00000001 #define TF_PROFILETYPE_INPUTPROCESSOR 0x00000001
@ -352,26 +354,69 @@ struct _RAIL_COMPARTMENT_INFO_ORDER
}; };
typedef struct _RAIL_COMPARTMENT_INFO_ORDER RAIL_COMPARTMENT_INFO_ORDER; typedef struct _RAIL_COMPARTMENT_INFO_ORDER RAIL_COMPARTMENT_INFO_ORDER;
struct _RAIL_ZORDER_SYNC
{
UINT32 windowIdMarker;
};
typedef struct _RAIL_ZORDER_SYNC RAIL_ZORDER_SYNC;
struct _RAIL_CLOAK
{
UINT32 windowId;
BOOL cloak;
};
typedef struct _RAIL_CLOAK RAIL_CLOAK;
struct _RAIL_POWER_DISPLAY_REQUEST
{
UINT32 active;
};
typedef struct _RAIL_POWER_DISPLAY_REQUEST RAIL_POWER_DISPLAY_REQUEST;
struct _RAIL_SNAP_ARRANGE
{
UINT32 windowId;
UINT16 left;
UINT16 top;
UINT16 right;
UINT16 bottom;
};
typedef struct _RAIL_SNAP_ARRANGE RAIL_SNAP_ARRANGE;
struct _RAIL_GET_APPID_RESP_EX
{
UINT32 windowID;
WCHAR applicationID[512 / sizeof(WCHAR)];
UINT32 processId;
WCHAR processImageName[512 / sizeof(WCHAR)];
};
typedef struct _RAIL_GET_APPID_RESP_EX RAIL_GET_APPID_RESP_EX;
/* RAIL Constants */ /* RAIL Constants */
#define RDP_RAIL_ORDER_EXEC 0x0001 #define RDP_RAIL_ORDER_EXEC 0x0001
#define RDP_RAIL_ORDER_ACTIVATE 0x0002 #define RDP_RAIL_ORDER_ACTIVATE 0x0002
#define RDP_RAIL_ORDER_SYSPARAM 0x0003 #define RDP_RAIL_ORDER_SYSPARAM 0x0003
#define RDP_RAIL_ORDER_SYSCOMMAND 0x0004 #define RDP_RAIL_ORDER_SYSCOMMAND 0x0004
#define RDP_RAIL_ORDER_HANDSHAKE 0x0005 #define RDP_RAIL_ORDER_HANDSHAKE 0x0005
#define RDP_RAIL_ORDER_NOTIFY_EVENT 0x0006 #define RDP_RAIL_ORDER_NOTIFY_EVENT 0x0006
#define RDP_RAIL_ORDER_WINDOWMOVE 0x0008 #define RDP_RAIL_ORDER_WINDOWMOVE 0x0008
#define RDP_RAIL_ORDER_LOCALMOVESIZE 0x0009 #define RDP_RAIL_ORDER_LOCALMOVESIZE 0x0009
#define RDP_RAIL_ORDER_MINMAXINFO 0x000A #define RDP_RAIL_ORDER_MINMAXINFO 0x000A
#define RDP_RAIL_ORDER_CLIENTSTATUS 0x000B #define RDP_RAIL_ORDER_CLIENTSTATUS 0x000B
#define RDP_RAIL_ORDER_SYSMENU 0x000C #define RDP_RAIL_ORDER_SYSMENU 0x000C
#define RDP_RAIL_ORDER_LANGBARINFO 0x000D #define RDP_RAIL_ORDER_LANGBARINFO 0x000D
#define RDP_RAIL_ORDER_EXEC_RESULT 0x0080 #define RDP_RAIL_ORDER_EXEC_RESULT 0x0080
#define RDP_RAIL_ORDER_GET_APPID_REQ 0x000E #define RDP_RAIL_ORDER_GET_APPID_REQ 0x000E
#define RDP_RAIL_ORDER_GET_APPID_RESP 0x000F #define RDP_RAIL_ORDER_GET_APPID_RESP 0x000F
#define RDP_RAIL_ORDER_LANGUAGEIMEINFO 0x0011 #define RDP_RAIL_ORDER_LANGUAGEIMEINFO 0x0011
#define RDP_RAIL_ORDER_COMPARTMENTINFO 0x0012 #define RDP_RAIL_ORDER_COMPARTMENTINFO 0x0012
#define RDP_RAIL_ORDER_HANDSHAKE_EX 0x0013 #define RDP_RAIL_ORDER_HANDSHAKE_EX 0x0013
#define RDP_RAIL_ORDER_ZORDER_SYNC 0x0014
#define RDP_RAIL_ORDER_CLOAK 0x0015
#define RDP_RAIL_ORDER_POWER_DISPLAY_REQUEST 0x0016
#define RDP_RAIL_ORDER_SNAP_ARRANGE 0x0017
#define RDP_RAIL_ORDER_GET_APPID_RESP_EX 0x0018
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -756,6 +756,7 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL;
#define FreeRDP_RemoteAppNumIconCacheEntries (2123) #define FreeRDP_RemoteAppNumIconCacheEntries (2123)
#define FreeRDP_RemoteAppLanguageBarSupported (2124) #define FreeRDP_RemoteAppLanguageBarSupported (2124)
#define FreeRDP_RemoteWndSupportLevel (2125) #define FreeRDP_RemoteWndSupportLevel (2125)
#define FreeRDP_RemoteApplicationSupportLevel (2126)
#define FreeRDP_ReceivedCapabilities (2240) #define FreeRDP_ReceivedCapabilities (2240)
#define FreeRDP_ReceivedCapabilitiesSize (2241) #define FreeRDP_ReceivedCapabilitiesSize (2241)
#define FreeRDP_OsMajorType (2304) #define FreeRDP_OsMajorType (2304)
@ -1253,7 +1254,8 @@ struct rdp_settings
ALIGN64 UINT32 RemoteAppNumIconCacheEntries; /* 2123 */ ALIGN64 UINT32 RemoteAppNumIconCacheEntries; /* 2123 */
ALIGN64 BOOL RemoteAppLanguageBarSupported; /* 2124 */ ALIGN64 BOOL RemoteAppLanguageBarSupported; /* 2124 */
ALIGN64 UINT32 RemoteWndSupportLevel; /* 2125 */ ALIGN64 UINT32 RemoteWndSupportLevel; /* 2125 */
UINT64 padding2176[2176 - 2126]; /* 2126 */ ALIGN64 UINT32 RemoteApplicationSupportLevel; /* 2126 */
UINT64 padding2176[2176 - 2127]; /* 2127 */
UINT64 padding2240[2240 - 2176]; /* 2176 */ UINT64 padding2240[2240 - 2176]; /* 2176 */
/** /**

View File

@ -2183,6 +2183,7 @@ static BOOL rdp_read_remote_programs_capability_set(wStream* s, UINT16 length,
return FALSE; return FALSE;
Stream_Read_UINT32(s, railSupportLevel); /* railSupportLevel (4 bytes) */ Stream_Read_UINT32(s, railSupportLevel); /* railSupportLevel (4 bytes) */
settings->RemoteApplicationSupportLevel = railSupportLevel;
if ((railSupportLevel & RAIL_LEVEL_SUPPORTED) == 0) if ((railSupportLevel & RAIL_LEVEL_SUPPORTED) == 0)
{ {
@ -2215,8 +2216,14 @@ static BOOL rdp_write_remote_programs_capability_set(wStream* s,
header = rdp_capability_set_start(s); header = rdp_capability_set_start(s);
railSupportLevel = RAIL_LEVEL_SUPPORTED; railSupportLevel = RAIL_LEVEL_SUPPORTED;
if (settings->RemoteAppLanguageBarSupported) if (settings->RemoteApplicationSupportLevel & RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED)
railSupportLevel |= RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED; {
if (settings->RemoteAppLanguageBarSupported)
railSupportLevel |= RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED;
}
if (settings->RemoteApplicationSupportLevel & RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED)
railSupportLevel |= RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED;
Stream_Write_UINT32(s, railSupportLevel); /* railSupportLevel (4 bytes) */ Stream_Write_UINT32(s, railSupportLevel); /* railSupportLevel (4 bytes) */
rdp_capability_set_finish(s, header, CAPSET_TYPE_RAIL); rdp_capability_set_finish(s, header, CAPSET_TYPE_RAIL);

View File

@ -136,12 +136,14 @@
#define DRAW_GDIPLUS_CACHE_LEVEL_ONE 0x00000001 #define DRAW_GDIPLUS_CACHE_LEVEL_ONE 0x00000001
/* RAIL Support Level */ /* RAIL Support Level */
#define RAIL_LEVEL_SUPPORTED 0x00000001 #define RAIL_LEVEL_SUPPORTED 0x00000001
#define RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED 0x00000002 #define RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED 0x00000002
#define RAIL_LEVEL_SHELL_INTEGRATION_SUPPORTED 0x00000004 #define RAIL_LEVEL_SHELL_INTEGRATION_SUPPORTED 0x00000004
#define RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED 0x00000008 #define RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED 0x00000008
#define RAIL_LEVEL_SERVER_TO_CLIENT_IME_SYNC_SUPPORTED 0x00000010 #define RAIL_LEVEL_SERVER_TO_CLIENT_IME_SYNC_SUPPORTED 0x00000010
#define RAIL_LEVEL_HIDE_MINIMIZED_APPS_SUPPORTED 0x00000020 #define RAIL_LEVEL_HIDE_MINIMIZED_APPS_SUPPORTED 0x00000020
#define RAIL_LEVEL_WINDOW_CLOAKING_SUPPORTED 0x00000040
#define RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED 0x00000080
/* Window Support Level */ /* Window Support Level */
#define WINDOW_LEVEL_NOT_SUPPORTED 0x00000000 #define WINDOW_LEVEL_NOT_SUPPORTED 0x00000000