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#include <freerdp/utils/channel_pdu_tracker.h>
27
28#include <winpr/crt.h>
29#include <winpr/synch.h>
30#include <winpr/thread.h>
31#include <winpr/stream.h>
32
33#include "rail_main.h"
34
35#define TAG CHANNELS_TAG("rail.server")
36
42WINPR_ATTR_NODISCARD
43static UINT rail_send(RailServerContext* context, wStream* s, size_t length)
44{
45 UINT status = CHANNEL_RC_OK;
46 ULONG written = 0;
47
48 const ULONG ulen = WINPR_ASSERTING_INT_CAST(ULONG, length);
49 WINPR_ASSERT(context);
50
51 if (!WTSVirtualChannelWrite(context->priv->rail_channel, Stream_BufferAs(s, char), ulen,
52 &written))
53 {
54 WLog_ERR(TAG, "WTSVirtualChannelWrite failed!");
55 status = ERROR_INTERNAL_ERROR;
56 }
57
58 return status;
59}
60
66WINPR_ATTR_NODISCARD
67static UINT rail_server_send_pdu(RailServerContext* context, wStream* s, UINT16 orderType)
68{
69 char buffer[128] = WINPR_C_ARRAY_INIT;
70
71 WINPR_ASSERT(context);
72 WINPR_ASSERT(s);
73
74 const size_t orderLength = Stream_GetPosition(s);
75 Stream_ResetPosition(s);
76 if (!rail_write_pdu_header(s, orderType, WINPR_ASSERTING_INT_CAST(UINT16, orderLength)))
77 goto fail;
78 if (!Stream_SetPosition(s, orderLength))
79 goto fail;
80 WLog_DBG(TAG, "Sending %s PDU, length: %" PRIuz "",
81 rail_get_order_type_string_full(orderType, buffer, sizeof(buffer)), orderLength);
82 return rail_send(context, s, orderLength);
83
84fail:
85 Stream_Free(s, TRUE);
86 return ERROR_INVALID_DATA;
87}
88
89static void rail_write_local_move_size_order(wStream* s,
90 const RAIL_LOCALMOVESIZE_ORDER* localMoveSize)
91{
92 WINPR_ASSERT(s);
93 WINPR_ASSERT(localMoveSize);
94 WINPR_ASSERT(Stream_EnsureRemainingCapacity(s, 12));
95
96 Stream_Write_UINT32(s, localMoveSize->windowId); /* WindowId (4 bytes) */
97 Stream_Write_UINT16(s, localMoveSize->isMoveSizeStart ? 1 : 0); /* IsMoveSizeStart (2 bytes) */
98 Stream_Write_UINT16(s, localMoveSize->moveSizeType); /* MoveSizeType (2 bytes) */
99 Stream_Write_INT16(s, localMoveSize->posX); /* PosX (2 bytes) */
100 Stream_Write_INT16(s, localMoveSize->posY); /* PosY (2 bytes) */
101}
102
103static void rail_write_min_max_info_order(wStream* s, const RAIL_MINMAXINFO_ORDER* minMaxInfo)
104{
105 WINPR_ASSERT(s);
106 WINPR_ASSERT(minMaxInfo);
107 WINPR_ASSERT(Stream_EnsureRemainingCapacity(s, 20));
108
109 Stream_Write_UINT32(s, minMaxInfo->windowId); /* WindowId (4 bytes) */
110 Stream_Write_INT16(s, minMaxInfo->maxWidth); /* MaxWidth (2 bytes) */
111 Stream_Write_INT16(s, minMaxInfo->maxHeight); /* MaxHeight (2 bytes) */
112 Stream_Write_INT16(s, minMaxInfo->maxPosX); /* MaxPosX (2 bytes) */
113 Stream_Write_INT16(s, minMaxInfo->maxPosY); /* MaxPosY (2 bytes) */
114 Stream_Write_INT16(s, minMaxInfo->minTrackWidth); /* MinTrackWidth (2 bytes) */
115 Stream_Write_INT16(s, minMaxInfo->minTrackHeight); /* MinTrackHeight (2 bytes) */
116 Stream_Write_INT16(s, minMaxInfo->maxTrackWidth); /* MaxTrackWidth (2 bytes) */
117 Stream_Write_INT16(s, minMaxInfo->maxTrackHeight); /* MaxTrackHeight (2 bytes) */
118}
119
120static void rail_write_taskbar_info_order(wStream* s, const RAIL_TASKBAR_INFO_ORDER* taskbarInfo)
121{
122 WINPR_ASSERT(s);
123 WINPR_ASSERT(taskbarInfo);
124 WINPR_ASSERT(Stream_EnsureRemainingCapacity(s, 12));
125
126 Stream_Write_UINT32(s, taskbarInfo->TaskbarMessage); /* TaskbarMessage (4 bytes) */
127 Stream_Write_UINT32(s, taskbarInfo->WindowIdTab); /* WindowIdTab (4 bytes) */
128 Stream_Write_UINT32(s, taskbarInfo->Body); /* Body (4 bytes) */
129}
130
131static void rail_write_langbar_info_order(wStream* s, const RAIL_LANGBAR_INFO_ORDER* langbarInfo)
132{
133 WINPR_ASSERT(s);
134 WINPR_ASSERT(langbarInfo);
135 WINPR_ASSERT(Stream_EnsureRemainingCapacity(s, 4));
136
137 Stream_Write_UINT32(s, langbarInfo->languageBarStatus); /* LanguageBarStatus (4 bytes) */
138}
139
145WINPR_ATTR_NODISCARD
146static UINT rail_write_exec_result_order(wStream* s, const RAIL_EXEC_RESULT_ORDER* execResult)
147{
148 WINPR_ASSERT(s);
149 WINPR_ASSERT(execResult);
150
151 if (execResult->exeOrFile.length > 520 || execResult->exeOrFile.length < 1)
152 return ERROR_INVALID_DATA;
153
154 Stream_Write_UINT16(s, execResult->flags); /* Flags (2 bytes) */
155 Stream_Write_UINT16(s, execResult->execResult); /* ExecResult (2 bytes) */
156 Stream_Write_UINT32(s, execResult->rawResult); /* RawResult (4 bytes) */
157 Stream_Write_UINT16(s, 0); /* Padding (2 bytes) */
158 return rail_write_unicode_string(s, &execResult->exeOrFile);
159}
160
161static void rail_write_z_order_sync_order(wStream* s, const RAIL_ZORDER_SYNC* zOrderSync)
162{
163 WINPR_ASSERT(s);
164 WINPR_ASSERT(zOrderSync);
165 WINPR_ASSERT(Stream_EnsureRemainingCapacity(s, 4));
166 Stream_Write_UINT32(s, zOrderSync->windowIdMarker); /* WindowIdMarker (4 bytes) */
167}
168
169static void rail_write_cloak_order(wStream* s, const RAIL_CLOAK* cloak)
170{
171 WINPR_ASSERT(s);
172 WINPR_ASSERT(cloak);
173 WINPR_ASSERT(Stream_EnsureRemainingCapacity(s, 5));
174
175 Stream_Write_UINT32(s, cloak->windowId); /* WindowId (4 bytes) */
176 Stream_Write_UINT8(s, cloak->cloak ? 1 : 0); /* Cloaked (1 byte) */
177}
178
179static void
180rail_write_power_display_request_order(wStream* s,
181 const RAIL_POWER_DISPLAY_REQUEST* powerDisplayRequest)
182{
183 WINPR_ASSERT(s);
184 WINPR_ASSERT(powerDisplayRequest);
185 WINPR_ASSERT(Stream_EnsureRemainingCapacity(s, 4));
186
187 Stream_Write_UINT32(s, powerDisplayRequest->active ? 1 : 0); /* Active (4 bytes) */
188}
189
190WINPR_ATTR_NODISCARD
191static UINT rail_write_get_app_id_resp_order(wStream* s,
192 const RAIL_GET_APPID_RESP_ORDER* getAppidResp)
193{
194 WINPR_ASSERT(s);
195 WINPR_ASSERT(getAppidResp);
196 if (!Stream_EnsureRemainingCapacity(s, 4ull + ARRAYSIZE(getAppidResp->applicationId)))
197 return ERROR_OUTOFMEMORY;
198
199 Stream_Write_UINT32(s, getAppidResp->windowId); /* WindowId (4 bytes) */
200 if (!Stream_Write_UTF16_String(
201 s, getAppidResp->applicationId,
202 ARRAYSIZE(getAppidResp->applicationId))) /* ApplicationId (512 bytes) */
203 return ERROR_INVALID_DATA;
204 return ERROR_SUCCESS;
205}
206
207WINPR_ATTR_NODISCARD
208static UINT rail_write_get_appid_resp_ex_order(wStream* s,
209 const RAIL_GET_APPID_RESP_EX* getAppidRespEx)
210{
211 WINPR_ASSERT(s);
212 WINPR_ASSERT(getAppidRespEx);
213
214 if (!Stream_EnsureRemainingCapacity(s, (8ull + ARRAYSIZE(getAppidRespEx->applicationID) +
215 ARRAYSIZE(getAppidRespEx->processImageName))))
216 return ERROR_OUTOFMEMORY;
217
218 Stream_Write_UINT32(s, getAppidRespEx->windowID); /* WindowId (4 bytes) */
219 if (!Stream_Write_UTF16_String(
220 s, getAppidRespEx->applicationID,
221 ARRAYSIZE(getAppidRespEx->applicationID))) /* ApplicationId (520 bytes) */
222 return ERROR_INVALID_DATA;
223 Stream_Write_UINT32(s, getAppidRespEx->processId); /* ProcessId (4 bytes) */
224 if (!Stream_Write_UTF16_String(
225 s, getAppidRespEx->processImageName,
226 ARRAYSIZE(getAppidRespEx->processImageName))) /* ProcessImageName (520 bytes) */
227 return ERROR_INVALID_DATA;
228 return ERROR_SUCCESS;
229}
230
236WINPR_ATTR_NODISCARD
237static UINT rail_send_server_handshake(RailServerContext* context,
238 const RAIL_HANDSHAKE_ORDER* handshake)
239{
240 if (!context || !handshake)
241 return ERROR_INVALID_PARAMETER;
242
243 wStream* s = rail_pdu_init(RAIL_HANDSHAKE_ORDER_LENGTH);
244
245 if (!s)
246 {
247 WLog_ERR(TAG, "rail_pdu_init failed!");
248 return CHANNEL_RC_NO_MEMORY;
249 }
250
251 rail_write_handshake_order(s, handshake);
252 return rail_server_send_pdu(context, s, TS_RAIL_ORDER_HANDSHAKE);
253}
254
260WINPR_ATTR_NODISCARD
261static UINT rail_send_server_handshake_ex(RailServerContext* context,
262 const RAIL_HANDSHAKE_EX_ORDER* handshakeEx)
263{
264 if (!context || !handshakeEx || !context->priv)
265 return ERROR_INVALID_PARAMETER;
266
267 wStream* s = rail_pdu_init(RAIL_HANDSHAKE_EX_ORDER_LENGTH);
268
269 if (!s)
270 {
271 WLog_ERR(TAG, "rail_pdu_init failed!");
272 return CHANNEL_RC_NO_MEMORY;
273 }
274
275 rail_server_set_handshake_ex_flags(context, handshakeEx->railHandshakeFlags);
276 rail_write_handshake_ex_order(s, handshakeEx);
277 return rail_server_send_pdu(context, s, TS_RAIL_ORDER_HANDSHAKE_EX);
278}
279
285WINPR_ATTR_NODISCARD
286static UINT rail_send_server_sysparam(RailServerContext* context,
287 const RAIL_SYSPARAM_ORDER* sysparam)
288{
289 if (!context || !sysparam)
290 return ERROR_INVALID_PARAMETER;
291
292 RailServerPrivate* priv = context->priv;
293
294 if (!priv)
295 return ERROR_INVALID_PARAMETER;
296
297 const BOOL extendedSpiSupported = rail_is_extended_spi_supported(context->priv->channelFlags);
298 wStream* s = rail_pdu_init(RAIL_SYSPARAM_ORDER_LENGTH);
299
300 if (!s)
301 {
302 WLog_ERR(TAG, "rail_pdu_init failed!");
303 return CHANNEL_RC_NO_MEMORY;
304 }
305
306 const UINT error = rail_write_sysparam_order(s, sysparam, extendedSpiSupported);
307 if (error != CHANNEL_RC_OK)
308 {
309 Stream_Free(s, TRUE);
310 return error;
311 }
312 return rail_server_send_pdu(context, s, TS_RAIL_ORDER_SYSPARAM);
313}
314
320WINPR_ATTR_NODISCARD
321static UINT rail_send_server_local_move_size(RailServerContext* context,
322 const RAIL_LOCALMOVESIZE_ORDER* localMoveSize)
323{
324 if (!context || !localMoveSize)
325 return ERROR_INVALID_PARAMETER;
326
327 wStream* s = rail_pdu_init(RAIL_LOCALMOVESIZE_ORDER_LENGTH);
328
329 if (!s)
330 {
331 WLog_ERR(TAG, "rail_pdu_init failed!");
332 return CHANNEL_RC_NO_MEMORY;
333 }
334
335 rail_write_local_move_size_order(s, localMoveSize);
336 return rail_server_send_pdu(context, s, TS_RAIL_ORDER_LOCALMOVESIZE);
337}
338
344WINPR_ATTR_NODISCARD
345static UINT rail_send_server_min_max_info(RailServerContext* context,
346 const RAIL_MINMAXINFO_ORDER* minMaxInfo)
347{
348 if (!context || !minMaxInfo)
349 return ERROR_INVALID_PARAMETER;
350
351 wStream* s = rail_pdu_init(RAIL_MINMAXINFO_ORDER_LENGTH);
352
353 if (!s)
354 {
355 WLog_ERR(TAG, "rail_pdu_init failed!");
356 return CHANNEL_RC_NO_MEMORY;
357 }
358
359 rail_write_min_max_info_order(s, minMaxInfo);
360 return rail_server_send_pdu(context, s, TS_RAIL_ORDER_MINMAXINFO);
361}
362
368WINPR_ATTR_NODISCARD
369static UINT rail_send_server_taskbar_info(RailServerContext* context,
370 const RAIL_TASKBAR_INFO_ORDER* taskbarInfo)
371{
372 if (!context || !taskbarInfo)
373 return ERROR_INVALID_PARAMETER;
374
375 wStream* s = rail_pdu_init(RAIL_TASKBAR_INFO_ORDER_LENGTH);
376
377 if (!s)
378 {
379 WLog_ERR(TAG, "rail_pdu_init failed!");
380 return CHANNEL_RC_NO_MEMORY;
381 }
382
383 rail_write_taskbar_info_order(s, taskbarInfo);
384 return rail_server_send_pdu(context, s, TS_RAIL_ORDER_TASKBARINFO);
385}
386
392WINPR_ATTR_NODISCARD
393static UINT rail_send_server_langbar_info(RailServerContext* context,
394 const RAIL_LANGBAR_INFO_ORDER* langbarInfo)
395{
396 if (!context || !langbarInfo)
397 return ERROR_INVALID_PARAMETER;
398
399 wStream* s = rail_pdu_init(RAIL_LANGBAR_INFO_ORDER_LENGTH);
400
401 if (!s)
402 {
403 WLog_ERR(TAG, "rail_pdu_init failed!");
404 return CHANNEL_RC_NO_MEMORY;
405 }
406
407 rail_write_langbar_info_order(s, langbarInfo);
408 return rail_server_send_pdu(context, s, TS_RAIL_ORDER_LANGBARINFO);
409}
410
416WINPR_ATTR_NODISCARD
417static UINT rail_send_server_exec_result(RailServerContext* context,
418 const RAIL_EXEC_RESULT_ORDER* execResult)
419{
420 if (!context || !execResult)
421 return ERROR_INVALID_PARAMETER;
422
423 wStream* s = rail_pdu_init(RAIL_EXEC_RESULT_ORDER_LENGTH + execResult->exeOrFile.length);
424
425 if (!s)
426 {
427 WLog_ERR(TAG, "rail_pdu_init failed!");
428 return CHANNEL_RC_NO_MEMORY;
429 }
430
431 const UINT error = rail_write_exec_result_order(s, execResult);
432 if (error != CHANNEL_RC_OK)
433 {
434 Stream_Free(s, TRUE);
435 return error;
436 }
437 return rail_server_send_pdu(context, s, TS_RAIL_ORDER_EXEC_RESULT);
438}
439
445WINPR_ATTR_NODISCARD
446static UINT rail_send_server_z_order_sync(RailServerContext* context,
447 const RAIL_ZORDER_SYNC* zOrderSync)
448{
449 if (!context || !zOrderSync)
450 return ERROR_INVALID_PARAMETER;
451
452 wStream* s = rail_pdu_init(RAIL_Z_ORDER_SYNC_ORDER_LENGTH);
453
454 if (!s)
455 {
456 WLog_ERR(TAG, "rail_pdu_init failed!");
457 return CHANNEL_RC_NO_MEMORY;
458 }
459
460 rail_write_z_order_sync_order(s, zOrderSync);
461 return rail_server_send_pdu(context, s, TS_RAIL_ORDER_ZORDER_SYNC);
462}
463
469WINPR_ATTR_NODISCARD
470static UINT rail_send_server_cloak(RailServerContext* context, const RAIL_CLOAK* cloak)
471{
472 if (!context || !cloak)
473 return ERROR_INVALID_PARAMETER;
474
475 wStream* s = rail_pdu_init(RAIL_CLOAK_ORDER_LENGTH);
476
477 if (!s)
478 {
479 WLog_ERR(TAG, "rail_pdu_init failed!");
480 return CHANNEL_RC_NO_MEMORY;
481 }
482
483 rail_write_cloak_order(s, cloak);
484 return rail_server_send_pdu(context, s, TS_RAIL_ORDER_CLOAK);
485}
486
492WINPR_ATTR_NODISCARD
493static UINT
494rail_send_server_power_display_request(RailServerContext* context,
495 const RAIL_POWER_DISPLAY_REQUEST* powerDisplayRequest)
496{
497 if (!context || !powerDisplayRequest)
498 return ERROR_INVALID_PARAMETER;
499
500 wStream* s = rail_pdu_init(RAIL_POWER_DISPLAY_REQUEST_ORDER_LENGTH);
501
502 if (!s)
503 {
504 WLog_ERR(TAG, "rail_pdu_init failed!");
505 return CHANNEL_RC_NO_MEMORY;
506 }
507
508 rail_write_power_display_request_order(s, powerDisplayRequest);
509 return rail_server_send_pdu(context, s, TS_RAIL_ORDER_POWER_DISPLAY_REQUEST);
510}
511
517WINPR_ATTR_NODISCARD
518static UINT rail_send_server_get_app_id_resp(RailServerContext* context,
519 const RAIL_GET_APPID_RESP_ORDER* getAppidResp)
520{
521 if (!context || !getAppidResp)
522 return ERROR_INVALID_PARAMETER;
523
524 wStream* s = rail_pdu_init(RAIL_GET_APPID_RESP_ORDER_LENGTH);
525
526 if (!s)
527 {
528 WLog_ERR(TAG, "rail_pdu_init failed!");
529 return CHANNEL_RC_NO_MEMORY;
530 }
531
532 const UINT error = rail_write_get_app_id_resp_order(s, getAppidResp);
533 if (error != CHANNEL_RC_OK)
534 {
535 Stream_Free(s, TRUE);
536 return error;
537 }
538 return rail_server_send_pdu(context, s, TS_RAIL_ORDER_GET_APPID_RESP);
539}
540
546WINPR_ATTR_NODISCARD
547static UINT rail_send_server_get_appid_resp_ex(RailServerContext* context,
548 const RAIL_GET_APPID_RESP_EX* getAppidRespEx)
549{
550 if (!context || !getAppidRespEx)
551 return ERROR_INVALID_PARAMETER;
552
553 wStream* s = rail_pdu_init(RAIL_GET_APPID_RESP_EX_ORDER_LENGTH);
554
555 if (!s)
556 {
557 WLog_ERR(TAG, "rail_pdu_init failed!");
558 return CHANNEL_RC_NO_MEMORY;
559 }
560
561 const UINT error = rail_write_get_appid_resp_ex_order(s, getAppidRespEx);
562 if (error != CHANNEL_RC_OK)
563 {
564 Stream_Free(s, TRUE);
565 return error;
566 }
567 return rail_server_send_pdu(context, s, TS_RAIL_ORDER_GET_APPID_RESP_EX);
568}
569
575WINPR_ATTR_NODISCARD
576static UINT rail_read_client_status_order(wStream* s, RAIL_CLIENT_STATUS_ORDER* clientStatus)
577{
578 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_CLIENT_STATUS_ORDER_LENGTH))
579 return ERROR_INVALID_DATA;
580
581 Stream_Read_UINT32(s, clientStatus->flags); /* Flags (4 bytes) */
582 return CHANNEL_RC_OK;
583}
584
590WINPR_ATTR_NODISCARD
591static UINT rail_read_exec_order(wStream* s, RAIL_EXEC_ORDER* exec, char* args[])
592{
593 RAIL_EXEC_ORDER order = WINPR_C_ARRAY_INIT;
594
595 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_EXEC_ORDER_LENGTH))
596 return ERROR_INVALID_DATA;
597
598 exec->flags = Stream_Get_UINT16(s); /* Flags (2 bytes) */
599 const UINT16 exeLen = Stream_Get_UINT16(s); /* ExeOrFileLength (2 bytes) */
600 const UINT16 workLen = Stream_Get_UINT16(s); /* WorkingDirLength (2 bytes) */
601 const UINT16 argLen = Stream_Get_UINT16(s); /* ArgumentsLength (2 bytes) */
602
603 if (!Stream_CheckAndLogRequiredLength(TAG, s, (size_t)exeLen + workLen + argLen))
604 return ERROR_INVALID_DATA;
605
606 if (exeLen > 0)
607 {
608 const size_t len = exeLen / sizeof(WCHAR);
609 exec->RemoteApplicationProgram = args[0] =
610 Stream_Read_UTF16_String_As_UTF8(s, len, nullptr);
611 if (!exec->RemoteApplicationProgram)
612 goto fail;
613 }
614 if (workLen > 0)
615 {
616 const size_t len = workLen / sizeof(WCHAR);
617 exec->RemoteApplicationWorkingDir = args[1] =
618 Stream_Read_UTF16_String_As_UTF8(s, len, nullptr);
619 if (!exec->RemoteApplicationWorkingDir)
620 goto fail;
621 }
622 if (argLen > 0)
623 {
624 const size_t len = argLen / sizeof(WCHAR);
625 exec->RemoteApplicationArguments = args[2] =
626 Stream_Read_UTF16_String_As_UTF8(s, len, nullptr);
627 if (!exec->RemoteApplicationArguments)
628 goto fail;
629 }
630
631 return CHANNEL_RC_OK;
632fail:
633 free(args[0]);
634 free(args[1]);
635 free(args[2]);
636 *exec = order;
637 return ERROR_INTERNAL_ERROR;
638}
639
645WINPR_ATTR_NODISCARD
646static UINT rail_read_activate_order(wStream* s, RAIL_ACTIVATE_ORDER* activate)
647{
648 BYTE enabled = 0;
649
650 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_ACTIVATE_ORDER_LENGTH))
651 return ERROR_INVALID_DATA;
652
653 Stream_Read_UINT32(s, activate->windowId); /* WindowId (4 bytes) */
654 Stream_Read_UINT8(s, enabled); /* Enabled (1 byte) */
655 activate->enabled = (enabled != 0);
656 return CHANNEL_RC_OK;
657}
658
664WINPR_ATTR_NODISCARD
665static UINT rail_read_sysmenu_order(wStream* s, RAIL_SYSMENU_ORDER* sysmenu)
666{
667 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_SYSMENU_ORDER_LENGTH))
668 return ERROR_INVALID_DATA;
669
670 Stream_Read_UINT32(s, sysmenu->windowId); /* WindowId (4 bytes) */
671 Stream_Read_INT16(s, sysmenu->left); /* Left (2 bytes) */
672 Stream_Read_INT16(s, sysmenu->top); /* Top (2 bytes) */
673 return CHANNEL_RC_OK;
674}
675
681WINPR_ATTR_NODISCARD
682static UINT rail_read_syscommand_order(wStream* s, RAIL_SYSCOMMAND_ORDER* syscommand)
683{
684 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_SYSCOMMAND_ORDER_LENGTH))
685 return ERROR_INVALID_DATA;
686
687 Stream_Read_UINT32(s, syscommand->windowId); /* WindowId (4 bytes) */
688 Stream_Read_UINT16(s, syscommand->command); /* Command (2 bytes) */
689 return CHANNEL_RC_OK;
690}
691
697WINPR_ATTR_NODISCARD
698static UINT rail_read_notify_event_order(wStream* s, RAIL_NOTIFY_EVENT_ORDER* notifyEvent)
699{
700 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_NOTIFY_EVENT_ORDER_LENGTH))
701 return ERROR_INVALID_DATA;
702
703 Stream_Read_UINT32(s, notifyEvent->windowId); /* WindowId (4 bytes) */
704 Stream_Read_UINT32(s, notifyEvent->notifyIconId); /* NotifyIconId (4 bytes) */
705 Stream_Read_UINT32(s, notifyEvent->message); /* Message (4 bytes) */
706 return CHANNEL_RC_OK;
707}
708
714WINPR_ATTR_NODISCARD
715static UINT rail_read_get_appid_req_order(wStream* s, RAIL_GET_APPID_REQ_ORDER* getAppidReq)
716{
717 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_GET_APPID_REQ_ORDER_LENGTH))
718 return ERROR_INVALID_DATA;
719
720 Stream_Read_UINT32(s, getAppidReq->windowId); /* WindowId (4 bytes) */
721 return CHANNEL_RC_OK;
722}
723
729WINPR_ATTR_NODISCARD
730static UINT rail_read_window_move_order(wStream* s, RAIL_WINDOW_MOVE_ORDER* windowMove)
731{
732 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_WINDOW_MOVE_ORDER_LENGTH))
733 return ERROR_INVALID_DATA;
734
735 Stream_Read_UINT32(s, windowMove->windowId); /* WindowId (4 bytes) */
736 Stream_Read_INT16(s, windowMove->left); /* Left (2 bytes) */
737 Stream_Read_INT16(s, windowMove->top); /* Top (2 bytes) */
738 Stream_Read_INT16(s, windowMove->right); /* Right (2 bytes) */
739 Stream_Read_INT16(s, windowMove->bottom); /* Bottom (2 bytes) */
740 return CHANNEL_RC_OK;
741}
742
748WINPR_ATTR_NODISCARD
749static UINT rail_read_snap_arange_order(wStream* s, RAIL_SNAP_ARRANGE* snapArrange)
750{
751 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_SNAP_ARRANGE_ORDER_LENGTH))
752 return ERROR_INVALID_DATA;
753
754 Stream_Read_UINT32(s, snapArrange->windowId); /* WindowId (4 bytes) */
755 Stream_Read_INT16(s, snapArrange->left); /* Left (2 bytes) */
756 Stream_Read_INT16(s, snapArrange->top); /* Top (2 bytes) */
757 Stream_Read_INT16(s, snapArrange->right); /* Right (2 bytes) */
758 Stream_Read_INT16(s, snapArrange->bottom); /* Bottom (2 bytes) */
759 return CHANNEL_RC_OK;
760}
761
767WINPR_ATTR_NODISCARD
768static UINT rail_read_langbar_info_order(wStream* s, RAIL_LANGBAR_INFO_ORDER* langbarInfo)
769{
770 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_LANGBAR_INFO_ORDER_LENGTH))
771 return ERROR_INVALID_DATA;
772
773 Stream_Read_UINT32(s, langbarInfo->languageBarStatus); /* LanguageBarStatus (4 bytes) */
774 return CHANNEL_RC_OK;
775}
776
782WINPR_ATTR_NODISCARD
783static UINT rail_read_language_ime_info_order(wStream* s,
784 RAIL_LANGUAGEIME_INFO_ORDER* languageImeInfo)
785{
786 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_LANGUAGEIME_INFO_ORDER_LENGTH))
787 return ERROR_INVALID_DATA;
788
789 Stream_Read_UINT32(s, languageImeInfo->ProfileType); /* ProfileType (4 bytes) */
790 Stream_Read_UINT16(s, languageImeInfo->LanguageID); /* LanguageID (2 bytes) */
791 Stream_Read(
792 s, &languageImeInfo->LanguageProfileCLSID,
793 sizeof(languageImeInfo->LanguageProfileCLSID)); /* LanguageProfileCLSID (16 bytes) */
794 Stream_Read(s, &languageImeInfo->ProfileGUID,
795 sizeof(languageImeInfo->ProfileGUID)); /* ProfileGUID (16 bytes) */
796 Stream_Read_UINT32(s, languageImeInfo->KeyboardLayout); /* KeyboardLayout (4 bytes) */
797 return CHANNEL_RC_OK;
798}
799
805WINPR_ATTR_NODISCARD
806static UINT rail_read_compartment_info_order(wStream* s,
807 RAIL_COMPARTMENT_INFO_ORDER* compartmentInfo)
808{
809 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_COMPARTMENT_INFO_ORDER_LENGTH))
810 return ERROR_INVALID_DATA;
811
812 Stream_Read_UINT32(s, compartmentInfo->ImeState); /* ImeState (4 bytes) */
813 Stream_Read_UINT32(s, compartmentInfo->ImeConvMode); /* ImeConvMode (4 bytes) */
814 Stream_Read_UINT32(s, compartmentInfo->ImeSentenceMode); /* ImeSentenceMode (4 bytes) */
815 Stream_Read_UINT32(s, compartmentInfo->KanaMode); /* KANAMode (4 bytes) */
816 return CHANNEL_RC_OK;
817}
818
824WINPR_ATTR_NODISCARD
825static UINT rail_read_cloak_order(wStream* s, RAIL_CLOAK* cloak)
826{
827 BYTE cloaked = 0;
828
829 if (!Stream_CheckAndLogRequiredLength(TAG, s, RAIL_CLOAK_ORDER_LENGTH))
830 return ERROR_INVALID_DATA;
831
832 Stream_Read_UINT32(s, cloak->windowId); /* WindowId (4 bytes) */
833 Stream_Read_UINT8(s, cloaked); /* Cloaked (1 byte) */
834 cloak->cloak = (cloaked != 0);
835 return CHANNEL_RC_OK;
836}
837
843WINPR_ATTR_NODISCARD
844static UINT rail_recv_client_handshake_order(RailServerContext* context, wStream* s)
845{
846 UINT error = CHANNEL_RC_OK;
847
848 if (!context || !s)
849 return ERROR_INVALID_PARAMETER;
850
851 RAIL_HANDSHAKE_ORDER handshake = WINPR_C_ARRAY_INIT;
852 if ((error = rail_read_handshake_order(s, &handshake)))
853 {
854 WLog_ERR(TAG, "rail_read_handshake_order failed with error %" PRIu32 "!", error);
855 return error;
856 }
857
858 IFCALLRET(context->ClientHandshake, error, context, &handshake);
859
860 if (error)
861 WLog_ERR(TAG, "context.ClientHandshake failed with error %" PRIu32 "", error);
862
863 return error;
864}
865
871WINPR_ATTR_NODISCARD
872static UINT rail_recv_client_client_status_order(RailServerContext* context, wStream* s)
873{
874 UINT error = CHANNEL_RC_OK;
875
876 if (!context || !s)
877 return ERROR_INVALID_PARAMETER;
878
879 RAIL_CLIENT_STATUS_ORDER clientStatus = WINPR_C_ARRAY_INIT;
880 if ((error = rail_read_client_status_order(s, &clientStatus)))
881 {
882 WLog_ERR(TAG, "rail_read_client_status_order failed with error %" PRIu32 "!", error);
883 return error;
884 }
885
886 IFCALLRET(context->ClientClientStatus, error, context, &clientStatus);
887
888 if (error)
889 WLog_ERR(TAG, "context.ClientClientStatus failed with error %" PRIu32 "", error);
890
891 return error;
892}
893
899WINPR_ATTR_NODISCARD
900static UINT rail_recv_client_exec_order(RailServerContext* context, wStream* s)
901{
902 char* args[3] = WINPR_C_ARRAY_INIT;
903 RAIL_EXEC_ORDER exec = WINPR_C_ARRAY_INIT;
904
905 if (!context || !s)
906 return ERROR_INVALID_PARAMETER;
907
908 UINT error = rail_read_exec_order(s, &exec, args);
909 if (error)
910 {
911 WLog_ERR(TAG, "rail_read_client_status_order failed with error %" PRIu32 "!", error);
912 return error;
913 }
914
915 IFCALLRET(context->ClientExec, error, context, &exec);
916
917 if (error)
918 WLog_ERR(TAG, "context.Exec failed with error %" PRIu32 "", error);
919
920 free(args[0]);
921 free(args[1]);
922 free(args[2]);
923 return error;
924}
925
931WINPR_ATTR_NODISCARD
932static UINT rail_recv_client_sysparam_order(RailServerContext* context, wStream* s)
933{
934 if (!context || !s)
935 return ERROR_INVALID_PARAMETER;
936
937 const BOOL extendedSpiSupported = rail_is_extended_spi_supported(context->priv->channelFlags);
938
939 RAIL_SYSPARAM_ORDER sysparam = WINPR_C_ARRAY_INIT;
940 UINT error = rail_read_sysparam_order(s, &sysparam, extendedSpiSupported);
941 if (error != CHANNEL_RC_OK)
942 {
943 rail_unicode_string_free(&sysparam.highContrast.colorScheme);
944 WLog_ERR(TAG, "rail_read_sysparam_order failed with error %" PRIu32 "!", error);
945 return error;
946 }
947
948 IFCALLRET(context->ClientSysparam, error, context, &sysparam);
949 rail_unicode_string_free(&sysparam.highContrast.colorScheme);
950
951 if (error)
952 WLog_ERR(TAG, "context.ClientSysparam failed with error %" PRIu32 "", error);
953
954 return error;
955}
956
962WINPR_ATTR_NODISCARD
963static UINT rail_recv_client_activate_order(RailServerContext* context, wStream* s)
964{
965 UINT error = CHANNEL_RC_OK;
966
967 if (!context || !s)
968 return ERROR_INVALID_PARAMETER;
969
970 RAIL_ACTIVATE_ORDER activate = WINPR_C_ARRAY_INIT;
971 if ((error = rail_read_activate_order(s, &activate)))
972 {
973 WLog_ERR(TAG, "rail_read_activate_order failed with error %" PRIu32 "!", error);
974 return error;
975 }
976
977 IFCALLRET(context->ClientActivate, error, context, &activate);
978
979 if (error)
980 WLog_ERR(TAG, "context.ClientActivate failed with error %" PRIu32 "", error);
981
982 return error;
983}
984
990WINPR_ATTR_NODISCARD
991static UINT rail_recv_client_sysmenu_order(RailServerContext* context, wStream* s)
992{
993 UINT error = CHANNEL_RC_OK;
994
995 if (!context || !s)
996 return ERROR_INVALID_PARAMETER;
997
998 RAIL_SYSMENU_ORDER sysmenu = WINPR_C_ARRAY_INIT;
999 if ((error = rail_read_sysmenu_order(s, &sysmenu)))
1000 {
1001 WLog_ERR(TAG, "rail_read_sysmenu_order failed with error %" PRIu32 "!", error);
1002 return error;
1003 }
1004
1005 IFCALLRET(context->ClientSysmenu, error, context, &sysmenu);
1006
1007 if (error)
1008 WLog_ERR(TAG, "context.ClientSysmenu failed with error %" PRIu32 "", error);
1009
1010 return error;
1011}
1012
1018WINPR_ATTR_NODISCARD
1019static UINT rail_recv_client_syscommand_order(RailServerContext* context, wStream* s)
1020{
1021 UINT error = CHANNEL_RC_OK;
1022
1023 if (!context || !s)
1024 return ERROR_INVALID_PARAMETER;
1025
1026 RAIL_SYSCOMMAND_ORDER syscommand = WINPR_C_ARRAY_INIT;
1027 if ((error = rail_read_syscommand_order(s, &syscommand)))
1028 {
1029 WLog_ERR(TAG, "rail_read_syscommand_order failed with error %" PRIu32 "!", error);
1030 return error;
1031 }
1032
1033 IFCALLRET(context->ClientSyscommand, error, context, &syscommand);
1034
1035 if (error)
1036 WLog_ERR(TAG, "context.ClientSyscommand failed with error %" PRIu32 "", error);
1037
1038 return error;
1039}
1040
1046WINPR_ATTR_NODISCARD
1047static UINT rail_recv_client_notify_event_order(RailServerContext* context, wStream* s)
1048{
1049 UINT error = CHANNEL_RC_OK;
1050
1051 if (!context || !s)
1052 return ERROR_INVALID_PARAMETER;
1053
1054 RAIL_NOTIFY_EVENT_ORDER notifyEvent = WINPR_C_ARRAY_INIT;
1055 if ((error = rail_read_notify_event_order(s, &notifyEvent)))
1056 {
1057 WLog_ERR(TAG, "rail_read_notify_event_order failed with error %" PRIu32 "!", error);
1058 return error;
1059 }
1060
1061 IFCALLRET(context->ClientNotifyEvent, error, context, &notifyEvent);
1062
1063 if (error)
1064 WLog_ERR(TAG, "context.ClientNotifyEvent failed with error %" PRIu32 "", error);
1065
1066 return error;
1067}
1068
1074WINPR_ATTR_NODISCARD
1075static UINT rail_recv_client_window_move_order(RailServerContext* context, wStream* s)
1076{
1077 UINT error = CHANNEL_RC_OK;
1078
1079 if (!context || !s)
1080 return ERROR_INVALID_PARAMETER;
1081
1082 RAIL_WINDOW_MOVE_ORDER windowMove = WINPR_C_ARRAY_INIT;
1083 if ((error = rail_read_window_move_order(s, &windowMove)))
1084 {
1085 WLog_ERR(TAG, "rail_read_window_move_order failed with error %" PRIu32 "!", error);
1086 return error;
1087 }
1088
1089 IFCALLRET(context->ClientWindowMove, error, context, &windowMove);
1090
1091 if (error)
1092 WLog_ERR(TAG, "context.ClientWindowMove failed with error %" PRIu32 "", error);
1093
1094 return error;
1095}
1096
1102WINPR_ATTR_NODISCARD
1103static UINT rail_recv_client_snap_arrange_order(RailServerContext* context, wStream* s)
1104{
1105 UINT error = CHANNEL_RC_OK;
1106
1107 if (!context || !s)
1108 return ERROR_INVALID_PARAMETER;
1109
1110 RAIL_SNAP_ARRANGE snapArrange = WINPR_C_ARRAY_INIT;
1111 if ((error = rail_read_snap_arange_order(s, &snapArrange)))
1112 {
1113 WLog_ERR(TAG, "rail_read_snap_arange_order failed with error %" PRIu32 "!", error);
1114 return error;
1115 }
1116
1117 IFCALLRET(context->ClientSnapArrange, error, context, &snapArrange);
1118
1119 if (error)
1120 WLog_ERR(TAG, "context.ClientSnapArrange failed with error %" PRIu32 "", error);
1121
1122 return error;
1123}
1124
1130WINPR_ATTR_NODISCARD
1131static UINT rail_recv_client_get_appid_req_order(RailServerContext* context, wStream* s)
1132{
1133 UINT error = CHANNEL_RC_OK;
1134
1135 if (!context || !s)
1136 return ERROR_INVALID_PARAMETER;
1137
1138 RAIL_GET_APPID_REQ_ORDER getAppidReq = WINPR_C_ARRAY_INIT;
1139 if ((error = rail_read_get_appid_req_order(s, &getAppidReq)))
1140 {
1141 WLog_ERR(TAG, "rail_read_get_appid_req_order failed with error %" PRIu32 "!", error);
1142 return error;
1143 }
1144
1145 IFCALLRET(context->ClientGetAppidReq, error, context, &getAppidReq);
1146
1147 if (error)
1148 WLog_ERR(TAG, "context.ClientGetAppidReq failed with error %" PRIu32 "", error);
1149
1150 return error;
1151}
1152
1158WINPR_ATTR_NODISCARD
1159static UINT rail_recv_client_langbar_info_order(RailServerContext* context, wStream* s)
1160{
1161 UINT error = CHANNEL_RC_OK;
1162
1163 if (!context || !s)
1164 return ERROR_INVALID_PARAMETER;
1165
1166 RAIL_LANGBAR_INFO_ORDER langbarInfo = WINPR_C_ARRAY_INIT;
1167 if ((error = rail_read_langbar_info_order(s, &langbarInfo)))
1168 {
1169 WLog_ERR(TAG, "rail_read_langbar_info_order failed with error %" PRIu32 "!", error);
1170 return error;
1171 }
1172
1173 IFCALLRET(context->ClientLangbarInfo, error, context, &langbarInfo);
1174
1175 if (error)
1176 WLog_ERR(TAG, "context.ClientLangbarInfo failed with error %" PRIu32 "", error);
1177
1178 return error;
1179}
1180
1186WINPR_ATTR_NODISCARD
1187static UINT rail_recv_client_language_ime_info_order(RailServerContext* context, wStream* s)
1188{
1189 UINT error = CHANNEL_RC_OK;
1190
1191 if (!context || !s)
1192 return ERROR_INVALID_PARAMETER;
1193
1194 RAIL_LANGUAGEIME_INFO_ORDER languageImeInfo = WINPR_C_ARRAY_INIT;
1195 if ((error = rail_read_language_ime_info_order(s, &languageImeInfo)))
1196 {
1197 WLog_ERR(TAG, "rail_read_language_ime_info_order failed with error %" PRIu32 "!", error);
1198 return error;
1199 }
1200
1201 IFCALLRET(context->ClientLanguageImeInfo, error, context, &languageImeInfo);
1202
1203 if (error)
1204 WLog_ERR(TAG, "context.ClientLanguageImeInfo failed with error %" PRIu32 "", error);
1205
1206 return error;
1207}
1208
1214WINPR_ATTR_NODISCARD
1215static UINT rail_recv_client_compartment_info(RailServerContext* context, wStream* s)
1216{
1217 UINT error = CHANNEL_RC_OK;
1218
1219 if (!context || !s)
1220 return ERROR_INVALID_PARAMETER;
1221
1222 RAIL_COMPARTMENT_INFO_ORDER compartmentInfo = WINPR_C_ARRAY_INIT;
1223 if ((error = rail_read_compartment_info_order(s, &compartmentInfo)))
1224 {
1225 WLog_ERR(TAG, "rail_read_compartment_info_order failed with error %" PRIu32 "!", error);
1226 return error;
1227 }
1228
1229 IFCALLRET(context->ClientCompartmentInfo, error, context, &compartmentInfo);
1230
1231 if (error)
1232 WLog_ERR(TAG, "context.ClientCompartmentInfo failed with error %" PRIu32 "", error);
1233
1234 return error;
1235}
1236
1242WINPR_ATTR_NODISCARD
1243static UINT rail_recv_client_cloak_order(RailServerContext* context, wStream* s)
1244{
1245 UINT error = CHANNEL_RC_OK;
1246
1247 if (!context || !s)
1248 return ERROR_INVALID_PARAMETER;
1249
1250 RAIL_CLOAK cloak = WINPR_C_ARRAY_INIT;
1251 if ((error = rail_read_cloak_order(s, &cloak)))
1252 {
1253 WLog_ERR(TAG, "rail_read_cloak_order failed with error %" PRIu32 "!", error);
1254 return error;
1255 }
1256
1257 IFCALLRET(context->ClientCloak, error, context, &cloak);
1258
1259 if (error)
1260 WLog_ERR(TAG, "context.Cloak failed with error %" PRIu32 "", error);
1261
1262 return error;
1263}
1264
1265WINPR_ATTR_NODISCARD
1266static UINT rail_recv_client_text_scale_order(RailServerContext* context, wStream* s)
1267{
1268 UINT error = CHANNEL_RC_OK;
1269 UINT32 TextScaleFactor = 0;
1270
1271 if (!context || !s)
1272 return ERROR_INVALID_PARAMETER;
1273
1274 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1275 return ERROR_INVALID_DATA;
1276
1277 Stream_Read_UINT32(s, TextScaleFactor);
1278 IFCALLRET(context->ClientTextScale, error, context, TextScaleFactor);
1279
1280 if (error)
1281 WLog_ERR(TAG, "context.TextScale failed with error %" PRIu32 "", error);
1282
1283 return error;
1284}
1285
1286WINPR_ATTR_NODISCARD
1287static UINT rail_recv_client_caret_blink(RailServerContext* context, wStream* s)
1288{
1289 UINT error = CHANNEL_RC_OK;
1290 UINT32 CaretBlinkRate = 0;
1291
1292 if (!context || !s)
1293 return ERROR_INVALID_PARAMETER;
1294
1295 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1296 return ERROR_INVALID_DATA;
1297
1298 Stream_Read_UINT32(s, CaretBlinkRate);
1299 IFCALLRET(context->ClientCaretBlinkRate, error, context, CaretBlinkRate);
1300
1301 if (error)
1302 WLog_ERR(TAG, "context.CaretBlinkRate failed with error %" PRIu32 "", error);
1303
1304 return error;
1305}
1306
1307WINPR_ATTR_NODISCARD
1308static DWORD WINAPI rail_server_thread(LPVOID arg)
1309{
1310 RailServerContext* context = (RailServerContext*)arg;
1311 WINPR_ASSERT(context);
1312
1313 RailServerPrivate* priv = context->priv;
1314 WINPR_ASSERT(priv);
1315
1316 DWORD status = 0;
1317 DWORD nCount = 0;
1318 HANDLE events[8];
1319 UINT error = CHANNEL_RC_OK;
1320 events[nCount++] = priv->channelEvent;
1321 events[nCount++] = priv->stopEvent;
1322
1323 while (TRUE)
1324 {
1325 status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
1326
1327 if (status == WAIT_FAILED)
1328 {
1329 error = GetLastError();
1330 WLog_ERR(TAG, "WaitForMultipleObjects failed with error %" PRIu32 "!", error);
1331 break;
1332 }
1333
1334 status = WaitForSingleObject(context->priv->stopEvent, 0);
1335
1336 if (status == WAIT_FAILED)
1337 {
1338 error = GetLastError();
1339 WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "!", error);
1340 break;
1341 }
1342
1343 if (status == WAIT_OBJECT_0)
1344 break;
1345
1346 status = WaitForSingleObject(context->priv->channelEvent, 0);
1347
1348 if (status == WAIT_FAILED)
1349 {
1350 error = GetLastError();
1351 WLog_ERR(
1352 TAG,
1353 "WaitForSingleObject(context->priv->channelEvent, 0) failed with error %" PRIu32
1354 "!",
1355 error);
1356 break;
1357 }
1358
1359 if (status == WAIT_OBJECT_0)
1360 {
1361 if ((error = rail_server_handle_messages(context)))
1362 {
1363 WLog_ERR(TAG, "rail_server_handle_messages failed with error %" PRIu32 "", error);
1364 break;
1365 }
1366 }
1367 }
1368
1369 if (error && context->rdpcontext)
1370 setChannelError(context->rdpcontext, error, "rail_server_thread reported an error");
1371
1372 ExitThread(error);
1373 return error;
1374}
1375
1381WINPR_ATTR_NODISCARD
1382static UINT rail_server_start(RailServerContext* context)
1383{
1384 void* buffer = nullptr;
1385 DWORD bytesReturned = 0;
1386 UINT error = ERROR_INTERNAL_ERROR;
1387
1388 WINPR_ASSERT(context);
1389
1390 RailServerPrivate* priv = context->priv;
1391 WINPR_ASSERT(priv);
1392
1393 priv->rail_channel =
1394 WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, RAIL_SVC_CHANNEL_NAME);
1395
1396 if (!priv->rail_channel)
1397 {
1398 WLog_ERR(TAG, "WTSVirtualChannelOpen failed!");
1399 return error;
1400 }
1401
1402 if (!WTSVirtualChannelQuery(priv->rail_channel, WTSVirtualEventHandle, &buffer,
1403 &bytesReturned) ||
1404 (bytesReturned != sizeof(HANDLE)))
1405 {
1406 WLog_ERR(TAG,
1407 "error during WTSVirtualChannelQuery(WTSVirtualEventHandle) or invalid returned "
1408 "size(%" PRIu32 ")",
1409 bytesReturned);
1410
1411 if (buffer)
1412 WTSFreeMemory(buffer);
1413
1414 goto out_close;
1415 }
1416
1417 priv->channelEvent = *(HANDLE*)buffer;
1418 WTSFreeMemory(buffer);
1419 context->priv->stopEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
1420
1421 if (!context->priv->stopEvent)
1422 {
1423 WLog_ERR(TAG, "CreateEvent failed!");
1424 goto out_close;
1425 }
1426
1427 context->priv->thread =
1428 CreateThread(nullptr, 0, rail_server_thread, (void*)context, 0, nullptr);
1429
1430 if (!context->priv->thread)
1431 {
1432 WLog_ERR(TAG, "CreateThread failed!");
1433 goto out_stop_event;
1434 }
1435
1436 return CHANNEL_RC_OK;
1437out_stop_event:
1438 (void)CloseHandle(context->priv->stopEvent);
1439 context->priv->stopEvent = nullptr;
1440out_close:
1441 (void)WTSVirtualChannelClose(context->priv->rail_channel);
1442 context->priv->rail_channel = nullptr;
1443 return error;
1444}
1445
1446WINPR_ATTR_NODISCARD
1447static BOOL rail_server_stop(RailServerContext* context)
1448{
1449 WINPR_ASSERT(context);
1450 RailServerPrivate* priv = context->priv;
1451
1452 if (priv->thread)
1453 {
1454 (void)SetEvent(priv->stopEvent);
1455
1456 if (WaitForSingleObject(priv->thread, INFINITE) == WAIT_FAILED)
1457 {
1458 WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "", GetLastError());
1459 return FALSE;
1460 }
1461
1462 (void)CloseHandle(priv->thread);
1463 (void)CloseHandle(priv->stopEvent);
1464 priv->thread = nullptr;
1465 priv->stopEvent = nullptr;
1466 }
1467
1468 if (priv->rail_channel)
1469 {
1470 (void)WTSVirtualChannelClose(priv->rail_channel);
1471 priv->rail_channel = nullptr;
1472 }
1473
1474 priv->channelEvent = nullptr;
1475 return TRUE;
1476}
1477
1478static void rail_server_context_priv_free(RailServerPrivate* priv)
1479{
1480 if (!priv)
1481 return;
1482
1483 ChannelPduTracker_free(priv->channelPduTracker);
1484 free(priv);
1485}
1486
1487WINPR_ATTR_MALLOC(rail_server_context_priv_free, 1)
1488static RailServerPrivate* rail_server_context_priv_new(HANDLE vc)
1489{
1490 RailServerPrivate* priv = calloc(1, sizeof(RailServerPrivate));
1491 if (!priv)
1492 return nullptr;
1493
1494 priv->channelPduTracker = ChannelPduTracker_new(vc);
1495 if (!priv->channelPduTracker)
1496 goto fail;
1497 return priv;
1498fail:
1499 rail_server_context_priv_free(priv);
1500 return nullptr;
1501}
1502
1503RailServerContext* rail_server_context_new(HANDLE vcm)
1504{
1505 RailServerContext* context = (RailServerContext*)calloc(1, sizeof(RailServerContext));
1506
1507 if (!context)
1508 {
1509 WLog_ERR(TAG, "calloc failed!");
1510 return nullptr;
1511 }
1512
1513 context->vcm = vcm;
1514 context->Start = rail_server_start;
1515 context->Stop = rail_server_stop;
1516 context->ServerHandshake = rail_send_server_handshake;
1517 context->ServerHandshakeEx = rail_send_server_handshake_ex;
1518 context->ServerSysparam = rail_send_server_sysparam;
1519 context->ServerLocalMoveSize = rail_send_server_local_move_size;
1520 context->ServerMinMaxInfo = rail_send_server_min_max_info;
1521 context->ServerTaskbarInfo = rail_send_server_taskbar_info;
1522 context->ServerLangbarInfo = rail_send_server_langbar_info;
1523 context->ServerExecResult = rail_send_server_exec_result;
1524 context->ServerGetAppidResp = rail_send_server_get_app_id_resp;
1525 context->ServerZOrderSync = rail_send_server_z_order_sync;
1526 context->ServerCloak = rail_send_server_cloak;
1527 context->ServerPowerDisplayRequest = rail_send_server_power_display_request;
1528 context->ServerGetAppidRespEx = rail_send_server_get_appid_resp_ex;
1529 context->priv = rail_server_context_priv_new(vcm);
1530
1531 if (!context->priv)
1532 {
1533 WLog_ERR(TAG, "calloc failed!");
1534 goto fail;
1535 }
1536
1537 return context;
1538fail:
1539 rail_server_context_free(context);
1540 return nullptr;
1541}
1542
1543void rail_server_context_free(RailServerContext* context)
1544{
1545 if (!context)
1546 return;
1547 rail_server_context_priv_free(context->priv);
1548 free(context);
1549}
1550
1551void rail_server_set_handshake_ex_flags(RailServerContext* context, DWORD flags)
1552{
1553 WINPR_ASSERT(context);
1554 WINPR_ASSERT(context->priv);
1555
1556 RailServerPrivate* priv = context->priv;
1557 priv->channelFlags = flags;
1558}
1559
1560static UINT rail_server_read_pdu_header(wStream* s, UINT16* pOrderType, UINT16* pOrderLength)
1561{
1562 WINPR_ASSERT(pOrderType);
1563 WINPR_ASSERT(pOrderLength);
1564
1565 /* Parse header */
1566 const UINT status = rail_read_pdu_header(s, pOrderType, pOrderLength);
1567 if (status != CHANNEL_RC_OK)
1568 {
1569 WLog_ERR(TAG, "rail_read_pdu_header failed with error %" PRIu32 "!", status);
1570 return status;
1571 }
1572
1573 if (!Stream_EnsureRemainingCapacity(s, *pOrderLength - RAIL_PDU_HEADER_LENGTH))
1574 {
1575 WLog_ERR(TAG,
1576 "Stream_EnsureRemainingCapacity failed, orderLength - RAIL_PDU_HEADER_LENGTH");
1577 return CHANNEL_RC_NO_MEMORY;
1578 }
1579 return CHANNEL_RC_OK;
1580}
1581
1582static UINT rail_server_handle_message_completed(RailServerContext* context, wStream* s,
1583 UINT16 orderType, UINT16 orderLength)
1584{
1585 {
1586 char buffer[128] = WINPR_C_ARRAY_INIT;
1587 WLog_DBG(TAG, "Received %s PDU, length:%" PRIu16 "",
1588 rail_get_order_type_string_full(orderType, buffer, sizeof(buffer)), orderLength);
1589 }
1590
1591 switch (orderType)
1592 {
1593 case TS_RAIL_ORDER_HANDSHAKE:
1594 return rail_recv_client_handshake_order(context, s);
1595
1596 case TS_RAIL_ORDER_CLIENTSTATUS:
1597 return rail_recv_client_client_status_order(context, s);
1598
1599 case TS_RAIL_ORDER_EXEC:
1600 return rail_recv_client_exec_order(context, s);
1601
1602 case TS_RAIL_ORDER_SYSPARAM:
1603 return rail_recv_client_sysparam_order(context, s);
1604
1605 case TS_RAIL_ORDER_ACTIVATE:
1606 return rail_recv_client_activate_order(context, s);
1607
1608 case TS_RAIL_ORDER_SYSMENU:
1609 return rail_recv_client_sysmenu_order(context, s);
1610
1611 case TS_RAIL_ORDER_SYSCOMMAND:
1612 return rail_recv_client_syscommand_order(context, s);
1613
1614 case TS_RAIL_ORDER_NOTIFY_EVENT:
1615 return rail_recv_client_notify_event_order(context, s);
1616
1617 case TS_RAIL_ORDER_WINDOWMOVE:
1618 return rail_recv_client_window_move_order(context, s);
1619
1620 case TS_RAIL_ORDER_SNAP_ARRANGE:
1621 return rail_recv_client_snap_arrange_order(context, s);
1622
1623 case TS_RAIL_ORDER_GET_APPID_REQ:
1624 return rail_recv_client_get_appid_req_order(context, s);
1625
1626 case TS_RAIL_ORDER_LANGBARINFO:
1627 return rail_recv_client_langbar_info_order(context, s);
1628
1629 case TS_RAIL_ORDER_LANGUAGEIMEINFO:
1630 return rail_recv_client_language_ime_info_order(context, s);
1631
1632 case TS_RAIL_ORDER_COMPARTMENTINFO:
1633 return rail_recv_client_compartment_info(context, s);
1634
1635 case TS_RAIL_ORDER_CLOAK:
1636 return rail_recv_client_cloak_order(context, s);
1637
1638 case TS_RAIL_ORDER_TEXTSCALEINFO:
1639 return rail_recv_client_text_scale_order(context, s);
1640
1641 case TS_RAIL_ORDER_CARETBLINKINFO:
1642 return rail_recv_client_caret_blink(context, s);
1643
1644 default:
1645 WLog_ERR(TAG, "Unknown RAIL PDU order received.");
1646 return ERROR_INVALID_DATA;
1647 }
1648}
1649
1650UINT rail_server_handle_messages(RailServerContext* context)
1651{
1652 WINPR_ASSERT(context);
1653
1654 RailServerPrivate* priv = context->priv;
1655 WINPR_ASSERT(priv);
1656
1657 BOOL ok = FALSE;
1658 wStream* s = ChannelPduTracker_poll(priv->channelPduTracker, &ok);
1659
1660 if (!ok)
1661 return ERROR_INVALID_DATA;
1662
1663 if (!s)
1664 return CHANNEL_RC_OK;
1665
1666 UINT16 orderType = 0;
1667 UINT16 orderLength = 0;
1668 UINT rc = rail_server_read_pdu_header(s, &orderType, &orderLength);
1669 if (rc == CHANNEL_RC_OK)
1670 rc = rail_server_handle_message_completed(context, s, orderType, orderLength);
1671 Stream_Release(s);
1672 return rc;
1673}