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;
158 return CHANNEL_RC_OK;
168 if (!s || !langbarInfo)
169 return ERROR_INVALID_PARAMETER;
171 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_LANGBAR_INFO_ORDER_LENGTH))
172 return ERROR_INVALID_DATA;
174 Stream_Read_UINT32(s, langbarInfo->languageBarStatus);
175 return CHANNEL_RC_OK;
180 if (!s || !clientStatus)
181 return ERROR_INVALID_PARAMETER;
183 Stream_Write_UINT32(s, clientStatus->flags);
184 return ERROR_SUCCESS;
192static UINT rail_write_client_exec_order(
wStream* s, UINT16 flags,
199 if (!s || !exeOrFile || !workingDir || !arguments)
200 return ERROR_INVALID_PARAMETER;
204 if ((exeOrFile->length > 520) || (workingDir->length > 520) || (arguments->length > 16000))
207 "TS_RAIL_ORDER_EXEC argument limits exceeded: ExeOrFile=%" PRIu16
208 " [max=520], WorkingDir=%" PRIu16
" [max=520], Arguments=%" PRIu16
" [max=16000]",
209 exeOrFile->length, workingDir->length, arguments->length);
210 return ERROR_BAD_ARGUMENTS;
213 Stream_Write_UINT16(s, flags);
214 Stream_Write_UINT16(s, exeOrFile->length);
215 Stream_Write_UINT16(s, workingDir->length);
216 Stream_Write_UINT16(s, arguments->length);
218 if ((error = rail_write_unicode_string_value(s, exeOrFile)))
220 WLog_ERR(TAG,
"rail_write_unicode_string_value failed with error %" PRIu32
"", error);
224 if ((error = rail_write_unicode_string_value(s, workingDir)))
226 WLog_ERR(TAG,
"rail_write_unicode_string_value failed with error %" PRIu32
"", error);
230 if ((error = rail_write_unicode_string_value(s, arguments)))
232 WLog_ERR(TAG,
"rail_write_unicode_string_value failed with error %" PRIu32
"", error);
244 return ERROR_INVALID_PARAMETER;
246 Stream_Write_UINT32(s, activate->windowId);
247 enabled = activate->enabled ? 1 : 0;
248 Stream_Write_UINT8(s, enabled);
249 return ERROR_SUCCESS;
255 return ERROR_INVALID_PARAMETER;
257 Stream_Write_UINT32(s, sysmenu->windowId);
258 Stream_Write_INT16(s, sysmenu->left);
259 Stream_Write_INT16(s, sysmenu->top);
260 return ERROR_SUCCESS;
265 if (!s || !syscommand)
266 return ERROR_INVALID_PARAMETER;
268 Stream_Write_UINT32(s, syscommand->windowId);
269 Stream_Write_UINT16(s, syscommand->command);
270 return ERROR_SUCCESS;
273static UINT rail_write_client_notify_event_order(
wStream* s,
276 if (!s || !notifyEvent)
277 return ERROR_INVALID_PARAMETER;
279 Stream_Write_UINT32(s, notifyEvent->windowId);
280 Stream_Write_UINT32(s, notifyEvent->notifyIconId);
281 Stream_Write_UINT32(s, notifyEvent->message);
282 return ERROR_SUCCESS;
285static UINT rail_write_client_window_move_order(
wStream* s,
288 if (!s || !windowMove)
289 return ERROR_INVALID_PARAMETER;
291 Stream_Write_UINT32(s, windowMove->windowId);
292 Stream_Write_INT16(s, windowMove->left);
293 Stream_Write_INT16(s, windowMove->top);
294 Stream_Write_INT16(s, windowMove->right);
295 Stream_Write_INT16(s, windowMove->bottom);
296 return ERROR_SUCCESS;
299static UINT rail_write_client_get_appid_req_order(
wStream* s,
302 if (!s || !getAppidReq)
303 return ERROR_INVALID_PARAMETER;
305 Stream_Write_UINT32(s, getAppidReq->windowId);
306 return ERROR_SUCCESS;
311 if (!s || !langbarInfo)
312 return ERROR_INVALID_PARAMETER;
314 Stream_Write_UINT32(s, langbarInfo->languageBarStatus);
315 return ERROR_SUCCESS;
318static UINT rail_write_languageime_info_order(
wStream* s,
321 if (!s || !langImeInfo)
322 return ERROR_INVALID_PARAMETER;
324 Stream_Write_UINT32(s, langImeInfo->ProfileType);
325 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(UINT16, langImeInfo->LanguageID));
326 Stream_Write(s, &langImeInfo->LanguageProfileCLSID,
sizeof(langImeInfo->LanguageProfileCLSID));
327 Stream_Write(s, &langImeInfo->ProfileGUID,
sizeof(langImeInfo->ProfileGUID));
328 Stream_Write_UINT32(s, langImeInfo->KeyboardLayout);
329 return ERROR_SUCCESS;
332static UINT rail_write_compartment_info_order(
wStream* s,
335 if (!s || !compartmentInfo)
336 return ERROR_INVALID_PARAMETER;
338 Stream_Write_UINT32(s, compartmentInfo->ImeState);
339 Stream_Write_UINT32(s, compartmentInfo->ImeConvMode);
340 Stream_Write_UINT32(s, compartmentInfo->ImeSentenceMode);
341 Stream_Write_UINT32(s, compartmentInfo->KanaMode);
342 return ERROR_SUCCESS;
352 RailClientContext* context = rail_get_client_interface(rail);
357 return ERROR_INVALID_PARAMETER;
359 if ((error = rail_read_handshake_order(s, &serverHandshake)))
361 WLog_ERR(TAG,
"rail_read_handshake_order failed with error %" PRIu32
"!", error);
365 rail->channelBuildNumber = serverHandshake.buildNumber;
369 IFCALLRET(context->ServerHandshake, error, context, &serverHandshake);
372 WLog_ERR(TAG,
"context.ServerHandshake failed with error %" PRIu32
"", error);
378static UINT rail_read_compartment_info_order(
wStream* s,
381 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_COMPARTMENT_INFO_ORDER_LENGTH))
382 return ERROR_INVALID_DATA;
384 Stream_Read_UINT32(s, compartmentInfo->ImeState);
385 Stream_Read_UINT32(s, compartmentInfo->ImeConvMode);
386 Stream_Read_UINT32(s, compartmentInfo->ImeSentenceMode);
387 Stream_Read_UINT32(s, compartmentInfo->KanaMode);
388 return CHANNEL_RC_OK;
393 RailClientContext* context = rail_get_client_interface(rail);
398 return ERROR_INVALID_PARAMETER;
400 if (!rail_is_feature_supported(rail->rdpcontext, RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED))
401 return ERROR_BAD_CONFIGURATION;
403 if ((error = rail_read_compartment_info_order(s, &pdu)))
408 IFCALLRET(context->ClientCompartmentInfo, error, context, &pdu);
411 WLog_ERR(TAG,
"context.ClientCompartmentInfo failed with error %" PRIu32
"", error);
417BOOL rail_is_feature_supported(
const rdpContext* context, UINT32 featureMask)
419 UINT32 supported = 0;
422 if (!context || !context->settings)
429 supported = level & mask;
430 masked = (supported & featureMask);
432 if (masked != featureMask)
434 char maskstr[256] = WINPR_C_ARRAY_INIT;
435 char actualstr[256] = WINPR_C_ARRAY_INIT;
437 WLog_WARN(TAG,
"have %s, require %s",
453 RailClientContext* context = rail_get_client_interface(rail);
457 if (!rail || !context || !s)
458 return ERROR_INVALID_PARAMETER;
460 if (!rail_is_feature_supported(rail->rdpcontext, RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED))
461 return ERROR_BAD_CONFIGURATION;
463 if ((error = rail_read_handshake_ex_order(s, &serverHandshake)))
465 WLog_ERR(TAG,
"rail_read_handshake_ex_order failed with error %" PRIu32
"!", error);
469 rail->channelBuildNumber = serverHandshake.buildNumber;
470 rail->channelFlags = serverHandshake.railHandshakeFlags;
473 char buffer[192] = WINPR_C_ARRAY_INIT;
474 WLog_DBG(TAG,
"HandshakeFlags=%s [buildNumber=0x%08" PRIx32
"]",
475 rail_handshake_ex_flags_to_string(rail->channelFlags, buffer,
sizeof(buffer)),
476 rail->channelBuildNumber);
481 IFCALLRET(context->ServerHandshakeEx, error, context, &serverHandshake);
484 WLog_ERR(TAG,
"context.ServerHandshakeEx failed with error %" PRIu32
"", error);
497 RailClientContext* context = rail_get_client_interface(rail);
502 return ERROR_INVALID_PARAMETER;
504 if ((error = rail_read_server_exec_result_order(s, &execResult)))
506 WLog_ERR(TAG,
"rail_read_server_exec_result_order failed with error %" PRIu32
"!", error);
512 IFCALLRET(context->ServerExecuteResult, error, context, &execResult);
515 WLog_ERR(TAG,
"context.ServerExecuteResult failed with error %" PRIu32
"", error);
519 free(execResult.exeOrFile.string);
530 RailClientContext* context = rail_get_client_interface(rail);
533 return ERROR_INVALID_PARAMETER;
535 const BOOL extendedSpiSupported = rail_is_extended_spi_supported(rail->channelFlags);
537 UINT error = rail_read_sysparam_order(s, &sysparam, extendedSpiSupported);
540 WLog_ERR(TAG,
"rail_read_sysparam_order failed with error %" PRIu32
"!", error);
546 IFCALLRET(context->ServerSystemParam, error, context, &sysparam);
549 WLog_ERR(TAG,
"context.ServerSystemParam failed with error %" PRIu32
"", error);
552 free(sysparam.highContrast.colorScheme.string);
564 RailClientContext* context = rail_get_client_interface(rail);
569 return ERROR_INVALID_PARAMETER;
571 if ((error = rail_read_server_minmaxinfo_order(s, &minMaxInfo)))
573 WLog_ERR(TAG,
"rail_read_server_minmaxinfo_order failed with error %" PRIu32
"!", error);
579 IFCALLRET(context->ServerMinMaxInfo, error, context, &minMaxInfo);
582 WLog_ERR(TAG,
"context.ServerMinMaxInfo failed with error %" PRIu32
"", error);
595 RailClientContext* context = rail_get_client_interface(rail);
600 return ERROR_INVALID_PARAMETER;
602 if ((error = rail_read_server_localmovesize_order(s, &localMoveSize)))
604 WLog_ERR(TAG,
"rail_read_server_localmovesize_order failed with error %" PRIu32
"!", error);
610 IFCALLRET(context->ServerLocalMoveSize, error, context, &localMoveSize);
613 WLog_ERR(TAG,
"context.ServerLocalMoveSize failed with error %" PRIu32
"", error);
626 RailClientContext* context = rail_get_client_interface(rail);
631 return ERROR_INVALID_PARAMETER;
633 if ((error = rail_read_server_get_appid_resp_order(s, &getAppIdResp)))
635 WLog_ERR(TAG,
"rail_read_server_get_appid_resp_order failed with error %" PRIu32
"!",
642 IFCALLRET(context->ServerGetAppIdResponse, error, context, &getAppIdResp);
645 WLog_ERR(TAG,
"context.ServerGetAppIdResponse failed with error %" PRIu32
"", error);
658 RailClientContext* context = rail_get_client_interface(rail);
663 return ERROR_INVALID_PARAMETER;
665 if (!rail_is_feature_supported(rail->rdpcontext, RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED))
666 return ERROR_BAD_CONFIGURATION;
668 if ((error = rail_read_langbar_info_order(s, &langBarInfo)))
670 WLog_ERR(TAG,
"rail_read_langbar_info_order failed with error %" PRIu32
"!", error);
676 IFCALLRET(context->ServerLanguageBarInfo, error, context, &langBarInfo);
679 WLog_ERR(TAG,
"context.ServerLanguageBarInfo failed with error %" PRIu32
"", error);
687 if (!s || !taskbarInfo)
688 return ERROR_INVALID_PARAMETER;
690 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_TASKBAR_INFO_ORDER_LENGTH))
691 return ERROR_INVALID_DATA;
693 Stream_Read_UINT32(s, taskbarInfo->TaskbarMessage);
694 Stream_Read_UINT32(s, taskbarInfo->WindowIdTab);
695 Stream_Read_UINT32(s, taskbarInfo->Body);
696 return CHANNEL_RC_OK;
701 RailClientContext* context = rail_get_client_interface(rail);
706 return ERROR_INVALID_PARAMETER;
710 if (!rail_is_feature_supported(rail->rdpcontext, RAIL_LEVEL_SHELL_INTEGRATION_SUPPORTED))
711 return ERROR_BAD_CONFIGURATION;
713 if ((error = rail_read_taskbar_info_order(s, &taskBarInfo)))
715 WLog_ERR(TAG,
"rail_read_langbar_info_order failed with error %" PRIu32
"!", error);
721 IFCALLRET(context->ServerTaskBarInfo, error, context, &taskBarInfo);
724 WLog_ERR(TAG,
"context.ServerTaskBarInfo failed with error %" PRIu32
"", error);
733 return ERROR_INVALID_PARAMETER;
735 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_Z_ORDER_SYNC_ORDER_LENGTH))
736 return ERROR_INVALID_DATA;
738 Stream_Read_UINT32(s, zorder->windowIdMarker);
739 return CHANNEL_RC_OK;
744 RailClientContext* context = rail_get_client_interface(rail);
749 return ERROR_INVALID_PARAMETER;
751 if ((rail->clientStatus.flags & TS_RAIL_CLIENTSTATUS_ZORDER_SYNC) == 0)
752 return ERROR_INVALID_DATA;
754 if ((error = rail_read_zorder_sync_order(s, &zorder)))
756 WLog_ERR(TAG,
"rail_read_zorder_sync_order failed with error %" PRIu32
"!", error);
762 IFCALLRET(context->ServerZOrderSync, error, context, &zorder);
765 WLog_ERR(TAG,
"context.ServerZOrderSync failed with error %" PRIu32
"", error);
775 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_CLOAK_ORDER_LENGTH))
776 return ERROR_INVALID_DATA;
778 Stream_Read_UINT32(s, cloak->windowId);
779 Stream_Read_UINT8(s, cloaked);
780 cloak->cloak = (cloaked != 0);
781 return CHANNEL_RC_OK;
786 RailClientContext* context = rail_get_client_interface(rail);
791 return ERROR_INVALID_PARAMETER;
795 if ((rail->clientStatus.flags & TS_RAIL_CLIENTSTATUS_BIDIRECTIONAL_CLOAK_SUPPORTED) == 0)
796 return ERROR_INVALID_DATA;
798 if ((error = rail_read_cloak_order(s, &cloak)))
800 WLog_ERR(TAG,
"rail_read_zorder_sync_order failed with error %" PRIu32
"!", error);
806 IFCALLRET(context->ServerCloak, error, context, &cloak);
809 WLog_ERR(TAG,
"context.ServerZOrderSync failed with error %" PRIu32
"", error);
820 return ERROR_INVALID_PARAMETER;
822 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_POWER_DISPLAY_REQUEST_ORDER_LENGTH))
823 return ERROR_INVALID_DATA;
825 Stream_Read_UINT32(s, active);
826 power->active = active != 0;
827 return CHANNEL_RC_OK;
832 RailClientContext* context = rail_get_client_interface(rail);
837 return ERROR_INVALID_PARAMETER;
841 if ((rail->clientStatus.flags & TS_RAIL_CLIENTSTATUS_POWER_DISPLAY_REQUEST_SUPPORTED) == 0)
842 return ERROR_INVALID_DATA;
844 if ((error = rail_read_power_display_request_order(s, &power)))
846 WLog_ERR(TAG,
"rail_read_zorder_sync_order failed with error %" PRIu32
"!", error);
852 IFCALLRET(context->ServerPowerDisplayRequest, error, context, &power);
855 WLog_ERR(TAG,
"context.ServerPowerDisplayRequest failed with error %" PRIu32
"", error);
861static UINT rail_read_get_application_id_extended_response_order(
wStream* s,
865 return ERROR_INVALID_PARAMETER;
867 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
868 return ERROR_INVALID_DATA;
870 Stream_Read_UINT32(s, id->windowID);
872 if (!Stream_Read_UTF16_String(s, id->applicationID, ARRAYSIZE(id->applicationID)))
873 return ERROR_INVALID_DATA;
875 if (_wcsnlen(id->applicationID, ARRAYSIZE(id->applicationID)) >= ARRAYSIZE(id->applicationID))
876 return ERROR_INVALID_DATA;
878 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
879 return ERROR_INVALID_DATA;
881 Stream_Read_UINT32(s, id->processId);
883 if (!Stream_Read_UTF16_String(s, id->processImageName, ARRAYSIZE(id->processImageName)))
884 return ERROR_INVALID_DATA;
886 if (_wcsnlen(id->applicationID, ARRAYSIZE(id->processImageName)) >=
887 ARRAYSIZE(id->processImageName))
888 return ERROR_INVALID_DATA;
890 return CHANNEL_RC_OK;
893static UINT rail_recv_get_application_id_extended_response_order(
railPlugin* rail,
wStream* s)
895 RailClientContext* context = rail_get_client_interface(rail);
900 return ERROR_INVALID_PARAMETER;
902 if ((error = rail_read_get_application_id_extended_response_order(s, &
id)))
905 "rail_read_get_application_id_extended_response_order failed with error %" PRIu32
913 IFCALLRET(context->ServerGetAppidResponseExtended, error, context, &
id);
916 WLog_ERR(TAG,
"context.ServerGetAppidResponseExtended failed with error %" PRIu32
"",
923static UINT rail_read_textscaleinfo_order(
wStream* s, UINT32* pTextScaleFactor)
925 WINPR_ASSERT(pTextScaleFactor);
927 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
928 return ERROR_INVALID_DATA;
930 Stream_Read_UINT32(s, *pTextScaleFactor);
931 return CHANNEL_RC_OK;
936 RailClientContext* context = rail_get_client_interface(rail);
937 UINT32 TextScaleFactor = 0;
941 return ERROR_INVALID_PARAMETER;
943 if ((error = rail_read_textscaleinfo_order(s, &TextScaleFactor)))
948 IFCALLRET(context->ClientTextScale, error, context, TextScaleFactor);
951 WLog_ERR(TAG,
"context.ClientTextScale failed with error %" PRIu32
"", error);
957static UINT rail_read_caretblinkinfo_order(
wStream* s, UINT32* pCaretBlinkRate)
959 WINPR_ASSERT(pCaretBlinkRate);
961 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
962 return ERROR_INVALID_DATA;
964 Stream_Read_UINT32(s, *pCaretBlinkRate);
965 return CHANNEL_RC_OK;
970 RailClientContext* context = rail_get_client_interface(rail);
971 UINT32 CaretBlinkRate = 0;
975 return ERROR_INVALID_PARAMETER;
976 if ((error = rail_read_caretblinkinfo_order(s, &CaretBlinkRate)))
981 IFCALLRET(context->ClientCaretBlinkRate, error, context, CaretBlinkRate);
984 WLog_ERR(TAG,
"context.ClientCaretBlinkRate failed with error %" PRIu32
"", error);
995UINT rail_order_recv(LPVOID userdata,
wStream* s)
997 char buffer[128] = WINPR_C_ARRAY_INIT;
999 UINT16 orderType = 0;
1000 UINT16 orderLength = 0;
1001 UINT error = CHANNEL_RC_OK;
1005 error = ERROR_INVALID_PARAMETER;
1009 if ((error = rail_read_pdu_header(s, &orderType, &orderLength)))
1011 WLog_ERR(TAG,
"rail_read_pdu_header failed with error %" PRIu32
"!", error);
1012 error = ERROR_INVALID_DATA;
1016 WLog_Print(rail->log, WLOG_DEBUG,
"Received %s PDU, length:%" PRIu16
"",
1017 rail_get_order_type_string_full(orderType, buffer,
sizeof(buffer)), orderLength);
1021 case TS_RAIL_ORDER_HANDSHAKE:
1022 error = rail_recv_handshake_order(rail, s);
1025 case TS_RAIL_ORDER_COMPARTMENTINFO:
1026 error = rail_recv_compartmentinfo_order(rail, s);
1029 case TS_RAIL_ORDER_HANDSHAKE_EX:
1030 error = rail_recv_handshake_ex_order(rail, s);
1033 case TS_RAIL_ORDER_EXEC_RESULT:
1034 error = rail_recv_exec_result_order(rail, s);
1037 case TS_RAIL_ORDER_SYSPARAM:
1038 error = rail_recv_server_sysparam_order(rail, s);
1041 case TS_RAIL_ORDER_MINMAXINFO:
1042 error = rail_recv_server_minmaxinfo_order(rail, s);
1045 case TS_RAIL_ORDER_LOCALMOVESIZE:
1046 error = rail_recv_server_localmovesize_order(rail, s);
1049 case TS_RAIL_ORDER_GET_APPID_RESP:
1050 error = rail_recv_server_get_appid_resp_order(rail, s);
1053 case TS_RAIL_ORDER_LANGBARINFO:
1054 error = rail_recv_langbar_info_order(rail, s);
1057 case TS_RAIL_ORDER_TASKBARINFO:
1058 error = rail_recv_taskbar_info_order(rail, s);
1061 case TS_RAIL_ORDER_ZORDER_SYNC:
1062 error = rail_recv_zorder_sync_order(rail, s);
1065 case TS_RAIL_ORDER_CLOAK:
1066 error = rail_recv_cloak_order(rail, s);
1069 case TS_RAIL_ORDER_POWER_DISPLAY_REQUEST:
1070 error = rail_recv_power_display_request_order(rail, s);
1073 case TS_RAIL_ORDER_GET_APPID_RESP_EX:
1074 error = rail_recv_get_application_id_extended_response_order(rail, s);
1077 case TS_RAIL_ORDER_TEXTSCALEINFO:
1078 error = rail_recv_textscaleinfo_order(rail, s);
1081 case TS_RAIL_ORDER_CARETBLINKINFO:
1082 error = rail_recv_caretblinkinfo_order(rail, s);
1086 WLog_ERR(TAG,
"Unknown RAIL PDU %s received.",
1087 rail_get_order_type_string_full(orderType, buffer,
sizeof(buffer)));
1088 return ERROR_INVALID_DATA;
1091 if (error != CHANNEL_RC_OK)
1093 char ebuffer[128] = WINPR_C_ARRAY_INIT;
1094 WLog_Print(rail->log, WLOG_ERROR,
"Failed to process rail %s PDU, length:%" PRIu16
"",
1095 rail_get_order_type_string_full(orderType, ebuffer,
sizeof(ebuffer)),
1100 Stream_Free(s, TRUE);
1111 if (!rail || !handshake)
1112 return ERROR_INVALID_PARAMETER;
1114 wStream* s = rail_pdu_init(RAIL_HANDSHAKE_ORDER_LENGTH);
1118 WLog_ERR(TAG,
"rail_pdu_init failed!");
1119 return CHANNEL_RC_NO_MEMORY;
1122 rail_write_handshake_order(s, handshake);
1123 return rail_send_pdu(rail, s, TS_RAIL_ORDER_HANDSHAKE);
1133 if (!rail || !handshakeEx)
1134 return ERROR_INVALID_PARAMETER;
1136 wStream* s = rail_pdu_init(RAIL_HANDSHAKE_EX_ORDER_LENGTH);
1140 WLog_ERR(TAG,
"rail_pdu_init failed!");
1141 return CHANNEL_RC_NO_MEMORY;
1144 rail_write_handshake_ex_order(s, handshakeEx);
1145 return rail_send_pdu(rail, s, TS_RAIL_ORDER_HANDSHAKE_EX);
1158 if (!rail || !clientStatus)
1159 return ERROR_INVALID_PARAMETER;
1161 rail->clientStatus = *clientStatus;
1162 s = rail_pdu_init(RAIL_CLIENT_STATUS_ORDER_LENGTH);
1166 WLog_ERR(TAG,
"rail_pdu_init failed!");
1167 return CHANNEL_RC_NO_MEMORY;
1170 error = rail_write_client_status_order(s, clientStatus);
1172 if (ERROR_SUCCESS != error)
1175 Stream_Free(s, TRUE);
1179 return rail_send_pdu(rail, s, TS_RAIL_ORDER_CLIENTSTATUS);
1187UINT rail_send_client_exec_order(
railPlugin* rail, UINT16 flags,
1196 if (!rail || !exeOrFile || !workingDir || !arguments)
1197 return ERROR_INVALID_PARAMETER;
1199 length = RAIL_EXEC_ORDER_LENGTH + exeOrFile->length + workingDir->length + arguments->length;
1200 s = rail_pdu_init(length);
1204 WLog_ERR(TAG,
"rail_pdu_init failed!");
1205 return CHANNEL_RC_NO_MEMORY;
1208 if ((error = rail_write_client_exec_order(s, flags, exeOrFile, workingDir, arguments)))
1210 WLog_ERR(TAG,
"rail_write_client_exec_order failed with error %" PRIu32
"!", error);
1214 return rail_send_pdu(rail, s, TS_RAIL_ORDER_EXEC);
1217 Stream_Free(s, TRUE);
1231 if (!rail || !activate)
1232 return ERROR_INVALID_PARAMETER;
1234 s = rail_pdu_init(RAIL_ACTIVATE_ORDER_LENGTH);
1238 WLog_ERR(TAG,
"rail_pdu_init failed!");
1239 return CHANNEL_RC_NO_MEMORY;
1242 error = rail_write_client_activate_order(s, activate);
1244 if (ERROR_SUCCESS != error)
1247 Stream_Free(s, TRUE);
1251 return rail_send_pdu(rail, s, TS_RAIL_ORDER_ACTIVATE);
1264 if (!rail || !sysmenu)
1265 return ERROR_INVALID_PARAMETER;
1267 s = rail_pdu_init(RAIL_SYSMENU_ORDER_LENGTH);
1271 WLog_ERR(TAG,
"rail_pdu_init failed!");
1272 return CHANNEL_RC_NO_MEMORY;
1275 error = rail_write_client_sysmenu_order(s, sysmenu);
1277 if (ERROR_SUCCESS != error)
1280 Stream_Free(s, TRUE);
1284 return rail_send_pdu(rail, s, TS_RAIL_ORDER_SYSMENU);
1297 if (!rail || !syscommand)
1298 return ERROR_INVALID_PARAMETER;
1300 s = rail_pdu_init(RAIL_SYSCOMMAND_ORDER_LENGTH);
1304 WLog_ERR(TAG,
"rail_pdu_init failed!");
1305 return CHANNEL_RC_NO_MEMORY;
1308 error = rail_write_client_syscommand_order(s, syscommand);
1310 if (ERROR_SUCCESS != error)
1313 Stream_Free(s, TRUE);
1317 return rail_send_pdu(rail, s, TS_RAIL_ORDER_SYSCOMMAND);
1325UINT rail_send_client_notify_event_order(
railPlugin* rail,
1331 if (!rail || !notifyEvent)
1332 return ERROR_INVALID_PARAMETER;
1334 s = rail_pdu_init(RAIL_NOTIFY_EVENT_ORDER_LENGTH);
1338 WLog_ERR(TAG,
"rail_pdu_init failed!");
1339 return CHANNEL_RC_NO_MEMORY;
1342 error = rail_write_client_notify_event_order(s, notifyEvent);
1344 if (ERROR_SUCCESS != error)
1347 Stream_Free(s, TRUE);
1351 return rail_send_pdu(rail, s, TS_RAIL_ORDER_NOTIFY_EVENT);
1364 if (!rail || !windowMove)
1365 return ERROR_INVALID_PARAMETER;
1367 s = rail_pdu_init(RAIL_WINDOW_MOVE_ORDER_LENGTH);
1371 WLog_ERR(TAG,
"rail_pdu_init failed!");
1372 return CHANNEL_RC_NO_MEMORY;
1375 error = rail_write_client_window_move_order(s, windowMove);
1377 if (ERROR_SUCCESS != error)
1380 Stream_Free(s, TRUE);
1384 return rail_send_pdu(rail, s, TS_RAIL_ORDER_WINDOWMOVE);
1392UINT rail_send_client_get_appid_req_order(
railPlugin* rail,
1398 if (!rail || !getAppIdReq)
1399 return ERROR_INVALID_PARAMETER;
1401 s = rail_pdu_init(RAIL_GET_APPID_REQ_ORDER_LENGTH);
1405 WLog_ERR(TAG,
"rail_pdu_init failed!");
1406 return CHANNEL_RC_NO_MEMORY;
1409 error = rail_write_client_get_appid_req_order(s, getAppIdReq);
1411 if (ERROR_SUCCESS != error)
1414 Stream_Free(s, TRUE);
1417 return rail_send_pdu(rail, s, TS_RAIL_ORDER_GET_APPID_REQ);
1425UINT rail_send_client_langbar_info_order(
railPlugin* rail,
1431 if (!rail || !langBarInfo)
1432 return ERROR_INVALID_PARAMETER;
1434 if (!rail_is_feature_supported(rail->rdpcontext, RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED))
1435 return ERROR_BAD_CONFIGURATION;
1437 s = rail_pdu_init(RAIL_LANGBAR_INFO_ORDER_LENGTH);
1441 WLog_ERR(TAG,
"rail_pdu_init failed!");
1442 return CHANNEL_RC_NO_MEMORY;
1445 error = rail_write_langbar_info_order(s, langBarInfo);
1447 if (ERROR_SUCCESS != error)
1450 Stream_Free(s, TRUE);
1453 return rail_send_pdu(rail, s, TS_RAIL_ORDER_LANGBARINFO);
1456UINT rail_send_client_languageime_info_order(
railPlugin* rail,
1462 if (!rail || !langImeInfo)
1463 return ERROR_INVALID_PARAMETER;
1465 if (!rail_is_feature_supported(rail->rdpcontext, RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED))
1466 return ERROR_BAD_CONFIGURATION;
1468 s = rail_pdu_init(RAIL_LANGUAGEIME_INFO_ORDER_LENGTH);
1472 WLog_ERR(TAG,
"rail_pdu_init failed!");
1473 return CHANNEL_RC_NO_MEMORY;
1476 error = rail_write_languageime_info_order(s, langImeInfo);
1478 if (ERROR_SUCCESS != error)
1481 Stream_Free(s, TRUE);
1484 return rail_send_pdu(rail, s, TS_RAIL_ORDER_LANGUAGEIMEINFO);
1487UINT rail_send_client_compartment_info_order(
railPlugin* rail,
1493 if (!rail || !compartmentInfo)
1494 return ERROR_INVALID_PARAMETER;
1496 if (!rail_is_feature_supported(rail->rdpcontext, RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED))
1497 return ERROR_BAD_CONFIGURATION;
1499 s = rail_pdu_init(RAIL_COMPARTMENT_INFO_ORDER_LENGTH);
1503 WLog_ERR(TAG,
"rail_pdu_init failed!");
1504 return CHANNEL_RC_NO_MEMORY;
1507 error = rail_write_compartment_info_order(s, compartmentInfo);
1509 if (ERROR_SUCCESS != error)
1511 Stream_Free(s, TRUE);
1514 return rail_send_pdu(rail, s, TS_RAIL_ORDER_COMPARTMENTINFO);
1519 if (!rail || !cloak)
1520 return ERROR_INVALID_PARAMETER;
1522 wStream* s = rail_pdu_init(5);
1526 WLog_ERR(TAG,
"rail_pdu_init failed!");
1527 return CHANNEL_RC_NO_MEMORY;
1530 Stream_Write_UINT32(s, cloak->windowId);
1531 Stream_Write_UINT8(s, cloak->cloak ? 1 : 0);
1532 return rail_send_pdu(rail, s, TS_RAIL_ORDER_CLOAK);
1538 return ERROR_INVALID_PARAMETER;
1541 if ((rail->channelFlags & TS_RAIL_ORDER_HANDSHAKE_EX_FLAGS_SNAP_ARRANGE_SUPPORTED) == 0)
1544 move.top = snap->top;
1545 move.left = snap->left;
1546 move.right = snap->right;
1547 move.bottom = snap->bottom;
1548 move.windowId = snap->windowId;
1549 return rail_send_client_window_move_order(rail, &move);
1552 wStream* s = rail_pdu_init(12);
1556 WLog_ERR(TAG,
"rail_pdu_init failed!");
1557 return CHANNEL_RC_NO_MEMORY;
1560 Stream_Write_UINT32(s, snap->windowId);
1561 Stream_Write_INT16(s, snap->left);
1562 Stream_Write_INT16(s, snap->top);
1563 Stream_Write_INT16(s, snap->right);
1564 Stream_Write_INT16(s, snap->bottom);
1565 return rail_send_pdu(rail, s, TS_RAIL_ORDER_SNAP_ARRANGE);
1568UINT rail_send_client_text_scale_order(
railPlugin* rail, UINT32 textScale)
1571 return ERROR_INVALID_PARAMETER;
1573 wStream* s = rail_pdu_init(4);
1577 WLog_ERR(TAG,
"rail_pdu_init failed!");
1578 return CHANNEL_RC_NO_MEMORY;
1581 Stream_Write_UINT32(s, textScale);
1582 return rail_send_pdu(rail, s, TS_RAIL_ORDER_TEXTSCALEINFO);
1585UINT rail_send_client_caret_blink_rate_order(
railPlugin* rail, UINT32 rate)
1588 return ERROR_INVALID_PARAMETER;
1590 wStream* s = rail_pdu_init(4);
1594 WLog_ERR(TAG,
"rail_pdu_init failed!");
1595 return CHANNEL_RC_NO_MEMORY;
1598 Stream_Write_UINT32(s, rate);
1599 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.