Blame channels/rail/rail_common.c

Packit Service fa4841
/**
Packit Service fa4841
 * FreeRDP: A Remote Desktop Protocol Implementation
Packit Service fa4841
 * RAIL common functions
Packit Service fa4841
 *
Packit Service fa4841
 * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
Packit Service fa4841
 * Copyright 2011 Roman Barabanov <romanbarabanov@gmail.com>
Packit Service fa4841
 * Copyright 2011 Vic Lee
Packit Service fa4841
 * Copyright 2015 Thincast Technologies GmbH
Packit Service fa4841
 * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
Packit Service fa4841
 *
Packit Service fa4841
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit Service fa4841
 * you may not use this file except in compliance with the License.
Packit Service fa4841
 * You may obtain a copy of the License at
Packit Service fa4841
 *
Packit Service fa4841
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit Service fa4841
 *
Packit Service fa4841
 * Unless required by applicable law or agreed to in writing, software
Packit Service fa4841
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit Service fa4841
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit Service fa4841
 * See the License for the specific language governing permissions and
Packit Service fa4841
 * limitations under the License.
Packit Service fa4841
 */
Packit Service fa4841
#include "rail_common.h"
Packit Service fa4841
Packit Service fa4841
#include <winpr/crt.h>
Packit Service b1ea74
#include <freerdp/channels/log.h>
Packit Service fa4841
Packit Service b1ea74
#define TAG CHANNELS_TAG("rail.common")
Packit Service b1ea74
Packit Service b1ea74
static const char* const RAIL_ORDER_TYPE_STRINGS[] = { "",
Packit Service b1ea74
	                                                   "Execute",
Packit Service b1ea74
	                                                   "Activate",
Packit Service b1ea74
	                                                   "System Parameters Update",
Packit Service b1ea74
	                                                   "System Command",
Packit Service b1ea74
	                                                   "Handshake",
Packit Service b1ea74
	                                                   "Notify Event",
Packit Service b1ea74
	                                                   "",
Packit Service b1ea74
	                                                   "Window Move",
Packit Service b1ea74
	                                                   "Local Move/Size",
Packit Service b1ea74
	                                                   "Min Max Info",
Packit Service b1ea74
	                                                   "Client Status",
Packit Service b1ea74
	                                                   "System Menu",
Packit Service b1ea74
	                                                   "Language Bar Info",
Packit Service b1ea74
	                                                   "Get Application ID Request",
Packit Service b1ea74
	                                                   "Get Application ID Response",
Packit Service b1ea74
	                                                   "Execute Result",
Packit Service b1ea74
	                                                   "",
Packit Service b1ea74
	                                                   "",
Packit Service b1ea74
	                                                   "",
Packit Service b1ea74
	                                                   "",
Packit Service b1ea74
	                                                   "",
Packit Service b1ea74
	                                                   "" };
Packit Service fa4841
Packit Service b1ea74
const char* rail_get_order_type_string(UINT16 orderType)
Packit Service b1ea74
{
Packit Service b1ea74
	UINT32 index = ((orderType & 0xF0) >> 3) + (orderType & 0x0F);
Packit Service b1ea74
	if (index >= ARRAYSIZE(RAIL_ORDER_TYPE_STRINGS))
Packit Service b1ea74
		return "UNKNOWN";
Packit Service b1ea74
Packit Service b1ea74
	return RAIL_ORDER_TYPE_STRINGS[index];
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Function description
Packit Service fa4841
 *
Packit Service fa4841
 * @return 0 on success, otherwise a Win32 error code
Packit Service fa4841
 */
Packit Service fa4841
UINT rail_read_pdu_header(wStream* s, UINT16* orderType, UINT16* orderLength)
Packit Service fa4841
{
Packit Service fa4841
	if (!s || !orderType || !orderLength)
Packit Service fa4841
		return ERROR_INVALID_PARAMETER;
Packit Service fa4841
Packit Service fa4841
	if (Stream_GetRemainingLength(s) < 4)
Packit Service fa4841
		return ERROR_INVALID_DATA;
Packit Service fa4841
Packit Service b1ea74
	Stream_Read_UINT16(s, *orderType);   /* orderType (2 bytes) */
Packit Service fa4841
	Stream_Read_UINT16(s, *orderLength); /* orderLength (2 bytes) */
Packit Service fa4841
	return CHANNEL_RC_OK;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
void rail_write_pdu_header(wStream* s, UINT16 orderType, UINT16 orderLength)
Packit Service fa4841
{
Packit Service b1ea74
	Stream_Write_UINT16(s, orderType);   /* orderType (2 bytes) */
Packit Service fa4841
	Stream_Write_UINT16(s, orderLength); /* orderLength (2 bytes) */
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
wStream* rail_pdu_init(size_t length)
Packit Service fa4841
{
Packit Service fa4841
	wStream* s;
Packit Service fa4841
	s = Stream_New(NULL, length + RAIL_PDU_HEADER_LENGTH);
Packit Service fa4841
Packit Service fa4841
	if (!s)
Packit Service fa4841
		return NULL;
Packit Service fa4841
Packit Service fa4841
	Stream_Seek(s, RAIL_PDU_HEADER_LENGTH);
Packit Service fa4841
	return s;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Function description
Packit Service fa4841
 *
Packit Service fa4841
 * @return 0 on success, otherwise a Win32 error code
Packit Service fa4841
 */
Packit Service fa4841
UINT rail_read_handshake_order(wStream* s, RAIL_HANDSHAKE_ORDER* handshake)
Packit Service fa4841
{
Packit Service fa4841
	if (Stream_GetRemainingLength(s) < 4)
Packit Service fa4841
		return ERROR_INVALID_DATA;
Packit Service fa4841
Packit Service fa4841
	Stream_Read_UINT32(s, handshake->buildNumber); /* buildNumber (4 bytes) */
Packit Service fa4841
	return CHANNEL_RC_OK;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
void rail_write_handshake_order(wStream* s, const RAIL_HANDSHAKE_ORDER* handshake)
Packit Service fa4841
{
Packit Service fa4841
	Stream_Write_UINT32(s, handshake->buildNumber); /* buildNumber (4 bytes) */
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Function description
Packit Service fa4841
 *
Packit Service fa4841
 * @return 0 on success, otherwise a Win32 error code
Packit Service fa4841
 */
Packit Service fa4841
UINT rail_read_handshake_ex_order(wStream* s, RAIL_HANDSHAKE_EX_ORDER* handshakeEx)
Packit Service fa4841
{
Packit Service fa4841
	if (Stream_GetRemainingLength(s) < 8)
Packit Service fa4841
		return ERROR_INVALID_DATA;
Packit Service fa4841
Packit Service b1ea74
	Stream_Read_UINT32(s, handshakeEx->buildNumber);        /* buildNumber (4 bytes) */
Packit Service fa4841
	Stream_Read_UINT32(s, handshakeEx->railHandshakeFlags); /* railHandshakeFlags (4 bytes) */
Packit Service fa4841
	return CHANNEL_RC_OK;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
void rail_write_handshake_ex_order(wStream* s, const RAIL_HANDSHAKE_EX_ORDER* handshakeEx)
Packit Service fa4841
{
Packit Service b1ea74
	Stream_Write_UINT32(s, handshakeEx->buildNumber);        /* buildNumber (4 bytes) */
Packit Service fa4841
	Stream_Write_UINT32(s, handshakeEx->railHandshakeFlags); /* railHandshakeFlags (4 bytes) */
Packit Service fa4841
}
Packit Service b1ea74
Packit Service b1ea74
/**
Packit Service b1ea74
 * Function description
Packit Service b1ea74
 *
Packit Service b1ea74
 * @return 0 on success, otherwise a Win32 error code
Packit Service b1ea74
 */
Packit Service b1ea74
UINT rail_write_unicode_string(wStream* s, const RAIL_UNICODE_STRING* unicode_string)
Packit Service b1ea74
{
Packit Service b1ea74
	if (!s || !unicode_string)
Packit Service b1ea74
		return ERROR_INVALID_PARAMETER;
Packit Service b1ea74
Packit Service b1ea74
	if (!Stream_EnsureRemainingCapacity(s, 2 + unicode_string->length))
Packit Service b1ea74
	{
Packit Service b1ea74
		WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
Packit Service b1ea74
		return CHANNEL_RC_NO_MEMORY;
Packit Service b1ea74
	}
Packit Service b1ea74
Packit Service b1ea74
	Stream_Write_UINT16(s, unicode_string->length);                  /* cbString (2 bytes) */
Packit Service b1ea74
	Stream_Write(s, unicode_string->string, unicode_string->length); /* string */
Packit Service b1ea74
	return CHANNEL_RC_OK;
Packit Service b1ea74
}
Packit Service b1ea74
Packit Service b1ea74
/**
Packit Service b1ea74
 * Function description
Packit Service b1ea74
 *
Packit Service b1ea74
 * @return 0 on success, otherwise a Win32 error code
Packit Service b1ea74
 */
Packit Service b1ea74
UINT rail_write_unicode_string_value(wStream* s, const RAIL_UNICODE_STRING* unicode_string)
Packit Service b1ea74
{
Packit Service b1ea74
	size_t length;
Packit Service b1ea74
Packit Service b1ea74
	if (!s || !unicode_string)
Packit Service b1ea74
		return ERROR_INVALID_PARAMETER;
Packit Service b1ea74
Packit Service b1ea74
	length = unicode_string->length;
Packit Service b1ea74
Packit Service b1ea74
	if (length > 0)
Packit Service b1ea74
	{
Packit Service b1ea74
		if (!Stream_EnsureRemainingCapacity(s, length))
Packit Service b1ea74
		{
Packit Service b1ea74
			WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
Packit Service b1ea74
			return CHANNEL_RC_NO_MEMORY;
Packit Service b1ea74
		}
Packit Service b1ea74
Packit Service b1ea74
		Stream_Write(s, unicode_string->string, length); /* string */
Packit Service b1ea74
	}
Packit Service b1ea74
Packit Service b1ea74
	return CHANNEL_RC_OK;
Packit Service b1ea74
}
Packit Service b1ea74
Packit Service b1ea74
/**
Packit Service b1ea74
 * Function description
Packit Service b1ea74
 *
Packit Service b1ea74
 * @return 0 on success, otherwise a Win32 error code
Packit Service b1ea74
 */
Packit Service b1ea74
static UINT rail_read_high_contrast(wStream* s, RAIL_HIGH_CONTRAST* highContrast)
Packit Service b1ea74
{
Packit Service b1ea74
	if (!s || !highContrast)
Packit Service b1ea74
		return ERROR_INVALID_PARAMETER;
Packit Service b1ea74
Packit Service b1ea74
	if (Stream_GetRemainingLength(s) < 8)
Packit Service b1ea74
		return ERROR_INVALID_DATA;
Packit Service b1ea74
Packit Service b1ea74
	Stream_Read_UINT32(s, highContrast->flags);             /* flags (4 bytes) */
Packit Service b1ea74
	Stream_Read_UINT32(s, highContrast->colorSchemeLength); /* colorSchemeLength (4 bytes) */
Packit Service b1ea74
Packit Service b1ea74
	if (!rail_read_unicode_string(s, &highContrast->colorScheme)) /* colorScheme */
Packit Service b1ea74
		return ERROR_INTERNAL_ERROR;
Packit Service b1ea74
	return CHANNEL_RC_OK;
Packit Service b1ea74
}
Packit Service b1ea74
Packit Service b1ea74
/**
Packit Service b1ea74
 * Function description
Packit Service b1ea74
 *
Packit Service b1ea74
 * @return 0 on success, otherwise a Win32 error code
Packit Service b1ea74
 */
Packit Service b1ea74
static UINT rail_write_high_contrast(wStream* s, const RAIL_HIGH_CONTRAST* highContrast)
Packit Service b1ea74
{
Packit Service b1ea74
	UINT32 colorSchemeLength;
Packit Service b1ea74
Packit Service b1ea74
	if (!s || !highContrast)
Packit Service b1ea74
		return ERROR_INVALID_PARAMETER;
Packit Service b1ea74
Packit Service b1ea74
	if (!Stream_EnsureRemainingCapacity(s, 8))
Packit Service b1ea74
		return CHANNEL_RC_NO_MEMORY;
Packit Service b1ea74
Packit Service b1ea74
	colorSchemeLength = highContrast->colorScheme.length + 2;
Packit Service b1ea74
	Stream_Write_UINT32(s, highContrast->flags); /* flags (4 bytes) */
Packit Service b1ea74
	Stream_Write_UINT32(s, colorSchemeLength);   /* colorSchemeLength (4 bytes) */
Packit Service b1ea74
	return rail_write_unicode_string(s, &highContrast->colorScheme); /* colorScheme */
Packit Service b1ea74
}
Packit Service b1ea74
Packit Service b1ea74
/**
Packit Service b1ea74
 * Function description
Packit Service b1ea74
 *
Packit Service b1ea74
 * @return 0 on success, otherwise a Win32 error code
Packit Service b1ea74
 */
Packit Service b1ea74
static UINT rail_read_filterkeys(wStream* s, TS_FILTERKEYS* filterKeys)
Packit Service b1ea74
{
Packit Service b1ea74
	if (!s || !filterKeys)
Packit Service b1ea74
		return ERROR_INVALID_PARAMETER;
Packit Service b1ea74
Packit Service b1ea74
	if (Stream_GetRemainingLength(s) < 20)
Packit Service b1ea74
		return ERROR_INVALID_DATA;
Packit Service b1ea74
Packit Service b1ea74
	Stream_Read_UINT32(s, filterKeys->Flags);
Packit Service b1ea74
	Stream_Read_UINT32(s, filterKeys->WaitTime);
Packit Service b1ea74
	Stream_Read_UINT32(s, filterKeys->DelayTime);
Packit Service b1ea74
	Stream_Read_UINT32(s, filterKeys->RepeatTime);
Packit Service b1ea74
	Stream_Read_UINT32(s, filterKeys->BounceTime);
Packit Service b1ea74
	return CHANNEL_RC_OK;
Packit Service b1ea74
}
Packit Service b1ea74
Packit Service b1ea74
/**
Packit Service b1ea74
 * Function description
Packit Service b1ea74
 *
Packit Service b1ea74
 * @return 0 on success, otherwise a Win32 error code
Packit Service b1ea74
 */
Packit Service b1ea74
static UINT rail_write_filterkeys(wStream* s, const TS_FILTERKEYS* filterKeys)
Packit Service b1ea74
{
Packit Service b1ea74
	if (!s || !filterKeys)
Packit Service b1ea74
		return ERROR_INVALID_PARAMETER;
Packit Service b1ea74
Packit Service b1ea74
	if (!Stream_EnsureRemainingCapacity(s, 20))
Packit Service b1ea74
		return CHANNEL_RC_NO_MEMORY;
Packit Service b1ea74
Packit Service b1ea74
	Stream_Write_UINT32(s, filterKeys->Flags);
Packit Service b1ea74
	Stream_Write_UINT32(s, filterKeys->WaitTime);
Packit Service b1ea74
	Stream_Write_UINT32(s, filterKeys->DelayTime);
Packit Service b1ea74
	Stream_Write_UINT32(s, filterKeys->RepeatTime);
Packit Service b1ea74
	Stream_Write_UINT32(s, filterKeys->BounceTime);
Packit Service b1ea74
	return CHANNEL_RC_OK;
Packit Service b1ea74
}
Packit Service b1ea74
Packit Service b1ea74
/**
Packit Service b1ea74
 * Function description
Packit Service b1ea74
 *
Packit Service b1ea74
 * @return 0 on success, otherwise a Win32 error code
Packit Service b1ea74
 */
Packit Service b1ea74
UINT rail_read_sysparam_order(wStream* s, RAIL_SYSPARAM_ORDER* sysparam, BOOL extendedSpiSupported)
Packit Service b1ea74
{
Packit Service b1ea74
	BYTE body;
Packit Service b1ea74
	UINT error = CHANNEL_RC_OK;
Packit Service b1ea74
Packit Service b1ea74
	if (!s || !sysparam)
Packit Service b1ea74
		return ERROR_INVALID_PARAMETER;
Packit Service b1ea74
Packit Service b1ea74
	if (Stream_GetRemainingLength(s) < 5)
Packit Service b1ea74
	{
Packit Service b1ea74
		WLog_ERR(TAG, "Stream_GetRemainingLength failed!");
Packit Service b1ea74
		return ERROR_INVALID_DATA;
Packit Service b1ea74
	}
Packit Service b1ea74
Packit Service b1ea74
	Stream_Read_UINT32(s, sysparam->param); /* systemParam (4 bytes) */
Packit Service b1ea74
Packit Service b1ea74
	sysparam->params = 0; /* bitflags of received params */
Packit Service b1ea74
Packit Service b1ea74
	switch (sysparam->param)
Packit Service b1ea74
	{
Packit Service b1ea74
		/* Client sysparams */
Packit Service b1ea74
		case SPI_SET_DRAG_FULL_WINDOWS:
Packit Service b1ea74
			sysparam->params |= SPI_MASK_SET_DRAG_FULL_WINDOWS;
Packit Service b1ea74
			Stream_Read_UINT8(s, body); /* body (1 byte) */
Packit Service b1ea74
			sysparam->dragFullWindows = body != 0;
Packit Service b1ea74
			break;
Packit Service b1ea74
Packit Service b1ea74
		case SPI_SET_KEYBOARD_CUES:
Packit Service b1ea74
			sysparam->params |= SPI_MASK_SET_KEYBOARD_CUES;
Packit Service b1ea74
			Stream_Read_UINT8(s, body); /* body (1 byte) */
Packit Service b1ea74
			sysparam->keyboardCues = body != 0;
Packit Service b1ea74
			break;
Packit Service b1ea74
Packit Service b1ea74
		case SPI_SET_KEYBOARD_PREF:
Packit Service b1ea74
			sysparam->params |= SPI_MASK_SET_KEYBOARD_PREF;
Packit Service b1ea74
			Stream_Read_UINT8(s, body); /* body (1 byte) */
Packit Service b1ea74
			sysparam->keyboardPref = body != 0;
Packit Service b1ea74
			break;
Packit Service b1ea74
Packit Service b1ea74
		case SPI_SET_MOUSE_BUTTON_SWAP:
Packit Service b1ea74
			sysparam->params |= SPI_MASK_SET_MOUSE_BUTTON_SWAP;
Packit Service b1ea74
			Stream_Read_UINT8(s, body); /* body (1 byte) */
Packit Service b1ea74
			sysparam->mouseButtonSwap = body != 0;
Packit Service b1ea74
			break;
Packit Service b1ea74
Packit Service b1ea74
		case SPI_SET_WORK_AREA:
Packit Service b1ea74
			sysparam->params |= SPI_MASK_SET_WORK_AREA;
Packit Service b1ea74
Packit Service b1ea74
			if (Stream_GetRemainingLength(s) < 8)
Packit Service b1ea74
			{
Packit Service b1ea74
				WLog_ERR(TAG, "Stream_GetRemainingLength failed!");
Packit Service b1ea74
				return ERROR_INVALID_DATA;
Packit Service b1ea74
			}
Packit Service b1ea74
Packit Service b1ea74
			Stream_Read_UINT16(s, sysparam->workArea.left);   /* left (2 bytes) */
Packit Service b1ea74
			Stream_Read_UINT16(s, sysparam->workArea.top);    /* top (2 bytes) */
Packit Service b1ea74
			Stream_Read_UINT16(s, sysparam->workArea.right);  /* right (2 bytes) */
Packit Service b1ea74
			Stream_Read_UINT16(s, sysparam->workArea.bottom); /* bottom (2 bytes) */
Packit Service b1ea74
			break;
Packit Service b1ea74
Packit Service b1ea74
		case SPI_DISPLAY_CHANGE:
Packit Service b1ea74
			sysparam->params |= SPI_MASK_DISPLAY_CHANGE;
Packit Service b1ea74
Packit Service b1ea74
			if (Stream_GetRemainingLength(s) < 8)
Packit Service b1ea74
			{
Packit Service b1ea74
				WLog_ERR(TAG, "Stream_GetRemainingLength failed!");
Packit Service b1ea74
				return ERROR_INVALID_DATA;
Packit Service b1ea74
			}
Packit Service b1ea74
Packit Service b1ea74
			Stream_Read_UINT16(s, sysparam->displayChange.left);   /* left (2 bytes) */
Packit Service b1ea74
			Stream_Read_UINT16(s, sysparam->displayChange.top);    /* top (2 bytes) */
Packit Service b1ea74
			Stream_Read_UINT16(s, sysparam->displayChange.right);  /* right (2 bytes) */
Packit Service b1ea74
			Stream_Read_UINT16(s, sysparam->displayChange.bottom); /* bottom (2 bytes) */
Packit Service b1ea74
			break;
Packit Service b1ea74
Packit Service b1ea74
		case SPI_TASKBAR_POS:
Packit Service b1ea74
			sysparam->params |= SPI_MASK_TASKBAR_POS;
Packit Service b1ea74
Packit Service b1ea74
			if (Stream_GetRemainingLength(s) < 8)
Packit Service b1ea74
			{
Packit Service b1ea74
				WLog_ERR(TAG, "Stream_GetRemainingLength failed!");
Packit Service b1ea74
				return ERROR_INVALID_DATA;
Packit Service b1ea74
			}
Packit Service b1ea74
Packit Service b1ea74
			Stream_Read_UINT16(s, sysparam->taskbarPos.left);   /* left (2 bytes) */
Packit Service b1ea74
			Stream_Read_UINT16(s, sysparam->taskbarPos.top);    /* top (2 bytes) */
Packit Service b1ea74
			Stream_Read_UINT16(s, sysparam->taskbarPos.right);  /* right (2 bytes) */
Packit Service b1ea74
			Stream_Read_UINT16(s, sysparam->taskbarPos.bottom); /* bottom (2 bytes) */
Packit Service b1ea74
			break;
Packit Service b1ea74
Packit Service b1ea74
		case SPI_SET_HIGH_CONTRAST:
Packit Service b1ea74
			sysparam->params |= SPI_MASK_SET_HIGH_CONTRAST;
Packit Service b1ea74
			if (Stream_GetRemainingLength(s) < 8)
Packit Service b1ea74
			{
Packit Service b1ea74
				WLog_ERR(TAG, "Stream_GetRemainingLength failed!");
Packit Service b1ea74
				return ERROR_INVALID_DATA;
Packit Service b1ea74
			}
Packit Service b1ea74
Packit Service b1ea74
			error = rail_read_high_contrast(s, &sysparam->highContrast);
Packit Service b1ea74
			break;
Packit Service b1ea74
Packit Service b1ea74
		case SPI_SETCARETWIDTH:
Packit Service b1ea74
			sysparam->params |= SPI_MASK_SET_CARET_WIDTH;
Packit Service b1ea74
Packit Service b1ea74
			if (!extendedSpiSupported)
Packit Service b1ea74
				return ERROR_INVALID_DATA;
Packit Service b1ea74
Packit Service b1ea74
			if (Stream_GetRemainingLength(s) < 4)
Packit Service b1ea74
			{
Packit Service b1ea74
				WLog_ERR(TAG, "Stream_GetRemainingLength failed!");
Packit Service b1ea74
				return ERROR_INVALID_DATA;
Packit Service b1ea74
			}
Packit Service b1ea74
Packit Service b1ea74
			Stream_Read_UINT32(s, sysparam->caretWidth);
Packit Service b1ea74
Packit Service b1ea74
			if (sysparam->caretWidth < 0x0001)
Packit Service b1ea74
				return ERROR_INVALID_DATA;
Packit Service b1ea74
Packit Service b1ea74
			break;
Packit Service b1ea74
Packit Service b1ea74
		case SPI_SETSTICKYKEYS:
Packit Service b1ea74
			sysparam->params |= SPI_MASK_SET_STICKY_KEYS;
Packit Service b1ea74
Packit Service b1ea74
			if (!extendedSpiSupported)
Packit Service b1ea74
				return ERROR_INVALID_DATA;
Packit Service b1ea74
Packit Service b1ea74
			if (Stream_GetRemainingLength(s) < 4)
Packit Service b1ea74
			{
Packit Service b1ea74
				WLog_ERR(TAG, "Stream_GetRemainingLength failed!");
Packit Service b1ea74
				return ERROR_INVALID_DATA;
Packit Service b1ea74
			}
Packit Service b1ea74
Packit Service b1ea74
			Stream_Read_UINT32(s, sysparam->stickyKeys);
Packit Service b1ea74
			break;
Packit Service b1ea74
Packit Service b1ea74
		case SPI_SETTOGGLEKEYS:
Packit Service b1ea74
			sysparam->params |= SPI_MASK_SET_TOGGLE_KEYS;
Packit Service b1ea74
Packit Service b1ea74
			if (!extendedSpiSupported)
Packit Service b1ea74
				return ERROR_INVALID_DATA;
Packit Service b1ea74
Packit Service b1ea74
			if (Stream_GetRemainingLength(s) < 4)
Packit Service b1ea74
			{
Packit Service b1ea74
				WLog_ERR(TAG, "Stream_GetRemainingLength failed!");
Packit Service b1ea74
				return ERROR_INVALID_DATA;
Packit Service b1ea74
			}
Packit Service b1ea74
Packit Service b1ea74
			Stream_Read_UINT32(s, sysparam->toggleKeys);
Packit Service b1ea74
			break;
Packit Service b1ea74
Packit Service b1ea74
		case SPI_SETFILTERKEYS:
Packit Service b1ea74
			sysparam->params |= SPI_MASK_SET_FILTER_KEYS;
Packit Service b1ea74
Packit Service b1ea74
			if (!extendedSpiSupported)
Packit Service b1ea74
				return ERROR_INVALID_DATA;
Packit Service b1ea74
Packit Service b1ea74
			if (Stream_GetRemainingLength(s) < 20)
Packit Service b1ea74
			{
Packit Service b1ea74
				WLog_ERR(TAG, "Stream_GetRemainingLength failed!");
Packit Service b1ea74
				return ERROR_INVALID_DATA;
Packit Service b1ea74
			}
Packit Service b1ea74
Packit Service b1ea74
			error = rail_read_filterkeys(s, &sysparam->filterKeys);
Packit Service b1ea74
			break;
Packit Service b1ea74
Packit Service b1ea74
		/* Server sysparams */
Packit Service b1ea74
		case SPI_SETSCREENSAVEACTIVE:
Packit Service b1ea74
			sysparam->params |= SPI_MASK_SET_SCREEN_SAVE_ACTIVE;
Packit Service b1ea74
Packit Service b1ea74
			Stream_Read_UINT8(s, body); /* body (1 byte) */
Packit Service b1ea74
			sysparam->setScreenSaveActive = body != 0;
Packit Service b1ea74
			break;
Packit Service b1ea74
Packit Service b1ea74
		case SPI_SETSCREENSAVESECURE:
Packit Service b1ea74
			sysparam->params |= SPI_MASK_SET_SET_SCREEN_SAVE_SECURE;
Packit Service b1ea74
Packit Service b1ea74
			Stream_Read_UINT8(s, body); /* body (1 byte) */
Packit Service b1ea74
			sysparam->setScreenSaveSecure = body != 0;
Packit Service b1ea74
			break;
Packit Service b1ea74
Packit Service b1ea74
		default:
Packit Service b1ea74
			break;
Packit Service b1ea74
	}
Packit Service b1ea74
Packit Service b1ea74
	return CHANNEL_RC_OK;
Packit Service b1ea74
}
Packit Service b1ea74
Packit Service b1ea74
/**
Packit Service b1ea74
 * Function description
Packit Service b1ea74
 *
Packit Service b1ea74
 * @return 0 on success, otherwise a Win32 err2or code
Packit Service b1ea74
 */
Packit Service b1ea74
UINT rail_write_sysparam_order(wStream* s, const RAIL_SYSPARAM_ORDER* sysparam,
Packit Service b1ea74
                               BOOL extendedSpiSupported)
Packit Service b1ea74
{
Packit Service b1ea74
	BYTE body;
Packit Service b1ea74
	UINT error = CHANNEL_RC_OK;
Packit Service b1ea74
Packit Service b1ea74
	if (!s || !sysparam)
Packit Service b1ea74
		return ERROR_INVALID_PARAMETER;
Packit Service b1ea74
Packit Service b1ea74
	if (!Stream_EnsureRemainingCapacity(s, 12))
Packit Service b1ea74
		return CHANNEL_RC_NO_MEMORY;
Packit Service b1ea74
Packit Service b1ea74
	Stream_Write_UINT32(s, sysparam->param); /* systemParam (4 bytes) */
Packit Service b1ea74
Packit Service b1ea74
	switch (sysparam->param)
Packit Service b1ea74
	{
Packit Service b1ea74
		/* Client sysparams */
Packit Service b1ea74
		case SPI_SET_DRAG_FULL_WINDOWS:
Packit Service b1ea74
			body = sysparam->dragFullWindows ? 1 : 0;
Packit Service b1ea74
			Stream_Write_UINT8(s, body);
Packit Service b1ea74
			break;
Packit Service b1ea74
Packit Service b1ea74
		case SPI_SET_KEYBOARD_CUES:
Packit Service b1ea74
			body = sysparam->keyboardCues ? 1 : 0;
Packit Service b1ea74
			Stream_Write_UINT8(s, body);
Packit Service b1ea74
			break;
Packit Service b1ea74
Packit Service b1ea74
		case SPI_SET_KEYBOARD_PREF:
Packit Service b1ea74
			body = sysparam->keyboardPref ? 1 : 0;
Packit Service b1ea74
			Stream_Write_UINT8(s, body);
Packit Service b1ea74
			break;
Packit Service b1ea74
Packit Service b1ea74
		case SPI_SET_MOUSE_BUTTON_SWAP:
Packit Service b1ea74
			body = sysparam->mouseButtonSwap ? 1 : 0;
Packit Service b1ea74
			Stream_Write_UINT8(s, body);
Packit Service b1ea74
			break;
Packit Service b1ea74
Packit Service b1ea74
		case SPI_SET_WORK_AREA:
Packit Service b1ea74
			Stream_Write_UINT16(s, sysparam->workArea.left);   /* left (2 bytes) */
Packit Service b1ea74
			Stream_Write_UINT16(s, sysparam->workArea.top);    /* top (2 bytes) */
Packit Service b1ea74
			Stream_Write_UINT16(s, sysparam->workArea.right);  /* right (2 bytes) */
Packit Service b1ea74
			Stream_Write_UINT16(s, sysparam->workArea.bottom); /* bottom (2 bytes) */
Packit Service b1ea74
			break;
Packit Service b1ea74
Packit Service b1ea74
		case SPI_DISPLAY_CHANGE:
Packit Service b1ea74
			Stream_Write_UINT16(s, sysparam->displayChange.left);   /* left (2 bytes) */
Packit Service b1ea74
			Stream_Write_UINT16(s, sysparam->displayChange.top);    /* top (2 bytes) */
Packit Service b1ea74
			Stream_Write_UINT16(s, sysparam->displayChange.right);  /* right (2 bytes) */
Packit Service b1ea74
			Stream_Write_UINT16(s, sysparam->displayChange.bottom); /* bottom (2 bytes) */
Packit Service b1ea74
			break;
Packit Service b1ea74
Packit Service b1ea74
		case SPI_TASKBAR_POS:
Packit Service b1ea74
			Stream_Write_UINT16(s, sysparam->taskbarPos.left);   /* left (2 bytes) */
Packit Service b1ea74
			Stream_Write_UINT16(s, sysparam->taskbarPos.top);    /* top (2 bytes) */
Packit Service b1ea74
			Stream_Write_UINT16(s, sysparam->taskbarPos.right);  /* right (2 bytes) */
Packit Service b1ea74
			Stream_Write_UINT16(s, sysparam->taskbarPos.bottom); /* bottom (2 bytes) */
Packit Service b1ea74
			break;
Packit Service b1ea74
Packit Service b1ea74
		case SPI_SET_HIGH_CONTRAST:
Packit Service b1ea74
			error = rail_write_high_contrast(s, &sysparam->highContrast);
Packit Service b1ea74
			break;
Packit Service b1ea74
Packit Service b1ea74
		case SPI_SETCARETWIDTH:
Packit Service b1ea74
			if (!extendedSpiSupported)
Packit Service b1ea74
				return ERROR_INVALID_DATA;
Packit Service b1ea74
Packit Service b1ea74
			if (sysparam->caretWidth < 0x0001)
Packit Service b1ea74
				return ERROR_INVALID_DATA;
Packit Service b1ea74
Packit Service b1ea74
			Stream_Write_UINT32(s, sysparam->caretWidth);
Packit Service b1ea74
			break;
Packit Service b1ea74
Packit Service b1ea74
		case SPI_SETSTICKYKEYS:
Packit Service b1ea74
			if (!extendedSpiSupported)
Packit Service b1ea74
				return ERROR_INVALID_DATA;
Packit Service b1ea74
Packit Service b1ea74
			Stream_Write_UINT32(s, sysparam->stickyKeys);
Packit Service b1ea74
			break;
Packit Service b1ea74
Packit Service b1ea74
		case SPI_SETTOGGLEKEYS:
Packit Service b1ea74
			if (!extendedSpiSupported)
Packit Service b1ea74
				return ERROR_INVALID_DATA;
Packit Service b1ea74
Packit Service b1ea74
			Stream_Write_UINT32(s, sysparam->toggleKeys);
Packit Service b1ea74
			break;
Packit Service b1ea74
Packit Service b1ea74
		case SPI_SETFILTERKEYS:
Packit Service b1ea74
			if (!extendedSpiSupported)
Packit Service b1ea74
				return ERROR_INVALID_DATA;
Packit Service b1ea74
Packit Service b1ea74
			error = rail_write_filterkeys(s, &sysparam->filterKeys);
Packit Service b1ea74
			break;
Packit Service b1ea74
Packit Service b1ea74
		/* Server sysparams */
Packit Service b1ea74
		case SPI_SETSCREENSAVEACTIVE:
Packit Service b1ea74
			body = sysparam->setScreenSaveActive ? 1 : 0;
Packit Service b1ea74
			Stream_Write_UINT8(s, body);
Packit Service b1ea74
			break;
Packit Service b1ea74
Packit Service b1ea74
		case SPI_SETSCREENSAVESECURE:
Packit Service b1ea74
			body = sysparam->setScreenSaveSecure ? 1 : 0;
Packit Service b1ea74
			Stream_Write_UINT8(s, body);
Packit Service b1ea74
			break;
Packit Service b1ea74
Packit Service b1ea74
		default:
Packit Service b1ea74
			return ERROR_INVALID_PARAMETER;
Packit Service b1ea74
	}
Packit Service b1ea74
Packit Service b1ea74
	return error;
Packit Service b1ea74
}
Packit Service b1ea74
Packit Service b1ea74
BOOL rail_is_extended_spi_supported(UINT32 channelFlags)
Packit Service b1ea74
{
Packit Service b1ea74
	return channelFlags & TS_RAIL_ORDER_HANDSHAKE_EX_FLAGS_EXTENDED_SPI_SUPPORTED;
Packit Service b1ea74
}