Skip to content

Commit d2442d4

Browse files
committed
Unify monitor processing logic.
There are two places where monitor descriptions are passed through the RDP protocol: - TS_UD_CS_MONITOR - DISPLAYCONTROL_PDU_TYPE_MONITOR_LAYOUT The processing logic for both of them is similar enough that they should be unified. Note that this is also the first step to making resizing work with the Extension GFX channel.
1 parent 70a8af1 commit d2442d4

File tree

3 files changed

+269
-181
lines changed

3 files changed

+269
-181
lines changed

common/xrdp_client_info.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,34 @@
2424
#if !defined(XRDP_CLIENT_INFO_H)
2525
#define XRDP_CLIENT_INFO_H
2626

27+
/*
28+
* 2.2.1.3.6.1 Monitor Definition (TS_MONITOR_DEF)
29+
* 2.2.1.3.9.1 Monitor Attributes (TS_MONITOR_ATTRIBUTES)
30+
*/
2731
struct monitor_info
2832
{
2933
int left;
3034
int top;
35+
int width;
36+
int height;
3137
int right;
3238
int bottom;
39+
int physical_width;
40+
int physical_height;
41+
int orientation;
42+
int desktop_scale_factor;
43+
int device_scale_factor;
3344
int is_primary;
45+
int flags;
46+
};
47+
48+
struct display_size_description
49+
{
50+
int monitorCount; /* number of monitors detected (max = 16) */
51+
struct monitor_info minfo[CLIENT_MONITOR_DATA_MAXIMUM_MONITORS]; /* client monitor data */
52+
struct monitor_info minfo_wm[CLIENT_MONITOR_DATA_MAXIMUM_MONITORS]; /* client monitor data, non-negative values */
53+
int session_width;
54+
int session_height;
3455
};
3556

3657
/**

libxrdp/xrdp_sec.c

Lines changed: 141 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -2298,160 +2298,192 @@ xrdp_sec_process_mcs_data_channels(struct xrdp_sec *self, struct stream *s)
22982298
return 0;
22992299
}
23002300

2301-
/*****************************************************************************/
2302-
/* Process a [MS-RDPBCGR] TS_UD_CS_MONITOR message.
2303-
reads the client monitors data */
2304-
static int
2305-
xrdp_sec_process_mcs_data_monitors(struct xrdp_sec *self, struct stream *s)
2306-
{
2307-
int index;
2308-
int monitorCount;
2309-
int flags;
2310-
int x1;
2311-
int y1;
2312-
int x2;
2313-
int y2;
2314-
int got_primary;
2315-
struct xrdp_client_info *client_info = (struct xrdp_client_info *)NULL;
2301+
struct display_size_description*
2302+
process_monitor_stream(struct stream *s, int full_parameters) {
2303+
struct display_size_description *description = (struct display_size_description *)
2304+
g_malloc(sizeof(struct display_size_description), 1);
23162305

2317-
client_info = &(self->rdp_layer->client_info);
2306+
int NumMonitor;
2307+
struct monitor_info *monitor_layout;
2308+
struct xrdp_rect rect = {8192, 8192, -8192, -8192};
23182309

2319-
/* this is an option set in xrdp.ini */
2320-
if (client_info->multimon != 1) /* are multi-monitors allowed ? */
2321-
{
2322-
LOG(LOG_LEVEL_INFO, "Multi-monitor is disabled by server config");
2323-
return 0;
2324-
}
2325-
if (!s_check_rem_and_log(s, 8, "Parsing [MS-RDPBCGR] TS_UD_CS_MONITOR"))
2326-
{
2327-
return 1;
2328-
}
2329-
in_uint32_le(s, flags); /* flags */
2330-
in_uint32_le(s, monitorCount);
2331-
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_UD_CS_MONITOR "
2332-
"flags 0x%8.8x, monitorCount %d", flags, monitorCount);
2310+
in_uint32_le(s, NumMonitor);
2311+
LOG(LOG_LEVEL_DEBUG, " NumMonitor %d", NumMonitor);
23332312

2334-
//verify flags - must be 0x0
2335-
if (flags != 0)
2336-
{
2337-
LOG(LOG_LEVEL_ERROR,
2338-
"[MS-RDPBCGR] Protocol error: TS_UD_CS_MONITOR flags MUST be zero, "
2339-
"received: 0x%8.8x", flags);
2340-
return 1;
2341-
}
2342-
//verify monitorCount - max 16
2343-
if (monitorCount > 16)
2313+
if (NumMonitor >= CLIENT_MONITOR_DATA_MAXIMUM_MONITORS)
23442314
{
23452315
LOG(LOG_LEVEL_ERROR,
23462316
"[MS-RDPBCGR] Protocol error: TS_UD_CS_MONITOR monitorCount "
2347-
"MUST be less than 16, received: %d", monitorCount);
2348-
return 1;
2317+
"MUST be less than 16, received: %d", NumMonitor);
2318+
goto exit_error;
23492319
}
23502320

2351-
client_info->monitorCount = monitorCount;
2321+
description->monitorCount = NumMonitor;
2322+
2323+
int got_primary = 0;
23522324

2353-
x1 = 0;
2354-
y1 = 0;
2355-
x2 = 0;
2356-
y2 = 0;
2357-
got_primary = 0;
2358-
/* Add client_monitor_data to client_info struct, will later pass to X11rdp */
2359-
for (index = 0; index < monitorCount; index++)
2325+
for (int monitor_index = 0; monitor_index < NumMonitor; ++monitor_index)
23602326
{
2361-
if (!s_check_rem_and_log(s, 20, "Parsing [MS-RDPBCGR] TS_UD_CS_MONITOR.TS_MONITOR_DEF"))
2327+
if (!s_check_rem_and_log(s, full_parameters == 0 ? 20 : 40, "Parsing monitor definitions."))
23622328
{
2363-
return 1;
2329+
goto exit_error;
2330+
}
2331+
2332+
monitor_layout = description->minfo + monitor_index;
2333+
if (full_parameters != 0) {
2334+
in_uint32_le(s, monitor_layout->flags);
23642335
}
2365-
in_uint32_le(s, client_info->minfo[index].left);
2366-
in_uint32_le(s, client_info->minfo[index].top);
2367-
in_uint32_le(s, client_info->minfo[index].right);
2368-
in_uint32_le(s, client_info->minfo[index].bottom);
2369-
in_uint32_le(s, client_info->minfo[index].is_primary);
2370-
2371-
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] "
2372-
"TS_UD_CS_MONITOR.TS_MONITOR_DEF %d "
2373-
"left %d, top %d, right %d, bottom %d, flags 0x%8.8x",
2374-
index,
2375-
client_info->minfo[index].left,
2376-
client_info->minfo[index].top,
2377-
client_info->minfo[index].right,
2378-
client_info->minfo[index].bottom,
2379-
client_info->minfo[index].is_primary);
2380-
2381-
if (index == 0)
2382-
{
2383-
x1 = client_info->minfo[index].left;
2384-
y1 = client_info->minfo[index].top;
2385-
x2 = client_info->minfo[index].right;
2386-
y2 = client_info->minfo[index].bottom;
2336+
in_uint32_le(s, monitor_layout->left);
2337+
in_uint32_le(s, monitor_layout->top);
2338+
in_uint32_le(s, monitor_layout->width);
2339+
in_uint32_le(s, monitor_layout->height);
2340+
if (full_parameters != 0) {
2341+
in_uint32_le(s, monitor_layout->physical_width);
2342+
in_uint32_le(s, monitor_layout->physical_height);
2343+
in_uint32_le(s, monitor_layout->orientation);
2344+
in_uint32_le(s, monitor_layout->desktop_scale_factor);
2345+
in_uint32_le(s, monitor_layout->device_scale_factor);
2346+
}
2347+
2348+
monitor_layout->right = monitor_layout->left + monitor_layout->width;
2349+
monitor_layout->bottom = monitor_layout->top + monitor_layout->height;
2350+
2351+
if (full_parameters != 0)
2352+
{
2353+
LOG(LOG_LEVEL_INFO, " Index: %d, Flags 0x%8.8x Left %d Top %d "
2354+
"Width %d Height %d PhysicalWidth %d PhysicalHeight %d "
2355+
"Orientation %d DesktopScaleFactor %d DeviceScaleFactor %d",
2356+
monitor_index, monitor_layout->flags, monitor_layout->left,
2357+
monitor_layout->top, monitor_layout->width, monitor_layout->height,
2358+
monitor_layout->physical_width, monitor_layout->physical_height,
2359+
monitor_layout->orientation, monitor_layout->desktop_scale_factor,
2360+
monitor_layout->device_scale_factor);
23872361
}
23882362
else
23892363
{
2390-
x1 = MIN(x1, client_info->minfo[index].left);
2391-
y1 = MIN(y1, client_info->minfo[index].top);
2392-
x2 = MAX(x2, client_info->minfo[index].right);
2393-
y2 = MAX(y2, client_info->minfo[index].bottom);
2364+
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] "
2365+
"TS_UD_CS_MONITOR.TS_MONITOR_DEF %d "
2366+
"left %d, top %d, right %d, bottom %d, flags 0x%8.8x",
2367+
monitor_index,
2368+
monitor_layout->left,
2369+
monitor_layout->top,
2370+
monitor_layout->right,
2371+
monitor_layout->bottom,
2372+
monitor_layout->is_primary);
23942373
}
23952374

2396-
if (client_info->minfo[index].is_primary)
2375+
if (monitor_index == 0)
23972376
{
2398-
got_primary = 1;
2377+
rect.left = monitor_layout->left;
2378+
rect.top = monitor_layout->top;
2379+
rect.right = monitor_layout->right;
2380+
rect.bottom = monitor_layout->bottom;
2381+
}
2382+
else
2383+
{
2384+
rect.left = MIN(monitor_layout->left, rect.left);
2385+
rect.top = MIN(monitor_layout->top, rect.top);
2386+
rect.right = MAX(rect.right, monitor_layout->right);
2387+
rect.bottom = MAX(rect.bottom, monitor_layout->bottom);
23992388
}
24002389

2401-
LOG(LOG_LEVEL_DEBUG,
2402-
"Client monitor [%d]: left= %d, top= %d, right= %d, bottom= %d, "
2403-
"is_primary?= %d",
2404-
index,
2405-
client_info->minfo[index].left,
2406-
client_info->minfo[index].top,
2407-
client_info->minfo[index].right,
2408-
client_info->minfo[index].bottom,
2409-
client_info->minfo[index].is_primary);
2390+
if (monitor_layout->is_primary)
2391+
{
2392+
got_primary = 1;
2393+
}
24102394
}
24112395

24122396
if (!got_primary)
24132397
{
24142398
/* no primary monitor was set, choose the leftmost monitor as primary */
2415-
for (index = 0; index < monitorCount; index++)
2399+
for (int monitor_index = 0; monitor_index < NumMonitor; ++monitor_index)
24162400
{
2417-
if (client_info->minfo[index].left == x1 &&
2418-
client_info->minfo[index].top == y1)
2401+
monitor_layout = description->minfo + monitor_index;
2402+
if (monitor_layout->left != rect.left || monitor_layout->top != rect.top)
24192403
{
2420-
client_info->minfo[index].is_primary = 1;
2421-
break;
2404+
continue;
24222405
}
2406+
monitor_layout->is_primary = 1;
24232407
}
24242408
}
24252409

24262410
/* set wm geometry */
2427-
if ((x2 > x1) && (y2 > y1))
2411+
if ((rect.right > rect.left) && (rect.bottom > rect.top))
24282412
{
2429-
client_info->width = (x2 - x1) + 1;
2430-
client_info->height = (y2 - y1) + 1;
2413+
description->session_width = rect.right - rect.left;
2414+
description->session_height = rect.bottom - rect.top;
24312415
}
24322416
/* make sure virtual desktop size is ok */
2433-
if (client_info->width > 0x7FFE || client_info->width < 0xC8 ||
2434-
client_info->height > 0x7FFE || client_info->height < 0xC8)
2417+
if (description->session_width > 0x7FFE || description->session_width < 0xC8 ||
2418+
description->session_height > 0x7FFE || description->session_height < 0xC8)
24352419
{
2436-
LOG(LOG_LEVEL_ERROR,
2420+
LOG(LOG_LEVEL_INFO,
24372421
"Client supplied virtual desktop width or height is invalid. "
24382422
"Allowed width range: min %d, max %d. Width received: %d. "
24392423
"Allowed height range: min %d, max %d. Height received: %d",
2440-
0xC8, 0x7FFE, client_info->width,
2441-
0xC8, 0x7FFE, client_info->height);
2442-
return 1; /* error */
2424+
0xC8, 0x7FFE, description->session_width,
2425+
0xC8, 0x7FFE, description->session_width);
2426+
goto exit_error;
24432427
}
24442428

24452429
/* keep a copy of non negative monitor info values for xrdp_wm usage */
2446-
for (index = 0; index < monitorCount; index++)
2430+
for (int monitor_index = 0; monitor_index < NumMonitor; ++monitor_index)
2431+
{
2432+
monitor_layout = description->minfo_wm + monitor_index;
2433+
2434+
g_memcpy(monitor_layout, description->minfo + monitor_index, sizeof(struct monitor_info));
2435+
2436+
monitor_layout->left = monitor_layout->left - rect.left;
2437+
monitor_layout->top = monitor_layout->top - rect.top;
2438+
monitor_layout->right = monitor_layout->right - rect.left;
2439+
monitor_layout->bottom = monitor_layout->bottom - rect.top;
2440+
}
2441+
return description;
2442+
exit_error:
2443+
g_free(description);
2444+
return NULL;
2445+
}
2446+
2447+
/*****************************************************************************/
2448+
/* Process a [MS-RDPBCGR] TS_UD_CS_MONITOR message.
2449+
reads the client monitors data */
2450+
static int
2451+
xrdp_sec_process_mcs_data_monitors(struct xrdp_sec *self, struct stream *s)
2452+
{
2453+
int flags;
2454+
struct xrdp_client_info *client_info = &(self->rdp_layer->client_info);
2455+
2456+
/* this is an option set in xrdp.ini */
2457+
if (client_info->multimon != 1) /* are multi-monitors allowed ? */
2458+
{
2459+
LOG(LOG_LEVEL_INFO, "Multi-monitor is disabled by server config");
2460+
return 0;
2461+
}
2462+
if (!s_check_rem_and_log(s, 8, "Parsing [MS-RDPBCGR] TS_UD_CS_MONITOR"))
2463+
{
2464+
return 1;
2465+
}
2466+
in_uint32_le(s, flags); /* flags */
2467+
2468+
//verify flags - must be 0x0
2469+
if (flags != 0)
24472470
{
2448-
client_info->minfo_wm[index].left = client_info->minfo[index].left - x1;
2449-
client_info->minfo_wm[index].top = client_info->minfo[index].top - y1;
2450-
client_info->minfo_wm[index].right = client_info->minfo[index].right - x1;
2451-
client_info->minfo_wm[index].bottom = client_info->minfo[index].bottom - y1;
2452-
client_info->minfo_wm[index].is_primary = client_info->minfo[index].is_primary;
2471+
LOG(LOG_LEVEL_ERROR,
2472+
"[MS-RDPBCGR] Protocol error: TS_UD_CS_MONITOR flags MUST be zero, "
2473+
"received: 0x%8.8x", flags);
2474+
return 1;
24532475
}
24542476

2477+
struct display_size_description *description = process_monitor_stream(s, 0);
2478+
2479+
client_info->monitorCount = description->monitorCount;
2480+
client_info->width = description->session_width;
2481+
client_info->height = description->session_height;
2482+
g_memcpy(client_info->minfo, description->minfo, sizeof(struct monitor_info) * CLIENT_MONITOR_DATA_MAXIMUM_MONITORS);
2483+
g_memcpy(client_info->minfo_wm, description->minfo_wm, sizeof(struct monitor_info) * CLIENT_MONITOR_DATA_MAXIMUM_MONITORS);
2484+
2485+
g_free(description);
2486+
24552487
return 0;
24562488
}
24572489

0 commit comments

Comments
 (0)