23 #include "rail_common.h"
25 #include <winpr/crt.h>
26 #include <freerdp/channels/log.h>
28 #define TAG CHANNELS_TAG("rail.common")
30 const char* rail_get_order_type_string(UINT16 orderType)
34 case TS_RAIL_ORDER_EXEC:
35 return "TS_RAIL_ORDER_EXEC";
36 case TS_RAIL_ORDER_ACTIVATE:
37 return "TS_RAIL_ORDER_ACTIVATE";
38 case TS_RAIL_ORDER_SYSPARAM:
39 return "TS_RAIL_ORDER_SYSPARAM";
40 case TS_RAIL_ORDER_SYSCOMMAND:
41 return "TS_RAIL_ORDER_SYSCOMMAND";
42 case TS_RAIL_ORDER_HANDSHAKE:
43 return "TS_RAIL_ORDER_HANDSHAKE";
44 case TS_RAIL_ORDER_NOTIFY_EVENT:
45 return "TS_RAIL_ORDER_NOTIFY_EVENT";
46 case TS_RAIL_ORDER_WINDOWMOVE:
47 return "TS_RAIL_ORDER_WINDOWMOVE";
48 case TS_RAIL_ORDER_LOCALMOVESIZE:
49 return "TS_RAIL_ORDER_LOCALMOVESIZE";
50 case TS_RAIL_ORDER_MINMAXINFO:
51 return "TS_RAIL_ORDER_MINMAXINFO";
52 case TS_RAIL_ORDER_CLIENTSTATUS:
53 return "TS_RAIL_ORDER_CLIENTSTATUS";
54 case TS_RAIL_ORDER_SYSMENU:
55 return "TS_RAIL_ORDER_SYSMENU";
56 case TS_RAIL_ORDER_LANGBARINFO:
57 return "TS_RAIL_ORDER_LANGBARINFO";
58 case TS_RAIL_ORDER_GET_APPID_REQ:
59 return "TS_RAIL_ORDER_GET_APPID_REQ";
60 case TS_RAIL_ORDER_GET_APPID_RESP:
61 return "TS_RAIL_ORDER_GET_APPID_RESP";
62 case TS_RAIL_ORDER_TASKBARINFO:
63 return "TS_RAIL_ORDER_TASKBARINFO";
64 case TS_RAIL_ORDER_LANGUAGEIMEINFO:
65 return "TS_RAIL_ORDER_LANGUAGEIMEINFO";
66 case TS_RAIL_ORDER_COMPARTMENTINFO:
67 return "TS_RAIL_ORDER_COMPARTMENTINFO";
68 case TS_RAIL_ORDER_HANDSHAKE_EX:
69 return "TS_RAIL_ORDER_HANDSHAKE_EX";
70 case TS_RAIL_ORDER_ZORDER_SYNC:
71 return "TS_RAIL_ORDER_ZORDER_SYNC";
72 case TS_RAIL_ORDER_CLOAK:
73 return "TS_RAIL_ORDER_CLOAK";
74 case TS_RAIL_ORDER_POWER_DISPLAY_REQUEST:
75 return "TS_RAIL_ORDER_POWER_DISPLAY_REQUEST";
76 case TS_RAIL_ORDER_SNAP_ARRANGE:
77 return "TS_RAIL_ORDER_SNAP_ARRANGE";
78 case TS_RAIL_ORDER_GET_APPID_RESP_EX:
79 return "TS_RAIL_ORDER_GET_APPID_RESP_EX";
80 case TS_RAIL_ORDER_EXEC_RESULT:
81 return "TS_RAIL_ORDER_EXEC_RESULT";
82 case TS_RAIL_ORDER_TEXTSCALEINFO:
83 return "TS_RAIL_ORDER_TEXTSCALEINFO";
84 case TS_RAIL_ORDER_CARETBLINKINFO:
85 return "TS_RAIL_ORDER_CARETBLINKINFO";
87 return "TS_RAIL_ORDER_UNKNOWN";
91 const char* rail_get_order_type_string_full(UINT16 orderType,
char* buffer,
size_t length)
93 (void)_snprintf(buffer, length,
"%s[0x%04" PRIx16
"]", rail_get_order_type_string(orderType),
103 UINT rail_read_pdu_header(
wStream* s, UINT16* orderType, UINT16* orderLength)
105 if (!s || !orderType || !orderLength)
106 return ERROR_INVALID_PARAMETER;
108 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
109 return ERROR_INVALID_DATA;
111 Stream_Read_UINT16(s, *orderType);
112 Stream_Read_UINT16(s, *orderLength);
113 return CHANNEL_RC_OK;
116 void rail_write_pdu_header(
wStream* s, UINT16 orderType, UINT16 orderLength)
118 Stream_Write_UINT16(s, orderType);
119 Stream_Write_UINT16(s, orderLength);
122 wStream* rail_pdu_init(
size_t length)
124 wStream* s = Stream_New(NULL, length + RAIL_PDU_HEADER_LENGTH);
129 Stream_Seek(s, RAIL_PDU_HEADER_LENGTH);
140 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
141 return ERROR_INVALID_DATA;
143 Stream_Read_UINT32(s, handshake->buildNumber);
144 return CHANNEL_RC_OK;
149 Stream_Write_UINT32(s, handshake->buildNumber);
159 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
160 return ERROR_INVALID_DATA;
162 Stream_Read_UINT32(s, handshakeEx->buildNumber);
163 Stream_Read_UINT32(s, handshakeEx->railHandshakeFlags);
164 return CHANNEL_RC_OK;
169 Stream_Write_UINT32(s, handshakeEx->buildNumber);
170 Stream_Write_UINT32(s, handshakeEx->railHandshakeFlags);
180 if (!s || !unicode_string)
181 return ERROR_INVALID_PARAMETER;
183 if (!Stream_EnsureRemainingCapacity(s, 2 + unicode_string->length))
185 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
186 return CHANNEL_RC_NO_MEMORY;
189 Stream_Write_UINT16(s, unicode_string->length);
190 Stream_Write(s, unicode_string->string, unicode_string->length);
191 return CHANNEL_RC_OK;
203 if (!s || !unicode_string)
204 return ERROR_INVALID_PARAMETER;
206 length = unicode_string->length;
210 if (!Stream_EnsureRemainingCapacity(s, length))
212 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
213 return CHANNEL_RC_NO_MEMORY;
216 Stream_Write(s, unicode_string->string, length);
219 return CHANNEL_RC_OK;
229 if (!s || !highContrast)
230 return ERROR_INVALID_PARAMETER;
232 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
233 return ERROR_INVALID_DATA;
235 Stream_Read_UINT32(s, highContrast->flags);
236 Stream_Read_UINT32(s, highContrast->colorSchemeLength);
238 if (!rail_read_unicode_string(s, &highContrast->colorScheme))
239 return ERROR_INTERNAL_ERROR;
240 return CHANNEL_RC_OK;
250 UINT32 colorSchemeLength = 0;
252 if (!s || !highContrast)
253 return ERROR_INVALID_PARAMETER;
255 if (!Stream_EnsureRemainingCapacity(s, 8))
256 return CHANNEL_RC_NO_MEMORY;
258 colorSchemeLength = highContrast->colorScheme.length + 2;
259 Stream_Write_UINT32(s, highContrast->flags);
260 Stream_Write_UINT32(s, colorSchemeLength);
261 return rail_write_unicode_string(s, &highContrast->colorScheme);
271 if (!s || !filterKeys)
272 return ERROR_INVALID_PARAMETER;
274 if (!Stream_CheckAndLogRequiredLength(TAG, s, 20))
275 return ERROR_INVALID_DATA;
277 Stream_Read_UINT32(s, filterKeys->Flags);
278 Stream_Read_UINT32(s, filterKeys->WaitTime);
279 Stream_Read_UINT32(s, filterKeys->DelayTime);
280 Stream_Read_UINT32(s, filterKeys->RepeatTime);
281 Stream_Read_UINT32(s, filterKeys->BounceTime);
282 return CHANNEL_RC_OK;
292 if (!s || !filterKeys)
293 return ERROR_INVALID_PARAMETER;
295 if (!Stream_EnsureRemainingCapacity(s, 20))
296 return CHANNEL_RC_NO_MEMORY;
298 Stream_Write_UINT32(s, filterKeys->Flags);
299 Stream_Write_UINT32(s, filterKeys->WaitTime);
300 Stream_Write_UINT32(s, filterKeys->DelayTime);
301 Stream_Write_UINT32(s, filterKeys->RepeatTime);
302 Stream_Write_UINT32(s, filterKeys->BounceTime);
303 return CHANNEL_RC_OK;
314 UINT error = CHANNEL_RC_OK;
317 return ERROR_INVALID_PARAMETER;
319 if (!Stream_CheckAndLogRequiredLength(TAG, s, 5))
320 return ERROR_INVALID_DATA;
322 Stream_Read_UINT32(s, sysparam->param);
324 sysparam->params = 0;
326 switch (sysparam->param)
329 case SPI_SET_DRAG_FULL_WINDOWS:
330 sysparam->params |= SPI_MASK_SET_DRAG_FULL_WINDOWS;
331 Stream_Read_UINT8(s, body);
332 sysparam->dragFullWindows = body != 0;
335 case SPI_SET_KEYBOARD_CUES:
336 sysparam->params |= SPI_MASK_SET_KEYBOARD_CUES;
337 Stream_Read_UINT8(s, body);
338 sysparam->keyboardCues = body != 0;
341 case SPI_SET_KEYBOARD_PREF:
342 sysparam->params |= SPI_MASK_SET_KEYBOARD_PREF;
343 Stream_Read_UINT8(s, body);
344 sysparam->keyboardPref = body != 0;
347 case SPI_SET_MOUSE_BUTTON_SWAP:
348 sysparam->params |= SPI_MASK_SET_MOUSE_BUTTON_SWAP;
349 Stream_Read_UINT8(s, body);
350 sysparam->mouseButtonSwap = body != 0;
353 case SPI_SET_WORK_AREA:
354 sysparam->params |= SPI_MASK_SET_WORK_AREA;
356 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
357 return ERROR_INVALID_DATA;
359 Stream_Read_UINT16(s, sysparam->workArea.left);
360 Stream_Read_UINT16(s, sysparam->workArea.top);
361 Stream_Read_UINT16(s, sysparam->workArea.right);
362 Stream_Read_UINT16(s, sysparam->workArea.bottom);
365 case SPI_DISPLAY_CHANGE:
366 sysparam->params |= SPI_MASK_DISPLAY_CHANGE;
368 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
369 return ERROR_INVALID_DATA;
371 Stream_Read_UINT16(s, sysparam->displayChange.left);
372 Stream_Read_UINT16(s, sysparam->displayChange.top);
373 Stream_Read_UINT16(s, sysparam->displayChange.right);
374 Stream_Read_UINT16(s, sysparam->displayChange.bottom);
377 case SPI_TASKBAR_POS:
378 sysparam->params |= SPI_MASK_TASKBAR_POS;
380 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
381 return ERROR_INVALID_DATA;
383 Stream_Read_UINT16(s, sysparam->taskbarPos.left);
384 Stream_Read_UINT16(s, sysparam->taskbarPos.top);
385 Stream_Read_UINT16(s, sysparam->taskbarPos.right);
386 Stream_Read_UINT16(s, sysparam->taskbarPos.bottom);
389 case SPI_SET_HIGH_CONTRAST:
390 sysparam->params |= SPI_MASK_SET_HIGH_CONTRAST;
391 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
392 return ERROR_INVALID_DATA;
394 error = rail_read_high_contrast(s, &sysparam->highContrast);
397 case SPI_SETCARETWIDTH:
398 sysparam->params |= SPI_MASK_SET_CARET_WIDTH;
400 if (!extendedSpiSupported)
401 return ERROR_INVALID_DATA;
403 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
404 return ERROR_INVALID_DATA;
406 Stream_Read_UINT32(s, sysparam->caretWidth);
408 if (sysparam->caretWidth < 0x0001)
409 return ERROR_INVALID_DATA;
413 case SPI_SETSTICKYKEYS:
414 sysparam->params |= SPI_MASK_SET_STICKY_KEYS;
416 if (!extendedSpiSupported)
417 return ERROR_INVALID_DATA;
419 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
420 return ERROR_INVALID_DATA;
422 Stream_Read_UINT32(s, sysparam->stickyKeys);
425 case SPI_SETTOGGLEKEYS:
426 sysparam->params |= SPI_MASK_SET_TOGGLE_KEYS;
428 if (!extendedSpiSupported)
429 return ERROR_INVALID_DATA;
431 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
432 return ERROR_INVALID_DATA;
434 Stream_Read_UINT32(s, sysparam->toggleKeys);
437 case SPI_SETFILTERKEYS:
438 sysparam->params |= SPI_MASK_SET_FILTER_KEYS;
440 if (!extendedSpiSupported)
441 return ERROR_INVALID_DATA;
443 if (!Stream_CheckAndLogRequiredLength(TAG, s, 20))
444 return ERROR_INVALID_DATA;
446 error = rail_read_filterkeys(s, &sysparam->filterKeys);
450 case SPI_SETSCREENSAVEACTIVE:
451 sysparam->params |= SPI_MASK_SET_SCREEN_SAVE_ACTIVE;
453 Stream_Read_UINT8(s, body);
454 sysparam->setScreenSaveActive = body != 0;
457 case SPI_SETSCREENSAVESECURE:
458 sysparam->params |= SPI_MASK_SET_SET_SCREEN_SAVE_SECURE;
460 Stream_Read_UINT8(s, body);
461 sysparam->setScreenSaveSecure = body != 0;
477 BOOL extendedSpiSupported)
480 UINT error = CHANNEL_RC_OK;
483 return ERROR_INVALID_PARAMETER;
485 if (!Stream_EnsureRemainingCapacity(s, 12))
486 return CHANNEL_RC_NO_MEMORY;
488 Stream_Write_UINT32(s, sysparam->param);
490 switch (sysparam->param)
493 case SPI_SET_DRAG_FULL_WINDOWS:
494 body = sysparam->dragFullWindows ? 1 : 0;
495 Stream_Write_UINT8(s, body);
498 case SPI_SET_KEYBOARD_CUES:
499 body = sysparam->keyboardCues ? 1 : 0;
500 Stream_Write_UINT8(s, body);
503 case SPI_SET_KEYBOARD_PREF:
504 body = sysparam->keyboardPref ? 1 : 0;
505 Stream_Write_UINT8(s, body);
508 case SPI_SET_MOUSE_BUTTON_SWAP:
509 body = sysparam->mouseButtonSwap ? 1 : 0;
510 Stream_Write_UINT8(s, body);
513 case SPI_SET_WORK_AREA:
514 Stream_Write_UINT16(s, sysparam->workArea.left);
515 Stream_Write_UINT16(s, sysparam->workArea.top);
516 Stream_Write_UINT16(s, sysparam->workArea.right);
517 Stream_Write_UINT16(s, sysparam->workArea.bottom);
520 case SPI_DISPLAY_CHANGE:
521 Stream_Write_UINT16(s, sysparam->displayChange.left);
522 Stream_Write_UINT16(s, sysparam->displayChange.top);
523 Stream_Write_UINT16(s, sysparam->displayChange.right);
524 Stream_Write_UINT16(s, sysparam->displayChange.bottom);
527 case SPI_TASKBAR_POS:
528 Stream_Write_UINT16(s, sysparam->taskbarPos.left);
529 Stream_Write_UINT16(s, sysparam->taskbarPos.top);
530 Stream_Write_UINT16(s, sysparam->taskbarPos.right);
531 Stream_Write_UINT16(s, sysparam->taskbarPos.bottom);
534 case SPI_SET_HIGH_CONTRAST:
535 error = rail_write_high_contrast(s, &sysparam->highContrast);
538 case SPI_SETCARETWIDTH:
539 if (!extendedSpiSupported)
540 return ERROR_INVALID_DATA;
542 if (sysparam->caretWidth < 0x0001)
543 return ERROR_INVALID_DATA;
545 Stream_Write_UINT32(s, sysparam->caretWidth);
548 case SPI_SETSTICKYKEYS:
549 if (!extendedSpiSupported)
550 return ERROR_INVALID_DATA;
552 Stream_Write_UINT32(s, sysparam->stickyKeys);
555 case SPI_SETTOGGLEKEYS:
556 if (!extendedSpiSupported)
557 return ERROR_INVALID_DATA;
559 Stream_Write_UINT32(s, sysparam->toggleKeys);
562 case SPI_SETFILTERKEYS:
563 if (!extendedSpiSupported)
564 return ERROR_INVALID_DATA;
566 error = rail_write_filterkeys(s, &sysparam->filterKeys);
570 case SPI_SETSCREENSAVEACTIVE:
571 body = sysparam->setScreenSaveActive ? 1 : 0;
572 Stream_Write_UINT8(s, body);
575 case SPI_SETSCREENSAVESECURE:
576 body = sysparam->setScreenSaveSecure ? 1 : 0;
577 Stream_Write_UINT8(s, body);
581 return ERROR_INVALID_PARAMETER;
587 BOOL rail_is_extended_spi_supported(UINT32 channelFlags)
589 return (channelFlags & TS_RAIL_ORDER_HANDSHAKE_EX_FLAGS_EXTENDED_SPI_SUPPORTED) ? TRUE : FALSE;
592 const char* rail_handshake_ex_flags_to_string(UINT32 flags,
char* buffer,
size_t len)
597 (void)_snprintf(buffer, len,
"{");
598 char* fbuffer = &buffer[1];
601 if (flags & TS_RAIL_ORDER_HANDSHAKEEX_FLAGS_HIDEF)
602 winpr_str_append(
"HIDEF", fbuffer, len,
"|");
603 if (flags & TS_RAIL_ORDER_HANDSHAKE_EX_FLAGS_EXTENDED_SPI_SUPPORTED)
604 winpr_str_append(
"EXTENDED_SPI_SUPPORTED", fbuffer, len,
"|");
605 if (flags & TS_RAIL_ORDER_HANDSHAKE_EX_FLAGS_SNAP_ARRANGE_SUPPORTED)
606 winpr_str_append(
"SNAP_ARRANGE_SUPPORTED", fbuffer, len,
"|");
607 if (flags & TS_RAIL_ORDER_HANDSHAKE_EX_FLAGS_TEXT_SCALE_SUPPORTED)
608 winpr_str_append(
"TEXT_SCALE_SUPPORTED", fbuffer, len,
"|");
609 if (flags & TS_RAIL_ORDER_HANDSHAKE_EX_FLAGS_CARET_BLINK_SUPPORTED)
610 winpr_str_append(
"CARET_BLINK_SUPPORTED", fbuffer, len,
"|");
611 if (flags & TS_RAIL_ORDER_HANDSHAKE_EX_FLAGS_EXTENDED_SPI_2_SUPPORTED)
612 winpr_str_append(
"EXTENDED_SPI_2_SUPPORTED", fbuffer, len,
"|");
614 char number[16] = { 0 };
615 (void)_snprintf(number,
sizeof(number),
"[0x%08" PRIx32
"]", flags);
616 winpr_str_append(number, buffer, len,
"}");