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