1 /**
2 * FreeRDP: A Remote Desktop Protocol Implementation
3 * Remote Applications Integrated Locally (RAIL) Orders
4 *
5 * Copyright 2009 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6 * Copyright 2011 Roman Barabanov <romanbarabanov@gmail.com>
7 * Copyright 2015 Thincast Technologies GmbH
8 * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
9 * Copyright 2017 Armin Novak <armin.novak@thincast.com>
10 * Copyright 2017 Thincast Technologies GmbH
11 *
12 * Licensed under the Apache License, Version 2.0 (the "License");
13 * you may not use this file except in compliance with the License.
14 * You may obtain a copy of the License at
15 *
16 * http://www.apache.org/licenses/LICENSE-2.0
17 *
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
23 */
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include <winpr/crt.h>
30
31 #include <freerdp/channels/log.h>
32
33 #include "rail_orders.h"
34
35 /**
36 * Function description
37 *
38 * @return 0 on success, otherwise a Win32 error code
39 */
rail_send_pdu(railPlugin * rail,wStream * s,UINT16 orderType)40 UINT rail_send_pdu(railPlugin* rail, wStream* s, UINT16 orderType)
41 {
42 UINT16 orderLength;
43
44 if (!rail || !s)
45 return ERROR_INVALID_PARAMETER;
46
47 orderLength = (UINT16)Stream_GetPosition(s);
48 Stream_SetPosition(s, 0);
49 rail_write_pdu_header(s, orderType, orderLength);
50 Stream_SetPosition(s, orderLength);
51 WLog_Print(rail->log, WLOG_DEBUG, "Sending %s PDU, length: %" PRIu16 "",
52 rail_get_order_type_string(orderType), orderLength);
53 return rail_send_channel_data(rail, s);
54 }
55
56 /**
57 * Function description
58 *
59 * @return 0 on success, otherwise a Win32 error code
60 */
rail_read_server_exec_result_order(wStream * s,RAIL_EXEC_RESULT_ORDER * execResult)61 static UINT rail_read_server_exec_result_order(wStream* s, RAIL_EXEC_RESULT_ORDER* execResult)
62 {
63 if (!s || !execResult)
64 return ERROR_INVALID_PARAMETER;
65
66 if (Stream_GetRemainingLength(s) < RAIL_EXEC_RESULT_ORDER_LENGTH)
67 {
68 WLog_ERR(TAG, "Stream_GetRemainingLength failed!");
69 return ERROR_INVALID_DATA;
70 }
71
72 Stream_Read_UINT16(s, execResult->flags); /* flags (2 bytes) */
73 Stream_Read_UINT16(s, execResult->execResult); /* execResult (2 bytes) */
74 Stream_Read_UINT32(s, execResult->rawResult); /* rawResult (4 bytes) */
75 Stream_Seek_UINT16(s); /* padding (2 bytes) */
76 return rail_read_unicode_string(s, &execResult->exeOrFile)
77 ? CHANNEL_RC_OK
78 : ERROR_INTERNAL_ERROR; /* exeOrFile */
79 }
80
81 /**
82 * Function description
83 *
84 * @return 0 on success, otherwise a Win32 error code
85 */
rail_read_server_minmaxinfo_order(wStream * s,RAIL_MINMAXINFO_ORDER * minmaxinfo)86 static UINT rail_read_server_minmaxinfo_order(wStream* s, RAIL_MINMAXINFO_ORDER* minmaxinfo)
87 {
88 if (!s || !minmaxinfo)
89 return ERROR_INVALID_PARAMETER;
90
91 if (Stream_GetRemainingLength(s) < RAIL_MINMAXINFO_ORDER_LENGTH)
92 {
93 WLog_ERR(TAG, "Stream_GetRemainingLength failed!");
94 return ERROR_INVALID_DATA;
95 }
96
97 Stream_Read_UINT32(s, minmaxinfo->windowId); /* windowId (4 bytes) */
98 Stream_Read_INT16(s, minmaxinfo->maxWidth); /* maxWidth (2 bytes) */
99 Stream_Read_INT16(s, minmaxinfo->maxHeight); /* maxHeight (2 bytes) */
100 Stream_Read_INT16(s, minmaxinfo->maxPosX); /* maxPosX (2 bytes) */
101 Stream_Read_INT16(s, minmaxinfo->maxPosY); /* maxPosY (2 bytes) */
102 Stream_Read_INT16(s, minmaxinfo->minTrackWidth); /* minTrackWidth (2 bytes) */
103 Stream_Read_INT16(s, minmaxinfo->minTrackHeight); /* minTrackHeight (2 bytes) */
104 Stream_Read_INT16(s, minmaxinfo->maxTrackWidth); /* maxTrackWidth (2 bytes) */
105 Stream_Read_INT16(s, minmaxinfo->maxTrackHeight); /* maxTrackHeight (2 bytes) */
106 return CHANNEL_RC_OK;
107 }
108
109 /**
110 * Function description
111 *
112 * @return 0 on success, otherwise a Win32 error code
113 */
rail_read_server_localmovesize_order(wStream * s,RAIL_LOCALMOVESIZE_ORDER * localMoveSize)114 static UINT rail_read_server_localmovesize_order(wStream* s,
115 RAIL_LOCALMOVESIZE_ORDER* localMoveSize)
116 {
117 UINT16 isMoveSizeStart;
118
119 if (!s || !localMoveSize)
120 return ERROR_INVALID_PARAMETER;
121
122 if (Stream_GetRemainingLength(s) < RAIL_LOCALMOVESIZE_ORDER_LENGTH)
123 {
124 WLog_ERR(TAG, "Stream_GetRemainingLength failed!");
125 return ERROR_INVALID_DATA;
126 }
127
128 Stream_Read_UINT32(s, localMoveSize->windowId); /* windowId (4 bytes) */
129 Stream_Read_UINT16(s, isMoveSizeStart); /* isMoveSizeStart (2 bytes) */
130 localMoveSize->isMoveSizeStart = (isMoveSizeStart != 0) ? TRUE : FALSE;
131 Stream_Read_UINT16(s, localMoveSize->moveSizeType); /* moveSizeType (2 bytes) */
132 Stream_Read_INT16(s, localMoveSize->posX); /* posX (2 bytes) */
133 Stream_Read_INT16(s, localMoveSize->posY); /* posY (2 bytes) */
134 return CHANNEL_RC_OK;
135 }
136
137 /**
138 * Function description
139 *
140 * @return 0 on success, otherwise a Win32 error code
141 */
rail_read_server_get_appid_resp_order(wStream * s,RAIL_GET_APPID_RESP_ORDER * getAppidResp)142 static UINT rail_read_server_get_appid_resp_order(wStream* s,
143 RAIL_GET_APPID_RESP_ORDER* getAppidResp)
144 {
145 if (!s || !getAppidResp)
146 return ERROR_INVALID_PARAMETER;
147
148 if (Stream_GetRemainingLength(s) < RAIL_GET_APPID_RESP_ORDER_LENGTH)
149 {
150 WLog_ERR(TAG, "Stream_GetRemainingLength failed!");
151 return ERROR_INVALID_DATA;
152 }
153
154 Stream_Read_UINT32(s, getAppidResp->windowId); /* windowId (4 bytes) */
155 Stream_Read_UTF16_String(
156 s, getAppidResp->applicationId,
157 ARRAYSIZE(getAppidResp->applicationId)); /* applicationId (260 UNICODE chars) */
158 return CHANNEL_RC_OK;
159 }
160
161 /**
162 * Function description
163 *
164 * @return 0 on success, otherwise a Win32 error code
165 */
rail_read_langbar_info_order(wStream * s,RAIL_LANGBAR_INFO_ORDER * langbarInfo)166 static UINT rail_read_langbar_info_order(wStream* s, RAIL_LANGBAR_INFO_ORDER* langbarInfo)
167 {
168 if (!s || !langbarInfo)
169 return ERROR_INVALID_PARAMETER;
170
171 if (Stream_GetRemainingLength(s) < RAIL_LANGBAR_INFO_ORDER_LENGTH)
172 {
173 WLog_ERR(TAG, "Stream_GetRemainingLength failed!");
174 return ERROR_INVALID_DATA;
175 }
176
177 Stream_Read_UINT32(s, langbarInfo->languageBarStatus); /* languageBarStatus (4 bytes) */
178 return CHANNEL_RC_OK;
179 }
180
rail_write_client_status_order(wStream * s,const RAIL_CLIENT_STATUS_ORDER * clientStatus)181 static UINT rail_write_client_status_order(wStream* s, const RAIL_CLIENT_STATUS_ORDER* clientStatus)
182 {
183 if (!s || !clientStatus)
184 return ERROR_INVALID_PARAMETER;
185
186 Stream_Write_UINT32(s, clientStatus->flags); /* flags (4 bytes) */
187 return ERROR_SUCCESS;
188 }
189
190 /**
191 * Function description
192 *
193 * @return 0 on success, otherwise a Win32 error code
194 */
rail_write_client_exec_order(wStream * s,UINT16 flags,const RAIL_UNICODE_STRING * exeOrFile,const RAIL_UNICODE_STRING * workingDir,const RAIL_UNICODE_STRING * arguments)195 static UINT rail_write_client_exec_order(wStream* s, UINT16 flags,
196 const RAIL_UNICODE_STRING* exeOrFile,
197 const RAIL_UNICODE_STRING* workingDir,
198 const RAIL_UNICODE_STRING* arguments)
199 {
200 UINT error;
201
202 if (!s || !exeOrFile || !workingDir || !arguments)
203 return ERROR_INVALID_PARAMETER;
204
205 /* [MS-RDPERP] 2.2.2.3.1 Client Execute PDU (TS_RAIL_ORDER_EXEC)
206 * Check argument limits */
207 if ((exeOrFile->length > 520) || (workingDir->length > 520) || (arguments->length > 16000))
208 {
209 WLog_ERR(TAG,
210 "TS_RAIL_ORDER_EXEC argument limits exceeded: ExeOrFile=%" PRIu16
211 " [max=520], WorkingDir=%" PRIu16 " [max=520], Arguments=%" PRIu16 " [max=16000]",
212 exeOrFile->length, workingDir->length, arguments->length);
213 return ERROR_BAD_ARGUMENTS;
214 }
215
216 Stream_Write_UINT16(s, flags); /* flags (2 bytes) */
217 Stream_Write_UINT16(s, exeOrFile->length); /* exeOrFileLength (2 bytes) */
218 Stream_Write_UINT16(s, workingDir->length); /* workingDirLength (2 bytes) */
219 Stream_Write_UINT16(s, arguments->length); /* argumentsLength (2 bytes) */
220
221 if ((error = rail_write_unicode_string_value(s, exeOrFile)))
222 {
223 WLog_ERR(TAG, "rail_write_unicode_string_value failed with error %" PRIu32 "", error);
224 return error;
225 }
226
227 if ((error = rail_write_unicode_string_value(s, workingDir)))
228 {
229 WLog_ERR(TAG, "rail_write_unicode_string_value failed with error %" PRIu32 "", error);
230 return error;
231 }
232
233 if ((error = rail_write_unicode_string_value(s, arguments)))
234 {
235 WLog_ERR(TAG, "rail_write_unicode_string_value failed with error %" PRIu32 "", error);
236 return error;
237 }
238
239 return error;
240 }
241
rail_write_client_activate_order(wStream * s,const RAIL_ACTIVATE_ORDER * activate)242 static UINT rail_write_client_activate_order(wStream* s, const RAIL_ACTIVATE_ORDER* activate)
243 {
244 BYTE enabled;
245
246 if (!s || !activate)
247 return ERROR_INVALID_PARAMETER;
248
249 Stream_Write_UINT32(s, activate->windowId); /* windowId (4 bytes) */
250 enabled = activate->enabled ? 1 : 0;
251 Stream_Write_UINT8(s, enabled); /* enabled (1 byte) */
252 return ERROR_SUCCESS;
253 }
254
rail_write_client_sysmenu_order(wStream * s,const RAIL_SYSMENU_ORDER * sysmenu)255 static UINT rail_write_client_sysmenu_order(wStream* s, const RAIL_SYSMENU_ORDER* sysmenu)
256 {
257 if (!s || !sysmenu)
258 return ERROR_INVALID_PARAMETER;
259
260 Stream_Write_UINT32(s, sysmenu->windowId); /* windowId (4 bytes) */
261 Stream_Write_INT16(s, sysmenu->left); /* left (2 bytes) */
262 Stream_Write_INT16(s, sysmenu->top); /* top (2 bytes) */
263 return ERROR_SUCCESS;
264 }
265
rail_write_client_syscommand_order(wStream * s,const RAIL_SYSCOMMAND_ORDER * syscommand)266 static UINT rail_write_client_syscommand_order(wStream* s, const RAIL_SYSCOMMAND_ORDER* syscommand)
267 {
268 if (!s || !syscommand)
269 return ERROR_INVALID_PARAMETER;
270
271 Stream_Write_UINT32(s, syscommand->windowId); /* windowId (4 bytes) */
272 Stream_Write_UINT16(s, syscommand->command); /* command (2 bytes) */
273 return ERROR_SUCCESS;
274 }
275
rail_write_client_notify_event_order(wStream * s,const RAIL_NOTIFY_EVENT_ORDER * notifyEvent)276 static UINT rail_write_client_notify_event_order(wStream* s,
277 const RAIL_NOTIFY_EVENT_ORDER* notifyEvent)
278 {
279 if (!s || !notifyEvent)
280 return ERROR_INVALID_PARAMETER;
281
282 Stream_Write_UINT32(s, notifyEvent->windowId); /* windowId (4 bytes) */
283 Stream_Write_UINT32(s, notifyEvent->notifyIconId); /* notifyIconId (4 bytes) */
284 Stream_Write_UINT32(s, notifyEvent->message); /* notifyIconId (4 bytes) */
285 return ERROR_SUCCESS;
286 }
287
rail_write_client_window_move_order(wStream * s,const RAIL_WINDOW_MOVE_ORDER * windowMove)288 static UINT rail_write_client_window_move_order(wStream* s,
289 const RAIL_WINDOW_MOVE_ORDER* windowMove)
290 {
291 if (!s || !windowMove)
292 return ERROR_INVALID_PARAMETER;
293
294 Stream_Write_UINT32(s, windowMove->windowId); /* windowId (4 bytes) */
295 Stream_Write_INT16(s, windowMove->left); /* left (2 bytes) */
296 Stream_Write_INT16(s, windowMove->top); /* top (2 bytes) */
297 Stream_Write_INT16(s, windowMove->right); /* right (2 bytes) */
298 Stream_Write_INT16(s, windowMove->bottom); /* bottom (2 bytes) */
299 return ERROR_SUCCESS;
300 }
301
rail_write_client_get_appid_req_order(wStream * s,const RAIL_GET_APPID_REQ_ORDER * getAppidReq)302 static UINT rail_write_client_get_appid_req_order(wStream* s,
303 const RAIL_GET_APPID_REQ_ORDER* getAppidReq)
304 {
305 if (!s || !getAppidReq)
306 return ERROR_INVALID_PARAMETER;
307
308 Stream_Write_UINT32(s, getAppidReq->windowId); /* windowId (4 bytes) */
309 return ERROR_SUCCESS;
310 }
311
rail_write_langbar_info_order(wStream * s,const RAIL_LANGBAR_INFO_ORDER * langbarInfo)312 static UINT rail_write_langbar_info_order(wStream* s, const RAIL_LANGBAR_INFO_ORDER* langbarInfo)
313 {
314 if (!s || !langbarInfo)
315 return ERROR_INVALID_PARAMETER;
316
317 Stream_Write_UINT32(s, langbarInfo->languageBarStatus); /* languageBarStatus (4 bytes) */
318 return ERROR_SUCCESS;
319 }
320
rail_write_languageime_info_order(wStream * s,const RAIL_LANGUAGEIME_INFO_ORDER * langImeInfo)321 static UINT rail_write_languageime_info_order(wStream* s,
322 const RAIL_LANGUAGEIME_INFO_ORDER* langImeInfo)
323 {
324 if (!s || !langImeInfo)
325 return ERROR_INVALID_PARAMETER;
326
327 Stream_Write_UINT32(s, langImeInfo->ProfileType);
328 Stream_Write_UINT16(s, langImeInfo->LanguageID);
329 Stream_Write(s, &langImeInfo->LanguageProfileCLSID, sizeof(langImeInfo->LanguageProfileCLSID));
330 Stream_Write(s, &langImeInfo->ProfileGUID, sizeof(langImeInfo->ProfileGUID));
331 Stream_Write_UINT32(s, langImeInfo->KeyboardLayout);
332 return ERROR_SUCCESS;
333 }
334
rail_write_compartment_info_order(wStream * s,const RAIL_COMPARTMENT_INFO_ORDER * compartmentInfo)335 static UINT rail_write_compartment_info_order(wStream* s,
336 const RAIL_COMPARTMENT_INFO_ORDER* compartmentInfo)
337 {
338 if (!s || !compartmentInfo)
339 return ERROR_INVALID_PARAMETER;
340
341 Stream_Write_UINT32(s, compartmentInfo->ImeState);
342 Stream_Write_UINT32(s, compartmentInfo->ImeConvMode);
343 Stream_Write_UINT32(s, compartmentInfo->ImeSentenceMode);
344 Stream_Write_UINT32(s, compartmentInfo->KanaMode);
345 return ERROR_SUCCESS;
346 }
347
348 /**
349 * Function description
350 *
351 * @return 0 on success, otherwise a Win32 error code
352 */
rail_recv_handshake_order(railPlugin * rail,wStream * s)353 static UINT rail_recv_handshake_order(railPlugin* rail, wStream* s)
354 {
355 RailClientContext* context = rail_get_client_interface(rail);
356 RAIL_HANDSHAKE_ORDER serverHandshake = { 0 };
357 UINT error;
358
359 if (!context || !s)
360 return ERROR_INVALID_PARAMETER;
361
362 if ((error = rail_read_handshake_order(s, &serverHandshake)))
363 {
364 WLog_ERR(TAG, "rail_read_handshake_order failed with error %" PRIu32 "!", error);
365 return error;
366 }
367
368 rail->channelBuildNumber = serverHandshake.buildNumber;
369
370 if (rail->sendHandshake)
371 {
372 RAIL_HANDSHAKE_ORDER clientHandshake = { 0 };
373 clientHandshake.buildNumber = 0x00001DB0;
374 error = context->ClientHandshake(context, &clientHandshake);
375 }
376
377 if (error != CHANNEL_RC_OK)
378 return error;
379
380 if (context->custom)
381 {
382 IFCALLRET(context->ServerHandshake, error, context, &serverHandshake);
383
384 if (error)
385 WLog_ERR(TAG, "context.ServerHandshake failed with error %" PRIu32 "", error);
386 }
387
388 return error;
389 }
390
rail_is_feature_supported(const rdpContext * context,UINT32 featureMask)391 static BOOL rail_is_feature_supported(const rdpContext* context, UINT32 featureMask)
392 {
393 UINT32 supported, masked;
394
395 if (!context || !context->settings)
396 return FALSE;
397
398 supported = context->settings->RemoteApplicationSupportLevel &
399 context->settings->RemoteApplicationSupportMask;
400 masked = (supported & featureMask);
401
402 if (masked != featureMask)
403 return FALSE;
404
405 return TRUE;
406 }
407
408 /**
409 * Function description
410 *
411 * @return 0 on success, otherwise a Win32 error code
412 */
rail_recv_handshake_ex_order(railPlugin * rail,wStream * s)413 static UINT rail_recv_handshake_ex_order(railPlugin* rail, wStream* s)
414 {
415 RailClientContext* context = rail_get_client_interface(rail);
416 RAIL_HANDSHAKE_EX_ORDER serverHandshake = { 0 };
417 UINT error;
418
419 if (!rail || !context || !s)
420 return ERROR_INVALID_PARAMETER;
421
422 if (!rail_is_feature_supported(rail->rdpcontext, RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED))
423 return ERROR_BAD_CONFIGURATION;
424
425 if ((error = rail_read_handshake_ex_order(s, &serverHandshake)))
426 {
427 WLog_ERR(TAG, "rail_read_handshake_ex_order failed with error %" PRIu32 "!", error);
428 return error;
429 }
430
431 rail->channelBuildNumber = serverHandshake.buildNumber;
432 rail->channelFlags = serverHandshake.railHandshakeFlags;
433
434 if (rail->sendHandshake)
435 {
436 RAIL_HANDSHAKE_ORDER clientHandshake = { 0 };
437 clientHandshake.buildNumber = 0x00001DB0;
438 /* 2.2.2.2.3 HandshakeEx PDU (TS_RAIL_ORDER_HANDSHAKE_EX)
439 * Client response is really a Handshake PDU */
440 error = context->ClientHandshake(context, &clientHandshake);
441 }
442
443 if (error != CHANNEL_RC_OK)
444 return error;
445
446 if (context->custom)
447 {
448 IFCALLRET(context->ServerHandshakeEx, error, context, &serverHandshake);
449
450 if (error)
451 WLog_ERR(TAG, "context.ServerHandshakeEx failed with error %" PRIu32 "", error);
452 }
453
454 return error;
455 }
456
457 /**
458 * Function description
459 *
460 * @return 0 on success, otherwise a Win32 error code
461 */
rail_recv_exec_result_order(railPlugin * rail,wStream * s)462 static UINT rail_recv_exec_result_order(railPlugin* rail, wStream* s)
463 {
464 RailClientContext* context = rail_get_client_interface(rail);
465 RAIL_EXEC_RESULT_ORDER execResult = { 0 };
466 UINT error;
467
468 if (!context || !s)
469 return ERROR_INVALID_PARAMETER;
470
471 if ((error = rail_read_server_exec_result_order(s, &execResult)))
472 {
473 WLog_ERR(TAG, "rail_read_server_exec_result_order failed with error %" PRIu32 "!", error);
474 goto fail;
475 }
476
477 if (context->custom)
478 {
479 IFCALLRET(context->ServerExecuteResult, error, context, &execResult);
480
481 if (error)
482 WLog_ERR(TAG, "context.ServerExecuteResult failed with error %" PRIu32 "", error);
483 }
484
485 fail:
486 free(execResult.exeOrFile.string);
487 return error;
488 }
489
490 /**
491 * Function description
492 *
493 * @return 0 on success, otherwise a Win32 error code
494 */
rail_recv_server_sysparam_order(railPlugin * rail,wStream * s)495 static UINT rail_recv_server_sysparam_order(railPlugin* rail, wStream* s)
496 {
497 RailClientContext* context = rail_get_client_interface(rail);
498 RAIL_SYSPARAM_ORDER sysparam;
499 UINT error;
500 BOOL extendedSpiSupported;
501
502 if (!context || !s)
503 return ERROR_INVALID_PARAMETER;
504
505 extendedSpiSupported = rail_is_extended_spi_supported(rail->channelFlags);
506 if ((error = rail_read_sysparam_order(s, &sysparam, extendedSpiSupported)))
507 {
508 WLog_ERR(TAG, "rail_read_sysparam_order failed with error %" PRIu32 "!", error);
509 return error;
510 }
511
512 if (context->custom)
513 {
514 IFCALLRET(context->ServerSystemParam, error, context, &sysparam);
515
516 if (error)
517 WLog_ERR(TAG, "context.ServerSystemParam failed with error %" PRIu32 "", error);
518 }
519
520 return error;
521 }
522
523 /**
524 * Function description
525 *
526 * @return 0 on success, otherwise a Win32 error code
527 */
rail_recv_server_minmaxinfo_order(railPlugin * rail,wStream * s)528 static UINT rail_recv_server_minmaxinfo_order(railPlugin* rail, wStream* s)
529 {
530 RailClientContext* context = rail_get_client_interface(rail);
531 RAIL_MINMAXINFO_ORDER minMaxInfo = { 0 };
532 UINT error;
533
534 if (!context || !s)
535 return ERROR_INVALID_PARAMETER;
536
537 if ((error = rail_read_server_minmaxinfo_order(s, &minMaxInfo)))
538 {
539 WLog_ERR(TAG, "rail_read_server_minmaxinfo_order failed with error %" PRIu32 "!", error);
540 return error;
541 }
542
543 if (context->custom)
544 {
545 IFCALLRET(context->ServerMinMaxInfo, error, context, &minMaxInfo);
546
547 if (error)
548 WLog_ERR(TAG, "context.ServerMinMaxInfo failed with error %" PRIu32 "", error);
549 }
550
551 return error;
552 }
553
554 /**
555 * Function description
556 *
557 * @return 0 on success, otherwise a Win32 error code
558 */
rail_recv_server_localmovesize_order(railPlugin * rail,wStream * s)559 static UINT rail_recv_server_localmovesize_order(railPlugin* rail, wStream* s)
560 {
561 RailClientContext* context = rail_get_client_interface(rail);
562 RAIL_LOCALMOVESIZE_ORDER localMoveSize = { 0 };
563 UINT error;
564
565 if (!context || !s)
566 return ERROR_INVALID_PARAMETER;
567
568 if ((error = rail_read_server_localmovesize_order(s, &localMoveSize)))
569 {
570 WLog_ERR(TAG, "rail_read_server_localmovesize_order failed with error %" PRIu32 "!", error);
571 return error;
572 }
573
574 if (context->custom)
575 {
576 IFCALLRET(context->ServerLocalMoveSize, error, context, &localMoveSize);
577
578 if (error)
579 WLog_ERR(TAG, "context.ServerLocalMoveSize failed with error %" PRIu32 "", error);
580 }
581
582 return error;
583 }
584
585 /**
586 * Function description
587 *
588 * @return 0 on success, otherwise a Win32 error code
589 */
rail_recv_server_get_appid_resp_order(railPlugin * rail,wStream * s)590 static UINT rail_recv_server_get_appid_resp_order(railPlugin* rail, wStream* s)
591 {
592 RailClientContext* context = rail_get_client_interface(rail);
593 RAIL_GET_APPID_RESP_ORDER getAppIdResp = { 0 };
594 UINT error;
595
596 if (!context || !s)
597 return ERROR_INVALID_PARAMETER;
598
599 if ((error = rail_read_server_get_appid_resp_order(s, &getAppIdResp)))
600 {
601 WLog_ERR(TAG, "rail_read_server_get_appid_resp_order failed with error %" PRIu32 "!",
602 error);
603 return error;
604 }
605
606 if (context->custom)
607 {
608 IFCALLRET(context->ServerGetAppIdResponse, error, context, &getAppIdResp);
609
610 if (error)
611 WLog_ERR(TAG, "context.ServerGetAppIdResponse failed with error %" PRIu32 "", error);
612 }
613
614 return error;
615 }
616
617 /**
618 * Function description
619 *
620 * @return 0 on success, otherwise a Win32 error code
621 */
rail_recv_langbar_info_order(railPlugin * rail,wStream * s)622 static UINT rail_recv_langbar_info_order(railPlugin* rail, wStream* s)
623 {
624 RailClientContext* context = rail_get_client_interface(rail);
625 RAIL_LANGBAR_INFO_ORDER langBarInfo = { 0 };
626 UINT error;
627
628 if (!context)
629 return ERROR_INVALID_PARAMETER;
630
631 if (!rail_is_feature_supported(rail->rdpcontext, RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED))
632 return ERROR_BAD_CONFIGURATION;
633
634 if ((error = rail_read_langbar_info_order(s, &langBarInfo)))
635 {
636 WLog_ERR(TAG, "rail_read_langbar_info_order failed with error %" PRIu32 "!", error);
637 return error;
638 }
639
640 if (context->custom)
641 {
642 IFCALLRET(context->ServerLanguageBarInfo, error, context, &langBarInfo);
643
644 if (error)
645 WLog_ERR(TAG, "context.ServerLanguageBarInfo failed with error %" PRIu32 "", error);
646 }
647
648 return error;
649 }
650
rail_read_taskbar_info_order(wStream * s,RAIL_TASKBAR_INFO_ORDER * taskbarInfo)651 static UINT rail_read_taskbar_info_order(wStream* s, RAIL_TASKBAR_INFO_ORDER* taskbarInfo)
652 {
653 if (!s || !taskbarInfo)
654 return ERROR_INVALID_PARAMETER;
655
656 if (Stream_GetRemainingLength(s) < RAIL_TASKBAR_INFO_ORDER_LENGTH)
657 {
658 WLog_ERR(TAG, "Stream_GetRemainingLength failed!");
659 return ERROR_INVALID_DATA;
660 }
661
662 Stream_Read_UINT32(s, taskbarInfo->TaskbarMessage);
663 Stream_Read_UINT32(s, taskbarInfo->WindowIdTab);
664 Stream_Read_UINT32(s, taskbarInfo->Body);
665 return CHANNEL_RC_OK;
666 }
667
rail_recv_taskbar_info_order(railPlugin * rail,wStream * s)668 static UINT rail_recv_taskbar_info_order(railPlugin* rail, wStream* s)
669 {
670 RailClientContext* context = rail_get_client_interface(rail);
671 RAIL_TASKBAR_INFO_ORDER taskBarInfo = { 0 };
672 UINT error;
673
674 if (!context)
675 return ERROR_INVALID_PARAMETER;
676
677 /* 2.2.2.14.1 Taskbar Tab Info PDU (TS_RAIL_ORDER_TASKBARINFO)
678 * server -> client message only supported if announced. */
679 if (!rail_is_feature_supported(rail->rdpcontext, RAIL_LEVEL_SHELL_INTEGRATION_SUPPORTED))
680 return ERROR_BAD_CONFIGURATION;
681
682 if ((error = rail_read_taskbar_info_order(s, &taskBarInfo)))
683 {
684 WLog_ERR(TAG, "rail_read_langbar_info_order failed with error %" PRIu32 "!", error);
685 return error;
686 }
687
688 if (context->custom)
689 {
690 IFCALLRET(context->ServerTaskBarInfo, error, context, &taskBarInfo);
691
692 if (error)
693 WLog_ERR(TAG, "context.ServerTaskBarInfo failed with error %" PRIu32 "", error);
694 }
695
696 return error;
697 }
698
rail_read_zorder_sync_order(wStream * s,RAIL_ZORDER_SYNC * zorder)699 static UINT rail_read_zorder_sync_order(wStream* s, RAIL_ZORDER_SYNC* zorder)
700 {
701 if (!s || !zorder)
702 return ERROR_INVALID_PARAMETER;
703
704 if (Stream_GetRemainingLength(s) < RAIL_Z_ORDER_SYNC_ORDER_LENGTH)
705 {
706 WLog_ERR(TAG, "Stream_GetRemainingLength failed!");
707 return ERROR_INVALID_DATA;
708 }
709
710 Stream_Read_UINT32(s, zorder->windowIdMarker);
711 return CHANNEL_RC_OK;
712 }
713
rail_recv_zorder_sync_order(railPlugin * rail,wStream * s)714 static UINT rail_recv_zorder_sync_order(railPlugin* rail, wStream* s)
715 {
716 RailClientContext* context = rail_get_client_interface(rail);
717 RAIL_ZORDER_SYNC zorder = { 0 };
718 UINT error;
719
720 if (!context)
721 return ERROR_INVALID_PARAMETER;
722
723 if ((rail->clientStatus.flags & TS_RAIL_CLIENTSTATUS_ZORDER_SYNC) == 0)
724 return ERROR_INVALID_DATA;
725
726 if ((error = rail_read_zorder_sync_order(s, &zorder)))
727 {
728 WLog_ERR(TAG, "rail_read_zorder_sync_order failed with error %" PRIu32 "!", error);
729 return error;
730 }
731
732 if (context->custom)
733 {
734 IFCALLRET(context->ServerZOrderSync, error, context, &zorder);
735
736 if (error)
737 WLog_ERR(TAG, "context.ServerZOrderSync failed with error %" PRIu32 "", error);
738 }
739
740 return error;
741 }
742
rail_read_cloak_order(wStream * s,RAIL_CLOAK * cloak)743 static UINT rail_read_cloak_order(wStream* s, RAIL_CLOAK* cloak)
744 {
745 BYTE cloaked;
746
747 if (Stream_GetRemainingLength(s) < RAIL_CLOAK_ORDER_LENGTH)
748 {
749 WLog_ERR(TAG, "Stream_GetRemainingLength failed!");
750 return ERROR_INVALID_DATA;
751 }
752
753 Stream_Read_UINT32(s, cloak->windowId); /* WindowId (4 bytes) */
754 Stream_Read_UINT8(s, cloaked); /* Cloaked (1 byte) */
755 cloak->cloak = (cloaked != 0) ? TRUE : FALSE;
756 return CHANNEL_RC_OK;
757 }
758
rail_recv_cloak_order(railPlugin * rail,wStream * s)759 static UINT rail_recv_cloak_order(railPlugin* rail, wStream* s)
760 {
761 RailClientContext* context = rail_get_client_interface(rail);
762 RAIL_CLOAK cloak = { 0 };
763 UINT error;
764
765 if (!context)
766 return ERROR_INVALID_PARAMETER;
767
768 /* 2.2.2.12.1 Window Cloak State Change PDU (TS_RAIL_ORDER_CLOAK)
769 * server -> client message only supported if announced. */
770 if ((rail->clientStatus.flags & TS_RAIL_CLIENTSTATUS_BIDIRECTIONAL_CLOAK_SUPPORTED) == 0)
771 return ERROR_INVALID_DATA;
772
773 if ((error = rail_read_cloak_order(s, &cloak)))
774 {
775 WLog_ERR(TAG, "rail_read_zorder_sync_order failed with error %" PRIu32 "!", error);
776 return error;
777 }
778
779 if (context->custom)
780 {
781 IFCALLRET(context->ServerCloak, error, context, &cloak);
782
783 if (error)
784 WLog_ERR(TAG, "context.ServerZOrderSync failed with error %" PRIu32 "", error);
785 }
786
787 return error;
788 }
789
rail_read_power_display_request_order(wStream * s,RAIL_POWER_DISPLAY_REQUEST * power)790 static UINT rail_read_power_display_request_order(wStream* s, RAIL_POWER_DISPLAY_REQUEST* power)
791 {
792 UINT32 active;
793
794 if (!s || !power)
795 return ERROR_INVALID_PARAMETER;
796
797 if (Stream_GetRemainingLength(s) < RAIL_POWER_DISPLAY_REQUEST_ORDER_LENGTH)
798 {
799 WLog_ERR(TAG, "Stream_GetRemainingLength failed!");
800 return ERROR_INVALID_DATA;
801 }
802
803 Stream_Read_UINT32(s, active);
804 power->active = active != 0;
805 return CHANNEL_RC_OK;
806 }
807
rail_recv_power_display_request_order(railPlugin * rail,wStream * s)808 static UINT rail_recv_power_display_request_order(railPlugin* rail, wStream* s)
809 {
810 RailClientContext* context = rail_get_client_interface(rail);
811 RAIL_POWER_DISPLAY_REQUEST power = { 0 };
812 UINT error;
813
814 if (!context)
815 return ERROR_INVALID_PARAMETER;
816
817 /* 2.2.2.13.1 Power Display Request PDU(TS_RAIL_ORDER_POWER_DISPLAY_REQUEST)
818 */
819 if ((rail->clientStatus.flags & TS_RAIL_CLIENTSTATUS_POWER_DISPLAY_REQUEST_SUPPORTED) == 0)
820 return ERROR_INVALID_DATA;
821
822 if ((error = rail_read_power_display_request_order(s, &power)))
823 {
824 WLog_ERR(TAG, "rail_read_zorder_sync_order failed with error %" PRIu32 "!", error);
825 return error;
826 }
827
828 if (context->custom)
829 {
830 IFCALLRET(context->ServerPowerDisplayRequest, error, context, &power);
831
832 if (error)
833 WLog_ERR(TAG, "context.ServerPowerDisplayRequest failed with error %" PRIu32 "", error);
834 }
835
836 return error;
837 }
838
rail_read_get_application_id_extended_response_order(wStream * s,RAIL_GET_APPID_RESP_EX * id)839 static UINT rail_read_get_application_id_extended_response_order(wStream* s,
840 RAIL_GET_APPID_RESP_EX* id)
841 {
842 if (!s || !id)
843 return ERROR_INVALID_PARAMETER;
844
845 if (Stream_GetRemainingLength(s) < 4)
846 {
847 WLog_ERR(TAG, "Stream_GetRemainingLength failed!");
848 return ERROR_INVALID_DATA;
849 }
850
851 Stream_Read_UINT32(s, id->windowID);
852
853 if (!Stream_Read_UTF16_String(s, id->applicationID, ARRAYSIZE(id->applicationID)))
854 return ERROR_INVALID_DATA;
855
856 if (_wcsnlen(id->applicationID, ARRAYSIZE(id->applicationID)) >= ARRAYSIZE(id->applicationID))
857 return ERROR_INVALID_DATA;
858
859 if (Stream_GetRemainingLength(s) < 4)
860 {
861 WLog_ERR(TAG, "Stream_GetRemainingLength failed!");
862 return ERROR_INVALID_DATA;
863 }
864
865 Stream_Read_UINT32(s, id->processId);
866
867 if (!Stream_Read_UTF16_String(s, id->processImageName, ARRAYSIZE(id->processImageName)))
868 return ERROR_INVALID_DATA;
869
870 if (_wcsnlen(id->applicationID, ARRAYSIZE(id->processImageName)) >=
871 ARRAYSIZE(id->processImageName))
872 return ERROR_INVALID_DATA;
873
874 return CHANNEL_RC_OK;
875 }
876
rail_recv_get_application_id_extended_response_order(railPlugin * rail,wStream * s)877 static UINT rail_recv_get_application_id_extended_response_order(railPlugin* rail, wStream* s)
878 {
879 RailClientContext* context = rail_get_client_interface(rail);
880 RAIL_GET_APPID_RESP_EX id = { 0 };
881 UINT error;
882
883 if (!context)
884 return ERROR_INVALID_PARAMETER;
885
886 if ((error = rail_read_get_application_id_extended_response_order(s, &id)))
887 {
888 WLog_ERR(TAG,
889 "rail_read_get_application_id_extended_response_order failed with error %" PRIu32
890 "!",
891 error);
892 return error;
893 }
894
895 if (context->custom)
896 {
897 IFCALLRET(context->ServerGetAppidResponseExtended, error, context, &id);
898
899 if (error)
900 WLog_ERR(TAG, "context.ServerGetAppidResponseExtended failed with error %" PRIu32 "",
901 error);
902 }
903
904 return error;
905 }
906
907 /**
908 * Function description
909 *
910 * @return 0 on success, otherwise a Win32 error code
911 */
rail_order_recv(railPlugin * rail,wStream * s)912 UINT rail_order_recv(railPlugin* rail, wStream* s)
913 {
914 UINT16 orderType;
915 UINT16 orderLength;
916 UINT error;
917
918 if (!rail || !s)
919 return ERROR_INVALID_PARAMETER;
920
921 if ((error = rail_read_pdu_header(s, &orderType, &orderLength)))
922 {
923 WLog_ERR(TAG, "rail_read_pdu_header failed with error %" PRIu32 "!", error);
924 return error;
925 }
926
927 WLog_Print(rail->log, WLOG_DEBUG, "Received %s PDU, length:%" PRIu16 "",
928 rail_get_order_type_string(orderType), orderLength);
929
930 switch (orderType)
931 {
932 case TS_RAIL_ORDER_HANDSHAKE:
933 return rail_recv_handshake_order(rail, s);
934
935 case TS_RAIL_ORDER_HANDSHAKE_EX:
936 return rail_recv_handshake_ex_order(rail, s);
937
938 case TS_RAIL_ORDER_EXEC_RESULT:
939 return rail_recv_exec_result_order(rail, s);
940
941 case TS_RAIL_ORDER_SYSPARAM:
942 return rail_recv_server_sysparam_order(rail, s);
943
944 case TS_RAIL_ORDER_MINMAXINFO:
945 return rail_recv_server_minmaxinfo_order(rail, s);
946
947 case TS_RAIL_ORDER_LOCALMOVESIZE:
948 return rail_recv_server_localmovesize_order(rail, s);
949
950 case TS_RAIL_ORDER_GET_APPID_RESP:
951 return rail_recv_server_get_appid_resp_order(rail, s);
952
953 case TS_RAIL_ORDER_LANGBARINFO:
954 return rail_recv_langbar_info_order(rail, s);
955
956 case TS_RAIL_ORDER_TASKBARINFO:
957 return rail_recv_taskbar_info_order(rail, s);
958
959 case TS_RAIL_ORDER_ZORDER_SYNC:
960 return rail_recv_zorder_sync_order(rail, s);
961
962 case TS_RAIL_ORDER_CLOAK:
963 return rail_recv_cloak_order(rail, s);
964
965 case TS_RAIL_ORDER_POWER_DISPLAY_REQUEST:
966 return rail_recv_power_display_request_order(rail, s);
967
968 case TS_RAIL_ORDER_GET_APPID_RESP_EX:
969 return rail_recv_get_application_id_extended_response_order(rail, s);
970
971 default:
972 WLog_ERR(TAG, "Unknown RAIL PDU order reveived.");
973 return ERROR_INVALID_DATA;
974 }
975
976 return CHANNEL_RC_OK;
977 }
978
979 /**
980 * Function description
981 *
982 * @return 0 on success, otherwise a Win32 error code
983 */
rail_send_handshake_order(railPlugin * rail,const RAIL_HANDSHAKE_ORDER * handshake)984 UINT rail_send_handshake_order(railPlugin* rail, const RAIL_HANDSHAKE_ORDER* handshake)
985 {
986 wStream* s;
987 UINT error;
988
989 if (!rail || !handshake)
990 return ERROR_INVALID_PARAMETER;
991
992 s = rail_pdu_init(RAIL_HANDSHAKE_ORDER_LENGTH);
993
994 if (!s)
995 {
996 WLog_ERR(TAG, "rail_pdu_init failed!");
997 return CHANNEL_RC_NO_MEMORY;
998 }
999
1000 rail_write_handshake_order(s, handshake);
1001 error = rail_send_pdu(rail, s, TS_RAIL_ORDER_HANDSHAKE);
1002 Stream_Free(s, TRUE);
1003 return error;
1004 }
1005
1006 /**
1007 * Function description
1008 *
1009 * @return 0 on success, otherwise a Win32 error code
1010 */
rail_send_handshake_ex_order(railPlugin * rail,const RAIL_HANDSHAKE_EX_ORDER * handshakeEx)1011 UINT rail_send_handshake_ex_order(railPlugin* rail, const RAIL_HANDSHAKE_EX_ORDER* handshakeEx)
1012 {
1013 wStream* s;
1014 UINT error;
1015
1016 if (!rail || !handshakeEx)
1017 return ERROR_INVALID_PARAMETER;
1018
1019 s = rail_pdu_init(RAIL_HANDSHAKE_EX_ORDER_LENGTH);
1020
1021 if (!s)
1022 {
1023 WLog_ERR(TAG, "rail_pdu_init failed!");
1024 return CHANNEL_RC_NO_MEMORY;
1025 }
1026
1027 rail_write_handshake_ex_order(s, handshakeEx);
1028 error = rail_send_pdu(rail, s, TS_RAIL_ORDER_HANDSHAKE_EX);
1029 Stream_Free(s, TRUE);
1030 return error;
1031 }
1032
1033 /**
1034 * Function description
1035 *
1036 * @return 0 on success, otherwise a Win32 error code
1037 */
rail_send_client_status_order(railPlugin * rail,const RAIL_CLIENT_STATUS_ORDER * clientStatus)1038 UINT rail_send_client_status_order(railPlugin* rail, const RAIL_CLIENT_STATUS_ORDER* clientStatus)
1039 {
1040 wStream* s;
1041 UINT error;
1042
1043 if (!rail || !clientStatus)
1044 return ERROR_INVALID_PARAMETER;
1045
1046 rail->clientStatus = *clientStatus;
1047 s = rail_pdu_init(RAIL_CLIENT_STATUS_ORDER_LENGTH);
1048
1049 if (!s)
1050 {
1051 WLog_ERR(TAG, "rail_pdu_init failed!");
1052 return CHANNEL_RC_NO_MEMORY;
1053 }
1054
1055 error = rail_write_client_status_order(s, clientStatus);
1056
1057 if (error == ERROR_SUCCESS)
1058 error = rail_send_pdu(rail, s, TS_RAIL_ORDER_CLIENTSTATUS);
1059
1060 Stream_Free(s, TRUE);
1061 return error;
1062 }
1063
1064 /**
1065 * Function description
1066 *
1067 * @return 0 on success, otherwise a Win32 error code
1068 */
rail_send_client_exec_order(railPlugin * rail,UINT16 flags,const RAIL_UNICODE_STRING * exeOrFile,const RAIL_UNICODE_STRING * workingDir,const RAIL_UNICODE_STRING * arguments)1069 UINT rail_send_client_exec_order(railPlugin* rail, UINT16 flags,
1070 const RAIL_UNICODE_STRING* exeOrFile,
1071 const RAIL_UNICODE_STRING* workingDir,
1072 const RAIL_UNICODE_STRING* arguments)
1073 {
1074 wStream* s;
1075 UINT error;
1076 size_t length;
1077
1078 if (!rail || !exeOrFile || !workingDir || !arguments)
1079 return ERROR_INVALID_PARAMETER;
1080
1081 length = RAIL_EXEC_ORDER_LENGTH + exeOrFile->length + workingDir->length + arguments->length;
1082 s = rail_pdu_init(length);
1083
1084 if (!s)
1085 {
1086 WLog_ERR(TAG, "rail_pdu_init failed!");
1087 return CHANNEL_RC_NO_MEMORY;
1088 }
1089
1090 if ((error = rail_write_client_exec_order(s, flags, exeOrFile, workingDir, arguments)))
1091 {
1092 WLog_ERR(TAG, "rail_write_client_exec_order failed with error %" PRIu32 "!", error);
1093 goto out;
1094 }
1095
1096 if ((error = rail_send_pdu(rail, s, TS_RAIL_ORDER_EXEC)))
1097 {
1098 WLog_ERR(TAG, "rail_send_pdu failed with error %" PRIu32 "!", error);
1099 goto out;
1100 }
1101
1102 out:
1103 Stream_Free(s, TRUE);
1104 return error;
1105 }
1106
1107 /**
1108 * Function description
1109 *
1110 * @return 0 on success, otherwise a Win32 error code
1111 */
rail_send_client_activate_order(railPlugin * rail,const RAIL_ACTIVATE_ORDER * activate)1112 UINT rail_send_client_activate_order(railPlugin* rail, const RAIL_ACTIVATE_ORDER* activate)
1113 {
1114 wStream* s;
1115 UINT error;
1116
1117 if (!rail || !activate)
1118 return ERROR_INVALID_PARAMETER;
1119
1120 s = rail_pdu_init(RAIL_ACTIVATE_ORDER_LENGTH);
1121
1122 if (!s)
1123 {
1124 WLog_ERR(TAG, "rail_pdu_init failed!");
1125 return CHANNEL_RC_NO_MEMORY;
1126 }
1127
1128 error = rail_write_client_activate_order(s, activate);
1129
1130 if (error == ERROR_SUCCESS)
1131 error = rail_send_pdu(rail, s, TS_RAIL_ORDER_ACTIVATE);
1132
1133 Stream_Free(s, TRUE);
1134 return error;
1135 }
1136
1137 /**
1138 * Function description
1139 *
1140 * @return 0 on success, otherwise a Win32 error code
1141 */
rail_send_client_sysmenu_order(railPlugin * rail,const RAIL_SYSMENU_ORDER * sysmenu)1142 UINT rail_send_client_sysmenu_order(railPlugin* rail, const RAIL_SYSMENU_ORDER* sysmenu)
1143 {
1144 wStream* s;
1145 UINT error;
1146
1147 if (!rail || !sysmenu)
1148 return ERROR_INVALID_PARAMETER;
1149
1150 s = rail_pdu_init(RAIL_SYSMENU_ORDER_LENGTH);
1151
1152 if (!s)
1153 {
1154 WLog_ERR(TAG, "rail_pdu_init failed!");
1155 return CHANNEL_RC_NO_MEMORY;
1156 }
1157
1158 error = rail_write_client_sysmenu_order(s, sysmenu);
1159
1160 if (error == ERROR_SUCCESS)
1161 error = rail_send_pdu(rail, s, TS_RAIL_ORDER_SYSMENU);
1162
1163 Stream_Free(s, TRUE);
1164 return error;
1165 }
1166
1167 /**
1168 * Function description
1169 *
1170 * @return 0 on success, otherwise a Win32 error code
1171 */
rail_send_client_syscommand_order(railPlugin * rail,const RAIL_SYSCOMMAND_ORDER * syscommand)1172 UINT rail_send_client_syscommand_order(railPlugin* rail, const RAIL_SYSCOMMAND_ORDER* syscommand)
1173 {
1174 wStream* s;
1175 UINT error;
1176
1177 if (!rail || !syscommand)
1178 return ERROR_INVALID_PARAMETER;
1179
1180 s = rail_pdu_init(RAIL_SYSCOMMAND_ORDER_LENGTH);
1181
1182 if (!s)
1183 {
1184 WLog_ERR(TAG, "rail_pdu_init failed!");
1185 return CHANNEL_RC_NO_MEMORY;
1186 }
1187
1188 error = rail_write_client_syscommand_order(s, syscommand);
1189
1190 if (error == ERROR_SUCCESS)
1191 error = rail_send_pdu(rail, s, TS_RAIL_ORDER_SYSCOMMAND);
1192
1193 Stream_Free(s, TRUE);
1194 return error;
1195 }
1196
1197 /**
1198 * Function description
1199 *
1200 * @return 0 on success, otherwise a Win32 error code
1201 */
rail_send_client_notify_event_order(railPlugin * rail,const RAIL_NOTIFY_EVENT_ORDER * notifyEvent)1202 UINT rail_send_client_notify_event_order(railPlugin* rail,
1203 const RAIL_NOTIFY_EVENT_ORDER* notifyEvent)
1204 {
1205 wStream* s;
1206 UINT error;
1207
1208 if (!rail || !notifyEvent)
1209 return ERROR_INVALID_PARAMETER;
1210
1211 s = rail_pdu_init(RAIL_NOTIFY_EVENT_ORDER_LENGTH);
1212
1213 if (!s)
1214 {
1215 WLog_ERR(TAG, "rail_pdu_init failed!");
1216 return CHANNEL_RC_NO_MEMORY;
1217 }
1218
1219 error = rail_write_client_notify_event_order(s, notifyEvent);
1220
1221 if (ERROR_SUCCESS == error)
1222 error = rail_send_pdu(rail, s, TS_RAIL_ORDER_NOTIFY_EVENT);
1223
1224 Stream_Free(s, TRUE);
1225 return error;
1226 }
1227
1228 /**
1229 * Function description
1230 *
1231 * @return 0 on success, otherwise a Win32 error code
1232 */
rail_send_client_window_move_order(railPlugin * rail,const RAIL_WINDOW_MOVE_ORDER * windowMove)1233 UINT rail_send_client_window_move_order(railPlugin* rail, const RAIL_WINDOW_MOVE_ORDER* windowMove)
1234 {
1235 wStream* s;
1236 UINT error;
1237
1238 if (!rail || !windowMove)
1239 return ERROR_INVALID_PARAMETER;
1240
1241 s = rail_pdu_init(RAIL_WINDOW_MOVE_ORDER_LENGTH);
1242
1243 if (!s)
1244 {
1245 WLog_ERR(TAG, "rail_pdu_init failed!");
1246 return CHANNEL_RC_NO_MEMORY;
1247 }
1248
1249 error = rail_write_client_window_move_order(s, windowMove);
1250
1251 if (error == ERROR_SUCCESS)
1252 error = rail_send_pdu(rail, s, TS_RAIL_ORDER_WINDOWMOVE);
1253
1254 Stream_Free(s, TRUE);
1255 return error;
1256 }
1257
1258 /**
1259 * Function description
1260 *
1261 * @return 0 on success, otherwise a Win32 error code
1262 */
rail_send_client_get_appid_req_order(railPlugin * rail,const RAIL_GET_APPID_REQ_ORDER * getAppIdReq)1263 UINT rail_send_client_get_appid_req_order(railPlugin* rail,
1264 const RAIL_GET_APPID_REQ_ORDER* getAppIdReq)
1265 {
1266 wStream* s;
1267 UINT error;
1268
1269 if (!rail || !getAppIdReq)
1270 return ERROR_INVALID_PARAMETER;
1271
1272 s = rail_pdu_init(RAIL_GET_APPID_REQ_ORDER_LENGTH);
1273
1274 if (!s)
1275 {
1276 WLog_ERR(TAG, "rail_pdu_init failed!");
1277 return CHANNEL_RC_NO_MEMORY;
1278 }
1279
1280 error = rail_write_client_get_appid_req_order(s, getAppIdReq);
1281
1282 if (error == ERROR_SUCCESS)
1283 error = rail_send_pdu(rail, s, TS_RAIL_ORDER_GET_APPID_REQ);
1284
1285 Stream_Free(s, TRUE);
1286 return error;
1287 }
1288
1289 /**
1290 * Function description
1291 *
1292 * @return 0 on success, otherwise a Win32 error code
1293 */
rail_send_client_langbar_info_order(railPlugin * rail,const RAIL_LANGBAR_INFO_ORDER * langBarInfo)1294 UINT rail_send_client_langbar_info_order(railPlugin* rail,
1295 const RAIL_LANGBAR_INFO_ORDER* langBarInfo)
1296 {
1297 wStream* s;
1298 UINT error;
1299
1300 if (!rail || !langBarInfo)
1301 return ERROR_INVALID_PARAMETER;
1302
1303 if (!rail_is_feature_supported(rail->rdpcontext, RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED))
1304 return ERROR_BAD_CONFIGURATION;
1305
1306 s = rail_pdu_init(RAIL_LANGBAR_INFO_ORDER_LENGTH);
1307
1308 if (!s)
1309 {
1310 WLog_ERR(TAG, "rail_pdu_init failed!");
1311 return CHANNEL_RC_NO_MEMORY;
1312 }
1313
1314 error = rail_write_langbar_info_order(s, langBarInfo);
1315
1316 if (ERROR_SUCCESS == error)
1317 error = rail_send_pdu(rail, s, TS_RAIL_ORDER_LANGBARINFO);
1318
1319 Stream_Free(s, TRUE);
1320 return error;
1321 }
1322
rail_send_client_languageime_info_order(railPlugin * rail,const RAIL_LANGUAGEIME_INFO_ORDER * langImeInfo)1323 UINT rail_send_client_languageime_info_order(railPlugin* rail,
1324 const RAIL_LANGUAGEIME_INFO_ORDER* langImeInfo)
1325 {
1326 wStream* s;
1327 UINT error;
1328
1329 if (!rail || !langImeInfo)
1330 return ERROR_INVALID_PARAMETER;
1331
1332 if (!rail_is_feature_supported(rail->rdpcontext, RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED))
1333 return ERROR_BAD_CONFIGURATION;
1334
1335 s = rail_pdu_init(RAIL_LANGUAGEIME_INFO_ORDER_LENGTH);
1336
1337 if (!s)
1338 {
1339 WLog_ERR(TAG, "rail_pdu_init failed!");
1340 return CHANNEL_RC_NO_MEMORY;
1341 }
1342
1343 error = rail_write_languageime_info_order(s, langImeInfo);
1344
1345 if (ERROR_SUCCESS == error)
1346 error = rail_send_pdu(rail, s, TS_RAIL_ORDER_LANGUAGEIMEINFO);
1347
1348 Stream_Free(s, TRUE);
1349 return error;
1350 }
1351
rail_send_client_compartment_info_order(railPlugin * rail,const RAIL_COMPARTMENT_INFO_ORDER * compartmentInfo)1352 UINT rail_send_client_compartment_info_order(railPlugin* rail,
1353 const RAIL_COMPARTMENT_INFO_ORDER* compartmentInfo)
1354 {
1355 wStream* s;
1356 UINT error;
1357
1358 if (!rail || !compartmentInfo)
1359 return ERROR_INVALID_PARAMETER;
1360
1361 s = rail_pdu_init(RAIL_COMPARTMENT_INFO_ORDER_LENGTH);
1362
1363 if (!s)
1364 {
1365 WLog_ERR(TAG, "rail_pdu_init failed!");
1366 return CHANNEL_RC_NO_MEMORY;
1367 }
1368
1369 error = rail_write_compartment_info_order(s, compartmentInfo);
1370
1371 if (ERROR_SUCCESS == error)
1372 error = rail_send_pdu(rail, s, TS_RAIL_ORDER_COMPARTMENTINFO);
1373
1374 Stream_Free(s, TRUE);
1375 return error;
1376 }
1377
rail_send_client_cloak_order(railPlugin * rail,const RAIL_CLOAK * cloak)1378 UINT rail_send_client_cloak_order(railPlugin* rail, const RAIL_CLOAK* cloak)
1379 {
1380 wStream* s;
1381 UINT error;
1382
1383 if (!rail || !cloak)
1384 return ERROR_INVALID_PARAMETER;
1385
1386 s = rail_pdu_init(5);
1387
1388 if (!s)
1389 {
1390 WLog_ERR(TAG, "rail_pdu_init failed!");
1391 return CHANNEL_RC_NO_MEMORY;
1392 }
1393
1394 Stream_Write_UINT32(s, cloak->windowId);
1395 Stream_Write_UINT8(s, cloak->cloak ? 1 : 0);
1396 error = rail_send_pdu(rail, s, TS_RAIL_ORDER_CLOAK);
1397 Stream_Free(s, TRUE);
1398 return error;
1399 }
1400
rail_send_client_snap_arrange_order(railPlugin * rail,const RAIL_SNAP_ARRANGE * snap)1401 UINT rail_send_client_snap_arrange_order(railPlugin* rail, const RAIL_SNAP_ARRANGE* snap)
1402 {
1403 wStream* s;
1404 UINT error;
1405
1406 if (!rail)
1407 return ERROR_INVALID_PARAMETER;
1408
1409 /* 2.2.2.7.5 Client Window Snap PDU (TS_RAIL_ORDER_SNAP_ARRANGE) */
1410 if ((rail->channelFlags & TS_RAIL_ORDER_HANDSHAKE_EX_FLAGS_SNAP_ARRANGE_SUPPORTED) == 0)
1411 {
1412 RAIL_WINDOW_MOVE_ORDER move = { 0 };
1413 move.top = snap->top;
1414 move.left = snap->left;
1415 move.right = snap->right;
1416 move.bottom = snap->bottom;
1417 move.windowId = snap->windowId;
1418 return rail_send_client_window_move_order(rail, &move);
1419 }
1420
1421 s = rail_pdu_init(12);
1422
1423 if (!s)
1424 {
1425 WLog_ERR(TAG, "rail_pdu_init failed!");
1426 return CHANNEL_RC_NO_MEMORY;
1427 }
1428
1429 Stream_Write_UINT32(s, snap->windowId);
1430 Stream_Write_INT16(s, snap->left);
1431 Stream_Write_INT16(s, snap->top);
1432 Stream_Write_INT16(s, snap->right);
1433 Stream_Write_INT16(s, snap->bottom);
1434 error = rail_send_pdu(rail, s, TS_RAIL_ORDER_SNAP_ARRANGE);
1435 Stream_Free(s, TRUE);
1436 return error;
1437 }
1438