25#include <freerdp/config.h>
28#include <winpr/cast.h>
30#include <freerdp/channels/log.h>
31#include <freerdp/freerdp.h>
33#include "rail_orders.h"
35static BOOL rail_is_feature_supported(
const rdpContext* context, UINT32 featureMask);
44 char buffer[128] = WINPR_C_ARRAY_INIT;
49 return ERROR_INVALID_PARAMETER;
52 const UINT16 orderLength = (UINT16)Stream_GetPosition(s);
53 Stream_ResetPosition(s);
54 if (!rail_write_pdu_header(s, orderType, orderLength))
56 if (!Stream_SetPosition(s, orderLength))
58 WLog_Print(rail->log, WLOG_DEBUG,
"Sending %s PDU, length: %" PRIu16
"",
59 rail_get_order_type_string_full(orderType, buffer,
sizeof(buffer)), orderLength);
60 return rail_send_channel_data(rail, s);
64 return ERROR_INVALID_DATA;
74 if (!s || !execResult)
75 return ERROR_INVALID_PARAMETER;
77 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_EXEC_RESULT_ORDER_LENGTH))
78 return ERROR_INVALID_DATA;
80 Stream_Read_UINT16(s, execResult->flags);
81 Stream_Read_UINT16(s, execResult->execResult);
82 Stream_Read_UINT32(s, execResult->rawResult);
83 Stream_Seek_UINT16(s);
84 return rail_read_unicode_string(s, &execResult->exeOrFile)
86 : ERROR_INTERNAL_ERROR;
96 if (!s || !minmaxinfo)
97 return ERROR_INVALID_PARAMETER;
99 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_MINMAXINFO_ORDER_LENGTH))
100 return ERROR_INVALID_DATA;
102 Stream_Read_UINT32(s, minmaxinfo->windowId);
103 Stream_Read_INT16(s, minmaxinfo->maxWidth);
104 Stream_Read_INT16(s, minmaxinfo->maxHeight);
105 Stream_Read_INT16(s, minmaxinfo->maxPosX);
106 Stream_Read_INT16(s, minmaxinfo->maxPosY);
107 Stream_Read_INT16(s, minmaxinfo->minTrackWidth);
108 Stream_Read_INT16(s, minmaxinfo->minTrackHeight);
109 Stream_Read_INT16(s, minmaxinfo->maxTrackWidth);
110 Stream_Read_INT16(s, minmaxinfo->maxTrackHeight);
111 return CHANNEL_RC_OK;
119static UINT rail_read_server_localmovesize_order(
wStream* s,
122 UINT16 isMoveSizeStart = 0;
124 if (!s || !localMoveSize)
125 return ERROR_INVALID_PARAMETER;
127 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_LOCALMOVESIZE_ORDER_LENGTH))
128 return ERROR_INVALID_DATA;
130 Stream_Read_UINT32(s, localMoveSize->windowId);
131 Stream_Read_UINT16(s, isMoveSizeStart);
132 localMoveSize->isMoveSizeStart = (isMoveSizeStart != 0);
133 Stream_Read_UINT16(s, localMoveSize->moveSizeType);
134 Stream_Read_INT16(s, localMoveSize->posX);
135 Stream_Read_INT16(s, localMoveSize->posY);
136 return CHANNEL_RC_OK;
144static UINT rail_read_server_get_appid_resp_order(
wStream* s,
147 if (!s || !getAppidResp)
148 return ERROR_INVALID_PARAMETER;
150 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_GET_APPID_RESP_ORDER_LENGTH))
151 return ERROR_INVALID_DATA;
153 Stream_Read_UINT32(s, getAppidResp->windowId);
154 if (!Stream_Read_UTF16_String(
155 s, getAppidResp->applicationId,
156 ARRAYSIZE(getAppidResp->applicationId)))
157 return ERROR_INVALID_DATA;
159 if (_wcsnlen(getAppidResp->applicationId, ARRAYSIZE(getAppidResp->applicationId)) >=
160 ARRAYSIZE(getAppidResp->applicationId))
161 return ERROR_INVALID_DATA;
163 return CHANNEL_RC_OK;
173 if (!s || !langbarInfo)
174 return ERROR_INVALID_PARAMETER;
176 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_LANGBAR_INFO_ORDER_LENGTH))
177 return ERROR_INVALID_DATA;
179 Stream_Read_UINT32(s, langbarInfo->languageBarStatus);
180 return CHANNEL_RC_OK;
185 if (!s || !clientStatus)
186 return ERROR_INVALID_PARAMETER;
188 Stream_Write_UINT32(s, clientStatus->flags);
189 return ERROR_SUCCESS;
197static UINT rail_write_client_exec_order(
wStream* s, UINT16 flags,
204 if (!s || !exeOrFile || !workingDir || !arguments)
205 return ERROR_INVALID_PARAMETER;
209 if ((exeOrFile->length > 520) || (workingDir->length > 520) || (arguments->length > 16000))
212 "TS_RAIL_ORDER_EXEC argument limits exceeded: ExeOrFile=%" PRIu16
213 " [max=520], WorkingDir=%" PRIu16
" [max=520], Arguments=%" PRIu16
" [max=16000]",
214 exeOrFile->length, workingDir->length, arguments->length);
215 return ERROR_BAD_ARGUMENTS;
218 Stream_Write_UINT16(s, flags);
219 Stream_Write_UINT16(s, exeOrFile->length);
220 Stream_Write_UINT16(s, workingDir->length);
221 Stream_Write_UINT16(s, arguments->length);
223 if ((error = rail_write_unicode_string_value(s, exeOrFile)))
225 WLog_ERR(TAG,
"rail_write_unicode_string_value failed with error %" PRIu32
"", error);
229 if ((error = rail_write_unicode_string_value(s, workingDir)))
231 WLog_ERR(TAG,
"rail_write_unicode_string_value failed with error %" PRIu32
"", error);
235 if ((error = rail_write_unicode_string_value(s, arguments)))
237 WLog_ERR(TAG,
"rail_write_unicode_string_value failed with error %" PRIu32
"", error);
249 return ERROR_INVALID_PARAMETER;
251 Stream_Write_UINT32(s, activate->windowId);
252 enabled = activate->enabled ? 1 : 0;
253 Stream_Write_UINT8(s, enabled);
254 return ERROR_SUCCESS;
260 return ERROR_INVALID_PARAMETER;
262 Stream_Write_UINT32(s, sysmenu->windowId);
263 Stream_Write_INT16(s, sysmenu->left);
264 Stream_Write_INT16(s, sysmenu->top);
265 return ERROR_SUCCESS;
270 if (!s || !syscommand)
271 return ERROR_INVALID_PARAMETER;
273 Stream_Write_UINT32(s, syscommand->windowId);
274 Stream_Write_UINT16(s, syscommand->command);
275 return ERROR_SUCCESS;
278static UINT rail_write_client_notify_event_order(
wStream* s,
281 if (!s || !notifyEvent)
282 return ERROR_INVALID_PARAMETER;
284 Stream_Write_UINT32(s, notifyEvent->windowId);
285 Stream_Write_UINT32(s, notifyEvent->notifyIconId);
286 Stream_Write_UINT32(s, notifyEvent->message);
287 return ERROR_SUCCESS;
290static UINT rail_write_client_window_move_order(
wStream* s,
293 if (!s || !windowMove)
294 return ERROR_INVALID_PARAMETER;
296 Stream_Write_UINT32(s, windowMove->windowId);
297 Stream_Write_INT16(s, windowMove->left);
298 Stream_Write_INT16(s, windowMove->top);
299 Stream_Write_INT16(s, windowMove->right);
300 Stream_Write_INT16(s, windowMove->bottom);
301 return ERROR_SUCCESS;
304static UINT rail_write_client_get_appid_req_order(
wStream* s,
307 if (!s || !getAppidReq)
308 return ERROR_INVALID_PARAMETER;
310 Stream_Write_UINT32(s, getAppidReq->windowId);
311 return ERROR_SUCCESS;
316 if (!s || !langbarInfo)
317 return ERROR_INVALID_PARAMETER;
319 Stream_Write_UINT32(s, langbarInfo->languageBarStatus);
320 return ERROR_SUCCESS;
323static UINT rail_write_languageime_info_order(
wStream* s,
326 if (!s || !langImeInfo)
327 return ERROR_INVALID_PARAMETER;
329 Stream_Write_UINT32(s, langImeInfo->ProfileType);
330 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(UINT16, langImeInfo->LanguageID));
331 Stream_Write(s, &langImeInfo->LanguageProfileCLSID,
sizeof(langImeInfo->LanguageProfileCLSID));
332 Stream_Write(s, &langImeInfo->ProfileGUID,
sizeof(langImeInfo->ProfileGUID));
333 Stream_Write_UINT32(s, langImeInfo->KeyboardLayout);
334 return ERROR_SUCCESS;
337static UINT rail_write_compartment_info_order(
wStream* s,
340 if (!s || !compartmentInfo)
341 return ERROR_INVALID_PARAMETER;
343 Stream_Write_UINT32(s, compartmentInfo->ImeState);
344 Stream_Write_UINT32(s, compartmentInfo->ImeConvMode);
345 Stream_Write_UINT32(s, compartmentInfo->ImeSentenceMode);
346 Stream_Write_UINT32(s, compartmentInfo->KanaMode);
347 return ERROR_SUCCESS;
357 RailClientContext* context = rail_get_client_interface(rail);
362 return ERROR_INVALID_PARAMETER;
364 if ((error = rail_read_handshake_order(s, &serverHandshake)))
366 WLog_ERR(TAG,
"rail_read_handshake_order failed with error %" PRIu32
"!", error);
370 rail->channelBuildNumber = serverHandshake.buildNumber;
374 IFCALLRET(context->ServerHandshake, error, context, &serverHandshake);
377 WLog_ERR(TAG,
"context.ServerHandshake failed with error %" PRIu32
"", error);
383static UINT rail_read_compartment_info_order(
wStream* s,
386 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_COMPARTMENT_INFO_ORDER_LENGTH))
387 return ERROR_INVALID_DATA;
389 Stream_Read_UINT32(s, compartmentInfo->ImeState);
390 Stream_Read_UINT32(s, compartmentInfo->ImeConvMode);
391 Stream_Read_UINT32(s, compartmentInfo->ImeSentenceMode);
392 Stream_Read_UINT32(s, compartmentInfo->KanaMode);
393 return CHANNEL_RC_OK;
398 RailClientContext* context = rail_get_client_interface(rail);
403 return ERROR_INVALID_PARAMETER;
405 if (!rail_is_feature_supported(rail->rdpcontext, RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED))
406 return ERROR_BAD_CONFIGURATION;
408 if ((error = rail_read_compartment_info_order(s, &pdu)))
413 IFCALLRET(context->ClientCompartmentInfo, error, context, &pdu);
416 WLog_ERR(TAG,
"context.ClientCompartmentInfo failed with error %" PRIu32
"", error);
422BOOL rail_is_feature_supported(
const rdpContext* context, UINT32 featureMask)
424 UINT32 supported = 0;
427 if (!context || !context->settings)
434 supported = level & mask;
435 masked = (supported & featureMask);
437 if (masked != featureMask)
439 char maskstr[256] = WINPR_C_ARRAY_INIT;
440 char actualstr[256] = WINPR_C_ARRAY_INIT;
442 WLog_WARN(TAG,
"have %s, require %s",
458 RailClientContext* context = rail_get_client_interface(rail);
462 if (!rail || !context || !s)
463 return ERROR_INVALID_PARAMETER;
465 if (!rail_is_feature_supported(rail->rdpcontext, RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED))
466 return ERROR_BAD_CONFIGURATION;
468 if ((error = rail_read_handshake_ex_order(s, &serverHandshake)))
470 WLog_ERR(TAG,
"rail_read_handshake_ex_order failed with error %" PRIu32
"!", error);
474 rail->channelBuildNumber = serverHandshake.buildNumber;
475 rail->channelFlags = serverHandshake.railHandshakeFlags;
478 char buffer[192] = WINPR_C_ARRAY_INIT;
479 WLog_DBG(TAG,
"HandshakeFlags=%s [buildNumber=0x%08" PRIx32
"]",
480 rail_handshake_ex_flags_to_string(rail->channelFlags, buffer,
sizeof(buffer)),
481 rail->channelBuildNumber);
486 IFCALLRET(context->ServerHandshakeEx, error, context, &serverHandshake);
489 WLog_ERR(TAG,
"context.ServerHandshakeEx failed with error %" PRIu32
"", error);
502 RailClientContext* context = rail_get_client_interface(rail);
507 return ERROR_INVALID_PARAMETER;
509 if ((error = rail_read_server_exec_result_order(s, &execResult)))
511 WLog_ERR(TAG,
"rail_read_server_exec_result_order failed with error %" PRIu32
"!", error);
517 IFCALLRET(context->ServerExecuteResult, error, context, &execResult);
520 WLog_ERR(TAG,
"context.ServerExecuteResult failed with error %" PRIu32
"", error);
524 rail_unicode_string_free(&execResult.exeOrFile);
535 RailClientContext* context = rail_get_client_interface(rail);
538 return ERROR_INVALID_PARAMETER;
540 const BOOL extendedSpiSupported = rail_is_extended_spi_supported(rail->channelFlags);
542 UINT error = rail_read_sysparam_order(s, &sysparam, extendedSpiSupported);
545 WLog_ERR(TAG,
"rail_read_sysparam_order failed with error %" PRIu32
"!", error);
551 IFCALLRET(context->ServerSystemParam, error, context, &sysparam);
554 WLog_ERR(TAG,
"context.ServerSystemParam failed with error %" PRIu32
"", error);
557 rail_unicode_string_free(&sysparam.highContrast.colorScheme);
569 RailClientContext* context = rail_get_client_interface(rail);
574 return ERROR_INVALID_PARAMETER;
576 if ((error = rail_read_server_minmaxinfo_order(s, &minMaxInfo)))
578 WLog_ERR(TAG,
"rail_read_server_minmaxinfo_order failed with error %" PRIu32
"!", error);
584 IFCALLRET(context->ServerMinMaxInfo, error, context, &minMaxInfo);
587 WLog_ERR(TAG,
"context.ServerMinMaxInfo failed with error %" PRIu32
"", error);
600 RailClientContext* context = rail_get_client_interface(rail);
605 return ERROR_INVALID_PARAMETER;
607 if ((error = rail_read_server_localmovesize_order(s, &localMoveSize)))
609 WLog_ERR(TAG,
"rail_read_server_localmovesize_order failed with error %" PRIu32
"!", error);
615 IFCALLRET(context->ServerLocalMoveSize, error, context, &localMoveSize);
618 WLog_ERR(TAG,
"context.ServerLocalMoveSize failed with error %" PRIu32
"", error);
631 RailClientContext* context = rail_get_client_interface(rail);
636 return ERROR_INVALID_PARAMETER;
638 if ((error = rail_read_server_get_appid_resp_order(s, &getAppIdResp)))
640 WLog_ERR(TAG,
"rail_read_server_get_appid_resp_order failed with error %" PRIu32
"!",
647 IFCALLRET(context->ServerGetAppIdResponse, error, context, &getAppIdResp);
650 WLog_ERR(TAG,
"context.ServerGetAppIdResponse failed with error %" PRIu32
"", error);
663 RailClientContext* context = rail_get_client_interface(rail);
668 return ERROR_INVALID_PARAMETER;
670 if (!rail_is_feature_supported(rail->rdpcontext, RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED))
671 return ERROR_BAD_CONFIGURATION;
673 if ((error = rail_read_langbar_info_order(s, &langBarInfo)))
675 WLog_ERR(TAG,
"rail_read_langbar_info_order failed with error %" PRIu32
"!", error);
681 IFCALLRET(context->ServerLanguageBarInfo, error, context, &langBarInfo);
684 WLog_ERR(TAG,
"context.ServerLanguageBarInfo failed with error %" PRIu32
"", error);
692 if (!s || !taskbarInfo)
693 return ERROR_INVALID_PARAMETER;
695 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_TASKBAR_INFO_ORDER_LENGTH))
696 return ERROR_INVALID_DATA;
698 Stream_Read_UINT32(s, taskbarInfo->TaskbarMessage);
699 Stream_Read_UINT32(s, taskbarInfo->WindowIdTab);
700 Stream_Read_UINT32(s, taskbarInfo->Body);
701 return CHANNEL_RC_OK;
706 RailClientContext* context = rail_get_client_interface(rail);
711 return ERROR_INVALID_PARAMETER;
715 if (!rail_is_feature_supported(rail->rdpcontext, RAIL_LEVEL_SHELL_INTEGRATION_SUPPORTED))
716 return ERROR_BAD_CONFIGURATION;
718 if ((error = rail_read_taskbar_info_order(s, &taskBarInfo)))
720 WLog_ERR(TAG,
"rail_read_langbar_info_order failed with error %" PRIu32
"!", error);
726 IFCALLRET(context->ServerTaskBarInfo, error, context, &taskBarInfo);
729 WLog_ERR(TAG,
"context.ServerTaskBarInfo failed with error %" PRIu32
"", error);
738 return ERROR_INVALID_PARAMETER;
740 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_Z_ORDER_SYNC_ORDER_LENGTH))
741 return ERROR_INVALID_DATA;
743 Stream_Read_UINT32(s, zorder->windowIdMarker);
744 return CHANNEL_RC_OK;
749 RailClientContext* context = rail_get_client_interface(rail);
754 return ERROR_INVALID_PARAMETER;
756 if ((rail->clientStatus.flags & TS_RAIL_CLIENTSTATUS_ZORDER_SYNC) == 0)
757 return ERROR_BAD_CONFIGURATION;
759 if ((error = rail_read_zorder_sync_order(s, &zorder)))
761 WLog_ERR(TAG,
"rail_read_zorder_sync_order failed with error %" PRIu32
"!", error);
767 IFCALLRET(context->ServerZOrderSync, error, context, &zorder);
770 WLog_ERR(TAG,
"context.ServerZOrderSync failed with error %" PRIu32
"", error);
780 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_CLOAK_ORDER_LENGTH))
781 return ERROR_INVALID_DATA;
783 Stream_Read_UINT32(s, cloak->windowId);
784 Stream_Read_UINT8(s, cloaked);
785 cloak->cloak = (cloaked != 0);
786 return CHANNEL_RC_OK;
791 RailClientContext* context = rail_get_client_interface(rail);
796 return ERROR_INVALID_PARAMETER;
800 if ((rail->clientStatus.flags & TS_RAIL_CLIENTSTATUS_BIDIRECTIONAL_CLOAK_SUPPORTED) == 0)
801 return ERROR_INVALID_DATA;
803 if ((error = rail_read_cloak_order(s, &cloak)))
805 WLog_ERR(TAG,
"rail_read_zorder_sync_order failed with error %" PRIu32
"!", error);
811 IFCALLRET(context->ServerCloak, error, context, &cloak);
814 WLog_ERR(TAG,
"context.ServerZOrderSync failed with error %" PRIu32
"", error);
825 return ERROR_INVALID_PARAMETER;
827 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_POWER_DISPLAY_REQUEST_ORDER_LENGTH))
828 return ERROR_INVALID_DATA;
830 Stream_Read_UINT32(s, active);
831 power->active = active != 0;
832 return CHANNEL_RC_OK;
837 RailClientContext* context = rail_get_client_interface(rail);
842 return ERROR_INVALID_PARAMETER;
846 if ((rail->clientStatus.flags & TS_RAIL_CLIENTSTATUS_POWER_DISPLAY_REQUEST_SUPPORTED) == 0)
847 return ERROR_BAD_CONFIGURATION;
849 if ((error = rail_read_power_display_request_order(s, &power)))
851 WLog_ERR(TAG,
"rail_read_zorder_sync_order failed with error %" PRIu32
"!", error);
857 IFCALLRET(context->ServerPowerDisplayRequest, error, context, &power);
860 WLog_ERR(TAG,
"context.ServerPowerDisplayRequest failed with error %" PRIu32
"", error);
866static UINT rail_read_get_application_id_extended_response_order(
wStream* s,
870 return ERROR_INVALID_PARAMETER;
872 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
873 return ERROR_INVALID_DATA;
875 Stream_Read_UINT32(s, id->windowID);
877 if (!Stream_Read_UTF16_String(s, id->applicationID, ARRAYSIZE(id->applicationID)))
878 return ERROR_INVALID_DATA;
880 if (_wcsnlen(id->applicationID, ARRAYSIZE(id->applicationID)) >= ARRAYSIZE(id->applicationID))
881 return ERROR_INVALID_DATA;
883 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
884 return ERROR_INVALID_DATA;
886 Stream_Read_UINT32(s, id->processId);
888 if (!Stream_Read_UTF16_String(s, id->processImageName, ARRAYSIZE(id->processImageName)))
889 return ERROR_INVALID_DATA;
891 if (_wcsnlen(id->processImageName, ARRAYSIZE(id->processImageName)) >=
892 ARRAYSIZE(id->processImageName))
893 return ERROR_INVALID_DATA;
895 return CHANNEL_RC_OK;
898static UINT rail_recv_get_application_id_extended_response_order(
railPlugin* rail,
wStream* s)
900 RailClientContext* context = rail_get_client_interface(rail);
905 return ERROR_INVALID_PARAMETER;
907 if ((error = rail_read_get_application_id_extended_response_order(s, &
id)))
910 "rail_read_get_application_id_extended_response_order failed with error %" PRIu32
918 IFCALLRET(context->ServerGetAppidResponseExtended, error, context, &
id);
921 WLog_ERR(TAG,
"context.ServerGetAppidResponseExtended failed with error %" PRIu32
"",
928static UINT rail_read_textscaleinfo_order(
wStream* s, UINT32* pTextScaleFactor)
930 WINPR_ASSERT(pTextScaleFactor);
932 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
933 return ERROR_INVALID_DATA;
935 Stream_Read_UINT32(s, *pTextScaleFactor);
936 return CHANNEL_RC_OK;
941 RailClientContext* context = rail_get_client_interface(rail);
942 UINT32 TextScaleFactor = 0;
946 return ERROR_INVALID_PARAMETER;
948 if ((error = rail_read_textscaleinfo_order(s, &TextScaleFactor)))
953 IFCALLRET(context->ClientTextScale, error, context, TextScaleFactor);
956 WLog_ERR(TAG,
"context.ClientTextScale failed with error %" PRIu32
"", error);
962static UINT rail_read_caretblinkinfo_order(
wStream* s, UINT32* pCaretBlinkRate)
964 WINPR_ASSERT(pCaretBlinkRate);
966 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
967 return ERROR_INVALID_DATA;
969 Stream_Read_UINT32(s, *pCaretBlinkRate);
970 return CHANNEL_RC_OK;
975 RailClientContext* context = rail_get_client_interface(rail);
976 UINT32 CaretBlinkRate = 0;
980 return ERROR_INVALID_PARAMETER;
981 if ((error = rail_read_caretblinkinfo_order(s, &CaretBlinkRate)))
986 IFCALLRET(context->ClientCaretBlinkRate, error, context, CaretBlinkRate);
989 WLog_ERR(TAG,
"context.ClientCaretBlinkRate failed with error %" PRIu32
"", error);
1000UINT rail_order_recv(LPVOID userdata,
wStream* s)
1002 char buffer[128] = WINPR_C_ARRAY_INIT;
1004 UINT16 orderType = 0;
1005 UINT16 orderLength = 0;
1006 UINT error = CHANNEL_RC_OK;
1010 error = ERROR_INVALID_PARAMETER;
1014 if ((error = rail_read_pdu_header(s, &orderType, &orderLength)))
1016 WLog_ERR(TAG,
"rail_read_pdu_header failed with error %" PRIu32
"!", error);
1017 error = ERROR_INVALID_DATA;
1021 WLog_Print(rail->log, WLOG_DEBUG,
"Received %s PDU, length:%" PRIu16
"",
1022 rail_get_order_type_string_full(orderType, buffer,
sizeof(buffer)), orderLength);
1026 case TS_RAIL_ORDER_HANDSHAKE:
1027 error = rail_recv_handshake_order(rail, s);
1030 case TS_RAIL_ORDER_COMPARTMENTINFO:
1031 error = rail_recv_compartmentinfo_order(rail, s);
1034 case TS_RAIL_ORDER_HANDSHAKE_EX:
1035 error = rail_recv_handshake_ex_order(rail, s);
1038 case TS_RAIL_ORDER_EXEC_RESULT:
1039 error = rail_recv_exec_result_order(rail, s);
1042 case TS_RAIL_ORDER_SYSPARAM:
1043 error = rail_recv_server_sysparam_order(rail, s);
1046 case TS_RAIL_ORDER_MINMAXINFO:
1047 error = rail_recv_server_minmaxinfo_order(rail, s);
1050 case TS_RAIL_ORDER_LOCALMOVESIZE:
1051 error = rail_recv_server_localmovesize_order(rail, s);
1054 case TS_RAIL_ORDER_GET_APPID_RESP:
1055 error = rail_recv_server_get_appid_resp_order(rail, s);
1058 case TS_RAIL_ORDER_LANGBARINFO:
1059 error = rail_recv_langbar_info_order(rail, s);
1062 case TS_RAIL_ORDER_TASKBARINFO:
1063 error = rail_recv_taskbar_info_order(rail, s);
1066 case TS_RAIL_ORDER_ZORDER_SYNC:
1067 error = rail_recv_zorder_sync_order(rail, s);
1070 case TS_RAIL_ORDER_CLOAK:
1071 error = rail_recv_cloak_order(rail, s);
1074 case TS_RAIL_ORDER_POWER_DISPLAY_REQUEST:
1075 error = rail_recv_power_display_request_order(rail, s);
1078 case TS_RAIL_ORDER_GET_APPID_RESP_EX:
1079 error = rail_recv_get_application_id_extended_response_order(rail, s);
1082 case TS_RAIL_ORDER_TEXTSCALEINFO:
1083 error = rail_recv_textscaleinfo_order(rail, s);
1086 case TS_RAIL_ORDER_CARETBLINKINFO:
1087 error = rail_recv_caretblinkinfo_order(rail, s);
1091 WLog_ERR(TAG,
"Unknown RAIL PDU %s received.",
1092 rail_get_order_type_string_full(orderType, buffer,
sizeof(buffer)));
1093 return ERROR_INVALID_DATA;
1096 if (error == ERROR_BAD_CONFIGURATION)
1098 char ebuffer[128] = WINPR_C_ARRAY_INIT;
1099 WLog_Print(rail->log, WLOG_WARN,
1100 "%s - SERVER BUG: The support for this feature was not announced!",
1101 rail_get_order_type_string_full(orderType, ebuffer,
sizeof(ebuffer)));
1104 FreeRDP_AllowUnanouncedOrdersFromServer))
1105 error = CHANNEL_RC_OK;
1107 if (error != CHANNEL_RC_OK)
1109 char ebuffer[128] = WINPR_C_ARRAY_INIT;
1110 WLog_Print(rail->log, WLOG_ERROR,
"Failed to process rail %s PDU, length:%" PRIu16
"",
1111 rail_get_order_type_string_full(orderType, ebuffer,
sizeof(ebuffer)),
1116 Stream_Free(s, TRUE);
1127 if (!rail || !handshake)
1128 return ERROR_INVALID_PARAMETER;
1130 wStream* s = rail_pdu_init(RAIL_HANDSHAKE_ORDER_LENGTH);
1134 WLog_ERR(TAG,
"rail_pdu_init failed!");
1135 return CHANNEL_RC_NO_MEMORY;
1138 rail_write_handshake_order(s, handshake);
1139 return rail_send_pdu(rail, s, TS_RAIL_ORDER_HANDSHAKE);
1149 if (!rail || !handshakeEx)
1150 return ERROR_INVALID_PARAMETER;
1152 wStream* s = rail_pdu_init(RAIL_HANDSHAKE_EX_ORDER_LENGTH);
1156 WLog_ERR(TAG,
"rail_pdu_init failed!");
1157 return CHANNEL_RC_NO_MEMORY;
1160 rail_write_handshake_ex_order(s, handshakeEx);
1161 return rail_send_pdu(rail, s, TS_RAIL_ORDER_HANDSHAKE_EX);
1174 if (!rail || !clientStatus)
1175 return ERROR_INVALID_PARAMETER;
1177 rail->clientStatus = *clientStatus;
1178 s = rail_pdu_init(RAIL_CLIENT_STATUS_ORDER_LENGTH);
1182 WLog_ERR(TAG,
"rail_pdu_init failed!");
1183 return CHANNEL_RC_NO_MEMORY;
1186 error = rail_write_client_status_order(s, clientStatus);
1188 if (ERROR_SUCCESS != error)
1191 Stream_Free(s, TRUE);
1195 return rail_send_pdu(rail, s, TS_RAIL_ORDER_CLIENTSTATUS);
1203UINT rail_send_client_exec_order(
railPlugin* rail, UINT16 flags,
1212 if (!rail || !exeOrFile || !workingDir || !arguments)
1213 return ERROR_INVALID_PARAMETER;
1215 length = RAIL_EXEC_ORDER_LENGTH + exeOrFile->length + workingDir->length + arguments->length;
1216 s = rail_pdu_init(length);
1220 WLog_ERR(TAG,
"rail_pdu_init failed!");
1221 return CHANNEL_RC_NO_MEMORY;
1224 if ((error = rail_write_client_exec_order(s, flags, exeOrFile, workingDir, arguments)))
1226 WLog_ERR(TAG,
"rail_write_client_exec_order failed with error %" PRIu32
"!", error);
1230 return rail_send_pdu(rail, s, TS_RAIL_ORDER_EXEC);
1233 Stream_Free(s, TRUE);
1247 if (!rail || !activate)
1248 return ERROR_INVALID_PARAMETER;
1250 s = rail_pdu_init(RAIL_ACTIVATE_ORDER_LENGTH);
1254 WLog_ERR(TAG,
"rail_pdu_init failed!");
1255 return CHANNEL_RC_NO_MEMORY;
1258 error = rail_write_client_activate_order(s, activate);
1260 if (ERROR_SUCCESS != error)
1263 Stream_Free(s, TRUE);
1267 return rail_send_pdu(rail, s, TS_RAIL_ORDER_ACTIVATE);
1280 if (!rail || !sysmenu)
1281 return ERROR_INVALID_PARAMETER;
1283 s = rail_pdu_init(RAIL_SYSMENU_ORDER_LENGTH);
1287 WLog_ERR(TAG,
"rail_pdu_init failed!");
1288 return CHANNEL_RC_NO_MEMORY;
1291 error = rail_write_client_sysmenu_order(s, sysmenu);
1293 if (ERROR_SUCCESS != error)
1296 Stream_Free(s, TRUE);
1300 return rail_send_pdu(rail, s, TS_RAIL_ORDER_SYSMENU);
1313 if (!rail || !syscommand)
1314 return ERROR_INVALID_PARAMETER;
1316 s = rail_pdu_init(RAIL_SYSCOMMAND_ORDER_LENGTH);
1320 WLog_ERR(TAG,
"rail_pdu_init failed!");
1321 return CHANNEL_RC_NO_MEMORY;
1324 error = rail_write_client_syscommand_order(s, syscommand);
1326 if (ERROR_SUCCESS != error)
1329 Stream_Free(s, TRUE);
1333 return rail_send_pdu(rail, s, TS_RAIL_ORDER_SYSCOMMAND);
1341UINT rail_send_client_notify_event_order(
railPlugin* rail,
1347 if (!rail || !notifyEvent)
1348 return ERROR_INVALID_PARAMETER;
1350 s = rail_pdu_init(RAIL_NOTIFY_EVENT_ORDER_LENGTH);
1354 WLog_ERR(TAG,
"rail_pdu_init failed!");
1355 return CHANNEL_RC_NO_MEMORY;
1358 error = rail_write_client_notify_event_order(s, notifyEvent);
1360 if (ERROR_SUCCESS != error)
1363 Stream_Free(s, TRUE);
1367 return rail_send_pdu(rail, s, TS_RAIL_ORDER_NOTIFY_EVENT);
1380 if (!rail || !windowMove)
1381 return ERROR_INVALID_PARAMETER;
1383 s = rail_pdu_init(RAIL_WINDOW_MOVE_ORDER_LENGTH);
1387 WLog_ERR(TAG,
"rail_pdu_init failed!");
1388 return CHANNEL_RC_NO_MEMORY;
1391 error = rail_write_client_window_move_order(s, windowMove);
1393 if (ERROR_SUCCESS != error)
1396 Stream_Free(s, TRUE);
1400 return rail_send_pdu(rail, s, TS_RAIL_ORDER_WINDOWMOVE);
1408UINT rail_send_client_get_appid_req_order(
railPlugin* rail,
1414 if (!rail || !getAppIdReq)
1415 return ERROR_INVALID_PARAMETER;
1417 s = rail_pdu_init(RAIL_GET_APPID_REQ_ORDER_LENGTH);
1421 WLog_ERR(TAG,
"rail_pdu_init failed!");
1422 return CHANNEL_RC_NO_MEMORY;
1425 error = rail_write_client_get_appid_req_order(s, getAppIdReq);
1427 if (ERROR_SUCCESS != error)
1430 Stream_Free(s, TRUE);
1433 return rail_send_pdu(rail, s, TS_RAIL_ORDER_GET_APPID_REQ);
1441UINT rail_send_client_langbar_info_order(
railPlugin* rail,
1447 if (!rail || !langBarInfo)
1448 return ERROR_INVALID_PARAMETER;
1450 if (!rail_is_feature_supported(rail->rdpcontext, RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED))
1451 return ERROR_BAD_CONFIGURATION;
1453 s = rail_pdu_init(RAIL_LANGBAR_INFO_ORDER_LENGTH);
1457 WLog_ERR(TAG,
"rail_pdu_init failed!");
1458 return CHANNEL_RC_NO_MEMORY;
1461 error = rail_write_langbar_info_order(s, langBarInfo);
1463 if (ERROR_SUCCESS != error)
1466 Stream_Free(s, TRUE);
1469 return rail_send_pdu(rail, s, TS_RAIL_ORDER_LANGBARINFO);
1472UINT rail_send_client_languageime_info_order(
railPlugin* rail,
1478 if (!rail || !langImeInfo)
1479 return ERROR_INVALID_PARAMETER;
1481 if (!rail_is_feature_supported(rail->rdpcontext, RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED))
1482 return ERROR_BAD_CONFIGURATION;
1484 s = rail_pdu_init(RAIL_LANGUAGEIME_INFO_ORDER_LENGTH);
1488 WLog_ERR(TAG,
"rail_pdu_init failed!");
1489 return CHANNEL_RC_NO_MEMORY;
1492 error = rail_write_languageime_info_order(s, langImeInfo);
1494 if (ERROR_SUCCESS != error)
1497 Stream_Free(s, TRUE);
1500 return rail_send_pdu(rail, s, TS_RAIL_ORDER_LANGUAGEIMEINFO);
1503UINT rail_send_client_compartment_info_order(
railPlugin* rail,
1509 if (!rail || !compartmentInfo)
1510 return ERROR_INVALID_PARAMETER;
1512 if (!rail_is_feature_supported(rail->rdpcontext, RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED))
1513 return ERROR_BAD_CONFIGURATION;
1515 s = rail_pdu_init(RAIL_COMPARTMENT_INFO_ORDER_LENGTH);
1519 WLog_ERR(TAG,
"rail_pdu_init failed!");
1520 return CHANNEL_RC_NO_MEMORY;
1523 error = rail_write_compartment_info_order(s, compartmentInfo);
1525 if (ERROR_SUCCESS != error)
1527 Stream_Free(s, TRUE);
1530 return rail_send_pdu(rail, s, TS_RAIL_ORDER_COMPARTMENTINFO);
1535 if (!rail || !cloak)
1536 return ERROR_INVALID_PARAMETER;
1538 wStream* s = rail_pdu_init(5);
1542 WLog_ERR(TAG,
"rail_pdu_init failed!");
1543 return CHANNEL_RC_NO_MEMORY;
1546 Stream_Write_UINT32(s, cloak->windowId);
1547 Stream_Write_UINT8(s, cloak->cloak ? 1 : 0);
1548 return rail_send_pdu(rail, s, TS_RAIL_ORDER_CLOAK);
1554 return ERROR_INVALID_PARAMETER;
1557 if ((rail->channelFlags & TS_RAIL_ORDER_HANDSHAKE_EX_FLAGS_SNAP_ARRANGE_SUPPORTED) == 0)
1560 move.top = snap->top;
1561 move.left = snap->left;
1562 move.right = snap->right;
1563 move.bottom = snap->bottom;
1564 move.windowId = snap->windowId;
1565 return rail_send_client_window_move_order(rail, &move);
1568 wStream* s = rail_pdu_init(12);
1572 WLog_ERR(TAG,
"rail_pdu_init failed!");
1573 return CHANNEL_RC_NO_MEMORY;
1576 Stream_Write_UINT32(s, snap->windowId);
1577 Stream_Write_INT16(s, snap->left);
1578 Stream_Write_INT16(s, snap->top);
1579 Stream_Write_INT16(s, snap->right);
1580 Stream_Write_INT16(s, snap->bottom);
1581 return rail_send_pdu(rail, s, TS_RAIL_ORDER_SNAP_ARRANGE);
1584UINT rail_send_client_text_scale_order(
railPlugin* rail, UINT32 textScale)
1587 return ERROR_INVALID_PARAMETER;
1589 wStream* s = rail_pdu_init(4);
1593 WLog_ERR(TAG,
"rail_pdu_init failed!");
1594 return CHANNEL_RC_NO_MEMORY;
1597 Stream_Write_UINT32(s, textScale);
1598 return rail_send_pdu(rail, s, TS_RAIL_ORDER_TEXTSCALEINFO);
1601UINT rail_send_client_caret_blink_rate_order(
railPlugin* rail, UINT32 rate)
1604 return ERROR_INVALID_PARAMETER;
1606 wStream* s = rail_pdu_init(4);
1610 WLog_ERR(TAG,
"rail_pdu_init failed!");
1611 return CHANNEL_RC_NO_MEMORY;
1614 Stream_Write_UINT32(s, rate);
1615 return rail_send_pdu(rail, s, TS_RAIL_ORDER_CARETBLINKINFO);
WINPR_ATTR_NODISCARD FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
WINPR_ATTR_NODISCARD FREERDP_API const char * freerdp_rail_support_flags_to_string(UINT32 flags, char *buffer, size_t length)
Returns a stringified representation of RAIL support flags.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.