21#include <freerdp/types.h>
22#include <freerdp/constants.h>
24#include <freerdp/freerdp.h>
25#include <freerdp/channels/log.h>
26#include <freerdp/utils/channel_pdu_tracker.h>
29#include <winpr/synch.h>
30#include <winpr/thread.h>
31#include <winpr/stream.h>
35#define TAG CHANNELS_TAG("rail.server")
43static UINT rail_send(RailServerContext* context,
wStream* s,
size_t length)
45 UINT status = CHANNEL_RC_OK;
48 const ULONG ulen = WINPR_ASSERTING_INT_CAST(ULONG, length);
49 WINPR_ASSERT(context);
51 if (!WTSVirtualChannelWrite(context->priv->rail_channel, Stream_BufferAs(s,
char), ulen,
54 WLog_ERR(TAG,
"WTSVirtualChannelWrite failed!");
55 status = ERROR_INTERNAL_ERROR;
67static UINT rail_server_send_pdu(RailServerContext* context,
wStream* s, UINT16 orderType)
69 char buffer[128] = WINPR_C_ARRAY_INIT;
71 WINPR_ASSERT(context);
74 const size_t orderLength = Stream_GetPosition(s);
75 Stream_ResetPosition(s);
76 if (!rail_write_pdu_header(s, orderType, WINPR_ASSERTING_INT_CAST(UINT16, orderLength)))
78 if (!Stream_SetPosition(s, orderLength))
80 WLog_DBG(TAG,
"Sending %s PDU, length: %" PRIuz
"",
81 rail_get_order_type_string_full(orderType, buffer,
sizeof(buffer)), orderLength);
82 return rail_send(context, s, orderLength);
86 return ERROR_INVALID_DATA;
89static void rail_write_local_move_size_order(
wStream* s,
93 WINPR_ASSERT(localMoveSize);
94 WINPR_ASSERT(Stream_EnsureRemainingCapacity(s, 12));
96 Stream_Write_UINT32(s, localMoveSize->windowId);
97 Stream_Write_UINT16(s, localMoveSize->isMoveSizeStart ? 1 : 0);
98 Stream_Write_UINT16(s, localMoveSize->moveSizeType);
99 Stream_Write_INT16(s, localMoveSize->posX);
100 Stream_Write_INT16(s, localMoveSize->posY);
106 WINPR_ASSERT(minMaxInfo);
107 WINPR_ASSERT(Stream_EnsureRemainingCapacity(s, 20));
109 Stream_Write_UINT32(s, minMaxInfo->windowId);
110 Stream_Write_INT16(s, minMaxInfo->maxWidth);
111 Stream_Write_INT16(s, minMaxInfo->maxHeight);
112 Stream_Write_INT16(s, minMaxInfo->maxPosX);
113 Stream_Write_INT16(s, minMaxInfo->maxPosY);
114 Stream_Write_INT16(s, minMaxInfo->minTrackWidth);
115 Stream_Write_INT16(s, minMaxInfo->minTrackHeight);
116 Stream_Write_INT16(s, minMaxInfo->maxTrackWidth);
117 Stream_Write_INT16(s, minMaxInfo->maxTrackHeight);
123 WINPR_ASSERT(taskbarInfo);
124 WINPR_ASSERT(Stream_EnsureRemainingCapacity(s, 12));
126 Stream_Write_UINT32(s, taskbarInfo->TaskbarMessage);
127 Stream_Write_UINT32(s, taskbarInfo->WindowIdTab);
128 Stream_Write_UINT32(s, taskbarInfo->Body);
134 WINPR_ASSERT(langbarInfo);
135 WINPR_ASSERT(Stream_EnsureRemainingCapacity(s, 4));
137 Stream_Write_UINT32(s, langbarInfo->languageBarStatus);
149 WINPR_ASSERT(execResult);
151 if (execResult->exeOrFile.length > 520 || execResult->exeOrFile.length < 1)
152 return ERROR_INVALID_DATA;
154 Stream_Write_UINT16(s, execResult->flags);
155 Stream_Write_UINT16(s, execResult->execResult);
156 Stream_Write_UINT32(s, execResult->rawResult);
157 Stream_Write_UINT16(s, 0);
158 return rail_write_unicode_string(s, &execResult->exeOrFile);
164 WINPR_ASSERT(zOrderSync);
165 WINPR_ASSERT(Stream_EnsureRemainingCapacity(s, 4));
166 Stream_Write_UINT32(s, zOrderSync->windowIdMarker);
173 WINPR_ASSERT(Stream_EnsureRemainingCapacity(s, 5));
175 Stream_Write_UINT32(s, cloak->windowId);
176 Stream_Write_UINT8(s, cloak->cloak ? 1 : 0);
180rail_write_power_display_request_order(
wStream* s,
184 WINPR_ASSERT(powerDisplayRequest);
185 WINPR_ASSERT(Stream_EnsureRemainingCapacity(s, 4));
187 Stream_Write_UINT32(s, powerDisplayRequest->active ? 1 : 0);
191static UINT rail_write_get_app_id_resp_order(
wStream* s,
195 WINPR_ASSERT(getAppidResp);
196 if (!Stream_EnsureRemainingCapacity(s, 4ull + ARRAYSIZE(getAppidResp->applicationId)))
197 return ERROR_OUTOFMEMORY;
199 Stream_Write_UINT32(s, getAppidResp->windowId);
200 if (!Stream_Write_UTF16_String(
201 s, getAppidResp->applicationId,
202 ARRAYSIZE(getAppidResp->applicationId)))
203 return ERROR_INVALID_DATA;
204 return ERROR_SUCCESS;
208static UINT rail_write_get_appid_resp_ex_order(
wStream* s,
212 WINPR_ASSERT(getAppidRespEx);
214 if (!Stream_EnsureRemainingCapacity(s, (8ull + ARRAYSIZE(getAppidRespEx->applicationID) +
215 ARRAYSIZE(getAppidRespEx->processImageName))))
216 return ERROR_OUTOFMEMORY;
218 Stream_Write_UINT32(s, getAppidRespEx->windowID);
219 if (!Stream_Write_UTF16_String(
220 s, getAppidRespEx->applicationID,
221 ARRAYSIZE(getAppidRespEx->applicationID)))
222 return ERROR_INVALID_DATA;
223 Stream_Write_UINT32(s, getAppidRespEx->processId);
224 if (!Stream_Write_UTF16_String(
225 s, getAppidRespEx->processImageName,
226 ARRAYSIZE(getAppidRespEx->processImageName)))
227 return ERROR_INVALID_DATA;
228 return ERROR_SUCCESS;
237static UINT rail_send_server_handshake(RailServerContext* context,
240 if (!context || !handshake)
241 return ERROR_INVALID_PARAMETER;
243 wStream* s = rail_pdu_init(RAIL_HANDSHAKE_ORDER_LENGTH);
247 WLog_ERR(TAG,
"rail_pdu_init failed!");
248 return CHANNEL_RC_NO_MEMORY;
251 rail_write_handshake_order(s, handshake);
252 return rail_server_send_pdu(context, s, TS_RAIL_ORDER_HANDSHAKE);
261static UINT rail_send_server_handshake_ex(RailServerContext* context,
264 if (!context || !handshakeEx || !context->priv)
265 return ERROR_INVALID_PARAMETER;
267 wStream* s = rail_pdu_init(RAIL_HANDSHAKE_EX_ORDER_LENGTH);
271 WLog_ERR(TAG,
"rail_pdu_init failed!");
272 return CHANNEL_RC_NO_MEMORY;
275 rail_server_set_handshake_ex_flags(context, handshakeEx->railHandshakeFlags);
276 rail_write_handshake_ex_order(s, handshakeEx);
277 return rail_server_send_pdu(context, s, TS_RAIL_ORDER_HANDSHAKE_EX);
286static UINT rail_send_server_sysparam(RailServerContext* context,
289 if (!context || !sysparam)
290 return ERROR_INVALID_PARAMETER;
292 RailServerPrivate* priv = context->priv;
295 return ERROR_INVALID_PARAMETER;
297 const BOOL extendedSpiSupported = rail_is_extended_spi_supported(context->priv->channelFlags);
298 wStream* s = rail_pdu_init(RAIL_SYSPARAM_ORDER_LENGTH);
302 WLog_ERR(TAG,
"rail_pdu_init failed!");
303 return CHANNEL_RC_NO_MEMORY;
306 const UINT error = rail_write_sysparam_order(s, sysparam, extendedSpiSupported);
307 if (error != CHANNEL_RC_OK)
309 Stream_Free(s, TRUE);
312 return rail_server_send_pdu(context, s, TS_RAIL_ORDER_SYSPARAM);
321static UINT rail_send_server_local_move_size(RailServerContext* context,
324 if (!context || !localMoveSize)
325 return ERROR_INVALID_PARAMETER;
327 wStream* s = rail_pdu_init(RAIL_LOCALMOVESIZE_ORDER_LENGTH);
331 WLog_ERR(TAG,
"rail_pdu_init failed!");
332 return CHANNEL_RC_NO_MEMORY;
335 rail_write_local_move_size_order(s, localMoveSize);
336 return rail_server_send_pdu(context, s, TS_RAIL_ORDER_LOCALMOVESIZE);
345static UINT rail_send_server_min_max_info(RailServerContext* context,
348 if (!context || !minMaxInfo)
349 return ERROR_INVALID_PARAMETER;
351 wStream* s = rail_pdu_init(RAIL_MINMAXINFO_ORDER_LENGTH);
355 WLog_ERR(TAG,
"rail_pdu_init failed!");
356 return CHANNEL_RC_NO_MEMORY;
359 rail_write_min_max_info_order(s, minMaxInfo);
360 return rail_server_send_pdu(context, s, TS_RAIL_ORDER_MINMAXINFO);
369static UINT rail_send_server_taskbar_info(RailServerContext* context,
372 if (!context || !taskbarInfo)
373 return ERROR_INVALID_PARAMETER;
375 wStream* s = rail_pdu_init(RAIL_TASKBAR_INFO_ORDER_LENGTH);
379 WLog_ERR(TAG,
"rail_pdu_init failed!");
380 return CHANNEL_RC_NO_MEMORY;
383 rail_write_taskbar_info_order(s, taskbarInfo);
384 return rail_server_send_pdu(context, s, TS_RAIL_ORDER_TASKBARINFO);
393static UINT rail_send_server_langbar_info(RailServerContext* context,
396 if (!context || !langbarInfo)
397 return ERROR_INVALID_PARAMETER;
399 wStream* s = rail_pdu_init(RAIL_LANGBAR_INFO_ORDER_LENGTH);
403 WLog_ERR(TAG,
"rail_pdu_init failed!");
404 return CHANNEL_RC_NO_MEMORY;
407 rail_write_langbar_info_order(s, langbarInfo);
408 return rail_server_send_pdu(context, s, TS_RAIL_ORDER_LANGBARINFO);
417static UINT rail_send_server_exec_result(RailServerContext* context,
420 if (!context || !execResult)
421 return ERROR_INVALID_PARAMETER;
423 wStream* s = rail_pdu_init(RAIL_EXEC_RESULT_ORDER_LENGTH + execResult->exeOrFile.length);
427 WLog_ERR(TAG,
"rail_pdu_init failed!");
428 return CHANNEL_RC_NO_MEMORY;
431 const UINT error = rail_write_exec_result_order(s, execResult);
432 if (error != CHANNEL_RC_OK)
434 Stream_Free(s, TRUE);
437 return rail_server_send_pdu(context, s, TS_RAIL_ORDER_EXEC_RESULT);
446static UINT rail_send_server_z_order_sync(RailServerContext* context,
449 if (!context || !zOrderSync)
450 return ERROR_INVALID_PARAMETER;
452 wStream* s = rail_pdu_init(RAIL_Z_ORDER_SYNC_ORDER_LENGTH);
456 WLog_ERR(TAG,
"rail_pdu_init failed!");
457 return CHANNEL_RC_NO_MEMORY;
460 rail_write_z_order_sync_order(s, zOrderSync);
461 return rail_server_send_pdu(context, s, TS_RAIL_ORDER_ZORDER_SYNC);
470static UINT rail_send_server_cloak(RailServerContext* context,
const RAIL_CLOAK* cloak)
472 if (!context || !cloak)
473 return ERROR_INVALID_PARAMETER;
475 wStream* s = rail_pdu_init(RAIL_CLOAK_ORDER_LENGTH);
479 WLog_ERR(TAG,
"rail_pdu_init failed!");
480 return CHANNEL_RC_NO_MEMORY;
483 rail_write_cloak_order(s, cloak);
484 return rail_server_send_pdu(context, s, TS_RAIL_ORDER_CLOAK);
494rail_send_server_power_display_request(RailServerContext* context,
497 if (!context || !powerDisplayRequest)
498 return ERROR_INVALID_PARAMETER;
500 wStream* s = rail_pdu_init(RAIL_POWER_DISPLAY_REQUEST_ORDER_LENGTH);
504 WLog_ERR(TAG,
"rail_pdu_init failed!");
505 return CHANNEL_RC_NO_MEMORY;
508 rail_write_power_display_request_order(s, powerDisplayRequest);
509 return rail_server_send_pdu(context, s, TS_RAIL_ORDER_POWER_DISPLAY_REQUEST);
518static UINT rail_send_server_get_app_id_resp(RailServerContext* context,
521 if (!context || !getAppidResp)
522 return ERROR_INVALID_PARAMETER;
524 wStream* s = rail_pdu_init(RAIL_GET_APPID_RESP_ORDER_LENGTH);
528 WLog_ERR(TAG,
"rail_pdu_init failed!");
529 return CHANNEL_RC_NO_MEMORY;
532 const UINT error = rail_write_get_app_id_resp_order(s, getAppidResp);
533 if (error != CHANNEL_RC_OK)
535 Stream_Free(s, TRUE);
538 return rail_server_send_pdu(context, s, TS_RAIL_ORDER_GET_APPID_RESP);
547static UINT rail_send_server_get_appid_resp_ex(RailServerContext* context,
550 if (!context || !getAppidRespEx)
551 return ERROR_INVALID_PARAMETER;
553 wStream* s = rail_pdu_init(RAIL_GET_APPID_RESP_EX_ORDER_LENGTH);
557 WLog_ERR(TAG,
"rail_pdu_init failed!");
558 return CHANNEL_RC_NO_MEMORY;
561 const UINT error = rail_write_get_appid_resp_ex_order(s, getAppidRespEx);
562 if (error != CHANNEL_RC_OK)
564 Stream_Free(s, TRUE);
567 return rail_server_send_pdu(context, s, TS_RAIL_ORDER_GET_APPID_RESP_EX);
578 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_CLIENT_STATUS_ORDER_LENGTH))
579 return ERROR_INVALID_DATA;
581 Stream_Read_UINT32(s, clientStatus->flags);
582 return CHANNEL_RC_OK;
595 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_EXEC_ORDER_LENGTH))
596 return ERROR_INVALID_DATA;
598 exec->flags = Stream_Get_UINT16(s);
599 const UINT16 exeLen = Stream_Get_UINT16(s);
600 const UINT16 workLen = Stream_Get_UINT16(s);
601 const UINT16 argLen = Stream_Get_UINT16(s);
603 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)exeLen + workLen + argLen))
604 return ERROR_INVALID_DATA;
608 const size_t len = exeLen /
sizeof(WCHAR);
609 exec->RemoteApplicationProgram = args[0] =
610 Stream_Read_UTF16_String_As_UTF8(s, len,
nullptr);
611 if (!exec->RemoteApplicationProgram)
616 const size_t len = workLen /
sizeof(WCHAR);
617 exec->RemoteApplicationWorkingDir = args[1] =
618 Stream_Read_UTF16_String_As_UTF8(s, len,
nullptr);
619 if (!exec->RemoteApplicationWorkingDir)
624 const size_t len = argLen /
sizeof(WCHAR);
625 exec->RemoteApplicationArguments = args[2] =
626 Stream_Read_UTF16_String_As_UTF8(s, len,
nullptr);
627 if (!exec->RemoteApplicationArguments)
631 return CHANNEL_RC_OK;
637 return ERROR_INTERNAL_ERROR;
650 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_ACTIVATE_ORDER_LENGTH))
651 return ERROR_INVALID_DATA;
653 Stream_Read_UINT32(s, activate->windowId);
654 Stream_Read_UINT8(s, enabled);
655 activate->enabled = (enabled != 0);
656 return CHANNEL_RC_OK;
667 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_SYSMENU_ORDER_LENGTH))
668 return ERROR_INVALID_DATA;
670 Stream_Read_UINT32(s, sysmenu->windowId);
671 Stream_Read_INT16(s, sysmenu->left);
672 Stream_Read_INT16(s, sysmenu->top);
673 return CHANNEL_RC_OK;
684 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_SYSCOMMAND_ORDER_LENGTH))
685 return ERROR_INVALID_DATA;
687 Stream_Read_UINT32(s, syscommand->windowId);
688 Stream_Read_UINT16(s, syscommand->command);
689 return CHANNEL_RC_OK;
700 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_NOTIFY_EVENT_ORDER_LENGTH))
701 return ERROR_INVALID_DATA;
703 Stream_Read_UINT32(s, notifyEvent->windowId);
704 Stream_Read_UINT32(s, notifyEvent->notifyIconId);
705 Stream_Read_UINT32(s, notifyEvent->message);
706 return CHANNEL_RC_OK;
717 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_GET_APPID_REQ_ORDER_LENGTH))
718 return ERROR_INVALID_DATA;
720 Stream_Read_UINT32(s, getAppidReq->windowId);
721 return CHANNEL_RC_OK;
732 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_WINDOW_MOVE_ORDER_LENGTH))
733 return ERROR_INVALID_DATA;
735 Stream_Read_UINT32(s, windowMove->windowId);
736 Stream_Read_INT16(s, windowMove->left);
737 Stream_Read_INT16(s, windowMove->top);
738 Stream_Read_INT16(s, windowMove->right);
739 Stream_Read_INT16(s, windowMove->bottom);
740 return CHANNEL_RC_OK;
751 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_SNAP_ARRANGE_ORDER_LENGTH))
752 return ERROR_INVALID_DATA;
754 Stream_Read_UINT32(s, snapArrange->windowId);
755 Stream_Read_INT16(s, snapArrange->left);
756 Stream_Read_INT16(s, snapArrange->top);
757 Stream_Read_INT16(s, snapArrange->right);
758 Stream_Read_INT16(s, snapArrange->bottom);
759 return CHANNEL_RC_OK;
770 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_LANGBAR_INFO_ORDER_LENGTH))
771 return ERROR_INVALID_DATA;
773 Stream_Read_UINT32(s, langbarInfo->languageBarStatus);
774 return CHANNEL_RC_OK;
783static UINT rail_read_language_ime_info_order(
wStream* s,
786 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_LANGUAGEIME_INFO_ORDER_LENGTH))
787 return ERROR_INVALID_DATA;
789 Stream_Read_UINT32(s, languageImeInfo->ProfileType);
790 Stream_Read_UINT16(s, languageImeInfo->LanguageID);
792 s, &languageImeInfo->LanguageProfileCLSID,
793 sizeof(languageImeInfo->LanguageProfileCLSID));
794 Stream_Read(s, &languageImeInfo->ProfileGUID,
795 sizeof(languageImeInfo->ProfileGUID));
796 Stream_Read_UINT32(s, languageImeInfo->KeyboardLayout);
797 return CHANNEL_RC_OK;
806static UINT rail_read_compartment_info_order(
wStream* s,
809 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_COMPARTMENT_INFO_ORDER_LENGTH))
810 return ERROR_INVALID_DATA;
812 Stream_Read_UINT32(s, compartmentInfo->ImeState);
813 Stream_Read_UINT32(s, compartmentInfo->ImeConvMode);
814 Stream_Read_UINT32(s, compartmentInfo->ImeSentenceMode);
815 Stream_Read_UINT32(s, compartmentInfo->KanaMode);
816 return CHANNEL_RC_OK;
829 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_CLOAK_ORDER_LENGTH))
830 return ERROR_INVALID_DATA;
832 Stream_Read_UINT32(s, cloak->windowId);
833 Stream_Read_UINT8(s, cloaked);
834 cloak->cloak = (cloaked != 0);
835 return CHANNEL_RC_OK;
844static UINT rail_recv_client_handshake_order(RailServerContext* context,
wStream* s)
846 UINT error = CHANNEL_RC_OK;
849 return ERROR_INVALID_PARAMETER;
852 if ((error = rail_read_handshake_order(s, &handshake)))
854 WLog_ERR(TAG,
"rail_read_handshake_order failed with error %" PRIu32
"!", error);
858 IFCALLRET(context->ClientHandshake, error, context, &handshake);
861 WLog_ERR(TAG,
"context.ClientHandshake failed with error %" PRIu32
"", error);
872static UINT rail_recv_client_client_status_order(RailServerContext* context,
wStream* s)
874 UINT error = CHANNEL_RC_OK;
877 return ERROR_INVALID_PARAMETER;
880 if ((error = rail_read_client_status_order(s, &clientStatus)))
882 WLog_ERR(TAG,
"rail_read_client_status_order failed with error %" PRIu32
"!", error);
886 IFCALLRET(context->ClientClientStatus, error, context, &clientStatus);
889 WLog_ERR(TAG,
"context.ClientClientStatus failed with error %" PRIu32
"", error);
900static UINT rail_recv_client_exec_order(RailServerContext* context,
wStream* s)
902 char* args[3] = WINPR_C_ARRAY_INIT;
906 return ERROR_INVALID_PARAMETER;
908 UINT error = rail_read_exec_order(s, &exec, args);
911 WLog_ERR(TAG,
"rail_read_client_status_order failed with error %" PRIu32
"!", error);
915 IFCALLRET(context->ClientExec, error, context, &exec);
918 WLog_ERR(TAG,
"context.Exec failed with error %" PRIu32
"", error);
932static UINT rail_recv_client_sysparam_order(RailServerContext* context,
wStream* s)
935 return ERROR_INVALID_PARAMETER;
937 const BOOL extendedSpiSupported = rail_is_extended_spi_supported(context->priv->channelFlags);
940 UINT error = rail_read_sysparam_order(s, &sysparam, extendedSpiSupported);
941 if (error != CHANNEL_RC_OK)
943 rail_unicode_string_free(&sysparam.highContrast.colorScheme);
944 WLog_ERR(TAG,
"rail_read_sysparam_order failed with error %" PRIu32
"!", error);
948 IFCALLRET(context->ClientSysparam, error, context, &sysparam);
949 rail_unicode_string_free(&sysparam.highContrast.colorScheme);
952 WLog_ERR(TAG,
"context.ClientSysparam failed with error %" PRIu32
"", error);
963static UINT rail_recv_client_activate_order(RailServerContext* context,
wStream* s)
965 UINT error = CHANNEL_RC_OK;
968 return ERROR_INVALID_PARAMETER;
971 if ((error = rail_read_activate_order(s, &activate)))
973 WLog_ERR(TAG,
"rail_read_activate_order failed with error %" PRIu32
"!", error);
977 IFCALLRET(context->ClientActivate, error, context, &activate);
980 WLog_ERR(TAG,
"context.ClientActivate failed with error %" PRIu32
"", error);
991static UINT rail_recv_client_sysmenu_order(RailServerContext* context,
wStream* s)
993 UINT error = CHANNEL_RC_OK;
996 return ERROR_INVALID_PARAMETER;
999 if ((error = rail_read_sysmenu_order(s, &sysmenu)))
1001 WLog_ERR(TAG,
"rail_read_sysmenu_order failed with error %" PRIu32
"!", error);
1005 IFCALLRET(context->ClientSysmenu, error, context, &sysmenu);
1008 WLog_ERR(TAG,
"context.ClientSysmenu failed with error %" PRIu32
"", error);
1019static UINT rail_recv_client_syscommand_order(RailServerContext* context,
wStream* s)
1021 UINT error = CHANNEL_RC_OK;
1024 return ERROR_INVALID_PARAMETER;
1027 if ((error = rail_read_syscommand_order(s, &syscommand)))
1029 WLog_ERR(TAG,
"rail_read_syscommand_order failed with error %" PRIu32
"!", error);
1033 IFCALLRET(context->ClientSyscommand, error, context, &syscommand);
1036 WLog_ERR(TAG,
"context.ClientSyscommand failed with error %" PRIu32
"", error);
1047static UINT rail_recv_client_notify_event_order(RailServerContext* context,
wStream* s)
1049 UINT error = CHANNEL_RC_OK;
1052 return ERROR_INVALID_PARAMETER;
1055 if ((error = rail_read_notify_event_order(s, ¬ifyEvent)))
1057 WLog_ERR(TAG,
"rail_read_notify_event_order failed with error %" PRIu32
"!", error);
1061 IFCALLRET(context->ClientNotifyEvent, error, context, ¬ifyEvent);
1064 WLog_ERR(TAG,
"context.ClientNotifyEvent failed with error %" PRIu32
"", error);
1075static UINT rail_recv_client_window_move_order(RailServerContext* context,
wStream* s)
1077 UINT error = CHANNEL_RC_OK;
1080 return ERROR_INVALID_PARAMETER;
1083 if ((error = rail_read_window_move_order(s, &windowMove)))
1085 WLog_ERR(TAG,
"rail_read_window_move_order failed with error %" PRIu32
"!", error);
1089 IFCALLRET(context->ClientWindowMove, error, context, &windowMove);
1092 WLog_ERR(TAG,
"context.ClientWindowMove failed with error %" PRIu32
"", error);
1103static UINT rail_recv_client_snap_arrange_order(RailServerContext* context,
wStream* s)
1105 UINT error = CHANNEL_RC_OK;
1108 return ERROR_INVALID_PARAMETER;
1111 if ((error = rail_read_snap_arange_order(s, &snapArrange)))
1113 WLog_ERR(TAG,
"rail_read_snap_arange_order failed with error %" PRIu32
"!", error);
1117 IFCALLRET(context->ClientSnapArrange, error, context, &snapArrange);
1120 WLog_ERR(TAG,
"context.ClientSnapArrange failed with error %" PRIu32
"", error);
1131static UINT rail_recv_client_get_appid_req_order(RailServerContext* context,
wStream* s)
1133 UINT error = CHANNEL_RC_OK;
1136 return ERROR_INVALID_PARAMETER;
1139 if ((error = rail_read_get_appid_req_order(s, &getAppidReq)))
1141 WLog_ERR(TAG,
"rail_read_get_appid_req_order failed with error %" PRIu32
"!", error);
1145 IFCALLRET(context->ClientGetAppidReq, error, context, &getAppidReq);
1148 WLog_ERR(TAG,
"context.ClientGetAppidReq failed with error %" PRIu32
"", error);
1159static UINT rail_recv_client_langbar_info_order(RailServerContext* context,
wStream* s)
1161 UINT error = CHANNEL_RC_OK;
1164 return ERROR_INVALID_PARAMETER;
1167 if ((error = rail_read_langbar_info_order(s, &langbarInfo)))
1169 WLog_ERR(TAG,
"rail_read_langbar_info_order failed with error %" PRIu32
"!", error);
1173 IFCALLRET(context->ClientLangbarInfo, error, context, &langbarInfo);
1176 WLog_ERR(TAG,
"context.ClientLangbarInfo failed with error %" PRIu32
"", error);
1187static UINT rail_recv_client_language_ime_info_order(RailServerContext* context,
wStream* s)
1189 UINT error = CHANNEL_RC_OK;
1192 return ERROR_INVALID_PARAMETER;
1195 if ((error = rail_read_language_ime_info_order(s, &languageImeInfo)))
1197 WLog_ERR(TAG,
"rail_read_language_ime_info_order failed with error %" PRIu32
"!", error);
1201 IFCALLRET(context->ClientLanguageImeInfo, error, context, &languageImeInfo);
1204 WLog_ERR(TAG,
"context.ClientLanguageImeInfo failed with error %" PRIu32
"", error);
1215static UINT rail_recv_client_compartment_info(RailServerContext* context,
wStream* s)
1217 UINT error = CHANNEL_RC_OK;
1220 return ERROR_INVALID_PARAMETER;
1223 if ((error = rail_read_compartment_info_order(s, &compartmentInfo)))
1225 WLog_ERR(TAG,
"rail_read_compartment_info_order failed with error %" PRIu32
"!", error);
1229 IFCALLRET(context->ClientCompartmentInfo, error, context, &compartmentInfo);
1232 WLog_ERR(TAG,
"context.ClientCompartmentInfo failed with error %" PRIu32
"", error);
1243static UINT rail_recv_client_cloak_order(RailServerContext* context,
wStream* s)
1245 UINT error = CHANNEL_RC_OK;
1248 return ERROR_INVALID_PARAMETER;
1251 if ((error = rail_read_cloak_order(s, &cloak)))
1253 WLog_ERR(TAG,
"rail_read_cloak_order failed with error %" PRIu32
"!", error);
1257 IFCALLRET(context->ClientCloak, error, context, &cloak);
1260 WLog_ERR(TAG,
"context.Cloak failed with error %" PRIu32
"", error);
1266static UINT rail_recv_client_text_scale_order(RailServerContext* context,
wStream* s)
1268 UINT error = CHANNEL_RC_OK;
1269 UINT32 TextScaleFactor = 0;
1272 return ERROR_INVALID_PARAMETER;
1274 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1275 return ERROR_INVALID_DATA;
1277 Stream_Read_UINT32(s, TextScaleFactor);
1278 IFCALLRET(context->ClientTextScale, error, context, TextScaleFactor);
1281 WLog_ERR(TAG,
"context.TextScale failed with error %" PRIu32
"", error);
1287static UINT rail_recv_client_caret_blink(RailServerContext* context,
wStream* s)
1289 UINT error = CHANNEL_RC_OK;
1290 UINT32 CaretBlinkRate = 0;
1293 return ERROR_INVALID_PARAMETER;
1295 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1296 return ERROR_INVALID_DATA;
1298 Stream_Read_UINT32(s, CaretBlinkRate);
1299 IFCALLRET(context->ClientCaretBlinkRate, error, context, CaretBlinkRate);
1302 WLog_ERR(TAG,
"context.CaretBlinkRate failed with error %" PRIu32
"", error);
1308static DWORD WINAPI rail_server_thread(LPVOID arg)
1310 RailServerContext* context = (RailServerContext*)arg;
1311 WINPR_ASSERT(context);
1313 RailServerPrivate* priv = context->priv;
1319 UINT error = CHANNEL_RC_OK;
1320 events[nCount++] = priv->channelEvent;
1321 events[nCount++] = priv->stopEvent;
1325 status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
1327 if (status == WAIT_FAILED)
1329 error = GetLastError();
1330 WLog_ERR(TAG,
"WaitForMultipleObjects failed with error %" PRIu32
"!", error);
1334 status = WaitForSingleObject(context->priv->stopEvent, 0);
1336 if (status == WAIT_FAILED)
1338 error = GetLastError();
1339 WLog_ERR(TAG,
"WaitForSingleObject failed with error %" PRIu32
"!", error);
1343 if (status == WAIT_OBJECT_0)
1346 status = WaitForSingleObject(context->priv->channelEvent, 0);
1348 if (status == WAIT_FAILED)
1350 error = GetLastError();
1353 "WaitForSingleObject(context->priv->channelEvent, 0) failed with error %" PRIu32
1359 if (status == WAIT_OBJECT_0)
1361 if ((error = rail_server_handle_messages(context)))
1363 WLog_ERR(TAG,
"rail_server_handle_messages failed with error %" PRIu32
"", error);
1369 if (error && context->rdpcontext)
1370 setChannelError(context->rdpcontext, error,
"rail_server_thread reported an error");
1382static UINT rail_server_start(RailServerContext* context)
1384 void* buffer =
nullptr;
1385 DWORD bytesReturned = 0;
1386 UINT error = ERROR_INTERNAL_ERROR;
1388 WINPR_ASSERT(context);
1390 RailServerPrivate* priv = context->priv;
1393 priv->rail_channel =
1394 WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, RAIL_SVC_CHANNEL_NAME);
1396 if (!priv->rail_channel)
1398 WLog_ERR(TAG,
"WTSVirtualChannelOpen failed!");
1402 if (!WTSVirtualChannelQuery(priv->rail_channel, WTSVirtualEventHandle, &buffer,
1404 (bytesReturned !=
sizeof(HANDLE)))
1407 "error during WTSVirtualChannelQuery(WTSVirtualEventHandle) or invalid returned "
1408 "size(%" PRIu32
")",
1412 WTSFreeMemory(buffer);
1417 priv->channelEvent = *(HANDLE*)buffer;
1418 WTSFreeMemory(buffer);
1419 context->priv->stopEvent = CreateEvent(
nullptr, TRUE, FALSE,
nullptr);
1421 if (!context->priv->stopEvent)
1423 WLog_ERR(TAG,
"CreateEvent failed!");
1427 context->priv->thread =
1428 CreateThread(
nullptr, 0, rail_server_thread, (
void*)context, 0,
nullptr);
1430 if (!context->priv->thread)
1432 WLog_ERR(TAG,
"CreateThread failed!");
1433 goto out_stop_event;
1436 return CHANNEL_RC_OK;
1438 (void)CloseHandle(context->priv->stopEvent);
1439 context->priv->stopEvent =
nullptr;
1441 (void)WTSVirtualChannelClose(context->priv->rail_channel);
1442 context->priv->rail_channel =
nullptr;
1447static BOOL rail_server_stop(RailServerContext* context)
1449 WINPR_ASSERT(context);
1450 RailServerPrivate* priv = context->priv;
1454 (void)SetEvent(priv->stopEvent);
1456 if (WaitForSingleObject(priv->thread, INFINITE) == WAIT_FAILED)
1458 WLog_ERR(TAG,
"WaitForSingleObject failed with error %" PRIu32
"", GetLastError());
1462 (void)CloseHandle(priv->thread);
1463 (void)CloseHandle(priv->stopEvent);
1464 priv->thread =
nullptr;
1465 priv->stopEvent =
nullptr;
1468 if (priv->rail_channel)
1470 (void)WTSVirtualChannelClose(priv->rail_channel);
1471 priv->rail_channel =
nullptr;
1474 priv->channelEvent =
nullptr;
1478static void rail_server_context_priv_free(RailServerPrivate* priv)
1483 ChannelPduTracker_free(priv->channelPduTracker);
1487WINPR_ATTR_MALLOC(rail_server_context_priv_free, 1)
1488static RailServerPrivate* rail_server_context_priv_new(HANDLE vc)
1490 RailServerPrivate* priv = calloc(1,
sizeof(RailServerPrivate));
1494 priv->channelPduTracker = ChannelPduTracker_new(vc);
1495 if (!priv->channelPduTracker)
1499 rail_server_context_priv_free(priv);
1503RailServerContext* rail_server_context_new(HANDLE vcm)
1505 RailServerContext* context = (RailServerContext*)calloc(1,
sizeof(RailServerContext));
1509 WLog_ERR(TAG,
"calloc failed!");
1514 context->Start = rail_server_start;
1515 context->Stop = rail_server_stop;
1516 context->ServerHandshake = rail_send_server_handshake;
1517 context->ServerHandshakeEx = rail_send_server_handshake_ex;
1518 context->ServerSysparam = rail_send_server_sysparam;
1519 context->ServerLocalMoveSize = rail_send_server_local_move_size;
1520 context->ServerMinMaxInfo = rail_send_server_min_max_info;
1521 context->ServerTaskbarInfo = rail_send_server_taskbar_info;
1522 context->ServerLangbarInfo = rail_send_server_langbar_info;
1523 context->ServerExecResult = rail_send_server_exec_result;
1524 context->ServerGetAppidResp = rail_send_server_get_app_id_resp;
1525 context->ServerZOrderSync = rail_send_server_z_order_sync;
1526 context->ServerCloak = rail_send_server_cloak;
1527 context->ServerPowerDisplayRequest = rail_send_server_power_display_request;
1528 context->ServerGetAppidRespEx = rail_send_server_get_appid_resp_ex;
1529 context->priv = rail_server_context_priv_new(vcm);
1533 WLog_ERR(TAG,
"calloc failed!");
1539 rail_server_context_free(context);
1543void rail_server_context_free(RailServerContext* context)
1547 rail_server_context_priv_free(context->priv);
1551void rail_server_set_handshake_ex_flags(RailServerContext* context, DWORD flags)
1553 WINPR_ASSERT(context);
1554 WINPR_ASSERT(context->priv);
1556 RailServerPrivate* priv = context->priv;
1557 priv->channelFlags = flags;
1560static UINT rail_server_read_pdu_header(
wStream* s, UINT16* pOrderType, UINT16* pOrderLength)
1562 WINPR_ASSERT(pOrderType);
1563 WINPR_ASSERT(pOrderLength);
1566 const UINT status = rail_read_pdu_header(s, pOrderType, pOrderLength);
1567 if (status != CHANNEL_RC_OK)
1569 WLog_ERR(TAG,
"rail_read_pdu_header failed with error %" PRIu32
"!", status);
1573 if (!Stream_EnsureRemainingCapacity(s, *pOrderLength - RAIL_PDU_HEADER_LENGTH))
1576 "Stream_EnsureRemainingCapacity failed, orderLength - RAIL_PDU_HEADER_LENGTH");
1577 return CHANNEL_RC_NO_MEMORY;
1579 return CHANNEL_RC_OK;
1582static UINT rail_server_handle_message_completed(RailServerContext* context,
wStream* s,
1583 UINT16 orderType, UINT16 orderLength)
1586 char buffer[128] = WINPR_C_ARRAY_INIT;
1587 WLog_DBG(TAG,
"Received %s PDU, length:%" PRIu16
"",
1588 rail_get_order_type_string_full(orderType, buffer,
sizeof(buffer)), orderLength);
1593 case TS_RAIL_ORDER_HANDSHAKE:
1594 return rail_recv_client_handshake_order(context, s);
1596 case TS_RAIL_ORDER_CLIENTSTATUS:
1597 return rail_recv_client_client_status_order(context, s);
1599 case TS_RAIL_ORDER_EXEC:
1600 return rail_recv_client_exec_order(context, s);
1602 case TS_RAIL_ORDER_SYSPARAM:
1603 return rail_recv_client_sysparam_order(context, s);
1605 case TS_RAIL_ORDER_ACTIVATE:
1606 return rail_recv_client_activate_order(context, s);
1608 case TS_RAIL_ORDER_SYSMENU:
1609 return rail_recv_client_sysmenu_order(context, s);
1611 case TS_RAIL_ORDER_SYSCOMMAND:
1612 return rail_recv_client_syscommand_order(context, s);
1614 case TS_RAIL_ORDER_NOTIFY_EVENT:
1615 return rail_recv_client_notify_event_order(context, s);
1617 case TS_RAIL_ORDER_WINDOWMOVE:
1618 return rail_recv_client_window_move_order(context, s);
1620 case TS_RAIL_ORDER_SNAP_ARRANGE:
1621 return rail_recv_client_snap_arrange_order(context, s);
1623 case TS_RAIL_ORDER_GET_APPID_REQ:
1624 return rail_recv_client_get_appid_req_order(context, s);
1626 case TS_RAIL_ORDER_LANGBARINFO:
1627 return rail_recv_client_langbar_info_order(context, s);
1629 case TS_RAIL_ORDER_LANGUAGEIMEINFO:
1630 return rail_recv_client_language_ime_info_order(context, s);
1632 case TS_RAIL_ORDER_COMPARTMENTINFO:
1633 return rail_recv_client_compartment_info(context, s);
1635 case TS_RAIL_ORDER_CLOAK:
1636 return rail_recv_client_cloak_order(context, s);
1638 case TS_RAIL_ORDER_TEXTSCALEINFO:
1639 return rail_recv_client_text_scale_order(context, s);
1641 case TS_RAIL_ORDER_CARETBLINKINFO:
1642 return rail_recv_client_caret_blink(context, s);
1645 WLog_ERR(TAG,
"Unknown RAIL PDU order received.");
1646 return ERROR_INVALID_DATA;
1650UINT rail_server_handle_messages(RailServerContext* context)
1652 WINPR_ASSERT(context);
1654 RailServerPrivate* priv = context->priv;
1658 wStream* s = ChannelPduTracker_poll(priv->channelPduTracker, &ok);
1661 return ERROR_INVALID_DATA;
1664 return CHANNEL_RC_OK;
1666 UINT16 orderType = 0;
1667 UINT16 orderLength = 0;
1668 UINT rc = rail_server_read_pdu_header(s, &orderType, &orderLength);
1669 if (rc == CHANNEL_RC_OK)
1670 rc = rail_server_handle_message_completed(context, s, orderType, orderLength);