25 #include <freerdp/config.h>
27 #include <winpr/crt.h>
29 #include <freerdp/channels/log.h>
30 #include <freerdp/freerdp.h>
32 #include "rail_orders.h"
34 static BOOL rail_is_feature_supported(
const rdpContext* context, UINT32 featureMask);
43 char buffer[128] = { 0 };
44 UINT16 orderLength = 0;
49 return ERROR_INVALID_PARAMETER;
52 orderLength = (UINT16)Stream_GetPosition(s);
53 Stream_SetPosition(s, 0);
54 rail_write_pdu_header(s, orderType, orderLength);
55 Stream_SetPosition(s, orderLength);
56 WLog_Print(rail->log, WLOG_DEBUG,
"Sending %s PDU, length: %" PRIu16
"",
57 rail_get_order_type_string_full(orderType, buffer,
sizeof(buffer)), orderLength);
58 return rail_send_channel_data(rail, s);
68 if (!s || !execResult)
69 return ERROR_INVALID_PARAMETER;
71 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_EXEC_RESULT_ORDER_LENGTH))
72 return ERROR_INVALID_DATA;
74 Stream_Read_UINT16(s, execResult->flags);
75 Stream_Read_UINT16(s, execResult->execResult);
76 Stream_Read_UINT32(s, execResult->rawResult);
77 Stream_Seek_UINT16(s);
78 return rail_read_unicode_string(s, &execResult->exeOrFile)
80 : ERROR_INTERNAL_ERROR;
90 if (!s || !minmaxinfo)
91 return ERROR_INVALID_PARAMETER;
93 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_MINMAXINFO_ORDER_LENGTH))
94 return ERROR_INVALID_DATA;
96 Stream_Read_UINT32(s, minmaxinfo->windowId);
97 Stream_Read_INT16(s, minmaxinfo->maxWidth);
98 Stream_Read_INT16(s, minmaxinfo->maxHeight);
99 Stream_Read_INT16(s, minmaxinfo->maxPosX);
100 Stream_Read_INT16(s, minmaxinfo->maxPosY);
101 Stream_Read_INT16(s, minmaxinfo->minTrackWidth);
102 Stream_Read_INT16(s, minmaxinfo->minTrackHeight);
103 Stream_Read_INT16(s, minmaxinfo->maxTrackWidth);
104 Stream_Read_INT16(s, minmaxinfo->maxTrackHeight);
105 return CHANNEL_RC_OK;
113 static UINT rail_read_server_localmovesize_order(
wStream* s,
116 UINT16 isMoveSizeStart = 0;
118 if (!s || !localMoveSize)
119 return ERROR_INVALID_PARAMETER;
121 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_LOCALMOVESIZE_ORDER_LENGTH))
122 return ERROR_INVALID_DATA;
124 Stream_Read_UINT32(s, localMoveSize->windowId);
125 Stream_Read_UINT16(s, isMoveSizeStart);
126 localMoveSize->isMoveSizeStart = (isMoveSizeStart != 0) ? TRUE : FALSE;
127 Stream_Read_UINT16(s, localMoveSize->moveSizeType);
128 Stream_Read_INT16(s, localMoveSize->posX);
129 Stream_Read_INT16(s, localMoveSize->posY);
130 return CHANNEL_RC_OK;
138 static UINT rail_read_server_get_appid_resp_order(
wStream* s,
141 if (!s || !getAppidResp)
142 return ERROR_INVALID_PARAMETER;
144 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_GET_APPID_RESP_ORDER_LENGTH))
145 return ERROR_INVALID_DATA;
147 Stream_Read_UINT32(s, getAppidResp->windowId);
148 Stream_Read_UTF16_String(
149 s, getAppidResp->applicationId,
150 ARRAYSIZE(getAppidResp->applicationId));
151 return CHANNEL_RC_OK;
161 if (!s || !langbarInfo)
162 return ERROR_INVALID_PARAMETER;
164 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_LANGBAR_INFO_ORDER_LENGTH))
165 return ERROR_INVALID_DATA;
167 Stream_Read_UINT32(s, langbarInfo->languageBarStatus);
168 return CHANNEL_RC_OK;
173 if (!s || !clientStatus)
174 return ERROR_INVALID_PARAMETER;
176 Stream_Write_UINT32(s, clientStatus->flags);
177 return ERROR_SUCCESS;
185 static UINT rail_write_client_exec_order(
wStream* s, UINT16 flags,
192 if (!s || !exeOrFile || !workingDir || !arguments)
193 return ERROR_INVALID_PARAMETER;
197 if ((exeOrFile->length > 520) || (workingDir->length > 520) || (arguments->length > 16000))
200 "TS_RAIL_ORDER_EXEC argument limits exceeded: ExeOrFile=%" PRIu16
201 " [max=520], WorkingDir=%" PRIu16
" [max=520], Arguments=%" PRIu16
" [max=16000]",
202 exeOrFile->length, workingDir->length, arguments->length);
203 return ERROR_BAD_ARGUMENTS;
206 Stream_Write_UINT16(s, flags);
207 Stream_Write_UINT16(s, exeOrFile->length);
208 Stream_Write_UINT16(s, workingDir->length);
209 Stream_Write_UINT16(s, arguments->length);
211 if ((error = rail_write_unicode_string_value(s, exeOrFile)))
213 WLog_ERR(TAG,
"rail_write_unicode_string_value failed with error %" PRIu32
"", error);
217 if ((error = rail_write_unicode_string_value(s, workingDir)))
219 WLog_ERR(TAG,
"rail_write_unicode_string_value failed with error %" PRIu32
"", error);
223 if ((error = rail_write_unicode_string_value(s, arguments)))
225 WLog_ERR(TAG,
"rail_write_unicode_string_value failed with error %" PRIu32
"", error);
237 return ERROR_INVALID_PARAMETER;
239 Stream_Write_UINT32(s, activate->windowId);
240 enabled = activate->enabled ? 1 : 0;
241 Stream_Write_UINT8(s, enabled);
242 return ERROR_SUCCESS;
248 return ERROR_INVALID_PARAMETER;
250 Stream_Write_UINT32(s, sysmenu->windowId);
251 Stream_Write_INT16(s, sysmenu->left);
252 Stream_Write_INT16(s, sysmenu->top);
253 return ERROR_SUCCESS;
258 if (!s || !syscommand)
259 return ERROR_INVALID_PARAMETER;
261 Stream_Write_UINT32(s, syscommand->windowId);
262 Stream_Write_UINT16(s, syscommand->command);
263 return ERROR_SUCCESS;
266 static UINT rail_write_client_notify_event_order(
wStream* s,
269 if (!s || !notifyEvent)
270 return ERROR_INVALID_PARAMETER;
272 Stream_Write_UINT32(s, notifyEvent->windowId);
273 Stream_Write_UINT32(s, notifyEvent->notifyIconId);
274 Stream_Write_UINT32(s, notifyEvent->message);
275 return ERROR_SUCCESS;
278 static UINT rail_write_client_window_move_order(
wStream* s,
281 if (!s || !windowMove)
282 return ERROR_INVALID_PARAMETER;
284 Stream_Write_UINT32(s, windowMove->windowId);
285 Stream_Write_INT16(s, windowMove->left);
286 Stream_Write_INT16(s, windowMove->top);
287 Stream_Write_INT16(s, windowMove->right);
288 Stream_Write_INT16(s, windowMove->bottom);
289 return ERROR_SUCCESS;
292 static UINT rail_write_client_get_appid_req_order(
wStream* s,
295 if (!s || !getAppidReq)
296 return ERROR_INVALID_PARAMETER;
298 Stream_Write_UINT32(s, getAppidReq->windowId);
299 return ERROR_SUCCESS;
304 if (!s || !langbarInfo)
305 return ERROR_INVALID_PARAMETER;
307 Stream_Write_UINT32(s, langbarInfo->languageBarStatus);
308 return ERROR_SUCCESS;
311 static UINT rail_write_languageime_info_order(
wStream* s,
314 if (!s || !langImeInfo)
315 return ERROR_INVALID_PARAMETER;
317 Stream_Write_UINT32(s, langImeInfo->ProfileType);
318 Stream_Write_UINT16(s, langImeInfo->LanguageID);
319 Stream_Write(s, &langImeInfo->LanguageProfileCLSID,
sizeof(langImeInfo->LanguageProfileCLSID));
320 Stream_Write(s, &langImeInfo->ProfileGUID,
sizeof(langImeInfo->ProfileGUID));
321 Stream_Write_UINT32(s, langImeInfo->KeyboardLayout);
322 return ERROR_SUCCESS;
325 static UINT rail_write_compartment_info_order(
wStream* s,
328 if (!s || !compartmentInfo)
329 return ERROR_INVALID_PARAMETER;
331 Stream_Write_UINT32(s, compartmentInfo->ImeState);
332 Stream_Write_UINT32(s, compartmentInfo->ImeConvMode);
333 Stream_Write_UINT32(s, compartmentInfo->ImeSentenceMode);
334 Stream_Write_UINT32(s, compartmentInfo->KanaMode);
335 return ERROR_SUCCESS;
345 RailClientContext* context = rail_get_client_interface(rail);
350 return ERROR_INVALID_PARAMETER;
352 if ((error = rail_read_handshake_order(s, &serverHandshake)))
354 WLog_ERR(TAG,
"rail_read_handshake_order failed with error %" PRIu32
"!", error);
358 rail->channelBuildNumber = serverHandshake.buildNumber;
360 if (rail->sendHandshake)
363 clientHandshake.buildNumber = 0x00001DB0;
364 error = context->ClientHandshake(context, &clientHandshake);
367 if (error != CHANNEL_RC_OK)
372 IFCALLRET(context->ServerHandshake, error, context, &serverHandshake);
375 WLog_ERR(TAG,
"context.ServerHandshake failed with error %" PRIu32
"", error);
381 static UINT rail_read_compartment_info_order(
wStream* s,
384 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_COMPARTMENT_INFO_ORDER_LENGTH))
385 return ERROR_INVALID_DATA;
387 Stream_Read_UINT32(s, compartmentInfo->ImeState);
388 Stream_Read_UINT32(s, compartmentInfo->ImeConvMode);
389 Stream_Read_UINT32(s, compartmentInfo->ImeSentenceMode);
390 Stream_Read_UINT32(s, compartmentInfo->KanaMode);
391 return CHANNEL_RC_OK;
396 RailClientContext* context = rail_get_client_interface(rail);
401 return ERROR_INVALID_PARAMETER;
403 if (!rail_is_feature_supported(rail->rdpcontext, RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED))
404 return ERROR_BAD_CONFIGURATION;
406 if ((error = rail_read_compartment_info_order(s, &pdu)))
411 IFCALLRET(context->ClientCompartmentInfo, error, context, &pdu);
414 WLog_ERR(TAG,
"context.ClientCompartmentInfo failed with error %" PRIu32
"", error);
420 BOOL rail_is_feature_supported(
const rdpContext* context, UINT32 featureMask)
422 UINT32 supported = 0;
425 if (!context || !context->settings)
432 supported = level & mask;
433 masked = (supported & featureMask);
435 if (masked != featureMask)
437 char maskstr[256] = { 0 };
438 char actualstr[256] = { 0 };
440 WLog_WARN(TAG,
"have %s, require %s",
456 RailClientContext* context = rail_get_client_interface(rail);
460 if (!rail || !context || !s)
461 return ERROR_INVALID_PARAMETER;
463 if (!rail_is_feature_supported(rail->rdpcontext, RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED))
464 return ERROR_BAD_CONFIGURATION;
466 if ((error = rail_read_handshake_ex_order(s, &serverHandshake)))
468 WLog_ERR(TAG,
"rail_read_handshake_ex_order failed with error %" PRIu32
"!", error);
472 rail->channelBuildNumber = serverHandshake.buildNumber;
473 rail->channelFlags = serverHandshake.railHandshakeFlags;
476 char buffer[192] = { 0 };
477 WLog_DBG(TAG,
"HandshakeFlags=%s [buildNumber=0x%08" PRIx32
"]",
478 rail_handshake_ex_flags_to_string(rail->channelFlags, buffer,
sizeof(buffer)),
479 rail->channelBuildNumber);
482 if (rail->sendHandshake)
485 clientHandshake.buildNumber = 0x00001DB0;
488 error = context->ClientHandshake(context, &clientHandshake);
491 if (error != CHANNEL_RC_OK)
496 IFCALLRET(context->ServerHandshakeEx, error, context, &serverHandshake);
499 WLog_ERR(TAG,
"context.ServerHandshakeEx failed with error %" PRIu32
"", error);
512 RailClientContext* context = rail_get_client_interface(rail);
517 return ERROR_INVALID_PARAMETER;
519 if ((error = rail_read_server_exec_result_order(s, &execResult)))
521 WLog_ERR(TAG,
"rail_read_server_exec_result_order failed with error %" PRIu32
"!", error);
527 IFCALLRET(context->ServerExecuteResult, error, context, &execResult);
530 WLog_ERR(TAG,
"context.ServerExecuteResult failed with error %" PRIu32
"", error);
534 free(execResult.exeOrFile.string);
545 RailClientContext* context = rail_get_client_interface(rail);
548 BOOL extendedSpiSupported = 0;
551 return ERROR_INVALID_PARAMETER;
553 extendedSpiSupported = rail_is_extended_spi_supported(rail->channelFlags);
554 if ((error = rail_read_sysparam_order(s, &sysparam, extendedSpiSupported)))
556 WLog_ERR(TAG,
"rail_read_sysparam_order failed with error %" PRIu32
"!", error);
562 IFCALLRET(context->ServerSystemParam, error, context, &sysparam);
565 WLog_ERR(TAG,
"context.ServerSystemParam failed with error %" PRIu32
"", error);
578 RailClientContext* context = rail_get_client_interface(rail);
583 return ERROR_INVALID_PARAMETER;
585 if ((error = rail_read_server_minmaxinfo_order(s, &minMaxInfo)))
587 WLog_ERR(TAG,
"rail_read_server_minmaxinfo_order failed with error %" PRIu32
"!", error);
593 IFCALLRET(context->ServerMinMaxInfo, error, context, &minMaxInfo);
596 WLog_ERR(TAG,
"context.ServerMinMaxInfo failed with error %" PRIu32
"", error);
609 RailClientContext* context = rail_get_client_interface(rail);
614 return ERROR_INVALID_PARAMETER;
616 if ((error = rail_read_server_localmovesize_order(s, &localMoveSize)))
618 WLog_ERR(TAG,
"rail_read_server_localmovesize_order failed with error %" PRIu32
"!", error);
624 IFCALLRET(context->ServerLocalMoveSize, error, context, &localMoveSize);
627 WLog_ERR(TAG,
"context.ServerLocalMoveSize failed with error %" PRIu32
"", error);
640 RailClientContext* context = rail_get_client_interface(rail);
645 return ERROR_INVALID_PARAMETER;
647 if ((error = rail_read_server_get_appid_resp_order(s, &getAppIdResp)))
649 WLog_ERR(TAG,
"rail_read_server_get_appid_resp_order failed with error %" PRIu32
"!",
656 IFCALLRET(context->ServerGetAppIdResponse, error, context, &getAppIdResp);
659 WLog_ERR(TAG,
"context.ServerGetAppIdResponse failed with error %" PRIu32
"", error);
672 RailClientContext* context = rail_get_client_interface(rail);
677 return ERROR_INVALID_PARAMETER;
679 if (!rail_is_feature_supported(rail->rdpcontext, RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED))
680 return ERROR_BAD_CONFIGURATION;
682 if ((error = rail_read_langbar_info_order(s, &langBarInfo)))
684 WLog_ERR(TAG,
"rail_read_langbar_info_order failed with error %" PRIu32
"!", error);
690 IFCALLRET(context->ServerLanguageBarInfo, error, context, &langBarInfo);
693 WLog_ERR(TAG,
"context.ServerLanguageBarInfo failed with error %" PRIu32
"", error);
701 if (!s || !taskbarInfo)
702 return ERROR_INVALID_PARAMETER;
704 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_TASKBAR_INFO_ORDER_LENGTH))
705 return ERROR_INVALID_DATA;
707 Stream_Read_UINT32(s, taskbarInfo->TaskbarMessage);
708 Stream_Read_UINT32(s, taskbarInfo->WindowIdTab);
709 Stream_Read_UINT32(s, taskbarInfo->Body);
710 return CHANNEL_RC_OK;
715 RailClientContext* context = rail_get_client_interface(rail);
720 return ERROR_INVALID_PARAMETER;
724 if (!rail_is_feature_supported(rail->rdpcontext, RAIL_LEVEL_SHELL_INTEGRATION_SUPPORTED))
725 return ERROR_BAD_CONFIGURATION;
727 if ((error = rail_read_taskbar_info_order(s, &taskBarInfo)))
729 WLog_ERR(TAG,
"rail_read_langbar_info_order failed with error %" PRIu32
"!", error);
735 IFCALLRET(context->ServerTaskBarInfo, error, context, &taskBarInfo);
738 WLog_ERR(TAG,
"context.ServerTaskBarInfo failed with error %" PRIu32
"", error);
747 return ERROR_INVALID_PARAMETER;
749 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_Z_ORDER_SYNC_ORDER_LENGTH))
750 return ERROR_INVALID_DATA;
752 Stream_Read_UINT32(s, zorder->windowIdMarker);
753 return CHANNEL_RC_OK;
758 RailClientContext* context = rail_get_client_interface(rail);
763 return ERROR_INVALID_PARAMETER;
765 if ((rail->clientStatus.flags & TS_RAIL_CLIENTSTATUS_ZORDER_SYNC) == 0)
766 return ERROR_INVALID_DATA;
768 if ((error = rail_read_zorder_sync_order(s, &zorder)))
770 WLog_ERR(TAG,
"rail_read_zorder_sync_order failed with error %" PRIu32
"!", error);
776 IFCALLRET(context->ServerZOrderSync, error, context, &zorder);
779 WLog_ERR(TAG,
"context.ServerZOrderSync failed with error %" PRIu32
"", error);
789 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_CLOAK_ORDER_LENGTH))
790 return ERROR_INVALID_DATA;
792 Stream_Read_UINT32(s, cloak->windowId);
793 Stream_Read_UINT8(s, cloaked);
794 cloak->cloak = (cloaked != 0) ? TRUE : FALSE;
795 return CHANNEL_RC_OK;
800 RailClientContext* context = rail_get_client_interface(rail);
805 return ERROR_INVALID_PARAMETER;
809 if ((rail->clientStatus.flags & TS_RAIL_CLIENTSTATUS_BIDIRECTIONAL_CLOAK_SUPPORTED) == 0)
810 return ERROR_INVALID_DATA;
812 if ((error = rail_read_cloak_order(s, &cloak)))
814 WLog_ERR(TAG,
"rail_read_zorder_sync_order failed with error %" PRIu32
"!", error);
820 IFCALLRET(context->ServerCloak, error, context, &cloak);
823 WLog_ERR(TAG,
"context.ServerZOrderSync failed with error %" PRIu32
"", error);
834 return ERROR_INVALID_PARAMETER;
836 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_POWER_DISPLAY_REQUEST_ORDER_LENGTH))
837 return ERROR_INVALID_DATA;
839 Stream_Read_UINT32(s, active);
840 power->active = active != 0;
841 return CHANNEL_RC_OK;
846 RailClientContext* context = rail_get_client_interface(rail);
851 return ERROR_INVALID_PARAMETER;
855 if ((rail->clientStatus.flags & TS_RAIL_CLIENTSTATUS_POWER_DISPLAY_REQUEST_SUPPORTED) == 0)
856 return ERROR_INVALID_DATA;
858 if ((error = rail_read_power_display_request_order(s, &power)))
860 WLog_ERR(TAG,
"rail_read_zorder_sync_order failed with error %" PRIu32
"!", error);
866 IFCALLRET(context->ServerPowerDisplayRequest, error, context, &power);
869 WLog_ERR(TAG,
"context.ServerPowerDisplayRequest failed with error %" PRIu32
"", error);
875 static UINT rail_read_get_application_id_extended_response_order(
wStream* s,
879 return ERROR_INVALID_PARAMETER;
881 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
882 return ERROR_INVALID_DATA;
884 Stream_Read_UINT32(s, id->windowID);
886 if (!Stream_Read_UTF16_String(s, id->applicationID, ARRAYSIZE(id->applicationID)))
887 return ERROR_INVALID_DATA;
889 if (_wcsnlen(id->applicationID, ARRAYSIZE(id->applicationID)) >= ARRAYSIZE(id->applicationID))
890 return ERROR_INVALID_DATA;
892 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
893 return ERROR_INVALID_DATA;
895 Stream_Read_UINT32(s, id->processId);
897 if (!Stream_Read_UTF16_String(s, id->processImageName, ARRAYSIZE(id->processImageName)))
898 return ERROR_INVALID_DATA;
900 if (_wcsnlen(id->applicationID, ARRAYSIZE(id->processImageName)) >=
901 ARRAYSIZE(id->processImageName))
902 return ERROR_INVALID_DATA;
904 return CHANNEL_RC_OK;
907 static UINT rail_recv_get_application_id_extended_response_order(
railPlugin* rail,
wStream* s)
909 RailClientContext* context = rail_get_client_interface(rail);
914 return ERROR_INVALID_PARAMETER;
916 if ((error = rail_read_get_application_id_extended_response_order(s, &
id)))
919 "rail_read_get_application_id_extended_response_order failed with error %" PRIu32
927 IFCALLRET(context->ServerGetAppidResponseExtended, error, context, &
id);
930 WLog_ERR(TAG,
"context.ServerGetAppidResponseExtended failed with error %" PRIu32
"",
937 static UINT rail_read_textscaleinfo_order(
wStream* s, UINT32* pTextScaleFactor)
939 WINPR_ASSERT(pTextScaleFactor);
941 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
942 return ERROR_INVALID_DATA;
944 Stream_Read_UINT32(s, *pTextScaleFactor);
945 return CHANNEL_RC_OK;
950 RailClientContext* context = rail_get_client_interface(rail);
951 UINT32 TextScaleFactor = 0;
955 return ERROR_INVALID_PARAMETER;
957 if ((error = rail_read_textscaleinfo_order(s, &TextScaleFactor)))
962 IFCALLRET(context->ClientTextScale, error, context, TextScaleFactor);
965 WLog_ERR(TAG,
"context.ClientTextScale failed with error %" PRIu32
"", error);
971 static UINT rail_read_caretblinkinfo_order(
wStream* s, UINT32* pCaretBlinkRate)
973 WINPR_ASSERT(pCaretBlinkRate);
975 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
976 return ERROR_INVALID_DATA;
978 Stream_Read_UINT32(s, *pCaretBlinkRate);
979 return CHANNEL_RC_OK;
984 RailClientContext* context = rail_get_client_interface(rail);
985 UINT32 CaretBlinkRate = 0;
989 return ERROR_INVALID_PARAMETER;
990 if ((error = rail_read_caretblinkinfo_order(s, &CaretBlinkRate)))
995 IFCALLRET(context->ClientCaretBlinkRate, error, context, CaretBlinkRate);
998 WLog_ERR(TAG,
"context.ClientCaretBlinkRate failed with error %" PRIu32
"", error);
1009 UINT rail_order_recv(LPVOID userdata,
wStream* s)
1011 char buffer[128] = { 0 };
1013 UINT16 orderType = 0;
1014 UINT16 orderLength = 0;
1015 UINT error = CHANNEL_RC_OK;
1018 return ERROR_INVALID_PARAMETER;
1020 if ((error = rail_read_pdu_header(s, &orderType, &orderLength)))
1022 WLog_ERR(TAG,
"rail_read_pdu_header failed with error %" PRIu32
"!", error);
1026 WLog_Print(rail->log, WLOG_DEBUG,
"Received %s PDU, length:%" PRIu16
"",
1027 rail_get_order_type_string_full(orderType, buffer,
sizeof(buffer)), orderLength);
1031 case TS_RAIL_ORDER_HANDSHAKE:
1032 error = rail_recv_handshake_order(rail, s);
1035 case TS_RAIL_ORDER_COMPARTMENTINFO:
1036 error = rail_recv_compartmentinfo_order(rail, s);
1039 case TS_RAIL_ORDER_HANDSHAKE_EX:
1040 error = rail_recv_handshake_ex_order(rail, s);
1043 case TS_RAIL_ORDER_EXEC_RESULT:
1044 error = rail_recv_exec_result_order(rail, s);
1047 case TS_RAIL_ORDER_SYSPARAM:
1048 error = rail_recv_server_sysparam_order(rail, s);
1051 case TS_RAIL_ORDER_MINMAXINFO:
1052 error = rail_recv_server_minmaxinfo_order(rail, s);
1055 case TS_RAIL_ORDER_LOCALMOVESIZE:
1056 error = rail_recv_server_localmovesize_order(rail, s);
1059 case TS_RAIL_ORDER_GET_APPID_RESP:
1060 error = rail_recv_server_get_appid_resp_order(rail, s);
1063 case TS_RAIL_ORDER_LANGBARINFO:
1064 error = rail_recv_langbar_info_order(rail, s);
1067 case TS_RAIL_ORDER_TASKBARINFO:
1068 error = rail_recv_taskbar_info_order(rail, s);
1071 case TS_RAIL_ORDER_ZORDER_SYNC:
1072 error = rail_recv_zorder_sync_order(rail, s);
1075 case TS_RAIL_ORDER_CLOAK:
1076 error = rail_recv_cloak_order(rail, s);
1079 case TS_RAIL_ORDER_POWER_DISPLAY_REQUEST:
1080 error = rail_recv_power_display_request_order(rail, s);
1083 case TS_RAIL_ORDER_GET_APPID_RESP_EX:
1084 error = rail_recv_get_application_id_extended_response_order(rail, s);
1087 case TS_RAIL_ORDER_TEXTSCALEINFO:
1088 error = rail_recv_textscaleinfo_order(rail, s);
1091 case TS_RAIL_ORDER_CARETBLINKINFO:
1092 error = rail_recv_caretblinkinfo_order(rail, s);
1096 WLog_ERR(TAG,
"Unknown RAIL PDU %s received.",
1097 rail_get_order_type_string_full(orderType, buffer,
sizeof(buffer)));
1098 return ERROR_INVALID_DATA;
1101 if (error != CHANNEL_RC_OK)
1103 char ebuffer[128] = { 0 };
1104 WLog_Print(rail->log, WLOG_ERROR,
"Failed to process rail %s PDU, length:%" PRIu16
"",
1105 rail_get_order_type_string_full(orderType, ebuffer,
sizeof(ebuffer)),
1109 Stream_Free(s, TRUE);
1120 if (!rail || !handshake)
1121 return ERROR_INVALID_PARAMETER;
1123 wStream* s = rail_pdu_init(RAIL_HANDSHAKE_ORDER_LENGTH);
1127 WLog_ERR(TAG,
"rail_pdu_init failed!");
1128 return CHANNEL_RC_NO_MEMORY;
1131 rail_write_handshake_order(s, handshake);
1132 return rail_send_pdu(rail, s, TS_RAIL_ORDER_HANDSHAKE);
1142 if (!rail || !handshakeEx)
1143 return ERROR_INVALID_PARAMETER;
1145 wStream* s = rail_pdu_init(RAIL_HANDSHAKE_EX_ORDER_LENGTH);
1149 WLog_ERR(TAG,
"rail_pdu_init failed!");
1150 return CHANNEL_RC_NO_MEMORY;
1153 rail_write_handshake_ex_order(s, handshakeEx);
1154 return rail_send_pdu(rail, s, TS_RAIL_ORDER_HANDSHAKE_EX);
1167 if (!rail || !clientStatus)
1168 return ERROR_INVALID_PARAMETER;
1170 rail->clientStatus = *clientStatus;
1171 s = rail_pdu_init(RAIL_CLIENT_STATUS_ORDER_LENGTH);
1175 WLog_ERR(TAG,
"rail_pdu_init failed!");
1176 return CHANNEL_RC_NO_MEMORY;
1179 error = rail_write_client_status_order(s, clientStatus);
1181 if (ERROR_SUCCESS != error)
1184 Stream_Free(s, TRUE);
1188 return rail_send_pdu(rail, s, TS_RAIL_ORDER_CLIENTSTATUS);
1196 UINT rail_send_client_exec_order(
railPlugin* rail, UINT16 flags,
1205 if (!rail || !exeOrFile || !workingDir || !arguments)
1206 return ERROR_INVALID_PARAMETER;
1208 length = RAIL_EXEC_ORDER_LENGTH + exeOrFile->length + workingDir->length + arguments->length;
1209 s = rail_pdu_init(length);
1213 WLog_ERR(TAG,
"rail_pdu_init failed!");
1214 return CHANNEL_RC_NO_MEMORY;
1217 if ((error = rail_write_client_exec_order(s, flags, exeOrFile, workingDir, arguments)))
1219 WLog_ERR(TAG,
"rail_write_client_exec_order failed with error %" PRIu32
"!", error);
1223 return rail_send_pdu(rail, s, TS_RAIL_ORDER_EXEC);
1226 Stream_Free(s, TRUE);
1240 if (!rail || !activate)
1241 return ERROR_INVALID_PARAMETER;
1243 s = rail_pdu_init(RAIL_ACTIVATE_ORDER_LENGTH);
1247 WLog_ERR(TAG,
"rail_pdu_init failed!");
1248 return CHANNEL_RC_NO_MEMORY;
1251 error = rail_write_client_activate_order(s, activate);
1253 if (ERROR_SUCCESS != error)
1256 Stream_Free(s, TRUE);
1260 return rail_send_pdu(rail, s, TS_RAIL_ORDER_ACTIVATE);
1273 if (!rail || !sysmenu)
1274 return ERROR_INVALID_PARAMETER;
1276 s = rail_pdu_init(RAIL_SYSMENU_ORDER_LENGTH);
1280 WLog_ERR(TAG,
"rail_pdu_init failed!");
1281 return CHANNEL_RC_NO_MEMORY;
1284 error = rail_write_client_sysmenu_order(s, sysmenu);
1286 if (ERROR_SUCCESS != error)
1289 Stream_Free(s, TRUE);
1293 return rail_send_pdu(rail, s, TS_RAIL_ORDER_SYSMENU);
1306 if (!rail || !syscommand)
1307 return ERROR_INVALID_PARAMETER;
1309 s = rail_pdu_init(RAIL_SYSCOMMAND_ORDER_LENGTH);
1313 WLog_ERR(TAG,
"rail_pdu_init failed!");
1314 return CHANNEL_RC_NO_MEMORY;
1317 error = rail_write_client_syscommand_order(s, syscommand);
1319 if (ERROR_SUCCESS != error)
1322 Stream_Free(s, TRUE);
1326 return rail_send_pdu(rail, s, TS_RAIL_ORDER_SYSCOMMAND);
1334 UINT rail_send_client_notify_event_order(
railPlugin* rail,
1340 if (!rail || !notifyEvent)
1341 return ERROR_INVALID_PARAMETER;
1343 s = rail_pdu_init(RAIL_NOTIFY_EVENT_ORDER_LENGTH);
1347 WLog_ERR(TAG,
"rail_pdu_init failed!");
1348 return CHANNEL_RC_NO_MEMORY;
1351 error = rail_write_client_notify_event_order(s, notifyEvent);
1353 if (ERROR_SUCCESS != error)
1356 Stream_Free(s, TRUE);
1360 return rail_send_pdu(rail, s, TS_RAIL_ORDER_NOTIFY_EVENT);
1373 if (!rail || !windowMove)
1374 return ERROR_INVALID_PARAMETER;
1376 s = rail_pdu_init(RAIL_WINDOW_MOVE_ORDER_LENGTH);
1380 WLog_ERR(TAG,
"rail_pdu_init failed!");
1381 return CHANNEL_RC_NO_MEMORY;
1384 error = rail_write_client_window_move_order(s, windowMove);
1386 if (ERROR_SUCCESS != error)
1389 Stream_Free(s, TRUE);
1393 return rail_send_pdu(rail, s, TS_RAIL_ORDER_WINDOWMOVE);
1401 UINT rail_send_client_get_appid_req_order(
railPlugin* rail,
1407 if (!rail || !getAppIdReq)
1408 return ERROR_INVALID_PARAMETER;
1410 s = rail_pdu_init(RAIL_GET_APPID_REQ_ORDER_LENGTH);
1414 WLog_ERR(TAG,
"rail_pdu_init failed!");
1415 return CHANNEL_RC_NO_MEMORY;
1418 error = rail_write_client_get_appid_req_order(s, getAppIdReq);
1420 if (ERROR_SUCCESS != error)
1423 Stream_Free(s, TRUE);
1426 return rail_send_pdu(rail, s, TS_RAIL_ORDER_GET_APPID_REQ);
1434 UINT rail_send_client_langbar_info_order(
railPlugin* rail,
1440 if (!rail || !langBarInfo)
1441 return ERROR_INVALID_PARAMETER;
1443 if (!rail_is_feature_supported(rail->rdpcontext, RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED))
1444 return ERROR_BAD_CONFIGURATION;
1446 s = rail_pdu_init(RAIL_LANGBAR_INFO_ORDER_LENGTH);
1450 WLog_ERR(TAG,
"rail_pdu_init failed!");
1451 return CHANNEL_RC_NO_MEMORY;
1454 error = rail_write_langbar_info_order(s, langBarInfo);
1456 if (ERROR_SUCCESS != error)
1459 Stream_Free(s, TRUE);
1462 return rail_send_pdu(rail, s, TS_RAIL_ORDER_LANGBARINFO);
1465 UINT rail_send_client_languageime_info_order(
railPlugin* rail,
1471 if (!rail || !langImeInfo)
1472 return ERROR_INVALID_PARAMETER;
1474 if (!rail_is_feature_supported(rail->rdpcontext, RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED))
1475 return ERROR_BAD_CONFIGURATION;
1477 s = rail_pdu_init(RAIL_LANGUAGEIME_INFO_ORDER_LENGTH);
1481 WLog_ERR(TAG,
"rail_pdu_init failed!");
1482 return CHANNEL_RC_NO_MEMORY;
1485 error = rail_write_languageime_info_order(s, langImeInfo);
1487 if (ERROR_SUCCESS != error)
1490 Stream_Free(s, TRUE);
1493 return rail_send_pdu(rail, s, TS_RAIL_ORDER_LANGUAGEIMEINFO);
1496 UINT rail_send_client_compartment_info_order(
railPlugin* rail,
1502 if (!rail || !compartmentInfo)
1503 return ERROR_INVALID_PARAMETER;
1505 if (!rail_is_feature_supported(rail->rdpcontext, RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED))
1506 return ERROR_BAD_CONFIGURATION;
1508 s = rail_pdu_init(RAIL_COMPARTMENT_INFO_ORDER_LENGTH);
1512 WLog_ERR(TAG,
"rail_pdu_init failed!");
1513 return CHANNEL_RC_NO_MEMORY;
1516 error = rail_write_compartment_info_order(s, compartmentInfo);
1518 if (ERROR_SUCCESS != error)
1520 Stream_Free(s, TRUE);
1523 return rail_send_pdu(rail, s, TS_RAIL_ORDER_COMPARTMENTINFO);
1528 if (!rail || !cloak)
1529 return ERROR_INVALID_PARAMETER;
1531 wStream* s = rail_pdu_init(5);
1535 WLog_ERR(TAG,
"rail_pdu_init failed!");
1536 return CHANNEL_RC_NO_MEMORY;
1539 Stream_Write_UINT32(s, cloak->windowId);
1540 Stream_Write_UINT8(s, cloak->cloak ? 1 : 0);
1541 return rail_send_pdu(rail, s, TS_RAIL_ORDER_CLOAK);
1547 return ERROR_INVALID_PARAMETER;
1550 if ((rail->channelFlags & TS_RAIL_ORDER_HANDSHAKE_EX_FLAGS_SNAP_ARRANGE_SUPPORTED) == 0)
1553 move.top = snap->top;
1554 move.left = snap->left;
1555 move.right = snap->right;
1556 move.bottom = snap->bottom;
1557 move.windowId = snap->windowId;
1558 return rail_send_client_window_move_order(rail, &move);
1561 wStream* s = rail_pdu_init(12);
1565 WLog_ERR(TAG,
"rail_pdu_init failed!");
1566 return CHANNEL_RC_NO_MEMORY;
1569 Stream_Write_UINT32(s, snap->windowId);
1570 Stream_Write_INT16(s, snap->left);
1571 Stream_Write_INT16(s, snap->top);
1572 Stream_Write_INT16(s, snap->right);
1573 Stream_Write_INT16(s, snap->bottom);
1574 return rail_send_pdu(rail, s, TS_RAIL_ORDER_SNAP_ARRANGE);
1577 UINT rail_send_client_text_scale_order(
railPlugin* rail, UINT32 textScale)
1580 return ERROR_INVALID_PARAMETER;
1582 wStream* s = rail_pdu_init(4);
1586 WLog_ERR(TAG,
"rail_pdu_init failed!");
1587 return CHANNEL_RC_NO_MEMORY;
1590 Stream_Write_UINT32(s, textScale);
1591 return rail_send_pdu(rail, s, TS_RAIL_ORDER_TEXTSCALEINFO);
1594 UINT rail_send_client_caret_blink_rate_order(
railPlugin* rail, UINT32 rate)
1597 return ERROR_INVALID_PARAMETER;
1599 wStream* s = rail_pdu_init(4);
1603 WLog_ERR(TAG,
"rail_pdu_init failed!");
1604 return CHANNEL_RC_NO_MEMORY;
1607 Stream_Write_UINT32(s, rate);
1608 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.