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,
wStream* s)
848 UINT error = CHANNEL_RC_OK;
851 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,
wStream* s)
876 UINT error = CHANNEL_RC_OK;
879 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,
wStream* s)
937 return ERROR_INVALID_PARAMETER;
939 const BOOL extendedSpiSupported = rail_is_extended_spi_supported(context->priv->channelFlags);
942 UINT error = rail_read_sysparam_order(s, &sysparam, extendedSpiSupported);
943 if (error != CHANNEL_RC_OK)
945 free(sysparam.highContrast.colorScheme.string);
946 WLog_ERR(TAG,
"rail_read_sysparam_order failed with error %" PRIu32
"!", error);
950 IFCALLRET(context->ClientSysparam, error, context, &sysparam);
951 free(sysparam.highContrast.colorScheme.string);
954 WLog_ERR(TAG,
"context.ClientSysparam failed with error %" PRIu32
"", error);
965static UINT rail_recv_client_activate_order(RailServerContext* context,
wStream* s)
967 UINT error = CHANNEL_RC_OK;
970 return ERROR_INVALID_PARAMETER;
973 if ((error = rail_read_activate_order(s, &activate)))
975 WLog_ERR(TAG,
"rail_read_activate_order failed with error %" PRIu32
"!", error);
979 IFCALLRET(context->ClientActivate, error, context, &activate);
982 WLog_ERR(TAG,
"context.ClientActivate failed with error %" PRIu32
"", error);
993static UINT rail_recv_client_sysmenu_order(RailServerContext* context,
wStream* s)
995 UINT error = CHANNEL_RC_OK;
998 return ERROR_INVALID_PARAMETER;
1001 if ((error = rail_read_sysmenu_order(s, &sysmenu)))
1003 WLog_ERR(TAG,
"rail_read_sysmenu_order failed with error %" PRIu32
"!", error);
1007 IFCALLRET(context->ClientSysmenu, error, context, &sysmenu);
1010 WLog_ERR(TAG,
"context.ClientSysmenu failed with error %" PRIu32
"", error);
1021static UINT rail_recv_client_syscommand_order(RailServerContext* context,
wStream* s)
1023 UINT error = CHANNEL_RC_OK;
1026 return ERROR_INVALID_PARAMETER;
1029 if ((error = rail_read_syscommand_order(s, &syscommand)))
1031 WLog_ERR(TAG,
"rail_read_syscommand_order failed with error %" PRIu32
"!", error);
1035 IFCALLRET(context->ClientSyscommand, error, context, &syscommand);
1038 WLog_ERR(TAG,
"context.ClientSyscommand failed with error %" PRIu32
"", error);
1049static UINT rail_recv_client_notify_event_order(RailServerContext* context,
wStream* s)
1051 UINT error = CHANNEL_RC_OK;
1054 return ERROR_INVALID_PARAMETER;
1057 if ((error = rail_read_notify_event_order(s, ¬ifyEvent)))
1059 WLog_ERR(TAG,
"rail_read_notify_event_order failed with error %" PRIu32
"!", error);
1063 IFCALLRET(context->ClientNotifyEvent, error, context, ¬ifyEvent);
1066 WLog_ERR(TAG,
"context.ClientNotifyEvent failed with error %" PRIu32
"", error);
1077static UINT rail_recv_client_window_move_order(RailServerContext* context,
wStream* s)
1079 UINT error = CHANNEL_RC_OK;
1082 return ERROR_INVALID_PARAMETER;
1085 if ((error = rail_read_window_move_order(s, &windowMove)))
1087 WLog_ERR(TAG,
"rail_read_window_move_order failed with error %" PRIu32
"!", error);
1091 IFCALLRET(context->ClientWindowMove, error, context, &windowMove);
1094 WLog_ERR(TAG,
"context.ClientWindowMove failed with error %" PRIu32
"", error);
1105static UINT rail_recv_client_snap_arrange_order(RailServerContext* context,
wStream* s)
1107 UINT error = CHANNEL_RC_OK;
1110 return ERROR_INVALID_PARAMETER;
1113 if ((error = rail_read_snap_arange_order(s, &snapArrange)))
1115 WLog_ERR(TAG,
"rail_read_snap_arange_order failed with error %" PRIu32
"!", error);
1119 IFCALLRET(context->ClientSnapArrange, error, context, &snapArrange);
1122 WLog_ERR(TAG,
"context.ClientSnapArrange failed with error %" PRIu32
"", error);
1133static UINT rail_recv_client_get_appid_req_order(RailServerContext* context,
wStream* s)
1135 UINT error = CHANNEL_RC_OK;
1138 return ERROR_INVALID_PARAMETER;
1141 if ((error = rail_read_get_appid_req_order(s, &getAppidReq)))
1143 WLog_ERR(TAG,
"rail_read_get_appid_req_order failed with error %" PRIu32
"!", error);
1147 IFCALLRET(context->ClientGetAppidReq, error, context, &getAppidReq);
1150 WLog_ERR(TAG,
"context.ClientGetAppidReq failed with error %" PRIu32
"", error);
1161static UINT rail_recv_client_langbar_info_order(RailServerContext* context,
wStream* s)
1163 UINT error = CHANNEL_RC_OK;
1166 return ERROR_INVALID_PARAMETER;
1169 if ((error = rail_read_langbar_info_order(s, &langbarInfo)))
1171 WLog_ERR(TAG,
"rail_read_langbar_info_order failed with error %" PRIu32
"!", error);
1175 IFCALLRET(context->ClientLangbarInfo, error, context, &langbarInfo);
1178 WLog_ERR(TAG,
"context.ClientLangbarInfo failed with error %" PRIu32
"", error);
1189static UINT rail_recv_client_language_ime_info_order(RailServerContext* context,
wStream* s)
1191 UINT error = CHANNEL_RC_OK;
1194 return ERROR_INVALID_PARAMETER;
1197 if ((error = rail_read_language_ime_info_order(s, &languageImeInfo)))
1199 WLog_ERR(TAG,
"rail_read_language_ime_info_order failed with error %" PRIu32
"!", error);
1203 IFCALLRET(context->ClientLanguageImeInfo, error, context, &languageImeInfo);
1206 WLog_ERR(TAG,
"context.ClientLanguageImeInfo failed with error %" PRIu32
"", error);
1217static UINT rail_recv_client_compartment_info(RailServerContext* context,
wStream* s)
1219 UINT error = CHANNEL_RC_OK;
1222 return ERROR_INVALID_PARAMETER;
1225 if ((error = rail_read_compartment_info_order(s, &compartmentInfo)))
1227 WLog_ERR(TAG,
"rail_read_compartment_info_order failed with error %" PRIu32
"!", error);
1231 IFCALLRET(context->ClientCompartmentInfo, error, context, &compartmentInfo);
1234 WLog_ERR(TAG,
"context.ClientCompartmentInfo failed with error %" PRIu32
"", error);
1245static UINT rail_recv_client_cloak_order(RailServerContext* context,
wStream* s)
1247 UINT error = CHANNEL_RC_OK;
1250 return ERROR_INVALID_PARAMETER;
1253 if ((error = rail_read_cloak_order(s, &cloak)))
1255 WLog_ERR(TAG,
"rail_read_cloak_order failed with error %" PRIu32
"!", error);
1259 IFCALLRET(context->ClientCloak, error, context, &cloak);
1262 WLog_ERR(TAG,
"context.Cloak failed with error %" PRIu32
"", error);
1268static UINT rail_recv_client_text_scale_order(RailServerContext* context,
wStream* s)
1270 UINT error = CHANNEL_RC_OK;
1271 UINT32 TextScaleFactor = 0;
1274 return ERROR_INVALID_PARAMETER;
1276 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1277 return ERROR_INVALID_DATA;
1279 Stream_Read_UINT32(s, TextScaleFactor);
1280 IFCALLRET(context->ClientTextScale, error, context, TextScaleFactor);
1283 WLog_ERR(TAG,
"context.TextScale failed with error %" PRIu32
"", error);
1289static UINT rail_recv_client_caret_blink(RailServerContext* context,
wStream* s)
1291 UINT error = CHANNEL_RC_OK;
1292 UINT32 CaretBlinkRate = 0;
1295 return ERROR_INVALID_PARAMETER;
1297 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1298 return ERROR_INVALID_DATA;
1300 Stream_Read_UINT32(s, CaretBlinkRate);
1301 IFCALLRET(context->ClientCaretBlinkRate, error, context, CaretBlinkRate);
1304 WLog_ERR(TAG,
"context.CaretBlinkRate failed with error %" PRIu32
"", error);
1310static DWORD WINAPI rail_server_thread(LPVOID arg)
1312 RailServerContext* context = (RailServerContext*)arg;
1313 WINPR_ASSERT(context);
1315 RailServerPrivate* priv = context->priv;
1321 UINT error = CHANNEL_RC_OK;
1322 events[nCount++] = priv->channelEvent;
1323 events[nCount++] = priv->stopEvent;
1327 status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
1329 if (status == WAIT_FAILED)
1331 error = GetLastError();
1332 WLog_ERR(TAG,
"WaitForMultipleObjects failed with error %" PRIu32
"!", error);
1336 status = WaitForSingleObject(context->priv->stopEvent, 0);
1338 if (status == WAIT_FAILED)
1340 error = GetLastError();
1341 WLog_ERR(TAG,
"WaitForSingleObject failed with error %" PRIu32
"!", error);
1345 if (status == WAIT_OBJECT_0)
1348 status = WaitForSingleObject(context->priv->channelEvent, 0);
1350 if (status == WAIT_FAILED)
1352 error = GetLastError();
1355 "WaitForSingleObject(context->priv->channelEvent, 0) failed with error %" PRIu32
1361 if (status == WAIT_OBJECT_0)
1363 if ((error = rail_server_handle_messages(context)))
1365 WLog_ERR(TAG,
"rail_server_handle_messages failed with error %" PRIu32
"", error);
1371 if (error && context->rdpcontext)
1372 setChannelError(context->rdpcontext, error,
"rail_server_thread reported an error");
1384static UINT rail_server_start(RailServerContext* context)
1386 void* buffer =
nullptr;
1387 DWORD bytesReturned = 0;
1388 UINT error = ERROR_INTERNAL_ERROR;
1390 WINPR_ASSERT(context);
1392 RailServerPrivate* priv = context->priv;
1395 priv->rail_channel =
1396 WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, RAIL_SVC_CHANNEL_NAME);
1398 if (!priv->rail_channel)
1400 WLog_ERR(TAG,
"WTSVirtualChannelOpen failed!");
1404 if (!WTSVirtualChannelQuery(priv->rail_channel, WTSVirtualEventHandle, &buffer,
1406 (bytesReturned !=
sizeof(HANDLE)))
1409 "error during WTSVirtualChannelQuery(WTSVirtualEventHandle) or invalid returned "
1410 "size(%" PRIu32
")",
1414 WTSFreeMemory(buffer);
1419 priv->channelEvent = *(HANDLE*)buffer;
1420 WTSFreeMemory(buffer);
1421 context->priv->stopEvent = CreateEvent(
nullptr, TRUE, FALSE,
nullptr);
1423 if (!context->priv->stopEvent)
1425 WLog_ERR(TAG,
"CreateEvent failed!");
1429 context->priv->thread =
1430 CreateThread(
nullptr, 0, rail_server_thread, (
void*)context, 0,
nullptr);
1432 if (!context->priv->thread)
1434 WLog_ERR(TAG,
"CreateThread failed!");
1435 goto out_stop_event;
1438 return CHANNEL_RC_OK;
1440 (void)CloseHandle(context->priv->stopEvent);
1441 context->priv->stopEvent =
nullptr;
1443 (void)WTSVirtualChannelClose(context->priv->rail_channel);
1444 context->priv->rail_channel =
nullptr;
1449static BOOL rail_server_stop(RailServerContext* context)
1451 WINPR_ASSERT(context);
1452 RailServerPrivate* priv = context->priv;
1456 (void)SetEvent(priv->stopEvent);
1458 if (WaitForSingleObject(priv->thread, INFINITE) == WAIT_FAILED)
1460 WLog_ERR(TAG,
"WaitForSingleObject failed with error %" PRIu32
"", GetLastError());
1464 (void)CloseHandle(priv->thread);
1465 (void)CloseHandle(priv->stopEvent);
1466 priv->thread =
nullptr;
1467 priv->stopEvent =
nullptr;
1470 if (priv->rail_channel)
1472 (void)WTSVirtualChannelClose(priv->rail_channel);
1473 priv->rail_channel =
nullptr;
1476 priv->channelEvent =
nullptr;
1480RailServerContext* rail_server_context_new(HANDLE vcm)
1482 RailServerContext* context =
nullptr;
1483 RailServerPrivate* priv =
nullptr;
1484 context = (RailServerContext*)calloc(1,
sizeof(RailServerContext));
1488 WLog_ERR(TAG,
"calloc failed!");
1493 context->Start = rail_server_start;
1494 context->Stop = rail_server_stop;
1495 context->ServerHandshake = rail_send_server_handshake;
1496 context->ServerHandshakeEx = rail_send_server_handshake_ex;
1497 context->ServerSysparam = rail_send_server_sysparam;
1498 context->ServerLocalMoveSize = rail_send_server_local_move_size;
1499 context->ServerMinMaxInfo = rail_send_server_min_max_info;
1500 context->ServerTaskbarInfo = rail_send_server_taskbar_info;
1501 context->ServerLangbarInfo = rail_send_server_langbar_info;
1502 context->ServerExecResult = rail_send_server_exec_result;
1503 context->ServerGetAppidResp = rail_send_server_get_app_id_resp;
1504 context->ServerZOrderSync = rail_send_server_z_order_sync;
1505 context->ServerCloak = rail_send_server_cloak;
1506 context->ServerPowerDisplayRequest = rail_send_server_power_display_request;
1507 context->ServerGetAppidRespEx = rail_send_server_get_appid_resp_ex;
1508 context->priv = priv = (RailServerPrivate*)calloc(1,
sizeof(RailServerPrivate));
1512 WLog_ERR(TAG,
"calloc failed!");
1517 priv->input_stream = Stream_New(
nullptr, 4096);
1519 if (!priv->input_stream)
1521 WLog_ERR(TAG,
"Stream_New failed!");
1527 rail_server_context_free(context);
1531void rail_server_context_free(RailServerContext* context)
1534 Stream_Free(context->priv->input_stream, TRUE);
1536 free(context->priv);
1540void rail_server_set_handshake_ex_flags(RailServerContext* context, DWORD flags)
1542 WINPR_ASSERT(context);
1543 WINPR_ASSERT(context->priv);
1545 RailServerPrivate* priv = context->priv;
1546 priv->channelFlags = flags;
1549UINT rail_server_handle_messages(RailServerContext* context)
1551 char buffer[128] = WINPR_C_ARRAY_INIT;
1552 UINT status = CHANNEL_RC_OK;
1553 DWORD bytesReturned = 0;
1554 UINT16 orderType = 0;
1555 UINT16 orderLength = 0;
1556 RailServerPrivate* priv = context->priv;
1557 wStream* s = priv->input_stream;
1560 if (!Stream_EnsureRemainingCapacity(s, RAIL_PDU_HEADER_LENGTH))
1562 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed, RAIL_PDU_HEADER_LENGTH");
1563 return CHANNEL_RC_NO_MEMORY;
1566 if (!WTSVirtualChannelRead(priv->rail_channel, 0, Stream_Pointer(s), RAIL_PDU_HEADER_LENGTH,
1569 if (GetLastError() == ERROR_NO_DATA)
1570 return ERROR_NO_DATA;
1572 WLog_ERR(TAG,
"channel connection closed");
1573 return ERROR_INTERNAL_ERROR;
1577 if ((status = rail_read_pdu_header(s, &orderType, &orderLength)) != CHANNEL_RC_OK)
1579 WLog_ERR(TAG,
"rail_read_pdu_header failed with error %" PRIu32
"!", status);
1583 if (!Stream_EnsureRemainingCapacity(s, orderLength - RAIL_PDU_HEADER_LENGTH))
1586 "Stream_EnsureRemainingCapacity failed, orderLength - RAIL_PDU_HEADER_LENGTH");
1587 return CHANNEL_RC_NO_MEMORY;
1591 if (!WTSVirtualChannelRead(priv->rail_channel, 0, Stream_Pointer(s),
1592 orderLength - RAIL_PDU_HEADER_LENGTH, &bytesReturned))
1594 if (GetLastError() == ERROR_NO_DATA)
1595 return ERROR_NO_DATA;
1597 WLog_ERR(TAG,
"channel connection closed");
1598 return ERROR_INTERNAL_ERROR;
1601 WLog_DBG(TAG,
"Received %s PDU, length:%" PRIu16
"",
1602 rail_get_order_type_string_full(orderType, buffer,
sizeof(buffer)), orderLength);
1606 case TS_RAIL_ORDER_HANDSHAKE:
1607 return rail_recv_client_handshake_order(context, s);
1609 case TS_RAIL_ORDER_CLIENTSTATUS:
1610 return rail_recv_client_client_status_order(context, s);
1612 case TS_RAIL_ORDER_EXEC:
1613 return rail_recv_client_exec_order(context, s);
1615 case TS_RAIL_ORDER_SYSPARAM:
1616 return rail_recv_client_sysparam_order(context, s);
1618 case TS_RAIL_ORDER_ACTIVATE:
1619 return rail_recv_client_activate_order(context, s);
1621 case TS_RAIL_ORDER_SYSMENU:
1622 return rail_recv_client_sysmenu_order(context, s);
1624 case TS_RAIL_ORDER_SYSCOMMAND:
1625 return rail_recv_client_syscommand_order(context, s);
1627 case TS_RAIL_ORDER_NOTIFY_EVENT:
1628 return rail_recv_client_notify_event_order(context, s);
1630 case TS_RAIL_ORDER_WINDOWMOVE:
1631 return rail_recv_client_window_move_order(context, s);
1633 case TS_RAIL_ORDER_SNAP_ARRANGE:
1634 return rail_recv_client_snap_arrange_order(context, s);
1636 case TS_RAIL_ORDER_GET_APPID_REQ:
1637 return rail_recv_client_get_appid_req_order(context, s);
1639 case TS_RAIL_ORDER_LANGBARINFO:
1640 return rail_recv_client_langbar_info_order(context, s);
1642 case TS_RAIL_ORDER_LANGUAGEIMEINFO:
1643 return rail_recv_client_language_ime_info_order(context, s);
1645 case TS_RAIL_ORDER_COMPARTMENTINFO:
1646 return rail_recv_client_compartment_info(context, s);
1648 case TS_RAIL_ORDER_CLOAK:
1649 return rail_recv_client_cloak_order(context, s);
1651 case TS_RAIL_ORDER_TEXTSCALEINFO:
1652 return rail_recv_client_text_scale_order(context, s);
1654 case TS_RAIL_ORDER_CARETBLINKINFO:
1655 return rail_recv_client_caret_blink(context, s);
1658 WLog_ERR(TAG,
"Unknown RAIL PDU order received.");
1659 return ERROR_INVALID_DATA;