FreeRDP
Loading...
Searching...
No Matches
server/rail_main.c
1
21#include <freerdp/types.h>
22#include <freerdp/constants.h>
23
24#include <freerdp/freerdp.h>
25#include <freerdp/channels/log.h>
26
27#include <winpr/crt.h>
28#include <winpr/synch.h>
29#include <winpr/thread.h>
30#include <winpr/stream.h>
31
32#include "rail_main.h"
33
34#define TAG CHANNELS_TAG("rail.server")
35
41static UINT rail_send(RailServerContext* context, wStream* s, ULONG length)
42{
43 UINT status = CHANNEL_RC_OK;
44 ULONG written = 0;
45
46 if (!context)
47 return CHANNEL_RC_BAD_INIT_HANDLE;
48
49 if (!WTSVirtualChannelWrite(context->priv->rail_channel, Stream_BufferAs(s, char), length,
50 &written))
51 {
52 WLog_ERR(TAG, "WTSVirtualChannelWrite failed!");
53 status = ERROR_INTERNAL_ERROR;
54 }
55
56 return status;
57}
58
64static UINT rail_server_send_pdu(RailServerContext* context, wStream* s, UINT16 orderType)
65{
66 char buffer[128] = WINPR_C_ARRAY_INIT;
67 UINT16 orderLength = 0;
68
69 if (!context || !s)
70 return ERROR_INVALID_PARAMETER;
71
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);
79}
80
86static UINT rail_write_local_move_size_order(wStream* s,
87 const RAIL_LOCALMOVESIZE_ORDER* localMoveSize)
88{
89 if (!s || !localMoveSize)
90 return ERROR_INVALID_PARAMETER;
91
92 Stream_Write_UINT32(s, localMoveSize->windowId); /* WindowId (4 bytes) */
93 Stream_Write_UINT16(s, localMoveSize->isMoveSizeStart ? 1 : 0); /* IsMoveSizeStart (2 bytes) */
94 Stream_Write_UINT16(s, localMoveSize->moveSizeType); /* MoveSizeType (2 bytes) */
95 Stream_Write_INT16(s, localMoveSize->posX); /* PosX (2 bytes) */
96 Stream_Write_INT16(s, localMoveSize->posY); /* PosY (2 bytes) */
97 return ERROR_SUCCESS;
98}
99
105static UINT rail_write_min_max_info_order(wStream* s, const RAIL_MINMAXINFO_ORDER* minMaxInfo)
106{
107 if (!s || !minMaxInfo)
108 return ERROR_INVALID_PARAMETER;
109
110 Stream_Write_UINT32(s, minMaxInfo->windowId); /* WindowId (4 bytes) */
111 Stream_Write_INT16(s, minMaxInfo->maxWidth); /* MaxWidth (2 bytes) */
112 Stream_Write_INT16(s, minMaxInfo->maxHeight); /* MaxHeight (2 bytes) */
113 Stream_Write_INT16(s, minMaxInfo->maxPosX); /* MaxPosX (2 bytes) */
114 Stream_Write_INT16(s, minMaxInfo->maxPosY); /* MaxPosY (2 bytes) */
115 Stream_Write_INT16(s, minMaxInfo->minTrackWidth); /* MinTrackWidth (2 bytes) */
116 Stream_Write_INT16(s, minMaxInfo->minTrackHeight); /* MinTrackHeight (2 bytes) */
117 Stream_Write_INT16(s, minMaxInfo->maxTrackWidth); /* MaxTrackWidth (2 bytes) */
118 Stream_Write_INT16(s, minMaxInfo->maxTrackHeight); /* MaxTrackHeight (2 bytes) */
119 return ERROR_SUCCESS;
120}
121
127static UINT rail_write_taskbar_info_order(wStream* s, const RAIL_TASKBAR_INFO_ORDER* taskbarInfo)
128{
129 if (!s || !taskbarInfo)
130 return ERROR_INVALID_PARAMETER;
131
132 Stream_Write_UINT32(s, taskbarInfo->TaskbarMessage); /* TaskbarMessage (4 bytes) */
133 Stream_Write_UINT32(s, taskbarInfo->WindowIdTab); /* WindowIdTab (4 bytes) */
134 Stream_Write_UINT32(s, taskbarInfo->Body); /* Body (4 bytes) */
135 return ERROR_SUCCESS;
136}
137
143static UINT rail_write_langbar_info_order(wStream* s, const RAIL_LANGBAR_INFO_ORDER* langbarInfo)
144{
145 if (!s || !langbarInfo)
146 return ERROR_INVALID_PARAMETER;
147
148 Stream_Write_UINT32(s, langbarInfo->languageBarStatus); /* LanguageBarStatus (4 bytes) */
149 return ERROR_SUCCESS;
150}
151
157static UINT rail_write_exec_result_order(wStream* s, const RAIL_EXEC_RESULT_ORDER* execResult)
158{
159 if (!s || !execResult)
160 return ERROR_INVALID_PARAMETER;
161
162 if (execResult->exeOrFile.length > 520 || execResult->exeOrFile.length < 1)
163 return ERROR_INVALID_DATA;
164
165 Stream_Write_UINT16(s, execResult->flags); /* Flags (2 bytes) */
166 Stream_Write_UINT16(s, execResult->execResult); /* ExecResult (2 bytes) */
167 Stream_Write_UINT32(s, execResult->rawResult); /* RawResult (4 bytes) */
168 Stream_Write_UINT16(s, 0); /* Padding (2 bytes) */
169 Stream_Write_UINT16(s, execResult->exeOrFile.length); /* ExeOrFileLength (2 bytes) */
170 Stream_Write(s, execResult->exeOrFile.string,
171 execResult->exeOrFile.length); /* ExeOrFile (variable) */
172 return ERROR_SUCCESS;
173}
174
180static UINT rail_write_z_order_sync_order(wStream* s, const RAIL_ZORDER_SYNC* zOrderSync)
181{
182 if (!s || !zOrderSync)
183 return ERROR_INVALID_PARAMETER;
184
185 Stream_Write_UINT32(s, zOrderSync->windowIdMarker); /* WindowIdMarker (4 bytes) */
186 return ERROR_SUCCESS;
187}
188
194static UINT rail_write_cloak_order(wStream* s, const RAIL_CLOAK* cloak)
195{
196 if (!s || !cloak)
197 return ERROR_INVALID_PARAMETER;
198
199 Stream_Write_UINT32(s, cloak->windowId); /* WindowId (4 bytes) */
200 Stream_Write_UINT8(s, cloak->cloak ? 1 : 0); /* Cloaked (1 byte) */
201 return ERROR_SUCCESS;
202}
203
209static UINT
210rail_write_power_display_request_order(wStream* s,
211 const RAIL_POWER_DISPLAY_REQUEST* powerDisplayRequest)
212{
213 if (!s || !powerDisplayRequest)
214 return ERROR_INVALID_PARAMETER;
215
216 Stream_Write_UINT32(s, powerDisplayRequest->active ? 1 : 0); /* Active (4 bytes) */
217 return ERROR_SUCCESS;
218}
219
225static UINT rail_write_get_app_id_resp_order(wStream* s,
226 const RAIL_GET_APPID_RESP_ORDER* getAppidResp)
227{
228 if (!s || !getAppidResp)
229 return ERROR_INVALID_PARAMETER;
230
231 Stream_Write_UINT32(s, getAppidResp->windowId); /* WindowId (4 bytes) */
232 Stream_Write_UTF16_String(
233 s, getAppidResp->applicationId,
234 ARRAYSIZE(getAppidResp->applicationId)); /* ApplicationId (512 bytes) */
235 return ERROR_SUCCESS;
236}
237
243static UINT rail_write_get_appid_resp_ex_order(wStream* s,
244 const RAIL_GET_APPID_RESP_EX* getAppidRespEx)
245{
246 if (!s || !getAppidRespEx)
247 return ERROR_INVALID_PARAMETER;
248
249 Stream_Write_UINT32(s, getAppidRespEx->windowID); /* WindowId (4 bytes) */
250 Stream_Write_UTF16_String(
251 s, getAppidRespEx->applicationID,
252 ARRAYSIZE(getAppidRespEx->applicationID)); /* ApplicationId (520 bytes) */
253 Stream_Write_UINT32(s, getAppidRespEx->processId); /* ProcessId (4 bytes) */
254 Stream_Write_UTF16_String(
255 s, getAppidRespEx->processImageName,
256 ARRAYSIZE(getAppidRespEx->processImageName)); /* ProcessImageName (520 bytes) */
257 return ERROR_SUCCESS;
258}
259
265static UINT rail_send_server_handshake(RailServerContext* context,
266 const RAIL_HANDSHAKE_ORDER* handshake)
267{
268 wStream* s = nullptr;
269 UINT error = 0;
270
271 if (!context || !handshake)
272 return ERROR_INVALID_PARAMETER;
273
274 s = rail_pdu_init(RAIL_HANDSHAKE_ORDER_LENGTH);
275
276 if (!s)
277 {
278 WLog_ERR(TAG, "rail_pdu_init failed!");
279 return CHANNEL_RC_NO_MEMORY;
280 }
281
282 rail_write_handshake_order(s, handshake);
283 error = rail_server_send_pdu(context, s, TS_RAIL_ORDER_HANDSHAKE);
284 Stream_Free(s, TRUE);
285 return error;
286}
287
293static UINT rail_send_server_handshake_ex(RailServerContext* context,
294 const RAIL_HANDSHAKE_EX_ORDER* handshakeEx)
295{
296 wStream* s = nullptr;
297 UINT error = 0;
298
299 if (!context || !handshakeEx || !context->priv)
300 return ERROR_INVALID_PARAMETER;
301
302 s = rail_pdu_init(RAIL_HANDSHAKE_EX_ORDER_LENGTH);
303
304 if (!s)
305 {
306 WLog_ERR(TAG, "rail_pdu_init failed!");
307 return CHANNEL_RC_NO_MEMORY;
308 }
309
310 rail_server_set_handshake_ex_flags(context, handshakeEx->railHandshakeFlags);
311
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);
315 return error;
316}
317
323static UINT rail_send_server_sysparam(RailServerContext* context,
324 const RAIL_SYSPARAM_ORDER* sysparam)
325{
326 wStream* s = nullptr;
327 UINT error = 0;
328 RailServerPrivate* priv = nullptr;
329 BOOL extendedSpiSupported = 0;
330
331 if (!context || !sysparam)
332 return ERROR_INVALID_PARAMETER;
333
334 priv = context->priv;
335
336 if (!priv)
337 return ERROR_INVALID_PARAMETER;
338
339 extendedSpiSupported = rail_is_extended_spi_supported(context->priv->channelFlags);
340 s = rail_pdu_init(RAIL_SYSPARAM_ORDER_LENGTH);
341
342 if (!s)
343 {
344 WLog_ERR(TAG, "rail_pdu_init failed!");
345 return CHANNEL_RC_NO_MEMORY;
346 }
347
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);
352 return error;
353}
354
360static UINT rail_send_server_local_move_size(RailServerContext* context,
361 const RAIL_LOCALMOVESIZE_ORDER* localMoveSize)
362{
363 wStream* s = nullptr;
364 UINT error = 0;
365
366 if (!context || !localMoveSize)
367 return ERROR_INVALID_PARAMETER;
368
369 s = rail_pdu_init(RAIL_LOCALMOVESIZE_ORDER_LENGTH);
370
371 if (!s)
372 {
373 WLog_ERR(TAG, "rail_pdu_init failed!");
374 return CHANNEL_RC_NO_MEMORY;
375 }
376
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);
380 return error;
381}
382
388static UINT rail_send_server_min_max_info(RailServerContext* context,
389 const RAIL_MINMAXINFO_ORDER* minMaxInfo)
390{
391 wStream* s = nullptr;
392 UINT error = 0;
393
394 if (!context || !minMaxInfo)
395 return ERROR_INVALID_PARAMETER;
396
397 s = rail_pdu_init(RAIL_MINMAXINFO_ORDER_LENGTH);
398
399 if (!s)
400 {
401 WLog_ERR(TAG, "rail_pdu_init failed!");
402 return CHANNEL_RC_NO_MEMORY;
403 }
404
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);
408 return error;
409}
410
416static UINT rail_send_server_taskbar_info(RailServerContext* context,
417 const RAIL_TASKBAR_INFO_ORDER* taskbarInfo)
418{
419 wStream* s = nullptr;
420 UINT error = 0;
421
422 if (!context || !taskbarInfo)
423 return ERROR_INVALID_PARAMETER;
424
425 s = rail_pdu_init(RAIL_TASKBAR_INFO_ORDER_LENGTH);
426
427 if (!s)
428 {
429 WLog_ERR(TAG, "rail_pdu_init failed!");
430 return CHANNEL_RC_NO_MEMORY;
431 }
432
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);
436 return error;
437}
438
444static UINT rail_send_server_langbar_info(RailServerContext* context,
445 const RAIL_LANGBAR_INFO_ORDER* langbarInfo)
446{
447 wStream* s = nullptr;
448 UINT error = 0;
449
450 if (!context || !langbarInfo)
451 return ERROR_INVALID_PARAMETER;
452
453 s = rail_pdu_init(RAIL_LANGBAR_INFO_ORDER_LENGTH);
454
455 if (!s)
456 {
457 WLog_ERR(TAG, "rail_pdu_init failed!");
458 return CHANNEL_RC_NO_MEMORY;
459 }
460
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);
464 return error;
465}
466
472static UINT rail_send_server_exec_result(RailServerContext* context,
473 const RAIL_EXEC_RESULT_ORDER* execResult)
474{
475 wStream* s = nullptr;
476 UINT error = 0;
477
478 if (!context || !execResult)
479 return ERROR_INVALID_PARAMETER;
480
481 s = rail_pdu_init(RAIL_EXEC_RESULT_ORDER_LENGTH + execResult->exeOrFile.length);
482
483 if (!s)
484 {
485 WLog_ERR(TAG, "rail_pdu_init failed!");
486 return CHANNEL_RC_NO_MEMORY;
487 }
488
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);
492 return error;
493}
494
500static UINT rail_send_server_z_order_sync(RailServerContext* context,
501 const RAIL_ZORDER_SYNC* zOrderSync)
502{
503 wStream* s = nullptr;
504 UINT error = 0;
505
506 if (!context || !zOrderSync)
507 return ERROR_INVALID_PARAMETER;
508
509 s = rail_pdu_init(RAIL_Z_ORDER_SYNC_ORDER_LENGTH);
510
511 if (!s)
512 {
513 WLog_ERR(TAG, "rail_pdu_init failed!");
514 return CHANNEL_RC_NO_MEMORY;
515 }
516
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);
520 return error;
521}
522
528static UINT rail_send_server_cloak(RailServerContext* context, const RAIL_CLOAK* cloak)
529{
530 wStream* s = nullptr;
531 UINT error = 0;
532
533 if (!context || !cloak)
534 return ERROR_INVALID_PARAMETER;
535
536 s = rail_pdu_init(RAIL_CLOAK_ORDER_LENGTH);
537
538 if (!s)
539 {
540 WLog_ERR(TAG, "rail_pdu_init failed!");
541 return CHANNEL_RC_NO_MEMORY;
542 }
543
544 rail_write_cloak_order(s, cloak);
545 error = rail_server_send_pdu(context, s, TS_RAIL_ORDER_CLOAK);
546 Stream_Free(s, TRUE);
547 return error;
548}
549
555static UINT
556rail_send_server_power_display_request(RailServerContext* context,
557 const RAIL_POWER_DISPLAY_REQUEST* powerDisplayRequest)
558{
559 wStream* s = nullptr;
560 UINT error = 0;
561
562 if (!context || !powerDisplayRequest)
563 return ERROR_INVALID_PARAMETER;
564
565 s = rail_pdu_init(RAIL_POWER_DISPLAY_REQUEST_ORDER_LENGTH);
566
567 if (!s)
568 {
569 WLog_ERR(TAG, "rail_pdu_init failed!");
570 return CHANNEL_RC_NO_MEMORY;
571 }
572
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);
576 return error;
577}
578
584static UINT rail_send_server_get_app_id_resp(RailServerContext* context,
585 const RAIL_GET_APPID_RESP_ORDER* getAppidResp)
586{
587 wStream* s = nullptr;
588 UINT error = 0;
589
590 if (!context || !getAppidResp)
591 return ERROR_INVALID_PARAMETER;
592
593 s = rail_pdu_init(RAIL_GET_APPID_RESP_ORDER_LENGTH);
594
595 if (!s)
596 {
597 WLog_ERR(TAG, "rail_pdu_init failed!");
598 return CHANNEL_RC_NO_MEMORY;
599 }
600
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);
604 return error;
605}
606
612static UINT rail_send_server_get_appid_resp_ex(RailServerContext* context,
613 const RAIL_GET_APPID_RESP_EX* getAppidRespEx)
614{
615 wStream* s = nullptr;
616 UINT error = 0;
617
618 if (!context || !getAppidRespEx)
619 return ERROR_INVALID_PARAMETER;
620
621 s = rail_pdu_init(RAIL_GET_APPID_RESP_EX_ORDER_LENGTH);
622
623 if (!s)
624 {
625 WLog_ERR(TAG, "rail_pdu_init failed!");
626 return CHANNEL_RC_NO_MEMORY;
627 }
628
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);
632 return error;
633}
634
640static UINT rail_read_client_status_order(wStream* s, RAIL_CLIENT_STATUS_ORDER* clientStatus)
641{
642 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_CLIENT_STATUS_ORDER_LENGTH))
643 return ERROR_INVALID_DATA;
644
645 Stream_Read_UINT32(s, clientStatus->flags); /* Flags (4 bytes) */
646 return CHANNEL_RC_OK;
647}
648
654static UINT rail_read_exec_order(wStream* s, RAIL_EXEC_ORDER* exec, char* args[])
655{
656 RAIL_EXEC_ORDER order = WINPR_C_ARRAY_INIT;
657 UINT16 exeLen = 0;
658 UINT16 workLen = 0;
659 UINT16 argLen = 0;
660
661 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_EXEC_ORDER_LENGTH))
662 return ERROR_INVALID_DATA;
663
664 Stream_Read_UINT16(s, exec->flags); /* Flags (2 bytes) */
665 Stream_Read_UINT16(s, exeLen); /* ExeOrFileLength (2 bytes) */
666 Stream_Read_UINT16(s, workLen); /* WorkingDirLength (2 bytes) */
667 Stream_Read_UINT16(s, argLen); /* ArgumentsLength (2 bytes) */
668
669 if (!Stream_CheckAndLogRequiredLength(TAG, s, (size_t)exeLen + workLen + argLen))
670 return ERROR_INVALID_DATA;
671
672 if (exeLen > 0)
673 {
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)
678 goto fail;
679 }
680 if (workLen > 0)
681 {
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)
686 goto fail;
687 }
688 if (argLen > 0)
689 {
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)
694 goto fail;
695 }
696
697 return CHANNEL_RC_OK;
698fail:
699 free(args[0]);
700 free(args[1]);
701 free(args[2]);
702 *exec = order;
703 return ERROR_INTERNAL_ERROR;
704}
705
711static UINT rail_read_activate_order(wStream* s, RAIL_ACTIVATE_ORDER* activate)
712{
713 BYTE enabled = 0;
714
715 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_ACTIVATE_ORDER_LENGTH))
716 return ERROR_INVALID_DATA;
717
718 Stream_Read_UINT32(s, activate->windowId); /* WindowId (4 bytes) */
719 Stream_Read_UINT8(s, enabled); /* Enabled (1 byte) */
720 activate->enabled = (enabled != 0);
721 return CHANNEL_RC_OK;
722}
723
729static UINT rail_read_sysmenu_order(wStream* s, RAIL_SYSMENU_ORDER* sysmenu)
730{
731 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_SYSMENU_ORDER_LENGTH))
732 return ERROR_INVALID_DATA;
733
734 Stream_Read_UINT32(s, sysmenu->windowId); /* WindowId (4 bytes) */
735 Stream_Read_INT16(s, sysmenu->left); /* Left (2 bytes) */
736 Stream_Read_INT16(s, sysmenu->top); /* Top (2 bytes) */
737 return CHANNEL_RC_OK;
738}
739
745static UINT rail_read_syscommand_order(wStream* s, RAIL_SYSCOMMAND_ORDER* syscommand)
746{
747 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_SYSCOMMAND_ORDER_LENGTH))
748 return ERROR_INVALID_DATA;
749
750 Stream_Read_UINT32(s, syscommand->windowId); /* WindowId (4 bytes) */
751 Stream_Read_UINT16(s, syscommand->command); /* Command (2 bytes) */
752 return CHANNEL_RC_OK;
753}
754
760static UINT rail_read_notify_event_order(wStream* s, RAIL_NOTIFY_EVENT_ORDER* notifyEvent)
761{
762 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_NOTIFY_EVENT_ORDER_LENGTH))
763 return ERROR_INVALID_DATA;
764
765 Stream_Read_UINT32(s, notifyEvent->windowId); /* WindowId (4 bytes) */
766 Stream_Read_UINT32(s, notifyEvent->notifyIconId); /* NotifyIconId (4 bytes) */
767 Stream_Read_UINT32(s, notifyEvent->message); /* Message (4 bytes) */
768 return CHANNEL_RC_OK;
769}
770
776static UINT rail_read_get_appid_req_order(wStream* s, RAIL_GET_APPID_REQ_ORDER* getAppidReq)
777{
778 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_GET_APPID_REQ_ORDER_LENGTH))
779 return ERROR_INVALID_DATA;
780
781 Stream_Read_UINT32(s, getAppidReq->windowId); /* WindowId (4 bytes) */
782 return CHANNEL_RC_OK;
783}
784
790static UINT rail_read_window_move_order(wStream* s, RAIL_WINDOW_MOVE_ORDER* windowMove)
791{
792 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_WINDOW_MOVE_ORDER_LENGTH))
793 return ERROR_INVALID_DATA;
794
795 Stream_Read_UINT32(s, windowMove->windowId); /* WindowId (4 bytes) */
796 Stream_Read_INT16(s, windowMove->left); /* Left (2 bytes) */
797 Stream_Read_INT16(s, windowMove->top); /* Top (2 bytes) */
798 Stream_Read_INT16(s, windowMove->right); /* Right (2 bytes) */
799 Stream_Read_INT16(s, windowMove->bottom); /* Bottom (2 bytes) */
800 return CHANNEL_RC_OK;
801}
802
808static UINT rail_read_snap_arange_order(wStream* s, RAIL_SNAP_ARRANGE* snapArrange)
809{
810 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_SNAP_ARRANGE_ORDER_LENGTH))
811 return ERROR_INVALID_DATA;
812
813 Stream_Read_UINT32(s, snapArrange->windowId); /* WindowId (4 bytes) */
814 Stream_Read_INT16(s, snapArrange->left); /* Left (2 bytes) */
815 Stream_Read_INT16(s, snapArrange->top); /* Top (2 bytes) */
816 Stream_Read_INT16(s, snapArrange->right); /* Right (2 bytes) */
817 Stream_Read_INT16(s, snapArrange->bottom); /* Bottom (2 bytes) */
818 return CHANNEL_RC_OK;
819}
820
826static UINT rail_read_langbar_info_order(wStream* s, RAIL_LANGBAR_INFO_ORDER* langbarInfo)
827{
828 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_LANGBAR_INFO_ORDER_LENGTH))
829 return ERROR_INVALID_DATA;
830
831 Stream_Read_UINT32(s, langbarInfo->languageBarStatus); /* LanguageBarStatus (4 bytes) */
832 return CHANNEL_RC_OK;
833}
834
840static UINT rail_read_language_ime_info_order(wStream* s,
841 RAIL_LANGUAGEIME_INFO_ORDER* languageImeInfo)
842{
843 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_LANGUAGEIME_INFO_ORDER_LENGTH))
844 return ERROR_INVALID_DATA;
845
846 Stream_Read_UINT32(s, languageImeInfo->ProfileType); /* ProfileType (4 bytes) */
847 Stream_Read_UINT16(s, languageImeInfo->LanguageID); /* LanguageID (2 bytes) */
848 Stream_Read(
849 s, &languageImeInfo->LanguageProfileCLSID,
850 sizeof(languageImeInfo->LanguageProfileCLSID)); /* LanguageProfileCLSID (16 bytes) */
851 Stream_Read(s, &languageImeInfo->ProfileGUID,
852 sizeof(languageImeInfo->ProfileGUID)); /* ProfileGUID (16 bytes) */
853 Stream_Read_UINT32(s, languageImeInfo->KeyboardLayout); /* KeyboardLayout (4 bytes) */
854 return CHANNEL_RC_OK;
855}
856
862static UINT rail_read_compartment_info_order(wStream* s,
863 RAIL_COMPARTMENT_INFO_ORDER* compartmentInfo)
864{
865 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_COMPARTMENT_INFO_ORDER_LENGTH))
866 return ERROR_INVALID_DATA;
867
868 Stream_Read_UINT32(s, compartmentInfo->ImeState); /* ImeState (4 bytes) */
869 Stream_Read_UINT32(s, compartmentInfo->ImeConvMode); /* ImeConvMode (4 bytes) */
870 Stream_Read_UINT32(s, compartmentInfo->ImeSentenceMode); /* ImeSentenceMode (4 bytes) */
871 Stream_Read_UINT32(s, compartmentInfo->KanaMode); /* KANAMode (4 bytes) */
872 return CHANNEL_RC_OK;
873}
874
880static UINT rail_read_cloak_order(wStream* s, RAIL_CLOAK* cloak)
881{
882 BYTE cloaked = 0;
883
884 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_CLOAK_ORDER_LENGTH))
885 return ERROR_INVALID_DATA;
886
887 Stream_Read_UINT32(s, cloak->windowId); /* WindowId (4 bytes) */
888 Stream_Read_UINT8(s, cloaked); /* Cloaked (1 byte) */
889 cloak->cloak = (cloaked != 0);
890 return CHANNEL_RC_OK;
891}
892
898static UINT rail_recv_client_handshake_order(RailServerContext* context,
899 RAIL_HANDSHAKE_ORDER* handshake, wStream* s)
900{
901 UINT error = 0;
902
903 if (!context || !handshake || !s)
904 return ERROR_INVALID_PARAMETER;
905
906 if ((error = rail_read_handshake_order(s, handshake)))
907 {
908 WLog_ERR(TAG, "rail_read_handshake_order failed with error %" PRIu32 "!", error);
909 return error;
910 }
911
912 IFCALLRET(context->ClientHandshake, error, context, handshake);
913
914 if (error)
915 WLog_ERR(TAG, "context.ClientHandshake failed with error %" PRIu32 "", error);
916
917 return error;
918}
919
925static UINT rail_recv_client_client_status_order(RailServerContext* context,
926 RAIL_CLIENT_STATUS_ORDER* clientStatus, wStream* s)
927{
928 UINT error = 0;
929
930 if (!context || !clientStatus || !s)
931 return ERROR_INVALID_PARAMETER;
932
933 if ((error = rail_read_client_status_order(s, clientStatus)))
934 {
935 WLog_ERR(TAG, "rail_read_client_status_order failed with error %" PRIu32 "!", error);
936 return error;
937 }
938
939 IFCALLRET(context->ClientClientStatus, error, context, clientStatus);
940
941 if (error)
942 WLog_ERR(TAG, "context.ClientClientStatus failed with error %" PRIu32 "", error);
943
944 return error;
945}
946
952static UINT rail_recv_client_exec_order(RailServerContext* context, wStream* s)
953{
954 UINT error = 0;
955 char* args[3] = WINPR_C_ARRAY_INIT;
956 RAIL_EXEC_ORDER exec = WINPR_C_ARRAY_INIT;
957
958 if (!context || !s)
959 return ERROR_INVALID_PARAMETER;
960
961 error = rail_read_exec_order(s, &exec, args);
962 if (error)
963 {
964 WLog_ERR(TAG, "rail_read_client_status_order failed with error %" PRIu32 "!", error);
965 return error;
966 }
967
968 IFCALLRET(context->ClientExec, error, context, &exec);
969
970 if (error)
971 WLog_ERR(TAG, "context.Exec failed with error %" PRIu32 "", error);
972
973 free(args[0]);
974 free(args[1]);
975 free(args[2]);
976 return error;
977}
978
984static UINT rail_recv_client_sysparam_order(RailServerContext* context,
985 RAIL_SYSPARAM_ORDER* sysparam, wStream* s)
986{
987 UINT error = 0;
988 BOOL extendedSpiSupported = 0;
989
990 if (!context || !sysparam || !s)
991 return ERROR_INVALID_PARAMETER;
992
993 extendedSpiSupported = rail_is_extended_spi_supported(context->priv->channelFlags);
994 if ((error = rail_read_sysparam_order(s, sysparam, extendedSpiSupported)))
995 {
996 WLog_ERR(TAG, "rail_read_sysparam_order failed with error %" PRIu32 "!", error);
997 return error;
998 }
999
1000 IFCALLRET(context->ClientSysparam, error, context, sysparam);
1001
1002 if (error)
1003 WLog_ERR(TAG, "context.ClientSysparam failed with error %" PRIu32 "", error);
1004
1005 return error;
1006}
1007
1013static UINT rail_recv_client_activate_order(RailServerContext* context,
1014 RAIL_ACTIVATE_ORDER* activate, wStream* s)
1015{
1016 UINT error = 0;
1017
1018 if (!context || !activate || !s)
1019 return ERROR_INVALID_PARAMETER;
1020
1021 if ((error = rail_read_activate_order(s, activate)))
1022 {
1023 WLog_ERR(TAG, "rail_read_activate_order failed with error %" PRIu32 "!", error);
1024 return error;
1025 }
1026
1027 IFCALLRET(context->ClientActivate, error, context, activate);
1028
1029 if (error)
1030 WLog_ERR(TAG, "context.ClientActivate failed with error %" PRIu32 "", error);
1031
1032 return error;
1033}
1034
1040static UINT rail_recv_client_sysmenu_order(RailServerContext* context, RAIL_SYSMENU_ORDER* sysmenu,
1041 wStream* s)
1042{
1043 UINT error = 0;
1044
1045 if (!context || !sysmenu || !s)
1046 return ERROR_INVALID_PARAMETER;
1047
1048 if ((error = rail_read_sysmenu_order(s, sysmenu)))
1049 {
1050 WLog_ERR(TAG, "rail_read_sysmenu_order failed with error %" PRIu32 "!", error);
1051 return error;
1052 }
1053
1054 IFCALLRET(context->ClientSysmenu, error, context, sysmenu);
1055
1056 if (error)
1057 WLog_ERR(TAG, "context.ClientSysmenu failed with error %" PRIu32 "", error);
1058
1059 return error;
1060}
1061
1067static UINT rail_recv_client_syscommand_order(RailServerContext* context,
1068 RAIL_SYSCOMMAND_ORDER* syscommand, wStream* s)
1069{
1070 UINT error = 0;
1071
1072 if (!context || !syscommand || !s)
1073 return ERROR_INVALID_PARAMETER;
1074
1075 if ((error = rail_read_syscommand_order(s, syscommand)))
1076 {
1077 WLog_ERR(TAG, "rail_read_syscommand_order failed with error %" PRIu32 "!", error);
1078 return error;
1079 }
1080
1081 IFCALLRET(context->ClientSyscommand, error, context, syscommand);
1082
1083 if (error)
1084 WLog_ERR(TAG, "context.ClientSyscommand failed with error %" PRIu32 "", error);
1085
1086 return error;
1087}
1088
1094static UINT rail_recv_client_notify_event_order(RailServerContext* context,
1095 RAIL_NOTIFY_EVENT_ORDER* notifyEvent, wStream* s)
1096{
1097 UINT error = 0;
1098
1099 if (!context || !notifyEvent || !s)
1100 return ERROR_INVALID_PARAMETER;
1101
1102 if ((error = rail_read_notify_event_order(s, notifyEvent)))
1103 {
1104 WLog_ERR(TAG, "rail_read_notify_event_order failed with error %" PRIu32 "!", error);
1105 return error;
1106 }
1107
1108 IFCALLRET(context->ClientNotifyEvent, error, context, notifyEvent);
1109
1110 if (error)
1111 WLog_ERR(TAG, "context.ClientNotifyEvent failed with error %" PRIu32 "", error);
1112
1113 return error;
1114}
1115
1121static UINT rail_recv_client_window_move_order(RailServerContext* context,
1122 RAIL_WINDOW_MOVE_ORDER* windowMove, wStream* s)
1123{
1124 UINT error = 0;
1125
1126 if (!context || !windowMove || !s)
1127 return ERROR_INVALID_PARAMETER;
1128
1129 if ((error = rail_read_window_move_order(s, windowMove)))
1130 {
1131 WLog_ERR(TAG, "rail_read_window_move_order failed with error %" PRIu32 "!", error);
1132 return error;
1133 }
1134
1135 IFCALLRET(context->ClientWindowMove, error, context, windowMove);
1136
1137 if (error)
1138 WLog_ERR(TAG, "context.ClientWindowMove failed with error %" PRIu32 "", error);
1139
1140 return error;
1141}
1142
1148static UINT rail_recv_client_snap_arrange_order(RailServerContext* context,
1149 RAIL_SNAP_ARRANGE* snapArrange, wStream* s)
1150{
1151 UINT error = 0;
1152
1153 if (!context || !snapArrange || !s)
1154 return ERROR_INVALID_PARAMETER;
1155
1156 if ((error = rail_read_snap_arange_order(s, snapArrange)))
1157 {
1158 WLog_ERR(TAG, "rail_read_snap_arange_order failed with error %" PRIu32 "!", error);
1159 return error;
1160 }
1161
1162 IFCALLRET(context->ClientSnapArrange, error, context, snapArrange);
1163
1164 if (error)
1165 WLog_ERR(TAG, "context.ClientSnapArrange failed with error %" PRIu32 "", error);
1166
1167 return error;
1168}
1169
1175static UINT rail_recv_client_get_appid_req_order(RailServerContext* context,
1176 RAIL_GET_APPID_REQ_ORDER* getAppidReq, wStream* s)
1177{
1178 UINT error = 0;
1179
1180 if (!context || !getAppidReq || !s)
1181 return ERROR_INVALID_PARAMETER;
1182
1183 if ((error = rail_read_get_appid_req_order(s, getAppidReq)))
1184 {
1185 WLog_ERR(TAG, "rail_read_get_appid_req_order failed with error %" PRIu32 "!", error);
1186 return error;
1187 }
1188
1189 IFCALLRET(context->ClientGetAppidReq, error, context, getAppidReq);
1190
1191 if (error)
1192 WLog_ERR(TAG, "context.ClientGetAppidReq failed with error %" PRIu32 "", error);
1193
1194 return error;
1195}
1196
1202static UINT rail_recv_client_langbar_info_order(RailServerContext* context,
1203 RAIL_LANGBAR_INFO_ORDER* langbarInfo, wStream* s)
1204{
1205 UINT error = 0;
1206
1207 if (!context || !langbarInfo || !s)
1208 return ERROR_INVALID_PARAMETER;
1209
1210 if ((error = rail_read_langbar_info_order(s, langbarInfo)))
1211 {
1212 WLog_ERR(TAG, "rail_read_langbar_info_order failed with error %" PRIu32 "!", error);
1213 return error;
1214 }
1215
1216 IFCALLRET(context->ClientLangbarInfo, error, context, langbarInfo);
1217
1218 if (error)
1219 WLog_ERR(TAG, "context.ClientLangbarInfo failed with error %" PRIu32 "", error);
1220
1221 return error;
1222}
1223
1229static UINT rail_recv_client_language_ime_info_order(RailServerContext* context,
1230 RAIL_LANGUAGEIME_INFO_ORDER* languageImeInfo,
1231 wStream* s)
1232{
1233 UINT error = 0;
1234
1235 if (!context || !languageImeInfo || !s)
1236 return ERROR_INVALID_PARAMETER;
1237
1238 if ((error = rail_read_language_ime_info_order(s, languageImeInfo)))
1239 {
1240 WLog_ERR(TAG, "rail_read_language_ime_info_order failed with error %" PRIu32 "!", error);
1241 return error;
1242 }
1243
1244 IFCALLRET(context->ClientLanguageImeInfo, error, context, languageImeInfo);
1245
1246 if (error)
1247 WLog_ERR(TAG, "context.ClientLanguageImeInfo failed with error %" PRIu32 "", error);
1248
1249 return error;
1250}
1251
1257static UINT rail_recv_client_compartment_info(RailServerContext* context,
1258 RAIL_COMPARTMENT_INFO_ORDER* compartmentInfo,
1259 wStream* s)
1260{
1261 UINT error = 0;
1262
1263 if (!context || !compartmentInfo || !s)
1264 return ERROR_INVALID_PARAMETER;
1265
1266 if ((error = rail_read_compartment_info_order(s, compartmentInfo)))
1267 {
1268 WLog_ERR(TAG, "rail_read_compartment_info_order failed with error %" PRIu32 "!", error);
1269 return error;
1270 }
1271
1272 IFCALLRET(context->ClientCompartmentInfo, error, context, compartmentInfo);
1273
1274 if (error)
1275 WLog_ERR(TAG, "context.ClientCompartmentInfo failed with error %" PRIu32 "", error);
1276
1277 return error;
1278}
1279
1285static UINT rail_recv_client_cloak_order(RailServerContext* context, RAIL_CLOAK* cloak, wStream* s)
1286{
1287 UINT error = 0;
1288
1289 if (!context || !cloak || !s)
1290 return ERROR_INVALID_PARAMETER;
1291
1292 if ((error = rail_read_cloak_order(s, cloak)))
1293 {
1294 WLog_ERR(TAG, "rail_read_cloak_order failed with error %" PRIu32 "!", error);
1295 return error;
1296 }
1297
1298 IFCALLRET(context->ClientCloak, error, context, cloak);
1299
1300 if (error)
1301 WLog_ERR(TAG, "context.Cloak failed with error %" PRIu32 "", error);
1302
1303 return error;
1304}
1305
1306static UINT rail_recv_client_text_scale_order(RailServerContext* context, wStream* s)
1307{
1308 UINT error = CHANNEL_RC_OK;
1309 UINT32 TextScaleFactor = 0;
1310
1311 if (!context || !s)
1312 return ERROR_INVALID_PARAMETER;
1313
1314 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1315 return ERROR_INVALID_DATA;
1316
1317 Stream_Read_UINT32(s, TextScaleFactor);
1318 IFCALLRET(context->ClientTextScale, error, context, TextScaleFactor);
1319
1320 if (error)
1321 WLog_ERR(TAG, "context.TextScale failed with error %" PRIu32 "", error);
1322
1323 return error;
1324}
1325
1326static UINT rail_recv_client_caret_blink(RailServerContext* context, wStream* s)
1327{
1328 UINT error = CHANNEL_RC_OK;
1329 UINT32 CaretBlinkRate = 0;
1330
1331 if (!context || !s)
1332 return ERROR_INVALID_PARAMETER;
1333
1334 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1335 return ERROR_INVALID_DATA;
1336
1337 Stream_Read_UINT32(s, CaretBlinkRate);
1338 IFCALLRET(context->ClientCaretBlinkRate, error, context, CaretBlinkRate);
1339
1340 if (error)
1341 WLog_ERR(TAG, "context.CaretBlinkRate failed with error %" PRIu32 "", error);
1342
1343 return error;
1344}
1345
1346static DWORD WINAPI rail_server_thread(LPVOID arg)
1347{
1348 RailServerContext* context = (RailServerContext*)arg;
1349 RailServerPrivate* priv = context->priv;
1350 DWORD status = 0;
1351 DWORD nCount = 0;
1352 HANDLE events[8];
1353 UINT error = CHANNEL_RC_OK;
1354 events[nCount++] = priv->channelEvent;
1355 events[nCount++] = priv->stopEvent;
1356
1357 while (TRUE)
1358 {
1359 status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
1360
1361 if (status == WAIT_FAILED)
1362 {
1363 error = GetLastError();
1364 WLog_ERR(TAG, "WaitForMultipleObjects failed with error %" PRIu32 "!", error);
1365 break;
1366 }
1367
1368 status = WaitForSingleObject(context->priv->stopEvent, 0);
1369
1370 if (status == WAIT_FAILED)
1371 {
1372 error = GetLastError();
1373 WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "!", error);
1374 break;
1375 }
1376
1377 if (status == WAIT_OBJECT_0)
1378 break;
1379
1380 status = WaitForSingleObject(context->priv->channelEvent, 0);
1381
1382 if (status == WAIT_FAILED)
1383 {
1384 error = GetLastError();
1385 WLog_ERR(
1386 TAG,
1387 "WaitForSingleObject(context->priv->channelEvent, 0) failed with error %" PRIu32
1388 "!",
1389 error);
1390 break;
1391 }
1392
1393 if (status == WAIT_OBJECT_0)
1394 {
1395 if ((error = rail_server_handle_messages(context)))
1396 {
1397 WLog_ERR(TAG, "rail_server_handle_messages failed with error %" PRIu32 "", error);
1398 break;
1399 }
1400 }
1401 }
1402
1403 if (error && context->rdpcontext)
1404 setChannelError(context->rdpcontext, error, "rail_server_thread reported an error");
1405
1406 ExitThread(error);
1407 return error;
1408}
1409
1415static UINT rail_server_start(RailServerContext* context)
1416{
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);
1423
1424 if (!priv->rail_channel)
1425 {
1426 WLog_ERR(TAG, "WTSVirtualChannelOpen failed!");
1427 return error;
1428 }
1429
1430 if (!WTSVirtualChannelQuery(priv->rail_channel, WTSVirtualEventHandle, &buffer,
1431 &bytesReturned) ||
1432 (bytesReturned != sizeof(HANDLE)))
1433 {
1434 WLog_ERR(TAG,
1435 "error during WTSVirtualChannelQuery(WTSVirtualEventHandle) or invalid returned "
1436 "size(%" PRIu32 ")",
1437 bytesReturned);
1438
1439 if (buffer)
1440 WTSFreeMemory(buffer);
1441
1442 goto out_close;
1443 }
1444
1445 priv->channelEvent = *(HANDLE*)buffer;
1446 WTSFreeMemory(buffer);
1447 context->priv->stopEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
1448
1449 if (!context->priv->stopEvent)
1450 {
1451 WLog_ERR(TAG, "CreateEvent failed!");
1452 goto out_close;
1453 }
1454
1455 context->priv->thread =
1456 CreateThread(nullptr, 0, rail_server_thread, (void*)context, 0, nullptr);
1457
1458 if (!context->priv->thread)
1459 {
1460 WLog_ERR(TAG, "CreateThread failed!");
1461 goto out_stop_event;
1462 }
1463
1464 return CHANNEL_RC_OK;
1465out_stop_event:
1466 (void)CloseHandle(context->priv->stopEvent);
1467 context->priv->stopEvent = nullptr;
1468out_close:
1469 (void)WTSVirtualChannelClose(context->priv->rail_channel);
1470 context->priv->rail_channel = nullptr;
1471 return error;
1472}
1473
1474static BOOL rail_server_stop(RailServerContext* context)
1475{
1476 RailServerPrivate* priv = context->priv;
1477
1478 if (priv->thread)
1479 {
1480 (void)SetEvent(priv->stopEvent);
1481
1482 if (WaitForSingleObject(priv->thread, INFINITE) == WAIT_FAILED)
1483 {
1484 WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "", GetLastError());
1485 return FALSE;
1486 }
1487
1488 (void)CloseHandle(priv->thread);
1489 (void)CloseHandle(priv->stopEvent);
1490 priv->thread = nullptr;
1491 priv->stopEvent = nullptr;
1492 }
1493
1494 if (priv->rail_channel)
1495 {
1496 (void)WTSVirtualChannelClose(priv->rail_channel);
1497 priv->rail_channel = nullptr;
1498 }
1499
1500 priv->channelEvent = nullptr;
1501 return TRUE;
1502}
1503
1504RailServerContext* rail_server_context_new(HANDLE vcm)
1505{
1506 RailServerContext* context = nullptr;
1507 RailServerPrivate* priv = nullptr;
1508 context = (RailServerContext*)calloc(1, sizeof(RailServerContext));
1509
1510 if (!context)
1511 {
1512 WLog_ERR(TAG, "calloc failed!");
1513 return nullptr;
1514 }
1515
1516 context->vcm = vcm;
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));
1533
1534 if (!priv)
1535 {
1536 WLog_ERR(TAG, "calloc failed!");
1537 goto out_free;
1538 }
1539
1540 /* Create shared input stream */
1541 priv->input_stream = Stream_New(nullptr, 4096);
1542
1543 if (!priv->input_stream)
1544 {
1545 WLog_ERR(TAG, "Stream_New failed!");
1546 goto out_free_priv;
1547 }
1548
1549 return context;
1550out_free_priv:
1551 free(context->priv);
1552out_free:
1553 free(context);
1554 return nullptr;
1555}
1556
1557void rail_server_context_free(RailServerContext* context)
1558{
1559 if (context->priv)
1560 Stream_Free(context->priv->input_stream, TRUE);
1561
1562 free(context->priv);
1563 free(context);
1564}
1565
1566void rail_server_set_handshake_ex_flags(RailServerContext* context, DWORD flags)
1567{
1568 RailServerPrivate* priv = nullptr;
1569
1570 if (!context || !context->priv)
1571 return;
1572
1573 priv = context->priv;
1574 priv->channelFlags = flags;
1575}
1576
1577UINT rail_server_handle_messages(RailServerContext* context)
1578{
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;
1586
1587 /* Read header */
1588 if (!Stream_EnsureRemainingCapacity(s, RAIL_PDU_HEADER_LENGTH))
1589 {
1590 WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed, RAIL_PDU_HEADER_LENGTH");
1591 return CHANNEL_RC_NO_MEMORY;
1592 }
1593
1594 if (!WTSVirtualChannelRead(priv->rail_channel, 0, Stream_Pointer(s), RAIL_PDU_HEADER_LENGTH,
1595 &bytesReturned))
1596 {
1597 if (GetLastError() == ERROR_NO_DATA)
1598 return ERROR_NO_DATA;
1599
1600 WLog_ERR(TAG, "channel connection closed");
1601 return ERROR_INTERNAL_ERROR;
1602 }
1603
1604 /* Parse header */
1605 if ((status = rail_read_pdu_header(s, &orderType, &orderLength)) != CHANNEL_RC_OK)
1606 {
1607 WLog_ERR(TAG, "rail_read_pdu_header failed with error %" PRIu32 "!", status);
1608 return status;
1609 }
1610
1611 if (!Stream_EnsureRemainingCapacity(s, orderLength - RAIL_PDU_HEADER_LENGTH))
1612 {
1613 WLog_ERR(TAG,
1614 "Stream_EnsureRemainingCapacity failed, orderLength - RAIL_PDU_HEADER_LENGTH");
1615 return CHANNEL_RC_NO_MEMORY;
1616 }
1617
1618 /* Read body */
1619 if (!WTSVirtualChannelRead(priv->rail_channel, 0, Stream_Pointer(s),
1620 orderLength - RAIL_PDU_HEADER_LENGTH, &bytesReturned))
1621 {
1622 if (GetLastError() == ERROR_NO_DATA)
1623 return ERROR_NO_DATA;
1624
1625 WLog_ERR(TAG, "channel connection closed");
1626 return ERROR_INTERNAL_ERROR;
1627 }
1628
1629 WLog_DBG(TAG, "Received %s PDU, length:%" PRIu16 "",
1630 rail_get_order_type_string_full(orderType, buffer, sizeof(buffer)), orderLength);
1631
1632 switch (orderType)
1633 {
1634 case TS_RAIL_ORDER_HANDSHAKE:
1635 {
1636 RAIL_HANDSHAKE_ORDER handshake;
1637 return rail_recv_client_handshake_order(context, &handshake, s);
1638 }
1639
1640 case TS_RAIL_ORDER_CLIENTSTATUS:
1641 {
1642 RAIL_CLIENT_STATUS_ORDER clientStatus;
1643 return rail_recv_client_client_status_order(context, &clientStatus, s);
1644 }
1645
1646 case TS_RAIL_ORDER_EXEC:
1647 return rail_recv_client_exec_order(context, s);
1648
1649 case TS_RAIL_ORDER_SYSPARAM:
1650 {
1651 RAIL_SYSPARAM_ORDER sysparam = WINPR_C_ARRAY_INIT;
1652 return rail_recv_client_sysparam_order(context, &sysparam, s);
1653 }
1654
1655 case TS_RAIL_ORDER_ACTIVATE:
1656 {
1657 RAIL_ACTIVATE_ORDER activate;
1658 return rail_recv_client_activate_order(context, &activate, s);
1659 }
1660
1661 case TS_RAIL_ORDER_SYSMENU:
1662 {
1663 RAIL_SYSMENU_ORDER sysmenu;
1664 return rail_recv_client_sysmenu_order(context, &sysmenu, s);
1665 }
1666
1667 case TS_RAIL_ORDER_SYSCOMMAND:
1668 {
1669 RAIL_SYSCOMMAND_ORDER syscommand;
1670 return rail_recv_client_syscommand_order(context, &syscommand, s);
1671 }
1672
1673 case TS_RAIL_ORDER_NOTIFY_EVENT:
1674 {
1675 RAIL_NOTIFY_EVENT_ORDER notifyEvent;
1676 return rail_recv_client_notify_event_order(context, &notifyEvent, s);
1677 }
1678
1679 case TS_RAIL_ORDER_WINDOWMOVE:
1680 {
1681 RAIL_WINDOW_MOVE_ORDER windowMove;
1682 return rail_recv_client_window_move_order(context, &windowMove, s);
1683 }
1684
1685 case TS_RAIL_ORDER_SNAP_ARRANGE:
1686 {
1687 RAIL_SNAP_ARRANGE snapArrange;
1688 return rail_recv_client_snap_arrange_order(context, &snapArrange, s);
1689 }
1690
1691 case TS_RAIL_ORDER_GET_APPID_REQ:
1692 {
1693 RAIL_GET_APPID_REQ_ORDER getAppidReq;
1694 return rail_recv_client_get_appid_req_order(context, &getAppidReq, s);
1695 }
1696
1697 case TS_RAIL_ORDER_LANGBARINFO:
1698 {
1699 RAIL_LANGBAR_INFO_ORDER langbarInfo;
1700 return rail_recv_client_langbar_info_order(context, &langbarInfo, s);
1701 }
1702
1703 case TS_RAIL_ORDER_LANGUAGEIMEINFO:
1704 {
1705 RAIL_LANGUAGEIME_INFO_ORDER languageImeInfo;
1706 return rail_recv_client_language_ime_info_order(context, &languageImeInfo, s);
1707 }
1708
1709 case TS_RAIL_ORDER_COMPARTMENTINFO:
1710 {
1711 RAIL_COMPARTMENT_INFO_ORDER compartmentInfo;
1712 return rail_recv_client_compartment_info(context, &compartmentInfo, s);
1713 }
1714
1715 case TS_RAIL_ORDER_CLOAK:
1716 {
1717 RAIL_CLOAK cloak;
1718 return rail_recv_client_cloak_order(context, &cloak, s);
1719 }
1720
1721 case TS_RAIL_ORDER_TEXTSCALEINFO:
1722 {
1723 return rail_recv_client_text_scale_order(context, s);
1724 }
1725
1726 case TS_RAIL_ORDER_CARETBLINKINFO:
1727 {
1728 return rail_recv_client_caret_blink(context, s);
1729 }
1730
1731 default:
1732 WLog_ERR(TAG, "Unknown RAIL PDU order received.");
1733 return ERROR_INVALID_DATA;
1734 }
1735}