21#include <freerdp/types.h>
22#include <freerdp/constants.h>
24#include <freerdp/freerdp.h>
25#include <freerdp/channels/log.h>
28#include <winpr/synch.h>
29#include <winpr/thread.h>
30#include <winpr/stream.h>
34#define TAG CHANNELS_TAG("rail.server")
42static UINT rail_send(RailServerContext* context,
wStream* s,
size_t length)
44 UINT status = CHANNEL_RC_OK;
47 const ULONG ulen = WINPR_ASSERTING_INT_CAST(ULONG, length);
48 WINPR_ASSERT(context);
50 if (!WTSVirtualChannelWrite(context->priv->rail_channel, Stream_BufferAs(s,
char), ulen,
53 WLog_ERR(TAG,
"WTSVirtualChannelWrite failed!");
54 status = ERROR_INTERNAL_ERROR;
66static UINT rail_server_send_pdu(RailServerContext* context,
wStream* s, UINT16 orderType)
68 char buffer[128] = WINPR_C_ARRAY_INIT;
70 WINPR_ASSERT(context);
73 const size_t orderLength = Stream_GetPosition(s);
74 Stream_ResetPosition(s);
75 if (!rail_write_pdu_header(s, orderType, WINPR_ASSERTING_INT_CAST(UINT16, orderLength)))
77 if (!Stream_SetPosition(s, orderLength))
79 WLog_DBG(TAG,
"Sending %s PDU, length: %" PRIuz
"",
80 rail_get_order_type_string_full(orderType, buffer,
sizeof(buffer)), orderLength);
81 return rail_send(context, s, orderLength);
85 return ERROR_INVALID_DATA;
88static void rail_write_local_move_size_order(
wStream* s,
92 WINPR_ASSERT(localMoveSize);
93 WINPR_ASSERT(Stream_EnsureRemainingCapacity(s, 12));
95 Stream_Write_UINT32(s, localMoveSize->windowId);
96 Stream_Write_UINT16(s, localMoveSize->isMoveSizeStart ? 1 : 0);
97 Stream_Write_UINT16(s, localMoveSize->moveSizeType);
98 Stream_Write_INT16(s, localMoveSize->posX);
99 Stream_Write_INT16(s, localMoveSize->posY);
105 WINPR_ASSERT(minMaxInfo);
106 WINPR_ASSERT(Stream_EnsureRemainingCapacity(s, 20));
108 Stream_Write_UINT32(s, minMaxInfo->windowId);
109 Stream_Write_INT16(s, minMaxInfo->maxWidth);
110 Stream_Write_INT16(s, minMaxInfo->maxHeight);
111 Stream_Write_INT16(s, minMaxInfo->maxPosX);
112 Stream_Write_INT16(s, minMaxInfo->maxPosY);
113 Stream_Write_INT16(s, minMaxInfo->minTrackWidth);
114 Stream_Write_INT16(s, minMaxInfo->minTrackHeight);
115 Stream_Write_INT16(s, minMaxInfo->maxTrackWidth);
116 Stream_Write_INT16(s, minMaxInfo->maxTrackHeight);
122 WINPR_ASSERT(taskbarInfo);
123 WINPR_ASSERT(Stream_EnsureRemainingCapacity(s, 12));
125 Stream_Write_UINT32(s, taskbarInfo->TaskbarMessage);
126 Stream_Write_UINT32(s, taskbarInfo->WindowIdTab);
127 Stream_Write_UINT32(s, taskbarInfo->Body);
133 WINPR_ASSERT(langbarInfo);
134 WINPR_ASSERT(Stream_EnsureRemainingCapacity(s, 4));
136 Stream_Write_UINT32(s, langbarInfo->languageBarStatus);
148 WINPR_ASSERT(execResult);
150 if (execResult->exeOrFile.length > 520 || execResult->exeOrFile.length < 1)
151 return ERROR_INVALID_DATA;
153 Stream_Write_UINT16(s, execResult->flags);
154 Stream_Write_UINT16(s, execResult->execResult);
155 Stream_Write_UINT32(s, execResult->rawResult);
156 Stream_Write_UINT16(s, 0);
157 Stream_Write_UINT16(s, execResult->exeOrFile.length);
158 Stream_Write(s, execResult->exeOrFile.string,
159 execResult->exeOrFile.length);
160 return ERROR_SUCCESS;
166 WINPR_ASSERT(zOrderSync);
167 WINPR_ASSERT(Stream_EnsureRemainingCapacity(s, 4));
168 Stream_Write_UINT32(s, zOrderSync->windowIdMarker);
175 WINPR_ASSERT(Stream_EnsureRemainingCapacity(s, 5));
177 Stream_Write_UINT32(s, cloak->windowId);
178 Stream_Write_UINT8(s, cloak->cloak ? 1 : 0);
182rail_write_power_display_request_order(
wStream* s,
186 WINPR_ASSERT(powerDisplayRequest);
187 WINPR_ASSERT(Stream_EnsureRemainingCapacity(s, 4));
189 Stream_Write_UINT32(s, powerDisplayRequest->active ? 1 : 0);
193static UINT rail_write_get_app_id_resp_order(
wStream* s,
197 WINPR_ASSERT(getAppidResp);
198 if (!Stream_EnsureRemainingCapacity(s, 4ull + ARRAYSIZE(getAppidResp->applicationId)))
199 return ERROR_OUTOFMEMORY;
201 Stream_Write_UINT32(s, getAppidResp->windowId);
202 if (!Stream_Write_UTF16_String(
203 s, getAppidResp->applicationId,
204 ARRAYSIZE(getAppidResp->applicationId)))
205 return ERROR_INVALID_DATA;
206 return ERROR_SUCCESS;
210static UINT rail_write_get_appid_resp_ex_order(
wStream* s,
214 WINPR_ASSERT(getAppidRespEx);
216 if (!Stream_EnsureRemainingCapacity(s, (8ull + ARRAYSIZE(getAppidRespEx->applicationID) +
217 ARRAYSIZE(getAppidRespEx->processImageName))))
218 return ERROR_OUTOFMEMORY;
220 Stream_Write_UINT32(s, getAppidRespEx->windowID);
221 if (!Stream_Write_UTF16_String(
222 s, getAppidRespEx->applicationID,
223 ARRAYSIZE(getAppidRespEx->applicationID)))
224 return ERROR_INVALID_DATA;
225 Stream_Write_UINT32(s, getAppidRespEx->processId);
226 if (!Stream_Write_UTF16_String(
227 s, getAppidRespEx->processImageName,
228 ARRAYSIZE(getAppidRespEx->processImageName)))
229 return ERROR_INVALID_DATA;
230 return ERROR_SUCCESS;
239static UINT rail_send_server_handshake(RailServerContext* context,
242 if (!context || !handshake)
243 return ERROR_INVALID_PARAMETER;
245 wStream* s = rail_pdu_init(RAIL_HANDSHAKE_ORDER_LENGTH);
249 WLog_ERR(TAG,
"rail_pdu_init failed!");
250 return CHANNEL_RC_NO_MEMORY;
253 rail_write_handshake_order(s, handshake);
254 return rail_server_send_pdu(context, s, TS_RAIL_ORDER_HANDSHAKE);
263static UINT rail_send_server_handshake_ex(RailServerContext* context,
266 if (!context || !handshakeEx || !context->priv)
267 return ERROR_INVALID_PARAMETER;
269 wStream* s = rail_pdu_init(RAIL_HANDSHAKE_EX_ORDER_LENGTH);
273 WLog_ERR(TAG,
"rail_pdu_init failed!");
274 return CHANNEL_RC_NO_MEMORY;
277 rail_server_set_handshake_ex_flags(context, handshakeEx->railHandshakeFlags);
278 rail_write_handshake_ex_order(s, handshakeEx);
279 return rail_server_send_pdu(context, s, TS_RAIL_ORDER_HANDSHAKE_EX);
288static UINT rail_send_server_sysparam(RailServerContext* context,
291 if (!context || !sysparam)
292 return ERROR_INVALID_PARAMETER;
294 RailServerPrivate* priv = context->priv;
297 return ERROR_INVALID_PARAMETER;
299 const BOOL extendedSpiSupported = rail_is_extended_spi_supported(context->priv->channelFlags);
300 wStream* s = rail_pdu_init(RAIL_SYSPARAM_ORDER_LENGTH);
304 WLog_ERR(TAG,
"rail_pdu_init failed!");
305 return CHANNEL_RC_NO_MEMORY;
308 const UINT error = rail_write_sysparam_order(s, sysparam, extendedSpiSupported);
309 if (error != CHANNEL_RC_OK)
311 Stream_Free(s, TRUE);
314 return rail_server_send_pdu(context, s, TS_RAIL_ORDER_SYSPARAM);
323static UINT rail_send_server_local_move_size(RailServerContext* context,
326 if (!context || !localMoveSize)
327 return ERROR_INVALID_PARAMETER;
329 wStream* s = rail_pdu_init(RAIL_LOCALMOVESIZE_ORDER_LENGTH);
333 WLog_ERR(TAG,
"rail_pdu_init failed!");
334 return CHANNEL_RC_NO_MEMORY;
337 rail_write_local_move_size_order(s, localMoveSize);
338 return rail_server_send_pdu(context, s, TS_RAIL_ORDER_LOCALMOVESIZE);
347static UINT rail_send_server_min_max_info(RailServerContext* context,
350 if (!context || !minMaxInfo)
351 return ERROR_INVALID_PARAMETER;
353 wStream* s = rail_pdu_init(RAIL_MINMAXINFO_ORDER_LENGTH);
357 WLog_ERR(TAG,
"rail_pdu_init failed!");
358 return CHANNEL_RC_NO_MEMORY;
361 rail_write_min_max_info_order(s, minMaxInfo);
362 return rail_server_send_pdu(context, s, TS_RAIL_ORDER_MINMAXINFO);
371static UINT rail_send_server_taskbar_info(RailServerContext* context,
374 if (!context || !taskbarInfo)
375 return ERROR_INVALID_PARAMETER;
377 wStream* s = rail_pdu_init(RAIL_TASKBAR_INFO_ORDER_LENGTH);
381 WLog_ERR(TAG,
"rail_pdu_init failed!");
382 return CHANNEL_RC_NO_MEMORY;
385 rail_write_taskbar_info_order(s, taskbarInfo);
386 return rail_server_send_pdu(context, s, TS_RAIL_ORDER_TASKBARINFO);
395static UINT rail_send_server_langbar_info(RailServerContext* context,
398 if (!context || !langbarInfo)
399 return ERROR_INVALID_PARAMETER;
401 wStream* s = rail_pdu_init(RAIL_LANGBAR_INFO_ORDER_LENGTH);
405 WLog_ERR(TAG,
"rail_pdu_init failed!");
406 return CHANNEL_RC_NO_MEMORY;
409 rail_write_langbar_info_order(s, langbarInfo);
410 return rail_server_send_pdu(context, s, TS_RAIL_ORDER_LANGBARINFO);
419static UINT rail_send_server_exec_result(RailServerContext* context,
422 if (!context || !execResult)
423 return ERROR_INVALID_PARAMETER;
425 wStream* s = rail_pdu_init(RAIL_EXEC_RESULT_ORDER_LENGTH + execResult->exeOrFile.length);
429 WLog_ERR(TAG,
"rail_pdu_init failed!");
430 return CHANNEL_RC_NO_MEMORY;
433 const UINT error = rail_write_exec_result_order(s, execResult);
434 if (error != CHANNEL_RC_OK)
436 Stream_Free(s, TRUE);
439 return rail_server_send_pdu(context, s, TS_RAIL_ORDER_EXEC_RESULT);
448static UINT rail_send_server_z_order_sync(RailServerContext* context,
451 if (!context || !zOrderSync)
452 return ERROR_INVALID_PARAMETER;
454 wStream* s = rail_pdu_init(RAIL_Z_ORDER_SYNC_ORDER_LENGTH);
458 WLog_ERR(TAG,
"rail_pdu_init failed!");
459 return CHANNEL_RC_NO_MEMORY;
462 rail_write_z_order_sync_order(s, zOrderSync);
463 return rail_server_send_pdu(context, s, TS_RAIL_ORDER_ZORDER_SYNC);
472static UINT rail_send_server_cloak(RailServerContext* context,
const RAIL_CLOAK* cloak)
474 if (!context || !cloak)
475 return ERROR_INVALID_PARAMETER;
477 wStream* s = rail_pdu_init(RAIL_CLOAK_ORDER_LENGTH);
481 WLog_ERR(TAG,
"rail_pdu_init failed!");
482 return CHANNEL_RC_NO_MEMORY;
485 rail_write_cloak_order(s, cloak);
486 return rail_server_send_pdu(context, s, TS_RAIL_ORDER_CLOAK);
496rail_send_server_power_display_request(RailServerContext* context,
499 if (!context || !powerDisplayRequest)
500 return ERROR_INVALID_PARAMETER;
502 wStream* s = rail_pdu_init(RAIL_POWER_DISPLAY_REQUEST_ORDER_LENGTH);
506 WLog_ERR(TAG,
"rail_pdu_init failed!");
507 return CHANNEL_RC_NO_MEMORY;
510 rail_write_power_display_request_order(s, powerDisplayRequest);
511 return rail_server_send_pdu(context, s, TS_RAIL_ORDER_POWER_DISPLAY_REQUEST);
520static UINT rail_send_server_get_app_id_resp(RailServerContext* context,
523 if (!context || !getAppidResp)
524 return ERROR_INVALID_PARAMETER;
526 wStream* s = rail_pdu_init(RAIL_GET_APPID_RESP_ORDER_LENGTH);
530 WLog_ERR(TAG,
"rail_pdu_init failed!");
531 return CHANNEL_RC_NO_MEMORY;
534 const UINT error = rail_write_get_app_id_resp_order(s, getAppidResp);
535 if (error != CHANNEL_RC_OK)
537 Stream_Free(s, TRUE);
540 return rail_server_send_pdu(context, s, TS_RAIL_ORDER_GET_APPID_RESP);
549static UINT rail_send_server_get_appid_resp_ex(RailServerContext* context,
552 if (!context || !getAppidRespEx)
553 return ERROR_INVALID_PARAMETER;
555 wStream* s = rail_pdu_init(RAIL_GET_APPID_RESP_EX_ORDER_LENGTH);
559 WLog_ERR(TAG,
"rail_pdu_init failed!");
560 return CHANNEL_RC_NO_MEMORY;
563 const UINT error = rail_write_get_appid_resp_ex_order(s, getAppidRespEx);
564 if (error != CHANNEL_RC_OK)
566 Stream_Free(s, TRUE);
569 return rail_server_send_pdu(context, s, TS_RAIL_ORDER_GET_APPID_RESP_EX);
580 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_CLIENT_STATUS_ORDER_LENGTH))
581 return ERROR_INVALID_DATA;
583 Stream_Read_UINT32(s, clientStatus->flags);
584 return CHANNEL_RC_OK;
597 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_EXEC_ORDER_LENGTH))
598 return ERROR_INVALID_DATA;
600 exec->flags = Stream_Get_UINT16(s);
601 const UINT16 exeLen = Stream_Get_UINT16(s);
602 const UINT16 workLen = Stream_Get_UINT16(s);
603 const UINT16 argLen = Stream_Get_UINT16(s);
605 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)exeLen + workLen + argLen))
606 return ERROR_INVALID_DATA;
610 const size_t len = exeLen /
sizeof(WCHAR);
611 exec->RemoteApplicationProgram = args[0] =
612 Stream_Read_UTF16_String_As_UTF8(s, len,
nullptr);
613 if (!exec->RemoteApplicationProgram)
618 const size_t len = workLen /
sizeof(WCHAR);
619 exec->RemoteApplicationWorkingDir = args[1] =
620 Stream_Read_UTF16_String_As_UTF8(s, len,
nullptr);
621 if (!exec->RemoteApplicationWorkingDir)
626 const size_t len = argLen /
sizeof(WCHAR);
627 exec->RemoteApplicationArguments = args[2] =
628 Stream_Read_UTF16_String_As_UTF8(s, len,
nullptr);
629 if (!exec->RemoteApplicationArguments)
633 return CHANNEL_RC_OK;
639 return ERROR_INTERNAL_ERROR;
652 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_ACTIVATE_ORDER_LENGTH))
653 return ERROR_INVALID_DATA;
655 Stream_Read_UINT32(s, activate->windowId);
656 Stream_Read_UINT8(s, enabled);
657 activate->enabled = (enabled != 0);
658 return CHANNEL_RC_OK;
669 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_SYSMENU_ORDER_LENGTH))
670 return ERROR_INVALID_DATA;
672 Stream_Read_UINT32(s, sysmenu->windowId);
673 Stream_Read_INT16(s, sysmenu->left);
674 Stream_Read_INT16(s, sysmenu->top);
675 return CHANNEL_RC_OK;
686 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_SYSCOMMAND_ORDER_LENGTH))
687 return ERROR_INVALID_DATA;
689 Stream_Read_UINT32(s, syscommand->windowId);
690 Stream_Read_UINT16(s, syscommand->command);
691 return CHANNEL_RC_OK;
702 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_NOTIFY_EVENT_ORDER_LENGTH))
703 return ERROR_INVALID_DATA;
705 Stream_Read_UINT32(s, notifyEvent->windowId);
706 Stream_Read_UINT32(s, notifyEvent->notifyIconId);
707 Stream_Read_UINT32(s, notifyEvent->message);
708 return CHANNEL_RC_OK;
719 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_GET_APPID_REQ_ORDER_LENGTH))
720 return ERROR_INVALID_DATA;
722 Stream_Read_UINT32(s, getAppidReq->windowId);
723 return CHANNEL_RC_OK;
734 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_WINDOW_MOVE_ORDER_LENGTH))
735 return ERROR_INVALID_DATA;
737 Stream_Read_UINT32(s, windowMove->windowId);
738 Stream_Read_INT16(s, windowMove->left);
739 Stream_Read_INT16(s, windowMove->top);
740 Stream_Read_INT16(s, windowMove->right);
741 Stream_Read_INT16(s, windowMove->bottom);
742 return CHANNEL_RC_OK;
753 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_SNAP_ARRANGE_ORDER_LENGTH))
754 return ERROR_INVALID_DATA;
756 Stream_Read_UINT32(s, snapArrange->windowId);
757 Stream_Read_INT16(s, snapArrange->left);
758 Stream_Read_INT16(s, snapArrange->top);
759 Stream_Read_INT16(s, snapArrange->right);
760 Stream_Read_INT16(s, snapArrange->bottom);
761 return CHANNEL_RC_OK;
772 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_LANGBAR_INFO_ORDER_LENGTH))
773 return ERROR_INVALID_DATA;
775 Stream_Read_UINT32(s, langbarInfo->languageBarStatus);
776 return CHANNEL_RC_OK;
785static UINT rail_read_language_ime_info_order(
wStream* s,
788 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_LANGUAGEIME_INFO_ORDER_LENGTH))
789 return ERROR_INVALID_DATA;
791 Stream_Read_UINT32(s, languageImeInfo->ProfileType);
792 Stream_Read_UINT16(s, languageImeInfo->LanguageID);
794 s, &languageImeInfo->LanguageProfileCLSID,
795 sizeof(languageImeInfo->LanguageProfileCLSID));
796 Stream_Read(s, &languageImeInfo->ProfileGUID,
797 sizeof(languageImeInfo->ProfileGUID));
798 Stream_Read_UINT32(s, languageImeInfo->KeyboardLayout);
799 return CHANNEL_RC_OK;
808static UINT rail_read_compartment_info_order(
wStream* s,
811 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_COMPARTMENT_INFO_ORDER_LENGTH))
812 return ERROR_INVALID_DATA;
814 Stream_Read_UINT32(s, compartmentInfo->ImeState);
815 Stream_Read_UINT32(s, compartmentInfo->ImeConvMode);
816 Stream_Read_UINT32(s, compartmentInfo->ImeSentenceMode);
817 Stream_Read_UINT32(s, compartmentInfo->KanaMode);
818 return CHANNEL_RC_OK;
831 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_CLOAK_ORDER_LENGTH))
832 return ERROR_INVALID_DATA;
834 Stream_Read_UINT32(s, cloak->windowId);
835 Stream_Read_UINT8(s, cloaked);
836 cloak->cloak = (cloaked != 0);
837 return CHANNEL_RC_OK;
846static UINT rail_recv_client_handshake_order(RailServerContext* context,
849 UINT error = CHANNEL_RC_OK;
851 if (!context || !handshake || !s)
852 return ERROR_INVALID_PARAMETER;
854 if ((error = rail_read_handshake_order(s, handshake)))
856 WLog_ERR(TAG,
"rail_read_handshake_order failed with error %" PRIu32
"!", error);
860 IFCALLRET(context->ClientHandshake, error, context, handshake);
863 WLog_ERR(TAG,
"context.ClientHandshake failed with error %" PRIu32
"", error);
874static UINT rail_recv_client_client_status_order(RailServerContext* context,
877 UINT error = CHANNEL_RC_OK;
879 if (!context || !clientStatus || !s)
880 return ERROR_INVALID_PARAMETER;
882 if ((error = rail_read_client_status_order(s, clientStatus)))
884 WLog_ERR(TAG,
"rail_read_client_status_order failed with error %" PRIu32
"!", error);
888 IFCALLRET(context->ClientClientStatus, error, context, clientStatus);
891 WLog_ERR(TAG,
"context.ClientClientStatus failed with error %" PRIu32
"", error);
902static UINT rail_recv_client_exec_order(RailServerContext* context,
wStream* s)
904 char* args[3] = WINPR_C_ARRAY_INIT;
908 return ERROR_INVALID_PARAMETER;
910 UINT error = rail_read_exec_order(s, &exec, args);
913 WLog_ERR(TAG,
"rail_read_client_status_order failed with error %" PRIu32
"!", error);
917 IFCALLRET(context->ClientExec, error, context, &exec);
920 WLog_ERR(TAG,
"context.Exec failed with error %" PRIu32
"", error);
934static UINT rail_recv_client_sysparam_order(RailServerContext* context,
937 if (!context || !sysparam || !s)
938 return ERROR_INVALID_PARAMETER;
940 const BOOL extendedSpiSupported = rail_is_extended_spi_supported(context->priv->channelFlags);
941 UINT error = rail_read_sysparam_order(s, sysparam, extendedSpiSupported);
942 if (error != CHANNEL_RC_OK)
944 WLog_ERR(TAG,
"rail_read_sysparam_order failed with error %" PRIu32
"!", error);
948 IFCALLRET(context->ClientSysparam, error, context, sysparam);
951 WLog_ERR(TAG,
"context.ClientSysparam failed with error %" PRIu32
"", error);
962static UINT rail_recv_client_activate_order(RailServerContext* context,
965 UINT error = CHANNEL_RC_OK;
967 if (!context || !activate || !s)
968 return ERROR_INVALID_PARAMETER;
970 if ((error = rail_read_activate_order(s, activate)))
972 WLog_ERR(TAG,
"rail_read_activate_order failed with error %" PRIu32
"!", error);
976 IFCALLRET(context->ClientActivate, error, context, activate);
979 WLog_ERR(TAG,
"context.ClientActivate failed with error %" PRIu32
"", error);
990static UINT rail_recv_client_sysmenu_order(RailServerContext* context,
RAIL_SYSMENU_ORDER* sysmenu,
993 UINT error = CHANNEL_RC_OK;
995 if (!context || !sysmenu || !s)
996 return ERROR_INVALID_PARAMETER;
998 if ((error = rail_read_sysmenu_order(s, sysmenu)))
1000 WLog_ERR(TAG,
"rail_read_sysmenu_order failed with error %" PRIu32
"!", error);
1004 IFCALLRET(context->ClientSysmenu, error, context, sysmenu);
1007 WLog_ERR(TAG,
"context.ClientSysmenu failed with error %" PRIu32
"", error);
1018static UINT rail_recv_client_syscommand_order(RailServerContext* context,
1021 UINT error = CHANNEL_RC_OK;
1023 if (!context || !syscommand || !s)
1024 return ERROR_INVALID_PARAMETER;
1026 if ((error = rail_read_syscommand_order(s, syscommand)))
1028 WLog_ERR(TAG,
"rail_read_syscommand_order failed with error %" PRIu32
"!", error);
1032 IFCALLRET(context->ClientSyscommand, error, context, syscommand);
1035 WLog_ERR(TAG,
"context.ClientSyscommand failed with error %" PRIu32
"", error);
1046static UINT rail_recv_client_notify_event_order(RailServerContext* context,
1049 UINT error = CHANNEL_RC_OK;
1051 if (!context || !notifyEvent || !s)
1052 return ERROR_INVALID_PARAMETER;
1054 if ((error = rail_read_notify_event_order(s, notifyEvent)))
1056 WLog_ERR(TAG,
"rail_read_notify_event_order failed with error %" PRIu32
"!", error);
1060 IFCALLRET(context->ClientNotifyEvent, error, context, notifyEvent);
1063 WLog_ERR(TAG,
"context.ClientNotifyEvent failed with error %" PRIu32
"", error);
1074static UINT rail_recv_client_window_move_order(RailServerContext* context,
1077 UINT error = CHANNEL_RC_OK;
1079 if (!context || !windowMove || !s)
1080 return ERROR_INVALID_PARAMETER;
1082 if ((error = rail_read_window_move_order(s, windowMove)))
1084 WLog_ERR(TAG,
"rail_read_window_move_order failed with error %" PRIu32
"!", error);
1088 IFCALLRET(context->ClientWindowMove, error, context, windowMove);
1091 WLog_ERR(TAG,
"context.ClientWindowMove failed with error %" PRIu32
"", error);
1102static UINT rail_recv_client_snap_arrange_order(RailServerContext* context,
1105 UINT error = CHANNEL_RC_OK;
1107 if (!context || !snapArrange || !s)
1108 return ERROR_INVALID_PARAMETER;
1110 if ((error = rail_read_snap_arange_order(s, snapArrange)))
1112 WLog_ERR(TAG,
"rail_read_snap_arange_order failed with error %" PRIu32
"!", error);
1116 IFCALLRET(context->ClientSnapArrange, error, context, snapArrange);
1119 WLog_ERR(TAG,
"context.ClientSnapArrange failed with error %" PRIu32
"", error);
1130static UINT rail_recv_client_get_appid_req_order(RailServerContext* context,
1133 UINT error = CHANNEL_RC_OK;
1135 if (!context || !getAppidReq || !s)
1136 return ERROR_INVALID_PARAMETER;
1138 if ((error = rail_read_get_appid_req_order(s, getAppidReq)))
1140 WLog_ERR(TAG,
"rail_read_get_appid_req_order failed with error %" PRIu32
"!", error);
1144 IFCALLRET(context->ClientGetAppidReq, error, context, getAppidReq);
1147 WLog_ERR(TAG,
"context.ClientGetAppidReq failed with error %" PRIu32
"", error);
1158static UINT rail_recv_client_langbar_info_order(RailServerContext* context,
1161 UINT error = CHANNEL_RC_OK;
1163 if (!context || !langbarInfo || !s)
1164 return ERROR_INVALID_PARAMETER;
1166 if ((error = rail_read_langbar_info_order(s, langbarInfo)))
1168 WLog_ERR(TAG,
"rail_read_langbar_info_order failed with error %" PRIu32
"!", error);
1172 IFCALLRET(context->ClientLangbarInfo, error, context, langbarInfo);
1175 WLog_ERR(TAG,
"context.ClientLangbarInfo failed with error %" PRIu32
"", error);
1186static UINT rail_recv_client_language_ime_info_order(RailServerContext* context,
1190 UINT error = CHANNEL_RC_OK;
1192 if (!context || !languageImeInfo || !s)
1193 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,
1219 UINT error = CHANNEL_RC_OK;
1221 if (!context || !compartmentInfo || !s)
1222 return ERROR_INVALID_PARAMETER;
1224 if ((error = rail_read_compartment_info_order(s, compartmentInfo)))
1226 WLog_ERR(TAG,
"rail_read_compartment_info_order failed with error %" PRIu32
"!", error);
1230 IFCALLRET(context->ClientCompartmentInfo, error, context, compartmentInfo);
1233 WLog_ERR(TAG,
"context.ClientCompartmentInfo failed with error %" PRIu32
"", error);
1244static UINT rail_recv_client_cloak_order(RailServerContext* context,
RAIL_CLOAK* cloak,
wStream* s)
1246 UINT error = CHANNEL_RC_OK;
1248 if (!context || !cloak || !s)
1249 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;
1478RailServerContext* rail_server_context_new(HANDLE vcm)
1480 RailServerContext* context =
nullptr;
1481 RailServerPrivate* priv =
nullptr;
1482 context = (RailServerContext*)calloc(1,
sizeof(RailServerContext));
1486 WLog_ERR(TAG,
"calloc failed!");
1491 context->Start = rail_server_start;
1492 context->Stop = rail_server_stop;
1493 context->ServerHandshake = rail_send_server_handshake;
1494 context->ServerHandshakeEx = rail_send_server_handshake_ex;
1495 context->ServerSysparam = rail_send_server_sysparam;
1496 context->ServerLocalMoveSize = rail_send_server_local_move_size;
1497 context->ServerMinMaxInfo = rail_send_server_min_max_info;
1498 context->ServerTaskbarInfo = rail_send_server_taskbar_info;
1499 context->ServerLangbarInfo = rail_send_server_langbar_info;
1500 context->ServerExecResult = rail_send_server_exec_result;
1501 context->ServerGetAppidResp = rail_send_server_get_app_id_resp;
1502 context->ServerZOrderSync = rail_send_server_z_order_sync;
1503 context->ServerCloak = rail_send_server_cloak;
1504 context->ServerPowerDisplayRequest = rail_send_server_power_display_request;
1505 context->ServerGetAppidRespEx = rail_send_server_get_appid_resp_ex;
1506 context->priv = priv = (RailServerPrivate*)calloc(1,
sizeof(RailServerPrivate));
1510 WLog_ERR(TAG,
"calloc failed!");
1515 priv->input_stream = Stream_New(
nullptr, 4096);
1517 if (!priv->input_stream)
1519 WLog_ERR(TAG,
"Stream_New failed!");
1525 rail_server_context_free(context);
1529void rail_server_context_free(RailServerContext* context)
1532 Stream_Free(context->priv->input_stream, TRUE);
1534 free(context->priv);
1538void rail_server_set_handshake_ex_flags(RailServerContext* context, DWORD flags)
1540 WINPR_ASSERT(context);
1541 WINPR_ASSERT(context->priv);
1543 RailServerPrivate* priv = context->priv;
1544 priv->channelFlags = flags;
1547UINT rail_server_handle_messages(RailServerContext* context)
1549 char buffer[128] = WINPR_C_ARRAY_INIT;
1550 UINT status = CHANNEL_RC_OK;
1551 DWORD bytesReturned = 0;
1552 UINT16 orderType = 0;
1553 UINT16 orderLength = 0;
1554 RailServerPrivate* priv = context->priv;
1555 wStream* s = priv->input_stream;
1558 if (!Stream_EnsureRemainingCapacity(s, RAIL_PDU_HEADER_LENGTH))
1560 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed, RAIL_PDU_HEADER_LENGTH");
1561 return CHANNEL_RC_NO_MEMORY;
1564 if (!WTSVirtualChannelRead(priv->rail_channel, 0, Stream_Pointer(s), RAIL_PDU_HEADER_LENGTH,
1567 if (GetLastError() == ERROR_NO_DATA)
1568 return ERROR_NO_DATA;
1570 WLog_ERR(TAG,
"channel connection closed");
1571 return ERROR_INTERNAL_ERROR;
1575 if ((status = rail_read_pdu_header(s, &orderType, &orderLength)) != CHANNEL_RC_OK)
1577 WLog_ERR(TAG,
"rail_read_pdu_header failed with error %" PRIu32
"!", status);
1581 if (!Stream_EnsureRemainingCapacity(s, orderLength - RAIL_PDU_HEADER_LENGTH))
1584 "Stream_EnsureRemainingCapacity failed, orderLength - RAIL_PDU_HEADER_LENGTH");
1585 return CHANNEL_RC_NO_MEMORY;
1589 if (!WTSVirtualChannelRead(priv->rail_channel, 0, Stream_Pointer(s),
1590 orderLength - RAIL_PDU_HEADER_LENGTH, &bytesReturned))
1592 if (GetLastError() == ERROR_NO_DATA)
1593 return ERROR_NO_DATA;
1595 WLog_ERR(TAG,
"channel connection closed");
1596 return ERROR_INTERNAL_ERROR;
1599 WLog_DBG(TAG,
"Received %s PDU, length:%" PRIu16
"",
1600 rail_get_order_type_string_full(orderType, buffer,
sizeof(buffer)), orderLength);
1604 case TS_RAIL_ORDER_HANDSHAKE:
1607 return rail_recv_client_handshake_order(context, &handshake, s);
1610 case TS_RAIL_ORDER_CLIENTSTATUS:
1613 return rail_recv_client_client_status_order(context, &clientStatus, s);
1616 case TS_RAIL_ORDER_EXEC:
1617 return rail_recv_client_exec_order(context, s);
1619 case TS_RAIL_ORDER_SYSPARAM:
1622 return rail_recv_client_sysparam_order(context, &sysparam, s);
1625 case TS_RAIL_ORDER_ACTIVATE:
1628 return rail_recv_client_activate_order(context, &activate, s);
1631 case TS_RAIL_ORDER_SYSMENU:
1634 return rail_recv_client_sysmenu_order(context, &sysmenu, s);
1637 case TS_RAIL_ORDER_SYSCOMMAND:
1640 return rail_recv_client_syscommand_order(context, &syscommand, s);
1643 case TS_RAIL_ORDER_NOTIFY_EVENT:
1646 return rail_recv_client_notify_event_order(context, ¬ifyEvent, s);
1649 case TS_RAIL_ORDER_WINDOWMOVE:
1652 return rail_recv_client_window_move_order(context, &windowMove, s);
1655 case TS_RAIL_ORDER_SNAP_ARRANGE:
1658 return rail_recv_client_snap_arrange_order(context, &snapArrange, s);
1661 case TS_RAIL_ORDER_GET_APPID_REQ:
1664 return rail_recv_client_get_appid_req_order(context, &getAppidReq, s);
1667 case TS_RAIL_ORDER_LANGBARINFO:
1670 return rail_recv_client_langbar_info_order(context, &langbarInfo, s);
1673 case TS_RAIL_ORDER_LANGUAGEIMEINFO:
1676 return rail_recv_client_language_ime_info_order(context, &languageImeInfo, s);
1679 case TS_RAIL_ORDER_COMPARTMENTINFO:
1682 return rail_recv_client_compartment_info(context, &compartmentInfo, s);
1685 case TS_RAIL_ORDER_CLOAK:
1688 return rail_recv_client_cloak_order(context, &cloak, s);
1691 case TS_RAIL_ORDER_TEXTSCALEINFO:
1693 return rail_recv_client_text_scale_order(context, s);
1696 case TS_RAIL_ORDER_CARETBLINKINFO:
1698 return rail_recv_client_caret_blink(context, s);
1702 WLog_ERR(TAG,
"Unknown RAIL PDU order received.");
1703 return ERROR_INVALID_DATA;