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,
847 RAIL_HANDSHAKE_ORDER* handshake, wStream* s)
848{
849 UINT error = CHANNEL_RC_OK;
850
851 if (!context || !handshake || !s)
852 return ERROR_INVALID_PARAMETER;
853
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,
875 RAIL_CLIENT_STATUS_ORDER* clientStatus, wStream* s)
876{
877 UINT error = CHANNEL_RC_OK;
878
879 if (!context || !clientStatus || !s)
880 return ERROR_INVALID_PARAMETER;
881
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,
935 RAIL_SYSPARAM_ORDER* sysparam, wStream* s)
936{
937 if (!context || !sysparam || !s)
938 return ERROR_INVALID_PARAMETER;
939
940 const BOOL extendedSpiSupported = rail_is_extended_spi_supported(context->priv->channelFlags);
941 UINT error = rail_read_sysparam_order(s, sysparam, extendedSpiSupported);
942 if (error != CHANNEL_RC_OK)
943 {
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
950 if (error)
951 WLog_ERR(TAG, "context.ClientSysparam failed with error %" PRIu32 "", error);
952
953 return error;
954}
955
961WINPR_ATTR_NODISCARD
962static UINT rail_recv_client_activate_order(RailServerContext* context,
963 RAIL_ACTIVATE_ORDER* activate, wStream* s)
964{
965 UINT error = CHANNEL_RC_OK;
966
967 if (!context || !activate || !s)
968 return ERROR_INVALID_PARAMETER;
969
970 if ((error = rail_read_activate_order(s, activate)))
971 {
972 WLog_ERR(TAG, "rail_read_activate_order failed with error %" PRIu32 "!", error);
973 return error;
974 }
975
976 IFCALLRET(context->ClientActivate, error, context, activate);
977
978 if (error)
979 WLog_ERR(TAG, "context.ClientActivate failed with error %" PRIu32 "", error);
980
981 return error;
982}
983
989WINPR_ATTR_NODISCARD
990static UINT rail_recv_client_sysmenu_order(RailServerContext* context, RAIL_SYSMENU_ORDER* sysmenu,
991 wStream* s)
992{
993 UINT error = CHANNEL_RC_OK;
994
995 if (!context || !sysmenu || !s)
996 return ERROR_INVALID_PARAMETER;
997
998 if ((error = rail_read_sysmenu_order(s, sysmenu)))
999 {
1000 WLog_ERR(TAG, "rail_read_sysmenu_order failed with error %" PRIu32 "!", error);
1001 return error;
1002 }
1003
1004 IFCALLRET(context->ClientSysmenu, error, context, sysmenu);
1005
1006 if (error)
1007 WLog_ERR(TAG, "context.ClientSysmenu failed with error %" PRIu32 "", error);
1008
1009 return error;
1010}
1011
1017WINPR_ATTR_NODISCARD
1018static UINT rail_recv_client_syscommand_order(RailServerContext* context,
1019 RAIL_SYSCOMMAND_ORDER* syscommand, wStream* s)
1020{
1021 UINT error = CHANNEL_RC_OK;
1022
1023 if (!context || !syscommand || !s)
1024 return ERROR_INVALID_PARAMETER;
1025
1026 if ((error = rail_read_syscommand_order(s, syscommand)))
1027 {
1028 WLog_ERR(TAG, "rail_read_syscommand_order failed with error %" PRIu32 "!", error);
1029 return error;
1030 }
1031
1032 IFCALLRET(context->ClientSyscommand, error, context, syscommand);
1033
1034 if (error)
1035 WLog_ERR(TAG, "context.ClientSyscommand failed with error %" PRIu32 "", error);
1036
1037 return error;
1038}
1039
1045WINPR_ATTR_NODISCARD
1046static UINT rail_recv_client_notify_event_order(RailServerContext* context,
1047 RAIL_NOTIFY_EVENT_ORDER* notifyEvent, wStream* s)
1048{
1049 UINT error = CHANNEL_RC_OK;
1050
1051 if (!context || !notifyEvent || !s)
1052 return ERROR_INVALID_PARAMETER;
1053
1054 if ((error = rail_read_notify_event_order(s, notifyEvent)))
1055 {
1056 WLog_ERR(TAG, "rail_read_notify_event_order failed with error %" PRIu32 "!", error);
1057 return error;
1058 }
1059
1060 IFCALLRET(context->ClientNotifyEvent, error, context, notifyEvent);
1061
1062 if (error)
1063 WLog_ERR(TAG, "context.ClientNotifyEvent failed with error %" PRIu32 "", error);
1064
1065 return error;
1066}
1067
1073WINPR_ATTR_NODISCARD
1074static UINT rail_recv_client_window_move_order(RailServerContext* context,
1075 RAIL_WINDOW_MOVE_ORDER* windowMove, wStream* s)
1076{
1077 UINT error = CHANNEL_RC_OK;
1078
1079 if (!context || !windowMove || !s)
1080 return ERROR_INVALID_PARAMETER;
1081
1082 if ((error = rail_read_window_move_order(s, windowMove)))
1083 {
1084 WLog_ERR(TAG, "rail_read_window_move_order failed with error %" PRIu32 "!", error);
1085 return error;
1086 }
1087
1088 IFCALLRET(context->ClientWindowMove, error, context, windowMove);
1089
1090 if (error)
1091 WLog_ERR(TAG, "context.ClientWindowMove failed with error %" PRIu32 "", error);
1092
1093 return error;
1094}
1095
1101WINPR_ATTR_NODISCARD
1102static UINT rail_recv_client_snap_arrange_order(RailServerContext* context,
1103 RAIL_SNAP_ARRANGE* snapArrange, wStream* s)
1104{
1105 UINT error = CHANNEL_RC_OK;
1106
1107 if (!context || !snapArrange || !s)
1108 return ERROR_INVALID_PARAMETER;
1109
1110 if ((error = rail_read_snap_arange_order(s, snapArrange)))
1111 {
1112 WLog_ERR(TAG, "rail_read_snap_arange_order failed with error %" PRIu32 "!", error);
1113 return error;
1114 }
1115
1116 IFCALLRET(context->ClientSnapArrange, error, context, snapArrange);
1117
1118 if (error)
1119 WLog_ERR(TAG, "context.ClientSnapArrange failed with error %" PRIu32 "", error);
1120
1121 return error;
1122}
1123
1129WINPR_ATTR_NODISCARD
1130static UINT rail_recv_client_get_appid_req_order(RailServerContext* context,
1131 RAIL_GET_APPID_REQ_ORDER* getAppidReq, wStream* s)
1132{
1133 UINT error = CHANNEL_RC_OK;
1134
1135 if (!context || !getAppidReq || !s)
1136 return ERROR_INVALID_PARAMETER;
1137
1138 if ((error = rail_read_get_appid_req_order(s, getAppidReq)))
1139 {
1140 WLog_ERR(TAG, "rail_read_get_appid_req_order failed with error %" PRIu32 "!", error);
1141 return error;
1142 }
1143
1144 IFCALLRET(context->ClientGetAppidReq, error, context, getAppidReq);
1145
1146 if (error)
1147 WLog_ERR(TAG, "context.ClientGetAppidReq failed with error %" PRIu32 "", error);
1148
1149 return error;
1150}
1151
1157WINPR_ATTR_NODISCARD
1158static UINT rail_recv_client_langbar_info_order(RailServerContext* context,
1159 RAIL_LANGBAR_INFO_ORDER* langbarInfo, wStream* s)
1160{
1161 UINT error = CHANNEL_RC_OK;
1162
1163 if (!context || !langbarInfo || !s)
1164 return ERROR_INVALID_PARAMETER;
1165
1166 if ((error = rail_read_langbar_info_order(s, langbarInfo)))
1167 {
1168 WLog_ERR(TAG, "rail_read_langbar_info_order failed with error %" PRIu32 "!", error);
1169 return error;
1170 }
1171
1172 IFCALLRET(context->ClientLangbarInfo, error, context, langbarInfo);
1173
1174 if (error)
1175 WLog_ERR(TAG, "context.ClientLangbarInfo failed with error %" PRIu32 "", error);
1176
1177 return error;
1178}
1179
1185WINPR_ATTR_NODISCARD
1186static UINT rail_recv_client_language_ime_info_order(RailServerContext* context,
1187 RAIL_LANGUAGEIME_INFO_ORDER* languageImeInfo,
1188 wStream* s)
1189{
1190 UINT error = CHANNEL_RC_OK;
1191
1192 if (!context || !languageImeInfo || !s)
1193 return ERROR_INVALID_PARAMETER;
1194
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,
1216 RAIL_COMPARTMENT_INFO_ORDER* compartmentInfo,
1217 wStream* s)
1218{
1219 UINT error = CHANNEL_RC_OK;
1220
1221 if (!context || !compartmentInfo || !s)
1222 return ERROR_INVALID_PARAMETER;
1223
1224 if ((error = rail_read_compartment_info_order(s, compartmentInfo)))
1225 {
1226 WLog_ERR(TAG, "rail_read_compartment_info_order failed with error %" PRIu32 "!", error);
1227 return error;
1228 }
1229
1230 IFCALLRET(context->ClientCompartmentInfo, error, context, compartmentInfo);
1231
1232 if (error)
1233 WLog_ERR(TAG, "context.ClientCompartmentInfo failed with error %" PRIu32 "", error);
1234
1235 return error;
1236}
1237
1243WINPR_ATTR_NODISCARD
1244static UINT rail_recv_client_cloak_order(RailServerContext* context, RAIL_CLOAK* cloak, wStream* s)
1245{
1246 UINT error = CHANNEL_RC_OK;
1247
1248 if (!context || !cloak || !s)
1249 return ERROR_INVALID_PARAMETER;
1250
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
1478RailServerContext* rail_server_context_new(HANDLE vcm)
1479{
1480 RailServerContext* context = nullptr;
1481 RailServerPrivate* priv = nullptr;
1482 context = (RailServerContext*)calloc(1, sizeof(RailServerContext));
1483
1484 if (!context)
1485 {
1486 WLog_ERR(TAG, "calloc failed!");
1487 return nullptr;
1488 }
1489
1490 context->vcm = vcm;
1491 context->Start = rail_server_start;
1492 context->Stop = rail_server_stop;
1493 context->ServerHandshake = rail_send_server_handshake;
1494 context->ServerHandshakeEx = rail_send_server_handshake_ex;
1495 context->ServerSysparam = rail_send_server_sysparam;
1496 context->ServerLocalMoveSize = rail_send_server_local_move_size;
1497 context->ServerMinMaxInfo = rail_send_server_min_max_info;
1498 context->ServerTaskbarInfo = rail_send_server_taskbar_info;
1499 context->ServerLangbarInfo = rail_send_server_langbar_info;
1500 context->ServerExecResult = rail_send_server_exec_result;
1501 context->ServerGetAppidResp = rail_send_server_get_app_id_resp;
1502 context->ServerZOrderSync = rail_send_server_z_order_sync;
1503 context->ServerCloak = rail_send_server_cloak;
1504 context->ServerPowerDisplayRequest = rail_send_server_power_display_request;
1505 context->ServerGetAppidRespEx = rail_send_server_get_appid_resp_ex;
1506 context->priv = priv = (RailServerPrivate*)calloc(1, sizeof(RailServerPrivate));
1507
1508 if (!priv)
1509 {
1510 WLog_ERR(TAG, "calloc failed!");
1511 goto fail;
1512 }
1513
1514 /* Create shared input stream */
1515 priv->input_stream = Stream_New(nullptr, 4096);
1516
1517 if (!priv->input_stream)
1518 {
1519 WLog_ERR(TAG, "Stream_New failed!");
1520 goto fail;
1521 }
1522
1523 return context;
1524fail:
1525 rail_server_context_free(context);
1526 return nullptr;
1527}
1528
1529void rail_server_context_free(RailServerContext* context)
1530{
1531 if (context->priv)
1532 Stream_Free(context->priv->input_stream, TRUE);
1533
1534 free(context->priv);
1535 free(context);
1536}
1537
1538void rail_server_set_handshake_ex_flags(RailServerContext* context, DWORD flags)
1539{
1540 WINPR_ASSERT(context);
1541 WINPR_ASSERT(context->priv);
1542
1543 RailServerPrivate* priv = context->priv;
1544 priv->channelFlags = flags;
1545}
1546
1547UINT rail_server_handle_messages(RailServerContext* context)
1548{
1549 char buffer[128] = WINPR_C_ARRAY_INIT;
1550 UINT status = CHANNEL_RC_OK;
1551 DWORD bytesReturned = 0;
1552 UINT16 orderType = 0;
1553 UINT16 orderLength = 0;
1554 RailServerPrivate* priv = context->priv;
1555 wStream* s = priv->input_stream;
1556
1557 /* Read header */
1558 if (!Stream_EnsureRemainingCapacity(s, RAIL_PDU_HEADER_LENGTH))
1559 {
1560 WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed, RAIL_PDU_HEADER_LENGTH");
1561 return CHANNEL_RC_NO_MEMORY;
1562 }
1563
1564 if (!WTSVirtualChannelRead(priv->rail_channel, 0, Stream_Pointer(s), RAIL_PDU_HEADER_LENGTH,
1565 &bytesReturned))
1566 {
1567 if (GetLastError() == ERROR_NO_DATA)
1568 return ERROR_NO_DATA;
1569
1570 WLog_ERR(TAG, "channel connection closed");
1571 return ERROR_INTERNAL_ERROR;
1572 }
1573
1574 /* Parse header */
1575 if ((status = rail_read_pdu_header(s, &orderType, &orderLength)) != CHANNEL_RC_OK)
1576 {
1577 WLog_ERR(TAG, "rail_read_pdu_header failed with error %" PRIu32 "!", status);
1578 return status;
1579 }
1580
1581 if (!Stream_EnsureRemainingCapacity(s, orderLength - RAIL_PDU_HEADER_LENGTH))
1582 {
1583 WLog_ERR(TAG,
1584 "Stream_EnsureRemainingCapacity failed, orderLength - RAIL_PDU_HEADER_LENGTH");
1585 return CHANNEL_RC_NO_MEMORY;
1586 }
1587
1588 /* Read body */
1589 if (!WTSVirtualChannelRead(priv->rail_channel, 0, Stream_Pointer(s),
1590 orderLength - RAIL_PDU_HEADER_LENGTH, &bytesReturned))
1591 {
1592 if (GetLastError() == ERROR_NO_DATA)
1593 return ERROR_NO_DATA;
1594
1595 WLog_ERR(TAG, "channel connection closed");
1596 return ERROR_INTERNAL_ERROR;
1597 }
1598
1599 WLog_DBG(TAG, "Received %s PDU, length:%" PRIu16 "",
1600 rail_get_order_type_string_full(orderType, buffer, sizeof(buffer)), orderLength);
1601
1602 switch (orderType)
1603 {
1604 case TS_RAIL_ORDER_HANDSHAKE:
1605 {
1606 RAIL_HANDSHAKE_ORDER handshake;
1607 return rail_recv_client_handshake_order(context, &handshake, s);
1608 }
1609
1610 case TS_RAIL_ORDER_CLIENTSTATUS:
1611 {
1612 RAIL_CLIENT_STATUS_ORDER clientStatus;
1613 return rail_recv_client_client_status_order(context, &clientStatus, s);
1614 }
1615
1616 case TS_RAIL_ORDER_EXEC:
1617 return rail_recv_client_exec_order(context, s);
1618
1619 case TS_RAIL_ORDER_SYSPARAM:
1620 {
1621 RAIL_SYSPARAM_ORDER sysparam = WINPR_C_ARRAY_INIT;
1622 return rail_recv_client_sysparam_order(context, &sysparam, s);
1623 }
1624
1625 case TS_RAIL_ORDER_ACTIVATE:
1626 {
1627 RAIL_ACTIVATE_ORDER activate;
1628 return rail_recv_client_activate_order(context, &activate, s);
1629 }
1630
1631 case TS_RAIL_ORDER_SYSMENU:
1632 {
1633 RAIL_SYSMENU_ORDER sysmenu;
1634 return rail_recv_client_sysmenu_order(context, &sysmenu, s);
1635 }
1636
1637 case TS_RAIL_ORDER_SYSCOMMAND:
1638 {
1639 RAIL_SYSCOMMAND_ORDER syscommand;
1640 return rail_recv_client_syscommand_order(context, &syscommand, s);
1641 }
1642
1643 case TS_RAIL_ORDER_NOTIFY_EVENT:
1644 {
1645 RAIL_NOTIFY_EVENT_ORDER notifyEvent;
1646 return rail_recv_client_notify_event_order(context, &notifyEvent, s);
1647 }
1648
1649 case TS_RAIL_ORDER_WINDOWMOVE:
1650 {
1651 RAIL_WINDOW_MOVE_ORDER windowMove;
1652 return rail_recv_client_window_move_order(context, &windowMove, s);
1653 }
1654
1655 case TS_RAIL_ORDER_SNAP_ARRANGE:
1656 {
1657 RAIL_SNAP_ARRANGE snapArrange;
1658 return rail_recv_client_snap_arrange_order(context, &snapArrange, s);
1659 }
1660
1661 case TS_RAIL_ORDER_GET_APPID_REQ:
1662 {
1663 RAIL_GET_APPID_REQ_ORDER getAppidReq;
1664 return rail_recv_client_get_appid_req_order(context, &getAppidReq, s);
1665 }
1666
1667 case TS_RAIL_ORDER_LANGBARINFO:
1668 {
1669 RAIL_LANGBAR_INFO_ORDER langbarInfo;
1670 return rail_recv_client_langbar_info_order(context, &langbarInfo, s);
1671 }
1672
1673 case TS_RAIL_ORDER_LANGUAGEIMEINFO:
1674 {
1675 RAIL_LANGUAGEIME_INFO_ORDER languageImeInfo;
1676 return rail_recv_client_language_ime_info_order(context, &languageImeInfo, s);
1677 }
1678
1679 case TS_RAIL_ORDER_COMPARTMENTINFO:
1680 {
1681 RAIL_COMPARTMENT_INFO_ORDER compartmentInfo;
1682 return rail_recv_client_compartment_info(context, &compartmentInfo, s);
1683 }
1684
1685 case TS_RAIL_ORDER_CLOAK:
1686 {
1687 RAIL_CLOAK cloak;
1688 return rail_recv_client_cloak_order(context, &cloak, s);
1689 }
1690
1691 case TS_RAIL_ORDER_TEXTSCALEINFO:
1692 {
1693 return rail_recv_client_text_scale_order(context, s);
1694 }
1695
1696 case TS_RAIL_ORDER_CARETBLINKINFO:
1697 {
1698 return rail_recv_client_caret_blink(context, s);
1699 }
1700
1701 default:
1702 WLog_ERR(TAG, "Unknown RAIL PDU order received.");
1703 return ERROR_INVALID_DATA;
1704 }
1705}