25 #include <freerdp/config.h>
27 #include <winpr/crt.h>
28 #include <winpr/cast.h>
30 #include <freerdp/channels/log.h>
31 #include <freerdp/freerdp.h>
33 #include "rail_orders.h"
35 static BOOL rail_is_feature_supported(
const rdpContext* context, UINT32 featureMask);
44 char buffer[128] = { 0 };
45 UINT16 orderLength = 0;
50 return ERROR_INVALID_PARAMETER;
53 orderLength = (UINT16)Stream_GetPosition(s);
54 Stream_SetPosition(s, 0);
55 rail_write_pdu_header(s, orderType, orderLength);
56 Stream_SetPosition(s, orderLength);
57 WLog_Print(rail->log, WLOG_DEBUG,
"Sending %s PDU, length: %" PRIu16
"",
58 rail_get_order_type_string_full(orderType, buffer,
sizeof(buffer)), orderLength);
59 return rail_send_channel_data(rail, s);
69 if (!s || !execResult)
70 return ERROR_INVALID_PARAMETER;
72 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_EXEC_RESULT_ORDER_LENGTH))
73 return ERROR_INVALID_DATA;
75 Stream_Read_UINT16(s, execResult->flags);
76 Stream_Read_UINT16(s, execResult->execResult);
77 Stream_Read_UINT32(s, execResult->rawResult);
78 Stream_Seek_UINT16(s);
79 return rail_read_unicode_string(s, &execResult->exeOrFile)
81 : ERROR_INTERNAL_ERROR;
91 if (!s || !minmaxinfo)
92 return ERROR_INVALID_PARAMETER;
94 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_MINMAXINFO_ORDER_LENGTH))
95 return ERROR_INVALID_DATA;
97 Stream_Read_UINT32(s, minmaxinfo->windowId);
98 Stream_Read_INT16(s, minmaxinfo->maxWidth);
99 Stream_Read_INT16(s, minmaxinfo->maxHeight);
100 Stream_Read_INT16(s, minmaxinfo->maxPosX);
101 Stream_Read_INT16(s, minmaxinfo->maxPosY);
102 Stream_Read_INT16(s, minmaxinfo->minTrackWidth);
103 Stream_Read_INT16(s, minmaxinfo->minTrackHeight);
104 Stream_Read_INT16(s, minmaxinfo->maxTrackWidth);
105 Stream_Read_INT16(s, minmaxinfo->maxTrackHeight);
106 return CHANNEL_RC_OK;
114 static UINT rail_read_server_localmovesize_order(
wStream* s,
117 UINT16 isMoveSizeStart = 0;
119 if (!s || !localMoveSize)
120 return ERROR_INVALID_PARAMETER;
122 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_LOCALMOVESIZE_ORDER_LENGTH))
123 return ERROR_INVALID_DATA;
125 Stream_Read_UINT32(s, localMoveSize->windowId);
126 Stream_Read_UINT16(s, isMoveSizeStart);
127 localMoveSize->isMoveSizeStart = (isMoveSizeStart != 0) ? TRUE : FALSE;
128 Stream_Read_UINT16(s, localMoveSize->moveSizeType);
129 Stream_Read_INT16(s, localMoveSize->posX);
130 Stream_Read_INT16(s, localMoveSize->posY);
131 return CHANNEL_RC_OK;
139 static UINT rail_read_server_get_appid_resp_order(
wStream* s,
142 if (!s || !getAppidResp)
143 return ERROR_INVALID_PARAMETER;
145 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_GET_APPID_RESP_ORDER_LENGTH))
146 return ERROR_INVALID_DATA;
148 Stream_Read_UINT32(s, getAppidResp->windowId);
149 Stream_Read_UTF16_String(
150 s, getAppidResp->applicationId,
151 ARRAYSIZE(getAppidResp->applicationId));
152 return CHANNEL_RC_OK;
162 if (!s || !langbarInfo)
163 return ERROR_INVALID_PARAMETER;
165 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_LANGBAR_INFO_ORDER_LENGTH))
166 return ERROR_INVALID_DATA;
168 Stream_Read_UINT32(s, langbarInfo->languageBarStatus);
169 return CHANNEL_RC_OK;
174 if (!s || !clientStatus)
175 return ERROR_INVALID_PARAMETER;
177 Stream_Write_UINT32(s, clientStatus->flags);
178 return ERROR_SUCCESS;
186 static UINT rail_write_client_exec_order(
wStream* s, UINT16 flags,
193 if (!s || !exeOrFile || !workingDir || !arguments)
194 return ERROR_INVALID_PARAMETER;
198 if ((exeOrFile->length > 520) || (workingDir->length > 520) || (arguments->length > 16000))
201 "TS_RAIL_ORDER_EXEC argument limits exceeded: ExeOrFile=%" PRIu16
202 " [max=520], WorkingDir=%" PRIu16
" [max=520], Arguments=%" PRIu16
" [max=16000]",
203 exeOrFile->length, workingDir->length, arguments->length);
204 return ERROR_BAD_ARGUMENTS;
207 Stream_Write_UINT16(s, flags);
208 Stream_Write_UINT16(s, exeOrFile->length);
209 Stream_Write_UINT16(s, workingDir->length);
210 Stream_Write_UINT16(s, arguments->length);
212 if ((error = rail_write_unicode_string_value(s, exeOrFile)))
214 WLog_ERR(TAG,
"rail_write_unicode_string_value failed with error %" PRIu32
"", error);
218 if ((error = rail_write_unicode_string_value(s, workingDir)))
220 WLog_ERR(TAG,
"rail_write_unicode_string_value failed with error %" PRIu32
"", error);
224 if ((error = rail_write_unicode_string_value(s, arguments)))
226 WLog_ERR(TAG,
"rail_write_unicode_string_value failed with error %" PRIu32
"", error);
238 return ERROR_INVALID_PARAMETER;
240 Stream_Write_UINT32(s, activate->windowId);
241 enabled = activate->enabled ? 1 : 0;
242 Stream_Write_UINT8(s, enabled);
243 return ERROR_SUCCESS;
249 return ERROR_INVALID_PARAMETER;
251 Stream_Write_UINT32(s, sysmenu->windowId);
252 Stream_Write_INT16(s, sysmenu->left);
253 Stream_Write_INT16(s, sysmenu->top);
254 return ERROR_SUCCESS;
259 if (!s || !syscommand)
260 return ERROR_INVALID_PARAMETER;
262 Stream_Write_UINT32(s, syscommand->windowId);
263 Stream_Write_UINT16(s, syscommand->command);
264 return ERROR_SUCCESS;
267 static UINT rail_write_client_notify_event_order(
wStream* s,
270 if (!s || !notifyEvent)
271 return ERROR_INVALID_PARAMETER;
273 Stream_Write_UINT32(s, notifyEvent->windowId);
274 Stream_Write_UINT32(s, notifyEvent->notifyIconId);
275 Stream_Write_UINT32(s, notifyEvent->message);
276 return ERROR_SUCCESS;
279 static UINT rail_write_client_window_move_order(
wStream* s,
282 if (!s || !windowMove)
283 return ERROR_INVALID_PARAMETER;
285 Stream_Write_UINT32(s, windowMove->windowId);
286 Stream_Write_INT16(s, windowMove->left);
287 Stream_Write_INT16(s, windowMove->top);
288 Stream_Write_INT16(s, windowMove->right);
289 Stream_Write_INT16(s, windowMove->bottom);
290 return ERROR_SUCCESS;
293 static UINT rail_write_client_get_appid_req_order(
wStream* s,
296 if (!s || !getAppidReq)
297 return ERROR_INVALID_PARAMETER;
299 Stream_Write_UINT32(s, getAppidReq->windowId);
300 return ERROR_SUCCESS;
305 if (!s || !langbarInfo)
306 return ERROR_INVALID_PARAMETER;
308 Stream_Write_UINT32(s, langbarInfo->languageBarStatus);
309 return ERROR_SUCCESS;
312 static UINT rail_write_languageime_info_order(
wStream* s,
315 if (!s || !langImeInfo)
316 return ERROR_INVALID_PARAMETER;
318 Stream_Write_UINT32(s, langImeInfo->ProfileType);
319 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(UINT16, langImeInfo->LanguageID));
320 Stream_Write(s, &langImeInfo->LanguageProfileCLSID,
sizeof(langImeInfo->LanguageProfileCLSID));
321 Stream_Write(s, &langImeInfo->ProfileGUID,
sizeof(langImeInfo->ProfileGUID));
322 Stream_Write_UINT32(s, langImeInfo->KeyboardLayout);
323 return ERROR_SUCCESS;
326 static UINT rail_write_compartment_info_order(
wStream* s,
329 if (!s || !compartmentInfo)
330 return ERROR_INVALID_PARAMETER;
332 Stream_Write_UINT32(s, compartmentInfo->ImeState);
333 Stream_Write_UINT32(s, compartmentInfo->ImeConvMode);
334 Stream_Write_UINT32(s, compartmentInfo->ImeSentenceMode);
335 Stream_Write_UINT32(s, compartmentInfo->KanaMode);
336 return ERROR_SUCCESS;
346 RailClientContext* context = rail_get_client_interface(rail);
351 return ERROR_INVALID_PARAMETER;
353 if ((error = rail_read_handshake_order(s, &serverHandshake)))
355 WLog_ERR(TAG,
"rail_read_handshake_order failed with error %" PRIu32
"!", error);
359 rail->channelBuildNumber = serverHandshake.buildNumber;
361 if (rail->sendHandshake)
364 clientHandshake.buildNumber = 0x00001DB0;
365 error = context->ClientHandshake(context, &clientHandshake);
368 if (error != CHANNEL_RC_OK)
373 IFCALLRET(context->ServerHandshake, error, context, &serverHandshake);
376 WLog_ERR(TAG,
"context.ServerHandshake failed with error %" PRIu32
"", error);
382 static UINT rail_read_compartment_info_order(
wStream* s,
385 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_COMPARTMENT_INFO_ORDER_LENGTH))
386 return ERROR_INVALID_DATA;
388 Stream_Read_UINT32(s, compartmentInfo->ImeState);
389 Stream_Read_UINT32(s, compartmentInfo->ImeConvMode);
390 Stream_Read_UINT32(s, compartmentInfo->ImeSentenceMode);
391 Stream_Read_UINT32(s, compartmentInfo->KanaMode);
392 return CHANNEL_RC_OK;
397 RailClientContext* context = rail_get_client_interface(rail);
402 return ERROR_INVALID_PARAMETER;
404 if (!rail_is_feature_supported(rail->rdpcontext, RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED))
405 return ERROR_BAD_CONFIGURATION;
407 if ((error = rail_read_compartment_info_order(s, &pdu)))
412 IFCALLRET(context->ClientCompartmentInfo, error, context, &pdu);
415 WLog_ERR(TAG,
"context.ClientCompartmentInfo failed with error %" PRIu32
"", error);
421 BOOL rail_is_feature_supported(
const rdpContext* context, UINT32 featureMask)
423 UINT32 supported = 0;
426 if (!context || !context->settings)
433 supported = level & mask;
434 masked = (supported & featureMask);
436 if (masked != featureMask)
438 char maskstr[256] = { 0 };
439 char actualstr[256] = { 0 };
441 WLog_WARN(TAG,
"have %s, require %s",
457 RailClientContext* context = rail_get_client_interface(rail);
461 if (!rail || !context || !s)
462 return ERROR_INVALID_PARAMETER;
464 if (!rail_is_feature_supported(rail->rdpcontext, RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED))
465 return ERROR_BAD_CONFIGURATION;
467 if ((error = rail_read_handshake_ex_order(s, &serverHandshake)))
469 WLog_ERR(TAG,
"rail_read_handshake_ex_order failed with error %" PRIu32
"!", error);
473 rail->channelBuildNumber = serverHandshake.buildNumber;
474 rail->channelFlags = serverHandshake.railHandshakeFlags;
477 char buffer[192] = { 0 };
478 WLog_DBG(TAG,
"HandshakeFlags=%s [buildNumber=0x%08" PRIx32
"]",
479 rail_handshake_ex_flags_to_string(rail->channelFlags, buffer,
sizeof(buffer)),
480 rail->channelBuildNumber);
483 if (rail->sendHandshake)
486 clientHandshake.buildNumber = 0x00001DB0;
489 error = context->ClientHandshake(context, &clientHandshake);
492 if (error != CHANNEL_RC_OK)
497 IFCALLRET(context->ServerHandshakeEx, error, context, &serverHandshake);
500 WLog_ERR(TAG,
"context.ServerHandshakeEx failed with error %" PRIu32
"", error);
513 RailClientContext* context = rail_get_client_interface(rail);
518 return ERROR_INVALID_PARAMETER;
520 if ((error = rail_read_server_exec_result_order(s, &execResult)))
522 WLog_ERR(TAG,
"rail_read_server_exec_result_order failed with error %" PRIu32
"!", error);
528 IFCALLRET(context->ServerExecuteResult, error, context, &execResult);
531 WLog_ERR(TAG,
"context.ServerExecuteResult failed with error %" PRIu32
"", error);
535 free(execResult.exeOrFile.string);
546 RailClientContext* context = rail_get_client_interface(rail);
549 BOOL extendedSpiSupported = 0;
552 return ERROR_INVALID_PARAMETER;
554 extendedSpiSupported = rail_is_extended_spi_supported(rail->channelFlags);
555 if ((error = rail_read_sysparam_order(s, &sysparam, extendedSpiSupported)))
557 WLog_ERR(TAG,
"rail_read_sysparam_order failed with error %" PRIu32
"!", error);
563 IFCALLRET(context->ServerSystemParam, error, context, &sysparam);
566 WLog_ERR(TAG,
"context.ServerSystemParam failed with error %" PRIu32
"", error);
579 RailClientContext* context = rail_get_client_interface(rail);
584 return ERROR_INVALID_PARAMETER;
586 if ((error = rail_read_server_minmaxinfo_order(s, &minMaxInfo)))
588 WLog_ERR(TAG,
"rail_read_server_minmaxinfo_order failed with error %" PRIu32
"!", error);
594 IFCALLRET(context->ServerMinMaxInfo, error, context, &minMaxInfo);
597 WLog_ERR(TAG,
"context.ServerMinMaxInfo failed with error %" PRIu32
"", error);
610 RailClientContext* context = rail_get_client_interface(rail);
615 return ERROR_INVALID_PARAMETER;
617 if ((error = rail_read_server_localmovesize_order(s, &localMoveSize)))
619 WLog_ERR(TAG,
"rail_read_server_localmovesize_order failed with error %" PRIu32
"!", error);
625 IFCALLRET(context->ServerLocalMoveSize, error, context, &localMoveSize);
628 WLog_ERR(TAG,
"context.ServerLocalMoveSize failed with error %" PRIu32
"", error);
641 RailClientContext* context = rail_get_client_interface(rail);
646 return ERROR_INVALID_PARAMETER;
648 if ((error = rail_read_server_get_appid_resp_order(s, &getAppIdResp)))
650 WLog_ERR(TAG,
"rail_read_server_get_appid_resp_order failed with error %" PRIu32
"!",
657 IFCALLRET(context->ServerGetAppIdResponse, error, context, &getAppIdResp);
660 WLog_ERR(TAG,
"context.ServerGetAppIdResponse failed with error %" PRIu32
"", error);
673 RailClientContext* context = rail_get_client_interface(rail);
678 return ERROR_INVALID_PARAMETER;
680 if (!rail_is_feature_supported(rail->rdpcontext, RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED))
681 return ERROR_BAD_CONFIGURATION;
683 if ((error = rail_read_langbar_info_order(s, &langBarInfo)))
685 WLog_ERR(TAG,
"rail_read_langbar_info_order failed with error %" PRIu32
"!", error);
691 IFCALLRET(context->ServerLanguageBarInfo, error, context, &langBarInfo);
694 WLog_ERR(TAG,
"context.ServerLanguageBarInfo failed with error %" PRIu32
"", error);
702 if (!s || !taskbarInfo)
703 return ERROR_INVALID_PARAMETER;
705 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_TASKBAR_INFO_ORDER_LENGTH))
706 return ERROR_INVALID_DATA;
708 Stream_Read_UINT32(s, taskbarInfo->TaskbarMessage);
709 Stream_Read_UINT32(s, taskbarInfo->WindowIdTab);
710 Stream_Read_UINT32(s, taskbarInfo->Body);
711 return CHANNEL_RC_OK;
716 RailClientContext* context = rail_get_client_interface(rail);
721 return ERROR_INVALID_PARAMETER;
725 if (!rail_is_feature_supported(rail->rdpcontext, RAIL_LEVEL_SHELL_INTEGRATION_SUPPORTED))
726 return ERROR_BAD_CONFIGURATION;
728 if ((error = rail_read_taskbar_info_order(s, &taskBarInfo)))
730 WLog_ERR(TAG,
"rail_read_langbar_info_order failed with error %" PRIu32
"!", error);
736 IFCALLRET(context->ServerTaskBarInfo, error, context, &taskBarInfo);
739 WLog_ERR(TAG,
"context.ServerTaskBarInfo failed with error %" PRIu32
"", error);
748 return ERROR_INVALID_PARAMETER;
750 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_Z_ORDER_SYNC_ORDER_LENGTH))
751 return ERROR_INVALID_DATA;
753 Stream_Read_UINT32(s, zorder->windowIdMarker);
754 return CHANNEL_RC_OK;
759 RailClientContext* context = rail_get_client_interface(rail);
764 return ERROR_INVALID_PARAMETER;
766 if ((rail->clientStatus.flags & TS_RAIL_CLIENTSTATUS_ZORDER_SYNC) == 0)
767 return ERROR_INVALID_DATA;
769 if ((error = rail_read_zorder_sync_order(s, &zorder)))
771 WLog_ERR(TAG,
"rail_read_zorder_sync_order failed with error %" PRIu32
"!", error);
777 IFCALLRET(context->ServerZOrderSync, error, context, &zorder);
780 WLog_ERR(TAG,
"context.ServerZOrderSync failed with error %" PRIu32
"", error);
790 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_CLOAK_ORDER_LENGTH))
791 return ERROR_INVALID_DATA;
793 Stream_Read_UINT32(s, cloak->windowId);
794 Stream_Read_UINT8(s, cloaked);
795 cloak->cloak = (cloaked != 0) ? TRUE : FALSE;
796 return CHANNEL_RC_OK;
801 RailClientContext* context = rail_get_client_interface(rail);
806 return ERROR_INVALID_PARAMETER;
810 if ((rail->clientStatus.flags & TS_RAIL_CLIENTSTATUS_BIDIRECTIONAL_CLOAK_SUPPORTED) == 0)
811 return ERROR_INVALID_DATA;
813 if ((error = rail_read_cloak_order(s, &cloak)))
815 WLog_ERR(TAG,
"rail_read_zorder_sync_order failed with error %" PRIu32
"!", error);
821 IFCALLRET(context->ServerCloak, error, context, &cloak);
824 WLog_ERR(TAG,
"context.ServerZOrderSync failed with error %" PRIu32
"", error);
835 return ERROR_INVALID_PARAMETER;
837 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_POWER_DISPLAY_REQUEST_ORDER_LENGTH))
838 return ERROR_INVALID_DATA;
840 Stream_Read_UINT32(s, active);
841 power->active = active != 0;
842 return CHANNEL_RC_OK;
847 RailClientContext* context = rail_get_client_interface(rail);
852 return ERROR_INVALID_PARAMETER;
856 if ((rail->clientStatus.flags & TS_RAIL_CLIENTSTATUS_POWER_DISPLAY_REQUEST_SUPPORTED) == 0)
857 return ERROR_INVALID_DATA;
859 if ((error = rail_read_power_display_request_order(s, &power)))
861 WLog_ERR(TAG,
"rail_read_zorder_sync_order failed with error %" PRIu32
"!", error);
867 IFCALLRET(context->ServerPowerDisplayRequest, error, context, &power);
870 WLog_ERR(TAG,
"context.ServerPowerDisplayRequest failed with error %" PRIu32
"", error);
876 static UINT rail_read_get_application_id_extended_response_order(
wStream* s,
880 return ERROR_INVALID_PARAMETER;
882 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
883 return ERROR_INVALID_DATA;
885 Stream_Read_UINT32(s, id->windowID);
887 if (!Stream_Read_UTF16_String(s, id->applicationID, ARRAYSIZE(id->applicationID)))
888 return ERROR_INVALID_DATA;
890 if (_wcsnlen(id->applicationID, ARRAYSIZE(id->applicationID)) >= ARRAYSIZE(id->applicationID))
891 return ERROR_INVALID_DATA;
893 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
894 return ERROR_INVALID_DATA;
896 Stream_Read_UINT32(s, id->processId);
898 if (!Stream_Read_UTF16_String(s, id->processImageName, ARRAYSIZE(id->processImageName)))
899 return ERROR_INVALID_DATA;
901 if (_wcsnlen(id->applicationID, ARRAYSIZE(id->processImageName)) >=
902 ARRAYSIZE(id->processImageName))
903 return ERROR_INVALID_DATA;
905 return CHANNEL_RC_OK;
908 static UINT rail_recv_get_application_id_extended_response_order(
railPlugin* rail,
wStream* s)
910 RailClientContext* context = rail_get_client_interface(rail);
915 return ERROR_INVALID_PARAMETER;
917 if ((error = rail_read_get_application_id_extended_response_order(s, &
id)))
920 "rail_read_get_application_id_extended_response_order failed with error %" PRIu32
928 IFCALLRET(context->ServerGetAppidResponseExtended, error, context, &
id);
931 WLog_ERR(TAG,
"context.ServerGetAppidResponseExtended failed with error %" PRIu32
"",
938 static UINT rail_read_textscaleinfo_order(
wStream* s, UINT32* pTextScaleFactor)
940 WINPR_ASSERT(pTextScaleFactor);
942 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
943 return ERROR_INVALID_DATA;
945 Stream_Read_UINT32(s, *pTextScaleFactor);
946 return CHANNEL_RC_OK;
951 RailClientContext* context = rail_get_client_interface(rail);
952 UINT32 TextScaleFactor = 0;
956 return ERROR_INVALID_PARAMETER;
958 if ((error = rail_read_textscaleinfo_order(s, &TextScaleFactor)))
963 IFCALLRET(context->ClientTextScale, error, context, TextScaleFactor);
966 WLog_ERR(TAG,
"context.ClientTextScale failed with error %" PRIu32
"", error);
972 static UINT rail_read_caretblinkinfo_order(
wStream* s, UINT32* pCaretBlinkRate)
974 WINPR_ASSERT(pCaretBlinkRate);
976 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
977 return ERROR_INVALID_DATA;
979 Stream_Read_UINT32(s, *pCaretBlinkRate);
980 return CHANNEL_RC_OK;
985 RailClientContext* context = rail_get_client_interface(rail);
986 UINT32 CaretBlinkRate = 0;
990 return ERROR_INVALID_PARAMETER;
991 if ((error = rail_read_caretblinkinfo_order(s, &CaretBlinkRate)))
996 IFCALLRET(context->ClientCaretBlinkRate, error, context, CaretBlinkRate);
999 WLog_ERR(TAG,
"context.ClientCaretBlinkRate failed with error %" PRIu32
"", error);
1010 UINT rail_order_recv(LPVOID userdata,
wStream* s)
1012 char buffer[128] = { 0 };
1014 UINT16 orderType = 0;
1015 UINT16 orderLength = 0;
1016 UINT error = CHANNEL_RC_OK;
1019 return ERROR_INVALID_PARAMETER;
1021 if ((error = rail_read_pdu_header(s, &orderType, &orderLength)))
1023 WLog_ERR(TAG,
"rail_read_pdu_header failed with error %" PRIu32
"!", error);
1027 WLog_Print(rail->log, WLOG_DEBUG,
"Received %s PDU, length:%" PRIu16
"",
1028 rail_get_order_type_string_full(orderType, buffer,
sizeof(buffer)), orderLength);
1032 case TS_RAIL_ORDER_HANDSHAKE:
1033 error = rail_recv_handshake_order(rail, s);
1036 case TS_RAIL_ORDER_COMPARTMENTINFO:
1037 error = rail_recv_compartmentinfo_order(rail, s);
1040 case TS_RAIL_ORDER_HANDSHAKE_EX:
1041 error = rail_recv_handshake_ex_order(rail, s);
1044 case TS_RAIL_ORDER_EXEC_RESULT:
1045 error = rail_recv_exec_result_order(rail, s);
1048 case TS_RAIL_ORDER_SYSPARAM:
1049 error = rail_recv_server_sysparam_order(rail, s);
1052 case TS_RAIL_ORDER_MINMAXINFO:
1053 error = rail_recv_server_minmaxinfo_order(rail, s);
1056 case TS_RAIL_ORDER_LOCALMOVESIZE:
1057 error = rail_recv_server_localmovesize_order(rail, s);
1060 case TS_RAIL_ORDER_GET_APPID_RESP:
1061 error = rail_recv_server_get_appid_resp_order(rail, s);
1064 case TS_RAIL_ORDER_LANGBARINFO:
1065 error = rail_recv_langbar_info_order(rail, s);
1068 case TS_RAIL_ORDER_TASKBARINFO:
1069 error = rail_recv_taskbar_info_order(rail, s);
1072 case TS_RAIL_ORDER_ZORDER_SYNC:
1073 error = rail_recv_zorder_sync_order(rail, s);
1076 case TS_RAIL_ORDER_CLOAK:
1077 error = rail_recv_cloak_order(rail, s);
1080 case TS_RAIL_ORDER_POWER_DISPLAY_REQUEST:
1081 error = rail_recv_power_display_request_order(rail, s);
1084 case TS_RAIL_ORDER_GET_APPID_RESP_EX:
1085 error = rail_recv_get_application_id_extended_response_order(rail, s);
1088 case TS_RAIL_ORDER_TEXTSCALEINFO:
1089 error = rail_recv_textscaleinfo_order(rail, s);
1092 case TS_RAIL_ORDER_CARETBLINKINFO:
1093 error = rail_recv_caretblinkinfo_order(rail, s);
1097 WLog_ERR(TAG,
"Unknown RAIL PDU %s received.",
1098 rail_get_order_type_string_full(orderType, buffer,
sizeof(buffer)));
1099 return ERROR_INVALID_DATA;
1102 if (error != CHANNEL_RC_OK)
1104 char ebuffer[128] = { 0 };
1105 WLog_Print(rail->log, WLOG_ERROR,
"Failed to process rail %s PDU, length:%" PRIu16
"",
1106 rail_get_order_type_string_full(orderType, ebuffer,
sizeof(ebuffer)),
1110 Stream_Free(s, TRUE);
1121 if (!rail || !handshake)
1122 return ERROR_INVALID_PARAMETER;
1124 wStream* s = rail_pdu_init(RAIL_HANDSHAKE_ORDER_LENGTH);
1128 WLog_ERR(TAG,
"rail_pdu_init failed!");
1129 return CHANNEL_RC_NO_MEMORY;
1132 rail_write_handshake_order(s, handshake);
1133 return rail_send_pdu(rail, s, TS_RAIL_ORDER_HANDSHAKE);
1143 if (!rail || !handshakeEx)
1144 return ERROR_INVALID_PARAMETER;
1146 wStream* s = rail_pdu_init(RAIL_HANDSHAKE_EX_ORDER_LENGTH);
1150 WLog_ERR(TAG,
"rail_pdu_init failed!");
1151 return CHANNEL_RC_NO_MEMORY;
1154 rail_write_handshake_ex_order(s, handshakeEx);
1155 return rail_send_pdu(rail, s, TS_RAIL_ORDER_HANDSHAKE_EX);
1168 if (!rail || !clientStatus)
1169 return ERROR_INVALID_PARAMETER;
1171 rail->clientStatus = *clientStatus;
1172 s = rail_pdu_init(RAIL_CLIENT_STATUS_ORDER_LENGTH);
1176 WLog_ERR(TAG,
"rail_pdu_init failed!");
1177 return CHANNEL_RC_NO_MEMORY;
1180 error = rail_write_client_status_order(s, clientStatus);
1182 if (ERROR_SUCCESS != error)
1185 Stream_Free(s, TRUE);
1189 return rail_send_pdu(rail, s, TS_RAIL_ORDER_CLIENTSTATUS);
1197 UINT rail_send_client_exec_order(
railPlugin* rail, UINT16 flags,
1206 if (!rail || !exeOrFile || !workingDir || !arguments)
1207 return ERROR_INVALID_PARAMETER;
1209 length = RAIL_EXEC_ORDER_LENGTH + exeOrFile->length + workingDir->length + arguments->length;
1210 s = rail_pdu_init(length);
1214 WLog_ERR(TAG,
"rail_pdu_init failed!");
1215 return CHANNEL_RC_NO_MEMORY;
1218 if ((error = rail_write_client_exec_order(s, flags, exeOrFile, workingDir, arguments)))
1220 WLog_ERR(TAG,
"rail_write_client_exec_order failed with error %" PRIu32
"!", error);
1224 return rail_send_pdu(rail, s, TS_RAIL_ORDER_EXEC);
1227 Stream_Free(s, TRUE);
1241 if (!rail || !activate)
1242 return ERROR_INVALID_PARAMETER;
1244 s = rail_pdu_init(RAIL_ACTIVATE_ORDER_LENGTH);
1248 WLog_ERR(TAG,
"rail_pdu_init failed!");
1249 return CHANNEL_RC_NO_MEMORY;
1252 error = rail_write_client_activate_order(s, activate);
1254 if (ERROR_SUCCESS != error)
1257 Stream_Free(s, TRUE);
1261 return rail_send_pdu(rail, s, TS_RAIL_ORDER_ACTIVATE);
1274 if (!rail || !sysmenu)
1275 return ERROR_INVALID_PARAMETER;
1277 s = rail_pdu_init(RAIL_SYSMENU_ORDER_LENGTH);
1281 WLog_ERR(TAG,
"rail_pdu_init failed!");
1282 return CHANNEL_RC_NO_MEMORY;
1285 error = rail_write_client_sysmenu_order(s, sysmenu);
1287 if (ERROR_SUCCESS != error)
1290 Stream_Free(s, TRUE);
1294 return rail_send_pdu(rail, s, TS_RAIL_ORDER_SYSMENU);
1307 if (!rail || !syscommand)
1308 return ERROR_INVALID_PARAMETER;
1310 s = rail_pdu_init(RAIL_SYSCOMMAND_ORDER_LENGTH);
1314 WLog_ERR(TAG,
"rail_pdu_init failed!");
1315 return CHANNEL_RC_NO_MEMORY;
1318 error = rail_write_client_syscommand_order(s, syscommand);
1320 if (ERROR_SUCCESS != error)
1323 Stream_Free(s, TRUE);
1327 return rail_send_pdu(rail, s, TS_RAIL_ORDER_SYSCOMMAND);
1335 UINT rail_send_client_notify_event_order(
railPlugin* rail,
1341 if (!rail || !notifyEvent)
1342 return ERROR_INVALID_PARAMETER;
1344 s = rail_pdu_init(RAIL_NOTIFY_EVENT_ORDER_LENGTH);
1348 WLog_ERR(TAG,
"rail_pdu_init failed!");
1349 return CHANNEL_RC_NO_MEMORY;
1352 error = rail_write_client_notify_event_order(s, notifyEvent);
1354 if (ERROR_SUCCESS != error)
1357 Stream_Free(s, TRUE);
1361 return rail_send_pdu(rail, s, TS_RAIL_ORDER_NOTIFY_EVENT);
1374 if (!rail || !windowMove)
1375 return ERROR_INVALID_PARAMETER;
1377 s = rail_pdu_init(RAIL_WINDOW_MOVE_ORDER_LENGTH);
1381 WLog_ERR(TAG,
"rail_pdu_init failed!");
1382 return CHANNEL_RC_NO_MEMORY;
1385 error = rail_write_client_window_move_order(s, windowMove);
1387 if (ERROR_SUCCESS != error)
1390 Stream_Free(s, TRUE);
1394 return rail_send_pdu(rail, s, TS_RAIL_ORDER_WINDOWMOVE);
1402 UINT rail_send_client_get_appid_req_order(
railPlugin* rail,
1408 if (!rail || !getAppIdReq)
1409 return ERROR_INVALID_PARAMETER;
1411 s = rail_pdu_init(RAIL_GET_APPID_REQ_ORDER_LENGTH);
1415 WLog_ERR(TAG,
"rail_pdu_init failed!");
1416 return CHANNEL_RC_NO_MEMORY;
1419 error = rail_write_client_get_appid_req_order(s, getAppIdReq);
1421 if (ERROR_SUCCESS != error)
1424 Stream_Free(s, TRUE);
1427 return rail_send_pdu(rail, s, TS_RAIL_ORDER_GET_APPID_REQ);
1435 UINT rail_send_client_langbar_info_order(
railPlugin* rail,
1441 if (!rail || !langBarInfo)
1442 return ERROR_INVALID_PARAMETER;
1444 if (!rail_is_feature_supported(rail->rdpcontext, RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED))
1445 return ERROR_BAD_CONFIGURATION;
1447 s = rail_pdu_init(RAIL_LANGBAR_INFO_ORDER_LENGTH);
1451 WLog_ERR(TAG,
"rail_pdu_init failed!");
1452 return CHANNEL_RC_NO_MEMORY;
1455 error = rail_write_langbar_info_order(s, langBarInfo);
1457 if (ERROR_SUCCESS != error)
1460 Stream_Free(s, TRUE);
1463 return rail_send_pdu(rail, s, TS_RAIL_ORDER_LANGBARINFO);
1466 UINT rail_send_client_languageime_info_order(
railPlugin* rail,
1472 if (!rail || !langImeInfo)
1473 return ERROR_INVALID_PARAMETER;
1475 if (!rail_is_feature_supported(rail->rdpcontext, RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED))
1476 return ERROR_BAD_CONFIGURATION;
1478 s = rail_pdu_init(RAIL_LANGUAGEIME_INFO_ORDER_LENGTH);
1482 WLog_ERR(TAG,
"rail_pdu_init failed!");
1483 return CHANNEL_RC_NO_MEMORY;
1486 error = rail_write_languageime_info_order(s, langImeInfo);
1488 if (ERROR_SUCCESS != error)
1491 Stream_Free(s, TRUE);
1494 return rail_send_pdu(rail, s, TS_RAIL_ORDER_LANGUAGEIMEINFO);
1497 UINT rail_send_client_compartment_info_order(
railPlugin* rail,
1503 if (!rail || !compartmentInfo)
1504 return ERROR_INVALID_PARAMETER;
1506 if (!rail_is_feature_supported(rail->rdpcontext, RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED))
1507 return ERROR_BAD_CONFIGURATION;
1509 s = rail_pdu_init(RAIL_COMPARTMENT_INFO_ORDER_LENGTH);
1513 WLog_ERR(TAG,
"rail_pdu_init failed!");
1514 return CHANNEL_RC_NO_MEMORY;
1517 error = rail_write_compartment_info_order(s, compartmentInfo);
1519 if (ERROR_SUCCESS != error)
1521 Stream_Free(s, TRUE);
1524 return rail_send_pdu(rail, s, TS_RAIL_ORDER_COMPARTMENTINFO);
1529 if (!rail || !cloak)
1530 return ERROR_INVALID_PARAMETER;
1532 wStream* s = rail_pdu_init(5);
1536 WLog_ERR(TAG,
"rail_pdu_init failed!");
1537 return CHANNEL_RC_NO_MEMORY;
1540 Stream_Write_UINT32(s, cloak->windowId);
1541 Stream_Write_UINT8(s, cloak->cloak ? 1 : 0);
1542 return rail_send_pdu(rail, s, TS_RAIL_ORDER_CLOAK);
1548 return ERROR_INVALID_PARAMETER;
1551 if ((rail->channelFlags & TS_RAIL_ORDER_HANDSHAKE_EX_FLAGS_SNAP_ARRANGE_SUPPORTED) == 0)
1554 move.top = snap->top;
1555 move.left = snap->left;
1556 move.right = snap->right;
1557 move.bottom = snap->bottom;
1558 move.windowId = snap->windowId;
1559 return rail_send_client_window_move_order(rail, &move);
1562 wStream* s = rail_pdu_init(12);
1566 WLog_ERR(TAG,
"rail_pdu_init failed!");
1567 return CHANNEL_RC_NO_MEMORY;
1570 Stream_Write_UINT32(s, snap->windowId);
1571 Stream_Write_INT16(s, snap->left);
1572 Stream_Write_INT16(s, snap->top);
1573 Stream_Write_INT16(s, snap->right);
1574 Stream_Write_INT16(s, snap->bottom);
1575 return rail_send_pdu(rail, s, TS_RAIL_ORDER_SNAP_ARRANGE);
1578 UINT rail_send_client_text_scale_order(
railPlugin* rail, UINT32 textScale)
1581 return ERROR_INVALID_PARAMETER;
1583 wStream* s = rail_pdu_init(4);
1587 WLog_ERR(TAG,
"rail_pdu_init failed!");
1588 return CHANNEL_RC_NO_MEMORY;
1591 Stream_Write_UINT32(s, textScale);
1592 return rail_send_pdu(rail, s, TS_RAIL_ORDER_TEXTSCALEINFO);
1595 UINT rail_send_client_caret_blink_rate_order(
railPlugin* rail, UINT32 rate)
1598 return ERROR_INVALID_PARAMETER;
1600 wStream* s = rail_pdu_init(4);
1604 WLog_ERR(TAG,
"rail_pdu_init failed!");
1605 return CHANNEL_RC_NO_MEMORY;
1608 Stream_Write_UINT32(s, rate);
1609 return rail_send_pdu(rail, s, TS_RAIL_ORDER_CARETBLINKINFO);
FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
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.