Blame channels/rail/rail_common.c

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