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