Skip to content

Commit d43821f

Browse files
authored
Merge pull request #2310 from matt335672/physical_desktop_size
Parse more physical monitor size information
2 parents 682ca95 + d5445e9 commit d43821f

File tree

6 files changed

+323
-109
lines changed

6 files changed

+323
-109
lines changed

common/ms-rdpbcgr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
#define SEC_TAG_CLI_CHANNELS 0xc003 /* CS_CHANNELS? */
5858
#define SEC_TAG_CLI_4 0xc004 /* CS_CLUSTER? */
5959
#define SEC_TAG_CLI_MONITOR 0xc005 /* CS_MONITOR */
60+
#define SEC_TAG_CLI_MONITOR_EX 0xc008 /* CS_MONITOR_EX */
6061

6162
/* Client Core Data: colorDepth, postBeta2ColorDepth (2.2.1.3.2) */
6263
#define RNS_UD_COLOR_4BPP 0xCA00

common/xrdp_client_info.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ struct monitor_info
3838
int bottom;
3939
int flags;
4040

41-
/* From 2.2.2.2.1 DISPLAYCONTROL_MONITOR_LAYOUT */
41+
/* From [MS-RDPEDISP] 2.2.2.2.1 DISPLAYCONTROL_MONITOR_LAYOUT, or
42+
* [MS-RDPBCGR] 2.2.1.3.9.1 (TS_MONITOR_ATTRIBUTES) */
4243
unsigned int physical_width;
4344
unsigned int physical_height;
4445
unsigned int orientation;
@@ -205,6 +206,13 @@ struct xrdp_client_info
205206

206207
/* xrdp.override_* values */
207208
struct xrdp_keyboard_overrides xrdp_keyboard_overrides;
209+
210+
/* These values are optionally send over as part of TS_UD_CS_CORE.
211+
* They can be used as a fallback for a single monitor session
212+
* if physical sizes are not available in the monitor-specific
213+
* data */
214+
unsigned int session_physical_width; /* in mm */
215+
unsigned int session_physical_height; /* in mm */
208216
};
209217

210218
/* yyyymmdd of last incompatible change to xrdp_client_info */

libxrdp/libxrdp.c

Lines changed: 196 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "ms-rdpbcgr.h"
3030

3131
#define MAX_BITMAP_BUF_SIZE (16 * 1024) /* 16K */
32+
#define TS_MONITOR_ATTRIBUTES_SIZE 20 /* [MS-RDPBCGR] 2.2.1.3.9 */
3233

3334
/******************************************************************************/
3435
struct xrdp_session *EXPORT_CC
@@ -1764,6 +1765,97 @@ libxrdp_send_session_info(struct xrdp_session *session, const char *data,
17641765
return xrdp_rdp_send_session_info(rdp, data, data_bytes);
17651766
}
17661767

1768+
/*****************************************************************************/
1769+
/*
1770+
Sanitise extended monitor attributes
1771+
1772+
The extended attributes are received from either
1773+
[MS-RDPEDISP] 2.2.2.2.1 (DISPLAYCONTROL_MONITOR_LAYOUT), or
1774+
[MS-RDPBCGR] 2.2.1.3.9.1 (TS_MONITOR_ATTRIBUTES)
1775+
1776+
@param monitor_layout struct containing extended attributes
1777+
*/
1778+
static void
1779+
sanitise_extended_monitor_attributes(struct monitor_info *monitor_layout)
1780+
{
1781+
/* if EITHER physical_width or physical_height are
1782+
* out of range, BOTH must be ignored.
1783+
*/
1784+
if (monitor_layout->physical_width > 10000
1785+
|| monitor_layout->physical_width < 10)
1786+
{
1787+
LOG(LOG_LEVEL_WARNING, "sanitise_extended_monitor_attributes:"
1788+
" physical_width is not within valid range."
1789+
" Setting physical_width to 0mm,"
1790+
" Setting physical_height to 0mm,"
1791+
" physical_width was: %d",
1792+
monitor_layout->physical_width);
1793+
monitor_layout->physical_width = 0;
1794+
monitor_layout->physical_height = 0;
1795+
}
1796+
1797+
if (monitor_layout->physical_height > 10000
1798+
|| monitor_layout->physical_height < 10)
1799+
{
1800+
LOG(LOG_LEVEL_WARNING, "sanitise_extended_monitor_attributes:"
1801+
" physical_height is not within valid range."
1802+
" Setting physical_width to 0mm,"
1803+
" Setting physical_height to 0mm,"
1804+
" physical_height was: %d",
1805+
monitor_layout->physical_height);
1806+
monitor_layout->physical_width = 0;
1807+
monitor_layout->physical_height = 0;
1808+
}
1809+
1810+
switch (monitor_layout->orientation)
1811+
{
1812+
case ORIENTATION_LANDSCAPE:
1813+
case ORIENTATION_PORTRAIT:
1814+
case ORIENTATION_LANDSCAPE_FLIPPED:
1815+
case ORIENTATION_PORTRAIT_FLIPPED:
1816+
break;
1817+
default:
1818+
LOG(LOG_LEVEL_WARNING, "sanitise_extended_monitor_attributes:"
1819+
" Orientation is not one of %d, %d, %d, or %d."
1820+
" Value was %d and ignored and set to default value of LANDSCAPE.",
1821+
ORIENTATION_LANDSCAPE,
1822+
ORIENTATION_PORTRAIT,
1823+
ORIENTATION_LANDSCAPE_FLIPPED,
1824+
ORIENTATION_PORTRAIT_FLIPPED,
1825+
monitor_layout->orientation);
1826+
monitor_layout->orientation = ORIENTATION_LANDSCAPE;
1827+
}
1828+
1829+
int check_desktop_scale_factor
1830+
= monitor_layout->desktop_scale_factor < 100
1831+
|| monitor_layout->desktop_scale_factor > 500;
1832+
if (check_desktop_scale_factor)
1833+
{
1834+
LOG(LOG_LEVEL_WARNING, "sanitise_extended_monitor_attributes:"
1835+
" desktop_scale_factor is not within valid range"
1836+
" of [100, 500]. Assuming 100. Value was: %d",
1837+
monitor_layout->desktop_scale_factor);
1838+
}
1839+
1840+
int check_device_scale_factor
1841+
= monitor_layout->device_scale_factor != 100
1842+
&& monitor_layout->device_scale_factor != 140
1843+
&& monitor_layout->device_scale_factor != 180;
1844+
if (check_device_scale_factor)
1845+
{
1846+
LOG(LOG_LEVEL_WARNING, "sanitise_extended_monitor_attributes:"
1847+
" device_scale_factor a valid value (One of 100, 140, 180)."
1848+
" Assuming 100. Value was: %d",
1849+
monitor_layout->device_scale_factor);
1850+
}
1851+
1852+
if (check_desktop_scale_factor || check_device_scale_factor)
1853+
{
1854+
monitor_layout->desktop_scale_factor = 100;
1855+
monitor_layout->device_scale_factor = 100;
1856+
}
1857+
}
1858+
17671859
/*****************************************************************************/
17681860
/*
17691861
Process a [MS-RDPBCGR] TS_UD_CS_MONITOR message.
@@ -1907,87 +1999,11 @@ libxrdp_process_monitor_stream(struct stream *s,
19071999

19082000
in_uint32_le(s, monitor_layout->physical_width);
19092001
in_uint32_le(s, monitor_layout->physical_height);
1910-
1911-
/* Per spec (2.2.2.2.1 DISPLAYCONTROL_MONITOR_LAYOUT),
1912-
* if EITHER physical_width or physical_height are
1913-
* out of range, BOTH must be ignored.
1914-
*/
1915-
if (monitor_layout->physical_width > 10000
1916-
|| monitor_layout->physical_width < 10)
1917-
{
1918-
LOG(LOG_LEVEL_WARNING, "libxrdp_process_monitor_stream:"
1919-
" physical_width is not within valid range."
1920-
" Setting physical_width to 0mm,"
1921-
" Setting physical_height to 0mm,"
1922-
" physical_width was: %d",
1923-
monitor_layout->physical_width);
1924-
monitor_layout->physical_width = 0;
1925-
monitor_layout->physical_height = 0;
1926-
}
1927-
1928-
if (monitor_layout->physical_height > 10000
1929-
|| monitor_layout->physical_height < 10)
1930-
{
1931-
LOG(LOG_LEVEL_WARNING, "libxrdp_process_monitor_stream:"
1932-
" physical_height is not within valid range."
1933-
" Setting physical_width to 0mm,"
1934-
" Setting physical_height to 0mm,"
1935-
" physical_height was: %d",
1936-
monitor_layout->physical_height);
1937-
monitor_layout->physical_width = 0;
1938-
monitor_layout->physical_height = 0;
1939-
}
1940-
19412002
in_uint32_le(s, monitor_layout->orientation);
1942-
switch (monitor_layout->orientation)
1943-
{
1944-
case ORIENTATION_LANDSCAPE:
1945-
case ORIENTATION_PORTRAIT:
1946-
case ORIENTATION_LANDSCAPE_FLIPPED:
1947-
case ORIENTATION_PORTRAIT_FLIPPED:
1948-
break;
1949-
default:
1950-
LOG(LOG_LEVEL_WARNING, "libxrdp_process_monitor_stream:"
1951-
" Orientation is not one of %d, %d, %d, or %d."
1952-
" Value was %d and ignored and set to default value of LANDSCAPE.",
1953-
ORIENTATION_LANDSCAPE,
1954-
ORIENTATION_PORTRAIT,
1955-
ORIENTATION_LANDSCAPE_FLIPPED,
1956-
ORIENTATION_PORTRAIT_FLIPPED,
1957-
monitor_layout->orientation);
1958-
monitor_layout->orientation = ORIENTATION_LANDSCAPE;
1959-
}
1960-
19612003
in_uint32_le(s, monitor_layout->desktop_scale_factor);
1962-
int check_desktop_scale_factor
1963-
= monitor_layout->desktop_scale_factor < 100
1964-
|| monitor_layout->desktop_scale_factor > 500;
1965-
if (check_desktop_scale_factor)
1966-
{
1967-
LOG(LOG_LEVEL_WARNING, "libxrdp_process_monitor_stream:"
1968-
" desktop_scale_factor is not within valid range"
1969-
" of [100, 500]. Assuming 100. Value was: %d",
1970-
monitor_layout->desktop_scale_factor);
1971-
}
1972-
19732004
in_uint32_le(s, monitor_layout->device_scale_factor);
1974-
int check_device_scale_factor
1975-
= monitor_layout->device_scale_factor != 100
1976-
&& monitor_layout->device_scale_factor != 140
1977-
&& monitor_layout->device_scale_factor != 180;
1978-
if (check_device_scale_factor)
1979-
{
1980-
LOG(LOG_LEVEL_WARNING, "libxrdp_process_monitor_stream:"
1981-
" device_scale_factor a valid value (One of 100, 140, 180)."
1982-
" Assuming 100. Value was: %d",
1983-
monitor_layout->device_scale_factor);
1984-
}
19852005

1986-
if (check_desktop_scale_factor || check_device_scale_factor)
1987-
{
1988-
monitor_layout->desktop_scale_factor = 100;
1989-
monitor_layout->device_scale_factor = 100;
1990-
}
2006+
sanitise_extended_monitor_attributes(monitor_layout);
19912007

19922008
/*
19932009
* 2.2.2.2.1 DISPLAYCONTROL_MONITOR_LAYOUT
@@ -2137,5 +2153,108 @@ libxrdp_process_monitor_stream(struct stream *s,
21372153
monitor_layout->bottom =
21382154
monitor_layout->bottom - all_monitors_encompassing_bounds.top;
21392155
}
2156+
2157+
return 0;
2158+
}
2159+
2160+
/*****************************************************************************/
2161+
int
2162+
libxrdp_process_monitor_ex_stream(struct stream *s,
2163+
struct display_size_description *description)
2164+
{
2165+
uint32_t num_monitor;
2166+
uint32_t monitor_index;
2167+
uint32_t attribute_size;
2168+
struct monitor_info *monitor_layout;
2169+
2170+
LOG_DEVEL(LOG_LEVEL_TRACE, "libxrdp_process_monitor_ex_stream:");
2171+
if (description == NULL)
2172+
{
2173+
LOG_DEVEL(LOG_LEVEL_ERROR, "libxrdp_process_monitor_ex_stream: "
2174+
"description was null. "
2175+
" Valid pointer to allocated description expected.");
2176+
return SEC_PROCESS_MONITORS_ERR;
2177+
}
2178+
2179+
if (!s_check_rem_and_log(s, 4,
2180+
"libxrdp_process_monitor_ex_stream:"
2181+
" Parsing [MS-RDPBCGR] TS_UD_CS_MONITOR_EX"))
2182+
{
2183+
return SEC_PROCESS_MONITORS_ERR;
2184+
}
2185+
2186+
in_uint32_le(s, attribute_size);
2187+
if (attribute_size != TS_MONITOR_ATTRIBUTES_SIZE)
2188+
{
2189+
LOG(LOG_LEVEL_ERROR,
2190+
"libxrdp_process_monitor_ex_stream: [MS-RDPBCGR] Protocol"
2191+
" error: TS_UD_CS_MONITOR_EX monitorAttributeSize"
2192+
" MUST be %d, received: %d",
2193+
TS_MONITOR_ATTRIBUTES_SIZE, attribute_size);
2194+
return SEC_PROCESS_MONITORS_ERR;
2195+
}
2196+
2197+
in_uint32_le(s, num_monitor);
2198+
LOG(LOG_LEVEL_DEBUG, "libxrdp_process_monitor_ex_stream:"
2199+
" The number of monitors received is: %d",
2200+
num_monitor);
2201+
2202+
if (num_monitor != description->monitorCount)
2203+
{
2204+
LOG(LOG_LEVEL_ERROR,
2205+
"libxrdp_process_monitor_ex_stream: [MS-RDPBCGR] Protocol"
2206+
" error: TS_UD_CS_MONITOR monitorCount"
2207+
" MUST be %d, received: %d",
2208+
description->monitorCount, num_monitor);
2209+
return SEC_PROCESS_MONITORS_ERR;
2210+
}
2211+
2212+
for (monitor_index = 0; monitor_index < num_monitor; ++monitor_index)
2213+
{
2214+
if (!s_check_rem_and_log(s, attribute_size,
2215+
"libxrdp_process_monitor_ex_stream:"
2216+
" Parsing TS_UD_CS_MONITOR_EX"))
2217+
{
2218+
return SEC_PROCESS_MONITORS_ERR;
2219+
}
2220+
2221+
monitor_layout = description->minfo + monitor_index;
2222+
2223+
in_uint32_le(s, monitor_layout->physical_width);
2224+
in_uint32_le(s, monitor_layout->physical_height);
2225+
in_uint32_le(s, monitor_layout->orientation);
2226+
in_uint32_le(s, monitor_layout->desktop_scale_factor);
2227+
in_uint32_le(s, monitor_layout->device_scale_factor);
2228+
2229+
sanitise_extended_monitor_attributes(monitor_layout);
2230+
2231+
LOG_DEVEL(LOG_LEVEL_INFO, "libxrdp_process_monitor_ex_stream:"
2232+
" Received [MS-RDPBCGR] 2.2.1.3.9.1 "
2233+
" TS_MONITOR_ATTRIBUTES"
2234+
" Index: %d, PhysicalWidth %d, PhysicalHeight %d,"
2235+
" Orientation %d, DesktopScaleFactor %d,"
2236+
" DeviceScaleFactor %d",
2237+
monitor_index,
2238+
monitor_layout->physical_width,
2239+
monitor_layout->physical_height,
2240+
monitor_layout->orientation,
2241+
monitor_layout->desktop_scale_factor,
2242+
monitor_layout->device_scale_factor);
2243+
}
2244+
2245+
/* Update non negative monitor info values */
2246+
const struct monitor_info *src = description->minfo;
2247+
struct monitor_info *dst = description->minfo_wm;
2248+
for (monitor_index = 0; monitor_index < num_monitor; ++monitor_index)
2249+
{
2250+
dst->physical_width = src->physical_width;
2251+
dst->physical_height = src->physical_height;
2252+
dst->orientation = src->orientation;
2253+
dst->desktop_scale_factor = src->desktop_scale_factor;
2254+
dst->device_scale_factor = src->device_scale_factor;
2255+
++src;
2256+
++dst;
2257+
}
2258+
21402259
return 0;
21412260
}

libxrdp/libxrdp.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,9 +364,10 @@ xrdp_mcs_disconnect(struct xrdp_mcs *self);
364364
/* xrdp_sec.c */
365365

366366
/*
367-
These are error return codes for both:
367+
These are error return codes for:-
368368
1. xrdp_sec_process_mcs_data_monitors
369369
2. libxrdp_process_monitor_stream
370+
3. libxrdp_process_monitor_ex_stream
370371
To clarify any reason for a non-zero response code.
371372
*/
372373
#define SEC_PROCESS_MONITORS_ERR 1

libxrdp/libxrdpinc.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,4 +324,19 @@ int EXPORT_CC
324324
libxrdp_process_monitor_stream(struct stream *s, struct display_size_description *description,
325325
int full_parameters);
326326

327+
/**
328+
* Processes a stream that is based on [MS-RDPBCGR] 2.2.1.3.9 Client
329+
* Monitor Extended Data (TS_UD_CS_MONITOR_EX)
330+
*
331+
* Data is stored in a struct which has already been read by
332+
* libxrdp_process_monitor_stream() withj full_parameters set to 0.
333+
*
334+
* @param s Stream to read data from. Stream is read up to monitorAttributeSize
335+
* @param description Result of reading TS_UD_CS_MONITOR PDU
336+
* @return 0 if the data is processed, non-zero if there is an error.
337+
*/
338+
int EXPORT_CC
339+
libxrdp_process_monitor_ex_stream(struct stream *s,
340+
struct display_size_description *description);
341+
327342
#endif

0 commit comments

Comments
 (0)