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")
41static UINT rail_send(RailServerContext* context,
wStream* s, ULONG length)
43 UINT status = CHANNEL_RC_OK;
47 return CHANNEL_RC_BAD_INIT_HANDLE;
49 if (!WTSVirtualChannelWrite(context->priv->rail_channel, Stream_BufferAs(s,
char), length,
52 WLog_ERR(TAG,
"WTSVirtualChannelWrite failed!");
53 status = ERROR_INTERNAL_ERROR;
64static UINT rail_server_send_pdu(RailServerContext* context,
wStream* s, UINT16 orderType)
66 char buffer[128] = WINPR_C_ARRAY_INIT;
67 UINT16 orderLength = 0;
70 return ERROR_INVALID_PARAMETER;
72 orderLength = (UINT16)Stream_GetPosition(s);
73 Stream_SetPosition(s, 0);
74 rail_write_pdu_header(s, orderType, orderLength);
75 Stream_SetPosition(s, orderLength);
76 WLog_DBG(TAG,
"Sending %s PDU, length: %" PRIu16
"",
77 rail_get_order_type_string_full(orderType, buffer,
sizeof(buffer)), orderLength);
78 return rail_send(context, s, orderLength);
86static UINT rail_write_local_move_size_order(
wStream* s,
89 if (!s || !localMoveSize)
90 return ERROR_INVALID_PARAMETER;
92 Stream_Write_UINT32(s, localMoveSize->windowId);
93 Stream_Write_UINT16(s, localMoveSize->isMoveSizeStart ? 1 : 0);
94 Stream_Write_UINT16(s, localMoveSize->moveSizeType);
95 Stream_Write_INT16(s, localMoveSize->posX);
96 Stream_Write_INT16(s, localMoveSize->posY);
107 if (!s || !minMaxInfo)
108 return ERROR_INVALID_PARAMETER;
110 Stream_Write_UINT32(s, minMaxInfo->windowId);
111 Stream_Write_INT16(s, minMaxInfo->maxWidth);
112 Stream_Write_INT16(s, minMaxInfo->maxHeight);
113 Stream_Write_INT16(s, minMaxInfo->maxPosX);
114 Stream_Write_INT16(s, minMaxInfo->maxPosY);
115 Stream_Write_INT16(s, minMaxInfo->minTrackWidth);
116 Stream_Write_INT16(s, minMaxInfo->minTrackHeight);
117 Stream_Write_INT16(s, minMaxInfo->maxTrackWidth);
118 Stream_Write_INT16(s, minMaxInfo->maxTrackHeight);
119 return ERROR_SUCCESS;
129 if (!s || !taskbarInfo)
130 return ERROR_INVALID_PARAMETER;
132 Stream_Write_UINT32(s, taskbarInfo->TaskbarMessage);
133 Stream_Write_UINT32(s, taskbarInfo->WindowIdTab);
134 Stream_Write_UINT32(s, taskbarInfo->Body);
135 return ERROR_SUCCESS;
145 if (!s || !langbarInfo)
146 return ERROR_INVALID_PARAMETER;
148 Stream_Write_UINT32(s, langbarInfo->languageBarStatus);
149 return ERROR_SUCCESS;
159 if (!s || !execResult)
160 return ERROR_INVALID_PARAMETER;
162 if (execResult->exeOrFile.length > 520 || execResult->exeOrFile.length < 1)
163 return ERROR_INVALID_DATA;
165 Stream_Write_UINT16(s, execResult->flags);
166 Stream_Write_UINT16(s, execResult->execResult);
167 Stream_Write_UINT32(s, execResult->rawResult);
168 Stream_Write_UINT16(s, 0);
169 Stream_Write_UINT16(s, execResult->exeOrFile.length);
170 Stream_Write(s, execResult->exeOrFile.string,
171 execResult->exeOrFile.length);
172 return ERROR_SUCCESS;
182 if (!s || !zOrderSync)
183 return ERROR_INVALID_PARAMETER;
185 Stream_Write_UINT32(s, zOrderSync->windowIdMarker);
186 return ERROR_SUCCESS;
197 return ERROR_INVALID_PARAMETER;
199 Stream_Write_UINT32(s, cloak->windowId);
200 Stream_Write_UINT8(s, cloak->cloak ? 1 : 0);
201 return ERROR_SUCCESS;
210rail_write_power_display_request_order(
wStream* s,
213 if (!s || !powerDisplayRequest)
214 return ERROR_INVALID_PARAMETER;
216 Stream_Write_UINT32(s, powerDisplayRequest->active ? 1 : 0);
217 return ERROR_SUCCESS;
225static UINT rail_write_get_app_id_resp_order(
wStream* s,
228 if (!s || !getAppidResp)
229 return ERROR_INVALID_PARAMETER;
231 Stream_Write_UINT32(s, getAppidResp->windowId);
232 Stream_Write_UTF16_String(
233 s, getAppidResp->applicationId,
234 ARRAYSIZE(getAppidResp->applicationId));
235 return ERROR_SUCCESS;
243static UINT rail_write_get_appid_resp_ex_order(
wStream* s,
246 if (!s || !getAppidRespEx)
247 return ERROR_INVALID_PARAMETER;
249 Stream_Write_UINT32(s, getAppidRespEx->windowID);
250 Stream_Write_UTF16_String(
251 s, getAppidRespEx->applicationID,
252 ARRAYSIZE(getAppidRespEx->applicationID));
253 Stream_Write_UINT32(s, getAppidRespEx->processId);
254 Stream_Write_UTF16_String(
255 s, getAppidRespEx->processImageName,
256 ARRAYSIZE(getAppidRespEx->processImageName));
257 return ERROR_SUCCESS;
265static UINT rail_send_server_handshake(RailServerContext* context,
271 if (!context || !handshake)
272 return ERROR_INVALID_PARAMETER;
274 s = rail_pdu_init(RAIL_HANDSHAKE_ORDER_LENGTH);
278 WLog_ERR(TAG,
"rail_pdu_init failed!");
279 return CHANNEL_RC_NO_MEMORY;
282 rail_write_handshake_order(s, handshake);
283 error = rail_server_send_pdu(context, s, TS_RAIL_ORDER_HANDSHAKE);
284 Stream_Free(s, TRUE);
293static UINT rail_send_server_handshake_ex(RailServerContext* context,
299 if (!context || !handshakeEx || !context->priv)
300 return ERROR_INVALID_PARAMETER;
302 s = rail_pdu_init(RAIL_HANDSHAKE_EX_ORDER_LENGTH);
306 WLog_ERR(TAG,
"rail_pdu_init failed!");
307 return CHANNEL_RC_NO_MEMORY;
310 rail_server_set_handshake_ex_flags(context, handshakeEx->railHandshakeFlags);
312 rail_write_handshake_ex_order(s, handshakeEx);
313 error = rail_server_send_pdu(context, s, TS_RAIL_ORDER_HANDSHAKE_EX);
314 Stream_Free(s, TRUE);
323static UINT rail_send_server_sysparam(RailServerContext* context,
328 RailServerPrivate* priv =
nullptr;
329 BOOL extendedSpiSupported = 0;
331 if (!context || !sysparam)
332 return ERROR_INVALID_PARAMETER;
334 priv = context->priv;
337 return ERROR_INVALID_PARAMETER;
339 extendedSpiSupported = rail_is_extended_spi_supported(context->priv->channelFlags);
340 s = rail_pdu_init(RAIL_SYSPARAM_ORDER_LENGTH);
344 WLog_ERR(TAG,
"rail_pdu_init failed!");
345 return CHANNEL_RC_NO_MEMORY;
348 error = rail_write_sysparam_order(s, sysparam, extendedSpiSupported);
349 if (error == CHANNEL_RC_OK)
350 error = rail_server_send_pdu(context, s, TS_RAIL_ORDER_SYSPARAM);
351 Stream_Free(s, TRUE);
360static UINT rail_send_server_local_move_size(RailServerContext* context,
366 if (!context || !localMoveSize)
367 return ERROR_INVALID_PARAMETER;
369 s = rail_pdu_init(RAIL_LOCALMOVESIZE_ORDER_LENGTH);
373 WLog_ERR(TAG,
"rail_pdu_init failed!");
374 return CHANNEL_RC_NO_MEMORY;
377 rail_write_local_move_size_order(s, localMoveSize);
378 error = rail_server_send_pdu(context, s, TS_RAIL_ORDER_LOCALMOVESIZE);
379 Stream_Free(s, TRUE);
388static UINT rail_send_server_min_max_info(RailServerContext* context,
394 if (!context || !minMaxInfo)
395 return ERROR_INVALID_PARAMETER;
397 s = rail_pdu_init(RAIL_MINMAXINFO_ORDER_LENGTH);
401 WLog_ERR(TAG,
"rail_pdu_init failed!");
402 return CHANNEL_RC_NO_MEMORY;
405 rail_write_min_max_info_order(s, minMaxInfo);
406 error = rail_server_send_pdu(context, s, TS_RAIL_ORDER_MINMAXINFO);
407 Stream_Free(s, TRUE);
416static UINT rail_send_server_taskbar_info(RailServerContext* context,
422 if (!context || !taskbarInfo)
423 return ERROR_INVALID_PARAMETER;
425 s = rail_pdu_init(RAIL_TASKBAR_INFO_ORDER_LENGTH);
429 WLog_ERR(TAG,
"rail_pdu_init failed!");
430 return CHANNEL_RC_NO_MEMORY;
433 rail_write_taskbar_info_order(s, taskbarInfo);
434 error = rail_server_send_pdu(context, s, TS_RAIL_ORDER_TASKBARINFO);
435 Stream_Free(s, TRUE);
444static UINT rail_send_server_langbar_info(RailServerContext* context,
450 if (!context || !langbarInfo)
451 return ERROR_INVALID_PARAMETER;
453 s = rail_pdu_init(RAIL_LANGBAR_INFO_ORDER_LENGTH);
457 WLog_ERR(TAG,
"rail_pdu_init failed!");
458 return CHANNEL_RC_NO_MEMORY;
461 rail_write_langbar_info_order(s, langbarInfo);
462 error = rail_server_send_pdu(context, s, TS_RAIL_ORDER_LANGBARINFO);
463 Stream_Free(s, TRUE);
472static UINT rail_send_server_exec_result(RailServerContext* context,
478 if (!context || !execResult)
479 return ERROR_INVALID_PARAMETER;
481 s = rail_pdu_init(RAIL_EXEC_RESULT_ORDER_LENGTH + execResult->exeOrFile.length);
485 WLog_ERR(TAG,
"rail_pdu_init failed!");
486 return CHANNEL_RC_NO_MEMORY;
489 rail_write_exec_result_order(s, execResult);
490 error = rail_server_send_pdu(context, s, TS_RAIL_ORDER_EXEC_RESULT);
491 Stream_Free(s, TRUE);
500static UINT rail_send_server_z_order_sync(RailServerContext* context,
506 if (!context || !zOrderSync)
507 return ERROR_INVALID_PARAMETER;
509 s = rail_pdu_init(RAIL_Z_ORDER_SYNC_ORDER_LENGTH);
513 WLog_ERR(TAG,
"rail_pdu_init failed!");
514 return CHANNEL_RC_NO_MEMORY;
517 rail_write_z_order_sync_order(s, zOrderSync);
518 error = rail_server_send_pdu(context, s, TS_RAIL_ORDER_ZORDER_SYNC);
519 Stream_Free(s, TRUE);
528static UINT rail_send_server_cloak(RailServerContext* context,
const RAIL_CLOAK* cloak)
533 if (!context || !cloak)
534 return ERROR_INVALID_PARAMETER;
536 s = rail_pdu_init(RAIL_CLOAK_ORDER_LENGTH);
540 WLog_ERR(TAG,
"rail_pdu_init failed!");
541 return CHANNEL_RC_NO_MEMORY;
544 rail_write_cloak_order(s, cloak);
545 error = rail_server_send_pdu(context, s, TS_RAIL_ORDER_CLOAK);
546 Stream_Free(s, TRUE);
556rail_send_server_power_display_request(RailServerContext* context,
562 if (!context || !powerDisplayRequest)
563 return ERROR_INVALID_PARAMETER;
565 s = rail_pdu_init(RAIL_POWER_DISPLAY_REQUEST_ORDER_LENGTH);
569 WLog_ERR(TAG,
"rail_pdu_init failed!");
570 return CHANNEL_RC_NO_MEMORY;
573 rail_write_power_display_request_order(s, powerDisplayRequest);
574 error = rail_server_send_pdu(context, s, TS_RAIL_ORDER_POWER_DISPLAY_REQUEST);
575 Stream_Free(s, TRUE);
584static UINT rail_send_server_get_app_id_resp(RailServerContext* context,
590 if (!context || !getAppidResp)
591 return ERROR_INVALID_PARAMETER;
593 s = rail_pdu_init(RAIL_GET_APPID_RESP_ORDER_LENGTH);
597 WLog_ERR(TAG,
"rail_pdu_init failed!");
598 return CHANNEL_RC_NO_MEMORY;
601 rail_write_get_app_id_resp_order(s, getAppidResp);
602 error = rail_server_send_pdu(context, s, TS_RAIL_ORDER_GET_APPID_RESP);
603 Stream_Free(s, TRUE);
612static UINT rail_send_server_get_appid_resp_ex(RailServerContext* context,
618 if (!context || !getAppidRespEx)
619 return ERROR_INVALID_PARAMETER;
621 s = rail_pdu_init(RAIL_GET_APPID_RESP_EX_ORDER_LENGTH);
625 WLog_ERR(TAG,
"rail_pdu_init failed!");
626 return CHANNEL_RC_NO_MEMORY;
629 rail_write_get_appid_resp_ex_order(s, getAppidRespEx);
630 error = rail_server_send_pdu(context, s, TS_RAIL_ORDER_GET_APPID_RESP_EX);
631 Stream_Free(s, TRUE);
642 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_CLIENT_STATUS_ORDER_LENGTH))
643 return ERROR_INVALID_DATA;
645 Stream_Read_UINT32(s, clientStatus->flags);
646 return CHANNEL_RC_OK;
661 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_EXEC_ORDER_LENGTH))
662 return ERROR_INVALID_DATA;
664 Stream_Read_UINT16(s, exec->flags);
665 Stream_Read_UINT16(s, exeLen);
666 Stream_Read_UINT16(s, workLen);
667 Stream_Read_UINT16(s, argLen);
669 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)exeLen + workLen + argLen))
670 return ERROR_INVALID_DATA;
674 const size_t len = exeLen /
sizeof(WCHAR);
675 exec->RemoteApplicationProgram = args[0] =
676 Stream_Read_UTF16_String_As_UTF8(s, len,
nullptr);
677 if (!exec->RemoteApplicationProgram)
682 const size_t len = workLen /
sizeof(WCHAR);
683 exec->RemoteApplicationWorkingDir = args[1] =
684 Stream_Read_UTF16_String_As_UTF8(s, len,
nullptr);
685 if (!exec->RemoteApplicationWorkingDir)
690 const size_t len = argLen /
sizeof(WCHAR);
691 exec->RemoteApplicationArguments = args[2] =
692 Stream_Read_UTF16_String_As_UTF8(s, len,
nullptr);
693 if (!exec->RemoteApplicationArguments)
697 return CHANNEL_RC_OK;
703 return ERROR_INTERNAL_ERROR;
715 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_ACTIVATE_ORDER_LENGTH))
716 return ERROR_INVALID_DATA;
718 Stream_Read_UINT32(s, activate->windowId);
719 Stream_Read_UINT8(s, enabled);
720 activate->enabled = (enabled != 0);
721 return CHANNEL_RC_OK;
731 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_SYSMENU_ORDER_LENGTH))
732 return ERROR_INVALID_DATA;
734 Stream_Read_UINT32(s, sysmenu->windowId);
735 Stream_Read_INT16(s, sysmenu->left);
736 Stream_Read_INT16(s, sysmenu->top);
737 return CHANNEL_RC_OK;
747 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_SYSCOMMAND_ORDER_LENGTH))
748 return ERROR_INVALID_DATA;
750 Stream_Read_UINT32(s, syscommand->windowId);
751 Stream_Read_UINT16(s, syscommand->command);
752 return CHANNEL_RC_OK;
762 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_NOTIFY_EVENT_ORDER_LENGTH))
763 return ERROR_INVALID_DATA;
765 Stream_Read_UINT32(s, notifyEvent->windowId);
766 Stream_Read_UINT32(s, notifyEvent->notifyIconId);
767 Stream_Read_UINT32(s, notifyEvent->message);
768 return CHANNEL_RC_OK;
778 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_GET_APPID_REQ_ORDER_LENGTH))
779 return ERROR_INVALID_DATA;
781 Stream_Read_UINT32(s, getAppidReq->windowId);
782 return CHANNEL_RC_OK;
792 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_WINDOW_MOVE_ORDER_LENGTH))
793 return ERROR_INVALID_DATA;
795 Stream_Read_UINT32(s, windowMove->windowId);
796 Stream_Read_INT16(s, windowMove->left);
797 Stream_Read_INT16(s, windowMove->top);
798 Stream_Read_INT16(s, windowMove->right);
799 Stream_Read_INT16(s, windowMove->bottom);
800 return CHANNEL_RC_OK;
810 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_SNAP_ARRANGE_ORDER_LENGTH))
811 return ERROR_INVALID_DATA;
813 Stream_Read_UINT32(s, snapArrange->windowId);
814 Stream_Read_INT16(s, snapArrange->left);
815 Stream_Read_INT16(s, snapArrange->top);
816 Stream_Read_INT16(s, snapArrange->right);
817 Stream_Read_INT16(s, snapArrange->bottom);
818 return CHANNEL_RC_OK;
828 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_LANGBAR_INFO_ORDER_LENGTH))
829 return ERROR_INVALID_DATA;
831 Stream_Read_UINT32(s, langbarInfo->languageBarStatus);
832 return CHANNEL_RC_OK;
840static UINT rail_read_language_ime_info_order(
wStream* s,
843 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_LANGUAGEIME_INFO_ORDER_LENGTH))
844 return ERROR_INVALID_DATA;
846 Stream_Read_UINT32(s, languageImeInfo->ProfileType);
847 Stream_Read_UINT16(s, languageImeInfo->LanguageID);
849 s, &languageImeInfo->LanguageProfileCLSID,
850 sizeof(languageImeInfo->LanguageProfileCLSID));
851 Stream_Read(s, &languageImeInfo->ProfileGUID,
852 sizeof(languageImeInfo->ProfileGUID));
853 Stream_Read_UINT32(s, languageImeInfo->KeyboardLayout);
854 return CHANNEL_RC_OK;
862static UINT rail_read_compartment_info_order(
wStream* s,
865 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_COMPARTMENT_INFO_ORDER_LENGTH))
866 return ERROR_INVALID_DATA;
868 Stream_Read_UINT32(s, compartmentInfo->ImeState);
869 Stream_Read_UINT32(s, compartmentInfo->ImeConvMode);
870 Stream_Read_UINT32(s, compartmentInfo->ImeSentenceMode);
871 Stream_Read_UINT32(s, compartmentInfo->KanaMode);
872 return CHANNEL_RC_OK;
884 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_CLOAK_ORDER_LENGTH))
885 return ERROR_INVALID_DATA;
887 Stream_Read_UINT32(s, cloak->windowId);
888 Stream_Read_UINT8(s, cloaked);
889 cloak->cloak = (cloaked != 0);
890 return CHANNEL_RC_OK;
898static UINT rail_recv_client_handshake_order(RailServerContext* context,
903 if (!context || !handshake || !s)
904 return ERROR_INVALID_PARAMETER;
906 if ((error = rail_read_handshake_order(s, handshake)))
908 WLog_ERR(TAG,
"rail_read_handshake_order failed with error %" PRIu32
"!", error);
912 IFCALLRET(context->ClientHandshake, error, context, handshake);
915 WLog_ERR(TAG,
"context.ClientHandshake failed with error %" PRIu32
"", error);
925static UINT rail_recv_client_client_status_order(RailServerContext* context,
930 if (!context || !clientStatus || !s)
931 return ERROR_INVALID_PARAMETER;
933 if ((error = rail_read_client_status_order(s, clientStatus)))
935 WLog_ERR(TAG,
"rail_read_client_status_order failed with error %" PRIu32
"!", error);
939 IFCALLRET(context->ClientClientStatus, error, context, clientStatus);
942 WLog_ERR(TAG,
"context.ClientClientStatus failed with error %" PRIu32
"", error);
952static UINT rail_recv_client_exec_order(RailServerContext* context,
wStream* s)
955 char* args[3] = WINPR_C_ARRAY_INIT;
959 return ERROR_INVALID_PARAMETER;
961 error = rail_read_exec_order(s, &exec, args);
964 WLog_ERR(TAG,
"rail_read_client_status_order failed with error %" PRIu32
"!", error);
968 IFCALLRET(context->ClientExec, error, context, &exec);
971 WLog_ERR(TAG,
"context.Exec failed with error %" PRIu32
"", error);
984static UINT rail_recv_client_sysparam_order(RailServerContext* context,
988 BOOL extendedSpiSupported = 0;
990 if (!context || !sysparam || !s)
991 return ERROR_INVALID_PARAMETER;
993 extendedSpiSupported = rail_is_extended_spi_supported(context->priv->channelFlags);
994 if ((error = rail_read_sysparam_order(s, sysparam, extendedSpiSupported)))
996 WLog_ERR(TAG,
"rail_read_sysparam_order failed with error %" PRIu32
"!", error);
1000 IFCALLRET(context->ClientSysparam, error, context, sysparam);
1003 WLog_ERR(TAG,
"context.ClientSysparam failed with error %" PRIu32
"", error);
1013static UINT rail_recv_client_activate_order(RailServerContext* context,
1018 if (!context || !activate || !s)
1019 return ERROR_INVALID_PARAMETER;
1021 if ((error = rail_read_activate_order(s, activate)))
1023 WLog_ERR(TAG,
"rail_read_activate_order failed with error %" PRIu32
"!", error);
1027 IFCALLRET(context->ClientActivate, error, context, activate);
1030 WLog_ERR(TAG,
"context.ClientActivate failed with error %" PRIu32
"", error);
1040static UINT rail_recv_client_sysmenu_order(RailServerContext* context,
RAIL_SYSMENU_ORDER* sysmenu,
1045 if (!context || !sysmenu || !s)
1046 return ERROR_INVALID_PARAMETER;
1048 if ((error = rail_read_sysmenu_order(s, sysmenu)))
1050 WLog_ERR(TAG,
"rail_read_sysmenu_order failed with error %" PRIu32
"!", error);
1054 IFCALLRET(context->ClientSysmenu, error, context, sysmenu);
1057 WLog_ERR(TAG,
"context.ClientSysmenu failed with error %" PRIu32
"", error);
1067static UINT rail_recv_client_syscommand_order(RailServerContext* context,
1072 if (!context || !syscommand || !s)
1073 return ERROR_INVALID_PARAMETER;
1075 if ((error = rail_read_syscommand_order(s, syscommand)))
1077 WLog_ERR(TAG,
"rail_read_syscommand_order failed with error %" PRIu32
"!", error);
1081 IFCALLRET(context->ClientSyscommand, error, context, syscommand);
1084 WLog_ERR(TAG,
"context.ClientSyscommand failed with error %" PRIu32
"", error);
1094static UINT rail_recv_client_notify_event_order(RailServerContext* context,
1099 if (!context || !notifyEvent || !s)
1100 return ERROR_INVALID_PARAMETER;
1102 if ((error = rail_read_notify_event_order(s, notifyEvent)))
1104 WLog_ERR(TAG,
"rail_read_notify_event_order failed with error %" PRIu32
"!", error);
1108 IFCALLRET(context->ClientNotifyEvent, error, context, notifyEvent);
1111 WLog_ERR(TAG,
"context.ClientNotifyEvent failed with error %" PRIu32
"", error);
1121static UINT rail_recv_client_window_move_order(RailServerContext* context,
1126 if (!context || !windowMove || !s)
1127 return ERROR_INVALID_PARAMETER;
1129 if ((error = rail_read_window_move_order(s, windowMove)))
1131 WLog_ERR(TAG,
"rail_read_window_move_order failed with error %" PRIu32
"!", error);
1135 IFCALLRET(context->ClientWindowMove, error, context, windowMove);
1138 WLog_ERR(TAG,
"context.ClientWindowMove failed with error %" PRIu32
"", error);
1148static UINT rail_recv_client_snap_arrange_order(RailServerContext* context,
1153 if (!context || !snapArrange || !s)
1154 return ERROR_INVALID_PARAMETER;
1156 if ((error = rail_read_snap_arange_order(s, snapArrange)))
1158 WLog_ERR(TAG,
"rail_read_snap_arange_order failed with error %" PRIu32
"!", error);
1162 IFCALLRET(context->ClientSnapArrange, error, context, snapArrange);
1165 WLog_ERR(TAG,
"context.ClientSnapArrange failed with error %" PRIu32
"", error);
1175static UINT rail_recv_client_get_appid_req_order(RailServerContext* context,
1180 if (!context || !getAppidReq || !s)
1181 return ERROR_INVALID_PARAMETER;
1183 if ((error = rail_read_get_appid_req_order(s, getAppidReq)))
1185 WLog_ERR(TAG,
"rail_read_get_appid_req_order failed with error %" PRIu32
"!", error);
1189 IFCALLRET(context->ClientGetAppidReq, error, context, getAppidReq);
1192 WLog_ERR(TAG,
"context.ClientGetAppidReq failed with error %" PRIu32
"", error);
1202static UINT rail_recv_client_langbar_info_order(RailServerContext* context,
1207 if (!context || !langbarInfo || !s)
1208 return ERROR_INVALID_PARAMETER;
1210 if ((error = rail_read_langbar_info_order(s, langbarInfo)))
1212 WLog_ERR(TAG,
"rail_read_langbar_info_order failed with error %" PRIu32
"!", error);
1216 IFCALLRET(context->ClientLangbarInfo, error, context, langbarInfo);
1219 WLog_ERR(TAG,
"context.ClientLangbarInfo failed with error %" PRIu32
"", error);
1229static UINT rail_recv_client_language_ime_info_order(RailServerContext* context,
1235 if (!context || !languageImeInfo || !s)
1236 return ERROR_INVALID_PARAMETER;
1238 if ((error = rail_read_language_ime_info_order(s, languageImeInfo)))
1240 WLog_ERR(TAG,
"rail_read_language_ime_info_order failed with error %" PRIu32
"!", error);
1244 IFCALLRET(context->ClientLanguageImeInfo, error, context, languageImeInfo);
1247 WLog_ERR(TAG,
"context.ClientLanguageImeInfo failed with error %" PRIu32
"", error);
1257static UINT rail_recv_client_compartment_info(RailServerContext* context,
1263 if (!context || !compartmentInfo || !s)
1264 return ERROR_INVALID_PARAMETER;
1266 if ((error = rail_read_compartment_info_order(s, compartmentInfo)))
1268 WLog_ERR(TAG,
"rail_read_compartment_info_order failed with error %" PRIu32
"!", error);
1272 IFCALLRET(context->ClientCompartmentInfo, error, context, compartmentInfo);
1275 WLog_ERR(TAG,
"context.ClientCompartmentInfo failed with error %" PRIu32
"", error);
1285static UINT rail_recv_client_cloak_order(RailServerContext* context,
RAIL_CLOAK* cloak,
wStream* s)
1289 if (!context || !cloak || !s)
1290 return ERROR_INVALID_PARAMETER;
1292 if ((error = rail_read_cloak_order(s, cloak)))
1294 WLog_ERR(TAG,
"rail_read_cloak_order failed with error %" PRIu32
"!", error);
1298 IFCALLRET(context->ClientCloak, error, context, cloak);
1301 WLog_ERR(TAG,
"context.Cloak failed with error %" PRIu32
"", error);
1306static UINT rail_recv_client_text_scale_order(RailServerContext* context,
wStream* s)
1308 UINT error = CHANNEL_RC_OK;
1309 UINT32 TextScaleFactor = 0;
1312 return ERROR_INVALID_PARAMETER;
1314 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1315 return ERROR_INVALID_DATA;
1317 Stream_Read_UINT32(s, TextScaleFactor);
1318 IFCALLRET(context->ClientTextScale, error, context, TextScaleFactor);
1321 WLog_ERR(TAG,
"context.TextScale failed with error %" PRIu32
"", error);
1326static UINT rail_recv_client_caret_blink(RailServerContext* context,
wStream* s)
1328 UINT error = CHANNEL_RC_OK;
1329 UINT32 CaretBlinkRate = 0;
1332 return ERROR_INVALID_PARAMETER;
1334 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1335 return ERROR_INVALID_DATA;
1337 Stream_Read_UINT32(s, CaretBlinkRate);
1338 IFCALLRET(context->ClientCaretBlinkRate, error, context, CaretBlinkRate);
1341 WLog_ERR(TAG,
"context.CaretBlinkRate failed with error %" PRIu32
"", error);
1346static DWORD WINAPI rail_server_thread(LPVOID arg)
1348 RailServerContext* context = (RailServerContext*)arg;
1349 RailServerPrivate* priv = context->priv;
1353 UINT error = CHANNEL_RC_OK;
1354 events[nCount++] = priv->channelEvent;
1355 events[nCount++] = priv->stopEvent;
1359 status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
1361 if (status == WAIT_FAILED)
1363 error = GetLastError();
1364 WLog_ERR(TAG,
"WaitForMultipleObjects failed with error %" PRIu32
"!", error);
1368 status = WaitForSingleObject(context->priv->stopEvent, 0);
1370 if (status == WAIT_FAILED)
1372 error = GetLastError();
1373 WLog_ERR(TAG,
"WaitForSingleObject failed with error %" PRIu32
"!", error);
1377 if (status == WAIT_OBJECT_0)
1380 status = WaitForSingleObject(context->priv->channelEvent, 0);
1382 if (status == WAIT_FAILED)
1384 error = GetLastError();
1387 "WaitForSingleObject(context->priv->channelEvent, 0) failed with error %" PRIu32
1393 if (status == WAIT_OBJECT_0)
1395 if ((error = rail_server_handle_messages(context)))
1397 WLog_ERR(TAG,
"rail_server_handle_messages failed with error %" PRIu32
"", error);
1403 if (error && context->rdpcontext)
1404 setChannelError(context->rdpcontext, error,
"rail_server_thread reported an error");
1415static UINT rail_server_start(RailServerContext* context)
1417 void* buffer =
nullptr;
1418 DWORD bytesReturned = 0;
1419 RailServerPrivate* priv = context->priv;
1420 UINT error = ERROR_INTERNAL_ERROR;
1421 priv->rail_channel =
1422 WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, RAIL_SVC_CHANNEL_NAME);
1424 if (!priv->rail_channel)
1426 WLog_ERR(TAG,
"WTSVirtualChannelOpen failed!");
1430 if (!WTSVirtualChannelQuery(priv->rail_channel, WTSVirtualEventHandle, &buffer,
1432 (bytesReturned !=
sizeof(HANDLE)))
1435 "error during WTSVirtualChannelQuery(WTSVirtualEventHandle) or invalid returned "
1436 "size(%" PRIu32
")",
1440 WTSFreeMemory(buffer);
1445 priv->channelEvent = *(HANDLE*)buffer;
1446 WTSFreeMemory(buffer);
1447 context->priv->stopEvent = CreateEvent(
nullptr, TRUE, FALSE,
nullptr);
1449 if (!context->priv->stopEvent)
1451 WLog_ERR(TAG,
"CreateEvent failed!");
1455 context->priv->thread =
1456 CreateThread(
nullptr, 0, rail_server_thread, (
void*)context, 0,
nullptr);
1458 if (!context->priv->thread)
1460 WLog_ERR(TAG,
"CreateThread failed!");
1461 goto out_stop_event;
1464 return CHANNEL_RC_OK;
1466 (void)CloseHandle(context->priv->stopEvent);
1467 context->priv->stopEvent =
nullptr;
1469 (void)WTSVirtualChannelClose(context->priv->rail_channel);
1470 context->priv->rail_channel =
nullptr;
1474static BOOL rail_server_stop(RailServerContext* context)
1476 RailServerPrivate* priv = context->priv;
1480 (void)SetEvent(priv->stopEvent);
1482 if (WaitForSingleObject(priv->thread, INFINITE) == WAIT_FAILED)
1484 WLog_ERR(TAG,
"WaitForSingleObject failed with error %" PRIu32
"", GetLastError());
1488 (void)CloseHandle(priv->thread);
1489 (void)CloseHandle(priv->stopEvent);
1490 priv->thread =
nullptr;
1491 priv->stopEvent =
nullptr;
1494 if (priv->rail_channel)
1496 (void)WTSVirtualChannelClose(priv->rail_channel);
1497 priv->rail_channel =
nullptr;
1500 priv->channelEvent =
nullptr;
1504RailServerContext* rail_server_context_new(HANDLE vcm)
1506 RailServerContext* context =
nullptr;
1507 RailServerPrivate* priv =
nullptr;
1508 context = (RailServerContext*)calloc(1,
sizeof(RailServerContext));
1512 WLog_ERR(TAG,
"calloc failed!");
1517 context->Start = rail_server_start;
1518 context->Stop = rail_server_stop;
1519 context->ServerHandshake = rail_send_server_handshake;
1520 context->ServerHandshakeEx = rail_send_server_handshake_ex;
1521 context->ServerSysparam = rail_send_server_sysparam;
1522 context->ServerLocalMoveSize = rail_send_server_local_move_size;
1523 context->ServerMinMaxInfo = rail_send_server_min_max_info;
1524 context->ServerTaskbarInfo = rail_send_server_taskbar_info;
1525 context->ServerLangbarInfo = rail_send_server_langbar_info;
1526 context->ServerExecResult = rail_send_server_exec_result;
1527 context->ServerGetAppidResp = rail_send_server_get_app_id_resp;
1528 context->ServerZOrderSync = rail_send_server_z_order_sync;
1529 context->ServerCloak = rail_send_server_cloak;
1530 context->ServerPowerDisplayRequest = rail_send_server_power_display_request;
1531 context->ServerGetAppidRespEx = rail_send_server_get_appid_resp_ex;
1532 context->priv = priv = (RailServerPrivate*)calloc(1,
sizeof(RailServerPrivate));
1536 WLog_ERR(TAG,
"calloc failed!");
1541 priv->input_stream = Stream_New(
nullptr, 4096);
1543 if (!priv->input_stream)
1545 WLog_ERR(TAG,
"Stream_New failed!");
1551 free(context->priv);
1557void rail_server_context_free(RailServerContext* context)
1560 Stream_Free(context->priv->input_stream, TRUE);
1562 free(context->priv);
1566void rail_server_set_handshake_ex_flags(RailServerContext* context, DWORD flags)
1568 RailServerPrivate* priv =
nullptr;
1570 if (!context || !context->priv)
1573 priv = context->priv;
1574 priv->channelFlags = flags;
1577UINT rail_server_handle_messages(RailServerContext* context)
1579 char buffer[128] = WINPR_C_ARRAY_INIT;
1580 UINT status = CHANNEL_RC_OK;
1581 DWORD bytesReturned = 0;
1582 UINT16 orderType = 0;
1583 UINT16 orderLength = 0;
1584 RailServerPrivate* priv = context->priv;
1585 wStream* s = priv->input_stream;
1588 if (!Stream_EnsureRemainingCapacity(s, RAIL_PDU_HEADER_LENGTH))
1590 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed, RAIL_PDU_HEADER_LENGTH");
1591 return CHANNEL_RC_NO_MEMORY;
1594 if (!WTSVirtualChannelRead(priv->rail_channel, 0, Stream_Pointer(s), RAIL_PDU_HEADER_LENGTH,
1597 if (GetLastError() == ERROR_NO_DATA)
1598 return ERROR_NO_DATA;
1600 WLog_ERR(TAG,
"channel connection closed");
1601 return ERROR_INTERNAL_ERROR;
1605 if ((status = rail_read_pdu_header(s, &orderType, &orderLength)) != CHANNEL_RC_OK)
1607 WLog_ERR(TAG,
"rail_read_pdu_header failed with error %" PRIu32
"!", status);
1611 if (!Stream_EnsureRemainingCapacity(s, orderLength - RAIL_PDU_HEADER_LENGTH))
1614 "Stream_EnsureRemainingCapacity failed, orderLength - RAIL_PDU_HEADER_LENGTH");
1615 return CHANNEL_RC_NO_MEMORY;
1619 if (!WTSVirtualChannelRead(priv->rail_channel, 0, Stream_Pointer(s),
1620 orderLength - RAIL_PDU_HEADER_LENGTH, &bytesReturned))
1622 if (GetLastError() == ERROR_NO_DATA)
1623 return ERROR_NO_DATA;
1625 WLog_ERR(TAG,
"channel connection closed");
1626 return ERROR_INTERNAL_ERROR;
1629 WLog_DBG(TAG,
"Received %s PDU, length:%" PRIu16
"",
1630 rail_get_order_type_string_full(orderType, buffer,
sizeof(buffer)), orderLength);
1634 case TS_RAIL_ORDER_HANDSHAKE:
1637 return rail_recv_client_handshake_order(context, &handshake, s);
1640 case TS_RAIL_ORDER_CLIENTSTATUS:
1643 return rail_recv_client_client_status_order(context, &clientStatus, s);
1646 case TS_RAIL_ORDER_EXEC:
1647 return rail_recv_client_exec_order(context, s);
1649 case TS_RAIL_ORDER_SYSPARAM:
1652 return rail_recv_client_sysparam_order(context, &sysparam, s);
1655 case TS_RAIL_ORDER_ACTIVATE:
1658 return rail_recv_client_activate_order(context, &activate, s);
1661 case TS_RAIL_ORDER_SYSMENU:
1664 return rail_recv_client_sysmenu_order(context, &sysmenu, s);
1667 case TS_RAIL_ORDER_SYSCOMMAND:
1670 return rail_recv_client_syscommand_order(context, &syscommand, s);
1673 case TS_RAIL_ORDER_NOTIFY_EVENT:
1676 return rail_recv_client_notify_event_order(context, ¬ifyEvent, s);
1679 case TS_RAIL_ORDER_WINDOWMOVE:
1682 return rail_recv_client_window_move_order(context, &windowMove, s);
1685 case TS_RAIL_ORDER_SNAP_ARRANGE:
1688 return rail_recv_client_snap_arrange_order(context, &snapArrange, s);
1691 case TS_RAIL_ORDER_GET_APPID_REQ:
1694 return rail_recv_client_get_appid_req_order(context, &getAppidReq, s);
1697 case TS_RAIL_ORDER_LANGBARINFO:
1700 return rail_recv_client_langbar_info_order(context, &langbarInfo, s);
1703 case TS_RAIL_ORDER_LANGUAGEIMEINFO:
1706 return rail_recv_client_language_ime_info_order(context, &languageImeInfo, s);
1709 case TS_RAIL_ORDER_COMPARTMENTINFO:
1712 return rail_recv_client_compartment_info(context, &compartmentInfo, s);
1715 case TS_RAIL_ORDER_CLOAK:
1718 return rail_recv_client_cloak_order(context, &cloak, s);
1721 case TS_RAIL_ORDER_TEXTSCALEINFO:
1723 return rail_recv_client_text_scale_order(context, s);
1726 case TS_RAIL_ORDER_CARETBLINKINFO:
1728 return rail_recv_client_caret_blink(context, s);
1732 WLog_ERR(TAG,
"Unknown RAIL PDU order received.");
1733 return ERROR_INVALID_DATA;