Rework xrdp to support new module resize interface

This commit compiles.
This commit is contained in:
matt335672
2024-02-15 16:20:04 +00:00
parent dd37720188
commit bc70a86de6
5 changed files with 288 additions and 251 deletions
+179 -154
View File
@@ -1136,34 +1136,10 @@ libxrdp_orders_send_font(struct xrdp_session *session,
}
/*****************************************************************************/
/* Note : if this is called on a multimon setup, the client is resized
* to a single monitor */
int EXPORT_CC
libxrdp_reset(struct xrdp_session *session,
unsigned int width, unsigned int height, int bpp)
libxrdp_reset(struct xrdp_session *session)
{
LOG_DEVEL(LOG_LEVEL_TRACE, "libxrdp_reset:");
if (session->client_info != 0)
{
struct xrdp_client_info *client_info = session->client_info;
/* older client can't resize */
if (client_info->build <= 419)
{
return 0;
}
client_info->display_sizes.session_width = width;
client_info->display_sizes.session_height = height;
client_info->display_sizes.monitorCount = 0;
client_info->bpp = bpp;
client_info->multimon = 0;
}
else
{
LOG(LOG_LEVEL_ERROR, "libxrdp_reset: session->client_info is NULL");
return 1;
}
/* this will send any lingering orders */
if (xrdp_orders_reset((struct xrdp_orders *)session->orders) != 0)
@@ -1792,6 +1768,19 @@ libxrdp_send_session_info(struct xrdp_session *session, const char *data,
static void
sanitise_extended_monitor_attributes(struct monitor_info *monitor_layout)
{
if (monitor_layout->physical_width == 0
&& monitor_layout->physical_width == 0
&& monitor_layout->orientation == 0
&& monitor_layout->desktop_scale_factor == 0
&& monitor_layout->device_scale_factor == 0)
{
/* Module expects us to provide defaults */
monitor_layout->orientation = ORIENTATION_LANDSCAPE;
monitor_layout->desktop_scale_factor = 100;
monitor_layout->device_scale_factor = 100;
return;
}
/* if EITHER physical_width or physical_height are
* out of range, BOTH must be ignored.
*/
@@ -1882,16 +1871,16 @@ libxrdp_process_monitor_stream(struct stream *s,
{
uint32_t num_monitor;
uint32_t monitor_index;
struct monitor_info monitors[CLIENT_MONITOR_DATA_MAXIMUM_MONITORS];
struct monitor_info *monitor_layout;
struct xrdp_rect all_monitors_encompassing_bounds = {0};
int got_primary = 0;
int monitor_struct_stream_check_bytes;
const char *monitor_struct_stream_check_message;
LOG_DEVEL(LOG_LEVEL_TRACE, "libxrdp_process_monitor_stream:");
if (description == NULL)
{
LOG_DEVEL(LOG_LEVEL_ERROR, "libxrdp_process_monitor_stream: description was"
LOG_DEVEL(LOG_LEVEL_ERROR,
"libxrdp_process_monitor_stream: description was"
" null. Valid pointer to allocated description expected.");
return SEC_PROCESS_MONITORS_ERR;
}
@@ -1939,7 +1928,7 @@ libxrdp_process_monitor_stream(struct stream *s,
" from [MS-RDPEDISP] 2.2.2.2.1 DISPLAYCONTROL_MONITOR_LAYOUT.";
}
description->monitorCount = num_monitor;
memset(monitors, 0, sizeof(monitors[0]) * num_monitor);
for (monitor_index = 0; monitor_index < num_monitor; ++monitor_index)
{
@@ -1951,7 +1940,8 @@ libxrdp_process_monitor_stream(struct stream *s,
return SEC_PROCESS_MONITORS_ERR;
}
monitor_layout = description->minfo + monitor_index;
monitor_layout = &monitors[monitor_index];
if (full_parameters != 0)
{
in_uint32_le(s, monitor_layout->flags);
@@ -2017,8 +2007,6 @@ libxrdp_process_monitor_stream(struct stream *s,
in_uint32_le(s, monitor_layout->desktop_scale_factor);
in_uint32_le(s, monitor_layout->device_scale_factor);
sanitise_extended_monitor_attributes(monitor_layout);
/*
* 2.2.2.2.1 DISPLAYCONTROL_MONITOR_LAYOUT
*/
@@ -2047,130 +2035,10 @@ libxrdp_process_monitor_stream(struct stream *s,
monitor_layout->is_primary = TS_MONITOR_PRIMARY;
}
}
if (monitor_index == 0)
{
all_monitors_encompassing_bounds.left = monitor_layout->left;
all_monitors_encompassing_bounds.top = monitor_layout->top;
all_monitors_encompassing_bounds.right = monitor_layout->right;
all_monitors_encompassing_bounds.bottom = monitor_layout->bottom;
}
else
{
all_monitors_encompassing_bounds.left =
MIN(monitor_layout->left,
all_monitors_encompassing_bounds.left);
all_monitors_encompassing_bounds.top =
MIN(monitor_layout->top,
all_monitors_encompassing_bounds.top);
all_monitors_encompassing_bounds.right =
MAX(all_monitors_encompassing_bounds.right,
monitor_layout->right);
all_monitors_encompassing_bounds.bottom =
MAX(all_monitors_encompassing_bounds.bottom,
monitor_layout->bottom);
}
if (monitor_layout->is_primary == TS_MONITOR_PRIMARY)
{
got_primary = 1;
}
}
if (!got_primary)
{
/* no primary monitor was set,
* choose the leftmost monitor as primary.
*/
for (monitor_index = 0; monitor_index < num_monitor; ++monitor_index)
{
monitor_layout = description->minfo + monitor_index;
if (monitor_layout->left
== all_monitors_encompassing_bounds.left
&& monitor_layout->top
== all_monitors_encompassing_bounds.top)
{
monitor_layout->is_primary = TS_MONITOR_PRIMARY;
break;
}
}
}
/* set wm geometry if the encompassing area is well formed.
Otherwise, log and return an error.
*/
if (all_monitors_encompassing_bounds.right
> all_monitors_encompassing_bounds.left
&& all_monitors_encompassing_bounds.bottom
> all_monitors_encompassing_bounds.top)
{
description->session_width =
all_monitors_encompassing_bounds.right
- all_monitors_encompassing_bounds.left + 1;
description->session_height =
all_monitors_encompassing_bounds.bottom
- all_monitors_encompassing_bounds.top + 1;
}
else
{
LOG(LOG_LEVEL_ERROR, "libxrdp_process_monitor_stream:"
" The area encompassing the monitors is not a"
" well-formed rectangle. Received"
" (top: %d, left: %d, right: %d, bottom: %d)."
" This will prevent initialization.",
all_monitors_encompassing_bounds.top,
all_monitors_encompassing_bounds.left,
all_monitors_encompassing_bounds.right,
all_monitors_encompassing_bounds.bottom);
return SEC_PROCESS_MONITORS_ERR_INVALID_DESKTOP;
}
/* Make sure virtual desktop size is OK
* 2.2.1.3.6 Client Monitor Data (TS_UD_CS_MONITOR)
*/
if (description->session_width
> CLIENT_MONITOR_DATA_MAXIMUM_VIRTUAL_DESKTOP_WIDTH
|| description->session_width
< CLIENT_MONITOR_DATA_MINIMUM_VIRTUAL_DESKTOP_WIDTH
|| description->session_height
> CLIENT_MONITOR_DATA_MAXIMUM_VIRTUAL_DESKTOP_HEIGHT
|| description->session_height
< CLIENT_MONITOR_DATA_MINIMUM_VIRTUAL_DESKTOP_HEIGHT)
{
LOG(LOG_LEVEL_ERROR,
"libxrdp_process_monitor_stream: Client supplied virtual"
" desktop width or height is invalid."
" Allowed width range: min %d, max %d. Width received: %d."
" Allowed height range: min %d, max %d. Height received: %d",
CLIENT_MONITOR_DATA_MINIMUM_VIRTUAL_DESKTOP_WIDTH,
CLIENT_MONITOR_DATA_MAXIMUM_VIRTUAL_DESKTOP_WIDTH,
description->session_width,
CLIENT_MONITOR_DATA_MINIMUM_VIRTUAL_DESKTOP_HEIGHT,
CLIENT_MONITOR_DATA_MAXIMUM_VIRTUAL_DESKTOP_HEIGHT,
description->session_width);
return SEC_PROCESS_MONITORS_ERR_INVALID_DESKTOP;
}
/* keep a copy of non negative monitor info values for xrdp_wm usage */
for (monitor_index = 0; monitor_index < num_monitor; ++monitor_index)
{
monitor_layout = description->minfo_wm + monitor_index;
g_memcpy(monitor_layout,
description->minfo + monitor_index,
sizeof(struct monitor_info));
monitor_layout->left =
monitor_layout->left - all_monitors_encompassing_bounds.left;
monitor_layout->top =
monitor_layout->top - all_monitors_encompassing_bounds.top;
monitor_layout->right =
monitor_layout->right - all_monitors_encompassing_bounds.left;
monitor_layout->bottom =
monitor_layout->bottom - all_monitors_encompassing_bounds.top;
}
return 0;
return libxrdp_init_display_size_description(
num_monitor, monitors, description);
}
/*****************************************************************************/
@@ -2274,6 +2142,163 @@ libxrdp_process_monitor_ex_stream(struct stream *s,
return 0;
}
/*****************************************************************************/
int
libxrdp_init_display_size_description(
unsigned int num_monitor,
const struct monitor_info *monitors,
struct display_size_description *description)
{
unsigned int monitor_index;
struct monitor_info *monitor_layout;
struct xrdp_rect all_monitors_encompassing_bounds = {0};
int got_primary = 0;
/* Caller should have checked this, so don't log an error */
if (num_monitor > CLIENT_MONITOR_DATA_MAXIMUM_MONITORS)
{
return SEC_PROCESS_MONITORS_ERR_TOO_MANY_MONITORS;
}
description->monitorCount = num_monitor;
for (monitor_index = 0 ; monitor_index < num_monitor; ++monitor_index)
{
monitor_layout = &description->minfo[monitor_index];
*monitor_layout = monitors[monitor_index];
sanitise_extended_monitor_attributes(monitor_layout);
if (monitor_index == 0)
{
all_monitors_encompassing_bounds.left = monitor_layout->left;
all_monitors_encompassing_bounds.top = monitor_layout->top;
all_monitors_encompassing_bounds.right = monitor_layout->right;
all_monitors_encompassing_bounds.bottom = monitor_layout->bottom;
}
else
{
all_monitors_encompassing_bounds.left =
MIN(monitor_layout->left,
all_monitors_encompassing_bounds.left);
all_monitors_encompassing_bounds.top =
MIN(monitor_layout->top,
all_monitors_encompassing_bounds.top);
all_monitors_encompassing_bounds.right =
MAX(all_monitors_encompassing_bounds.right,
monitor_layout->right);
all_monitors_encompassing_bounds.bottom =
MAX(all_monitors_encompassing_bounds.bottom,
monitor_layout->bottom);
}
if (monitor_layout->is_primary == TS_MONITOR_PRIMARY)
{
if (got_primary)
{
// Already got one - don't have two
monitor_layout->is_primary = 0;
}
else
{
got_primary = 1;
}
}
}
if (!got_primary)
{
/* no primary monitor was set,
* choose the leftmost monitor as primary.
*/
for (monitor_index = 0; monitor_index < num_monitor; ++monitor_index)
{
monitor_layout = description->minfo + monitor_index;
if (monitor_layout->left
== all_monitors_encompassing_bounds.left
&& monitor_layout->top
== all_monitors_encompassing_bounds.top)
{
monitor_layout->is_primary = TS_MONITOR_PRIMARY;
break;
}
}
}
/* set wm geometry if the encompassing area is well formed.
Otherwise, log and return an error.
*/
if (all_monitors_encompassing_bounds.right
> all_monitors_encompassing_bounds.left
&& all_monitors_encompassing_bounds.bottom
> all_monitors_encompassing_bounds.top)
{
description->session_width =
all_monitors_encompassing_bounds.right
- all_monitors_encompassing_bounds.left + 1;
description->session_height =
all_monitors_encompassing_bounds.bottom
- all_monitors_encompassing_bounds.top + 1;
}
else
{
LOG(LOG_LEVEL_ERROR, "libxrdp_init_display_size_description:"
" The area encompassing the monitors is not a"
" well-formed rectangle. Received"
" (top: %d, left: %d, right: %d, bottom: %d)."
" This will prevent initialization.",
all_monitors_encompassing_bounds.top,
all_monitors_encompassing_bounds.left,
all_monitors_encompassing_bounds.right,
all_monitors_encompassing_bounds.bottom);
return SEC_PROCESS_MONITORS_ERR_INVALID_DESKTOP;
}
/* Make sure virtual desktop size is OK
* 2.2.1.3.6 Client Monitor Data (TS_UD_CS_MONITOR)
*/
if (description->session_width
> CLIENT_MONITOR_DATA_MAXIMUM_VIRTUAL_DESKTOP_WIDTH
|| description->session_width
< CLIENT_MONITOR_DATA_MINIMUM_VIRTUAL_DESKTOP_WIDTH
|| description->session_height
> CLIENT_MONITOR_DATA_MAXIMUM_VIRTUAL_DESKTOP_HEIGHT
|| description->session_height
< CLIENT_MONITOR_DATA_MINIMUM_VIRTUAL_DESKTOP_HEIGHT)
{
LOG(LOG_LEVEL_ERROR,
"libxrdp_init_display_size_description: Calculated virtual"
" desktop width or height is invalid."
" Allowed width range: min %d, max %d. Width received: %d."
" Allowed height range: min %d, max %d. Height received: %d",
CLIENT_MONITOR_DATA_MINIMUM_VIRTUAL_DESKTOP_WIDTH,
CLIENT_MONITOR_DATA_MAXIMUM_VIRTUAL_DESKTOP_WIDTH,
description->session_width,
CLIENT_MONITOR_DATA_MINIMUM_VIRTUAL_DESKTOP_HEIGHT,
CLIENT_MONITOR_DATA_MAXIMUM_VIRTUAL_DESKTOP_HEIGHT,
description->session_width);
return SEC_PROCESS_MONITORS_ERR_INVALID_DESKTOP;
}
/* keep a copy of non negative monitor info values for xrdp_wm usage */
for (monitor_index = 0; monitor_index < num_monitor; ++monitor_index)
{
monitor_layout = description->minfo_wm + monitor_index;
*monitor_layout = description->minfo[monitor_index];
monitor_layout->left =
monitor_layout->left - all_monitors_encompassing_bounds.left;
monitor_layout->top =
monitor_layout->top - all_monitors_encompassing_bounds.top;
monitor_layout->right =
monitor_layout->right - all_monitors_encompassing_bounds.left;
monitor_layout->bottom =
monitor_layout->bottom - all_monitors_encompassing_bounds.top;
}
return 0;
}
/*****************************************************************************/
int EXPORT_CC
libxrdp_planar_compress(char *in_data, int width, int height,
+19 -2
View File
@@ -24,6 +24,7 @@
#include "xrdp_rail.h"
struct list;
struct monitor_info;
/* struct xrdp_client_info moved to xrdp_client_info.h */
@@ -195,8 +196,7 @@ libxrdp_orders_send_font(struct xrdp_session *session,
struct xrdp_font_char *font_char,
int font_index, int char_index);
int
libxrdp_reset(struct xrdp_session *session,
unsigned int width, unsigned int height, int bpp);
libxrdp_reset(struct xrdp_session *session);
int
libxrdp_orders_send_raw_bitmap2(struct xrdp_session *session,
int width, int height, int bpp, char *data,
@@ -346,4 +346,21 @@ int EXPORT_CC
libxrdp_process_monitor_ex_stream(struct stream *s,
struct display_size_description *description);
/**
* Convert a list of monitors into a full description
*
* Monitor data is sanitised during the conversion
*
* @param num_monitor Monitor count (> 0)
* @param monitors List of monitors
* @param[out] description Display size description
*
* @return 0 if the data is processed, non-zero if there is an error.
*/
int
libxrdp_init_display_size_description(
unsigned int num_monitor,
const struct monitor_info *monitors,
struct display_size_description *description);
#endif