Updated rail channel, supporting all new messages.
authorArmin Novak <armin.novak@thincast.com>
Tue, 19 Feb 2019 13:13:34 +0000 (14:13 +0100)
committerArmin Novak <armin.novak@thincast.com>
Tue, 19 Feb 2019 14:04:11 +0000 (15:04 +0100)
channels/rail/client/rail_main.c
channels/rail/client/rail_main.h
channels/rail/client/rail_orders.c
channels/rail/client/rail_orders.h
client/X11/xf_rail.c
include/freerdp/client/rail.h
include/freerdp/rail.h
include/freerdp/settings.h
libfreerdp/core/capabilities.c
libfreerdp/core/capabilities.h

index ea772dd..01f5ee2 100644 (file)
@@ -76,13 +76,15 @@ static UINT rail_send(railPlugin* rail, wStream* s)
  *
  * @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;
 
+       length = Stream_GetPosition(src);
        s = Stream_New(NULL, length);
 
        if (!s)
@@ -91,7 +93,7 @@ UINT rail_send_channel_data(railPlugin* rail, void* data, size_t length)
                return CHANNEL_RC_NO_MEMORY;
        }
 
-       Stream_Write(s, data, length);
+       Stream_Write(s, Stream_Buffer(src), length);
        return rail_send(rail, s);
 }
 
@@ -393,23 +395,6 @@ static UINT rail_server_handshake(RailClientContext* context,
  *
  * @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
- *
- * @return 0 on success, otherwise a Win32 error code
- */
 static UINT rail_server_handshake_ex(RailClientContext* context,
                                      const RAIL_HANDSHAKE_EX_ORDER* handshakeEx)
 {
@@ -577,6 +562,30 @@ static UINT rail_client_get_appid_request(RailClientContext* context,
        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
  *
@@ -917,7 +926,6 @@ BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS pEntryPoints, PVOID p
                context->ClientSystemCommand = rail_client_system_command;
                context->ClientHandshake = rail_client_handshake;
                context->ServerHandshake = rail_server_handshake;
-               context->ClientHandshakeEx = rail_client_handshake_ex;
                context->ServerHandshakeEx = rail_server_handshake_ex;
                context->ClientNotifyEvent = rail_client_notify_event;
                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->ClientGetAppIdRequest = rail_client_get_appid_request;
                context->ServerGetAppIdResponse = rail_server_get_appid_response;
+               context->ClientSnapArrange = rail_client_snap_arrange;
+               context->ClientCloak = rail_client_cloak;
                rail->rdpcontext = pEntryPointsEx->context;
                rail->context = context;
                isFreerdp = TRUE;
index 86e752f..01c3a5b 100644 (file)
@@ -54,6 +54,6 @@ struct rail_plugin
 typedef struct rail_plugin railPlugin;
 
 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 */
index 7e6cf42..1f47ba2 100644 (file)
@@ -99,7 +99,7 @@ UINT rail_send_pdu(railPlugin* rail, wStream* s, UINT16 orderType)
        Stream_SetPosition(s, orderLength);
        WLog_Print(rail->log, WLOG_DEBUG, "Sending %s PDU, length: %"PRIu16"",
                   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)
 {
        RailClientContext* context = rail_get_client_interface(rail);
+       RAIL_HANDSHAKE_ORDER clientHandshake = { 0 };
        UINT error;
 
        if (!context || !handshake || !s)
@@ -505,6 +506,14 @@ static UINT rail_recv_handshake_order(railPlugin* rail, RAIL_HANDSHAKE_ORDER* ha
                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)
        {
                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)
 {
        RailClientContext* context = rail_get_client_interface(rail);
+       RAIL_HANDSHAKE_ORDER clientHandshake = { 0 };
        UINT error;
 
        if (!context || !handshakeEx || !s)
@@ -536,9 +546,17 @@ static UINT rail_recv_handshake_ex_order(railPlugin* rail, RAIL_HANDSHAKE_EX_ORD
                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)
        {
-               IFCALLRET(context->ClientHandshakeEx, error, context, handshakeEx);
+               IFCALLRET(context->ServerHandshakeEx, error, context, handshakeEx);
 
                if (error)
                        WLog_ERR(TAG, "context.ClientHandshakeEx failed with error %"PRIu32"", error);
@@ -736,6 +754,155 @@ static UINT rail_recv_langbar_info_order(railPlugin* rail, RAIL_LANGBAR_INFO_ORD
        return error;
 }
 
+static UINT rail_read_zorder_sync_order(wStream* s, RAIL_ZORDER_ZYNC* 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_ZYNC* 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
  *
@@ -811,6 +978,24 @@ UINT rail_order_recv(railPlugin* rail, wStream* s)
                                return rail_recv_langbar_info_order(rail, &langBarInfo, s);
                        }
 
+               case RDP_RAIL_ORDER_ZORDER_SYNC:
+                       {
+                               RAIL_ZORDER_ZYNC 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:
                        WLog_ERR(TAG,  "Unknown RAIL PDU order reveived.");
                        return ERROR_INVALID_DATA;
@@ -1315,3 +1500,52 @@ UINT rail_send_client_langbar_info_order(railPlugin* rail,
        Stream_Free(s, TRUE);
        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;
+}
index 0b4fd93..182f07c 100644 (file)
@@ -52,4 +52,7 @@ UINT rail_send_client_get_appid_req_order(railPlugin* rail,
 UINT rail_send_client_langbar_info_order(railPlugin* rail,
         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 */
index df45e05..2bf5d46 100644 (file)
@@ -984,31 +984,23 @@ static UINT xf_rail_server_execute_result(RailClientContext* context,
 static UINT xf_rail_server_system_param(RailClientContext* context,
                                         const RAIL_SYSPARAM_ORDER* sysparam)
 {
+       // TODO: Actually apply param
        return CHANNEL_RC_OK;
 }
 
-/**
- * Function description
- *
- * @return 0 on success, otherwise a Win32 error code
- */
-static UINT xf_rail_server_handshake(RailClientContext* context,
-                                     const RAIL_HANDSHAKE_ORDER* handshake)
+static UINT xf_rail_server_start_cmd(RailClientContext* context)
 {
        UINT status;
        RAIL_EXEC_ORDER exec = { 0 };
        RAIL_SYSPARAM_ORDER sysparam = { 0 };
-       RAIL_HANDSHAKE_ORDER clientHandshake;
        RAIL_CLIENT_STATUS_ORDER clientStatus = { 0 };
        xfContext* xfc = (xfContext*) context->custom;
        rdpSettings* settings = xfc->context.settings;
-       clientHandshake.buildNumber = 0x00001DB0;
-       status = context->ClientHandshake(context, &clientHandshake);
+       clientStatus.flags = RAIL_CLIENTSTATUS_ALLOWLOCALMOVESIZE;
 
-       if (status != CHANNEL_RC_OK)
-               return status;
+       if (settings->AutoReconnectionEnabled)
+               clientStatus.flags |= RAIL_CLIENTSTATUS_AUTORECONNECT;
 
-       clientStatus.flags = RAIL_CLIENTSTATUS_ALLOWLOCALMOVESIZE;
        status = context->ClientInformation(context, &clientStatus);
 
        if (status != CHANNEL_RC_OK)
@@ -1018,7 +1010,10 @@ static UINT xf_rail_server_handshake(RailClientContext* context,
        {
                RAIL_LANGBAR_INFO_ORDER langBarInfo;
                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;
@@ -1050,6 +1045,16 @@ static UINT xf_rail_server_handshake(RailClientContext* context,
        exec.RemoteApplicationArguments = settings->RemoteApplicationCmdLine;
        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
@@ -1059,7 +1064,7 @@ static UINT xf_rail_server_handshake(RailClientContext* context,
 static UINT xf_rail_server_handshake_ex(RailClientContext* context,
                                         const RAIL_HANDSHAKE_EX_ORDER* handshakeEx)
 {
-       return CHANNEL_RC_OK;
+       return xf_rail_server_start_cmd(context);
 }
 
 /**
index 69c8ba9..7abacb4 100644 (file)
@@ -48,8 +48,6 @@ typedef UINT(*pcRailClientHandshake)(RailClientContext* context,
                                      const RAIL_HANDSHAKE_ORDER* handshake);
 typedef UINT(*pcRailServerHandshake)(RailClientContext* context,
                                      const RAIL_HANDSHAKE_ORDER* handshake);
-typedef UINT(*pcRailClientHandshakeEx)(RailClientContext* context,
-                                       const RAIL_HANDSHAKE_EX_ORDER* handshakeEx);
 typedef UINT(*pcRailServerHandshakeEx)(RailClientContext* context,
                                        const RAIL_HANDSHAKE_EX_ORDER* handshakeEx);
 typedef UINT(*pcRailClientNotifyEvent)(RailClientContext* context,
@@ -74,6 +72,16 @@ typedef UINT(*pcRailClientGetAppIdRequest)(RailClientContext* context,
         const RAIL_GET_APPID_REQ_ORDER* getAppIdReq);
 typedef UINT(*pcRailServerGetAppIdResponse)(RailClientContext* context,
         const RAIL_GET_APPID_RESP_ORDER* getAppIdResp);
+typedef UINT(*pcRailServerZOrderSync)(RailClientContext* context,
+                                      const RAIL_ZORDER_ZYNC* 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
 {
@@ -87,7 +95,6 @@ struct _rail_client_context
        pcRailClientSystemCommand ClientSystemCommand;
        pcRailClientHandshake ClientHandshake;
        pcRailServerHandshake ServerHandshake;
-       pcRailClientHandshakeEx ClientHandshakeEx;
        pcRailServerHandshakeEx ServerHandshakeEx;
        pcRailClientNotifyEvent ClientNotifyEvent;
        pcRailClientWindowMove ClientWindowMove;
@@ -100,6 +107,11 @@ struct _rail_client_context
        pcRailServerExecuteResult ServerExecuteResult;
        pcRailClientGetAppIdRequest ClientGetAppIdRequest;
        pcRailServerGetAppIdResponse ServerGetAppIdResponse;
+       pcRailServerZOrderSync ServerZOrderSync;
+       pcRailClientCloak ClientCloak;
+       pcRailServerPowerDisplayRequest ServerPowerDisplayRequest;
+       pcRailClientSnapArrange ClientSnapArrange;
+       pcRailServerGetAppidResponseExtended ServerGetAppidResponseExtended;
 };
 
 #endif /* FREERDP_CHANNEL_RAIL_CLIENT_RAIL_H */
index 993a1a2..b257d9b 100644 (file)
@@ -145,7 +145,9 @@ enum SPI_MASK
 #define TF_SFT_DESKBAND                                        0x00000800
 
 /* 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 */
 #define TF_PROFILETYPE_INPUTPROCESSOR                  0x00000001
@@ -352,26 +354,69 @@ struct _RAIL_COMPARTMENT_INFO_ORDER
 };
 typedef struct _RAIL_COMPARTMENT_INFO_ORDER RAIL_COMPARTMENT_INFO_ORDER;
 
+struct _RAIL_ZORDER_ZYNC
+{
+       UINT32 windowIdMarker;
+};
+typedef struct _RAIL_ZORDER_ZYNC RAIL_ZORDER_ZYNC;
+
+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 */
 
-#define RDP_RAIL_ORDER_EXEC            0x0001
-#define RDP_RAIL_ORDER_ACTIVATE                0x0002
-#define RDP_RAIL_ORDER_SYSPARAM                0x0003
-#define RDP_RAIL_ORDER_SYSCOMMAND      0x0004
-#define RDP_RAIL_ORDER_HANDSHAKE       0x0005
-#define RDP_RAIL_ORDER_NOTIFY_EVENT    0x0006
-#define RDP_RAIL_ORDER_WINDOWMOVE      0x0008
-#define RDP_RAIL_ORDER_LOCALMOVESIZE   0x0009
-#define RDP_RAIL_ORDER_MINMAXINFO      0x000A
-#define RDP_RAIL_ORDER_CLIENTSTATUS    0x000B
-#define RDP_RAIL_ORDER_SYSMENU         0x000C
-#define RDP_RAIL_ORDER_LANGBARINFO     0x000D
-#define RDP_RAIL_ORDER_EXEC_RESULT     0x0080
-#define RDP_RAIL_ORDER_GET_APPID_REQ   0x000E
-#define RDP_RAIL_ORDER_GET_APPID_RESP  0x000F
-#define RDP_RAIL_ORDER_LANGUAGEIMEINFO 0x0011
-#define RDP_RAIL_ORDER_COMPARTMENTINFO 0x0012
-#define RDP_RAIL_ORDER_HANDSHAKE_EX    0x0013
+#define RDP_RAIL_ORDER_EXEC                    0x0001
+#define RDP_RAIL_ORDER_ACTIVATE                0x0002
+#define RDP_RAIL_ORDER_SYSPARAM                0x0003
+#define RDP_RAIL_ORDER_SYSCOMMAND              0x0004
+#define RDP_RAIL_ORDER_HANDSHAKE               0x0005
+#define RDP_RAIL_ORDER_NOTIFY_EVENT            0x0006
+#define RDP_RAIL_ORDER_WINDOWMOVE              0x0008
+#define RDP_RAIL_ORDER_LOCALMOVESIZE           0x0009
+#define RDP_RAIL_ORDER_MINMAXINFO              0x000A
+#define RDP_RAIL_ORDER_CLIENTSTATUS            0x000B
+#define RDP_RAIL_ORDER_SYSMENU                 0x000C
+#define RDP_RAIL_ORDER_LANGBARINFO             0x000D
+#define RDP_RAIL_ORDER_EXEC_RESULT             0x0080
+#define RDP_RAIL_ORDER_GET_APPID_REQ           0x000E
+#define RDP_RAIL_ORDER_GET_APPID_RESP          0x000F
+#define RDP_RAIL_ORDER_LANGUAGEIMEINFO         0x0011
+#define RDP_RAIL_ORDER_COMPARTMENTINFO         0x0012
+#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
index d18c543..ba15b0a 100644 (file)
@@ -1239,7 +1239,7 @@ struct rdp_settings
         */
 
        /* RemoteApp */
-       ALIGN64 BOOL   RemoteApplicationMode;             /* 2112 */
+       ALIGN64 UINT32 RemoteApplicationMode;             /* 2112 */
        ALIGN64 char*  RemoteApplicationName;             /* 2113 */
        ALIGN64 char*  RemoteApplicationIcon;             /* 2114 */
        ALIGN64 char*  RemoteApplicationProgram;          /* 2115 */
index 1807b0e..1badada 100644 (file)
@@ -2183,16 +2183,7 @@ static BOOL rdp_read_remote_programs_capability_set(wStream* s, UINT16 length,
                return FALSE;
 
        Stream_Read_UINT32(s, railSupportLevel); /* railSupportLevel (4 bytes) */
-
-       if ((railSupportLevel & RAIL_LEVEL_SUPPORTED) == 0)
-       {
-               if (settings->RemoteApplicationMode == TRUE)
-               {
-                       /* RemoteApp Failure! */
-                       settings->RemoteApplicationMode = FALSE;
-               }
-       }
-
+       settings->RemoteApplicationMode = railSupportLevel;
        return TRUE;
 }
 
@@ -2215,8 +2206,14 @@ static BOOL rdp_write_remote_programs_capability_set(wStream* s,
        header = rdp_capability_set_start(s);
        railSupportLevel = RAIL_LEVEL_SUPPORTED;
 
-       if (settings->RemoteAppLanguageBarSupported)
-               railSupportLevel |= RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED;
+       if (settings->RemoteApplicationMode & RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED)
+       {
+               if (settings->RemoteAppLanguageBarSupported)
+                       railSupportLevel |= RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED;
+       }
+
+       if (settings->RemoteApplicationMode & RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED)
+               railSupportLevel |= RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED;
 
        Stream_Write_UINT32(s, railSupportLevel); /* railSupportLevel (4 bytes) */
        rdp_capability_set_finish(s, header, CAPSET_TYPE_RAIL);
@@ -3944,7 +3941,7 @@ BOOL rdp_write_demand_active(wStream* s, rdpSettings* settings)
                        return FALSE;
        }
 
-       if (settings->RemoteApplicationMode)
+       if (settings->RemoteApplicationMode & RAIL_LEVEL_SUPPORTED)
        {
                numberCapabilities += 2;
 
@@ -4128,7 +4125,7 @@ BOOL rdp_write_confirm_active(wStream* s, rdpSettings* settings)
                }
        }
 
-       if (settings->RemoteApplicationMode)
+       if (settings->RemoteApplicationMode & RAIL_LEVEL_SUPPORTED)
        {
                numberCapabilities += 2;
 
index b38d897..00e300e 100644 (file)
 #define DRAW_GDIPLUS_CACHE_LEVEL_ONE           0x00000001
 
 /* RAIL Support Level */
-#define RAIL_LEVEL_SUPPORTED                   0x00000001
-#define RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED    0x00000002
-#define RAIL_LEVEL_SHELL_INTEGRATION_SUPPORTED 0x00000004
-#define RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED 0x00000008
+#define RAIL_LEVEL_SUPPORTED                           0x00000001
+#define RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED            0x00000002
+#define RAIL_LEVEL_SHELL_INTEGRATION_SUPPORTED         0x00000004
+#define RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED         0x00000008
 #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 */
 #define WINDOW_LEVEL_NOT_SUPPORTED             0x00000000