Resolution switching without reconnecting.

- Based on https://github.com/jsorg71/xrdp/tree/dynamic_monitor
- Tested with xorgxrdp
- Tested with vnc
- Only works with single monitor.
- Update documentation to clarify the difference between MSTSC and
Microsoft Remote Desktop.
- Does not include compatibility with /gfx at this time, which is still
in testing.
- Updates to include ms-rdpedisp.h header for the 2.2.2 specification of
the protocol.
- Adds new dynamic_monitor_layout struct that shares the number of
monitors with xrdp_client_info.h
- Does not allow for BPP changes because the RDP protocol doesn't
support it.
- Option to disable feature as NeutrinoRDP doesn't support it (It was
based on FreeRDP 1.0.1 which didn't yet have this feature.)
- Add CLIENT_MONITOR_DATA_MAXIMUM_MONITORS constant and reference
spec definition.

Depends on https://github.com/neutrinolabs/xorgxrdp/pull/183
This commit is contained in:
Christopher Pitstick
2018-10-15 21:42:13 -07:00
parent 3a9d62b05c
commit deb66ce766
16 changed files with 499 additions and 69 deletions
+10 -4
View File
@@ -9,9 +9,15 @@
## Overview ## Overview
**xrdp** provides a graphical login to remote machines using Microsoft **xrdp** provides a graphical login to remote machines using Microsoft
Remote Desktop Protocol (RDP). xrdp accepts connections from a variety of Remote Desktop Protocol (RDP). xrdp accepts connections from a variety of RDP clients:
RDP clients: FreeRDP, rdesktop, KRDC, NeutrinoRDP and Microsoft Remote Desktop - FreeRDP
Client (for Windows, Mac OS, iOS and Android). - rdesktop
- KRDC
- NeutrinoRDP
- Windows MSTSC (Microsoft Terminal Services Client)
- Microsoft Remote Desktop (which is distinct from MSTSC)
Many of these work on some or all of Windows, Mac OS, iOS, and/or Android.
RDP transport is encrypted using TLS by default. RDP transport is encrypted using TLS by default.
@@ -24,7 +30,7 @@ RDP transport is encrypted using TLS by default.
* Connect to a Linux desktop using RDP from anywhere (requires * Connect to a Linux desktop using RDP from anywhere (requires
[xorgxrdp](https://github.com/neutrinolabs/xorgxrdp) Xorg module) [xorgxrdp](https://github.com/neutrinolabs/xorgxrdp) Xorg module)
* Reconnect to an existing session * Reconnect to an existing session
* Session resizing * Session resizing on connect and while an existing session is active.
* RDP/VNC proxy (connect to another RDP/VNC server via xrdp) * RDP/VNC proxy (connect to another RDP/VNC server via xrdp)
### Access to Remote Resources ### Access to Remote Resources
+1
View File
@@ -14,6 +14,7 @@ include_HEADERS = \
ms-rdpegdi.h \ ms-rdpegdi.h \
ms-rdpele.h \ ms-rdpele.h \
ms-rdperp.h \ ms-rdperp.h \
ms-rdpedisp.h \
ms-smb2.h \ ms-smb2.h \
xrdp_client_info.h \ xrdp_client_info.h \
xrdp_constants.h \ xrdp_constants.h \
+6 -1
View File
@@ -78,7 +78,12 @@
/* This isn't explicitly named in MS-RDPBCGR */ /* This isn't explicitly named in MS-RDPBCGR */
#define CHANNEL_NAME_LEN 7 #define CHANNEL_NAME_LEN 7
/* Oprions field */ /* 2.2.1.3.6 Client Monitor Data - */
/* monitorCount (4 bytes): A 32-bit, unsigned integer. The number of display */
/* monitor definitions in the monitorDefArray field (the maximum allowed is 16). */
#define CLIENT_MONITOR_DATA_MAXIMUM_MONITORS 16
/* Options field */
/* NOTE: XR_ prefixed to avoid conflict with FreeRDP */ /* NOTE: XR_ prefixed to avoid conflict with FreeRDP */
#define XR_CHANNEL_OPTION_INITIALIZED 0x80000000 #define XR_CHANNEL_OPTION_INITIALIZED 0x80000000
#define XR_CHANNEL_OPTION_ENCRYPT_RDP 0x40000000 #define XR_CHANNEL_OPTION_ENCRYPT_RDP 0x40000000
+29
View File
@@ -0,0 +1,29 @@
/**
* xrdp: A Remote Desktop Protocol server.
*
* MS-RDPEDISP : Definitions from [MS-RDPEDISP]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* References to MS-RDPEDISP are currently correct for v20201030 of that
* document
*/
#if !defined(MS_RDPEDISP_H)
#define MS_RDPEDISP_H
/* Display Control Messages: Display Virtual Channel Extension (2.2.2) */
#define DISPLAYCONTROL_PDU_TYPE_MONITOR_LAYOUT 0x00000002
#define DISPLAYCONTROL_PDU_TYPE_CAPS 0x00000005
#endif /* MS_RDPEDISP_H */
+3 -2
View File
@@ -19,6 +19,7 @@
*/ */
#include "xrdp_constants.h" #include "xrdp_constants.h"
#include "ms-rdpbcgr.h"
#if !defined(XRDP_CLIENT_INFO_H) #if !defined(XRDP_CLIENT_INFO_H)
#define XRDP_CLIENT_INFO_H #define XRDP_CLIENT_INFO_H
@@ -120,8 +121,8 @@ struct xrdp_client_info
int security_layer; /* 0 = rdp, 1 = tls , 2 = hybrid */ int security_layer; /* 0 = rdp, 1 = tls , 2 = hybrid */
int multimon; /* 0 = deny , 1 = allow */ int multimon; /* 0 = deny , 1 = allow */
int monitorCount; /* number of monitors detected (max = 16) */ int monitorCount; /* number of monitors detected (max = 16) */
struct monitor_info minfo[16]; /* client monitor data */ struct monitor_info minfo[CLIENT_MONITOR_DATA_MAXIMUM_MONITORS]; /* client monitor data */
struct monitor_info minfo_wm[16]; /* client monitor data, non-negative values */ struct monitor_info minfo_wm[CLIENT_MONITOR_DATA_MAXIMUM_MONITORS]; /* client monitor data, non-negative values */
int keyboard_type; int keyboard_type;
int keyboard_subtype; int keyboard_subtype;
+6 -1
View File
@@ -776,7 +776,12 @@ xrdp_channel_drdynvc_start(struct xrdp_channel *self)
struct mcs_channel_item *ci; struct mcs_channel_item *ci;
struct mcs_channel_item *dci; struct mcs_channel_item *dci;
LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_channel_drdynvc_start: drdynvc_channel_id %d", self->drdynvc_channel_id);
if (self->drdynvc_channel_id != -1)
{
LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_channel_drdynvc_start: already started");
return 0;
}
dci = NULL; dci = NULL;
count = self->mcs_layer->channel_list->count; count = self->mcs_layer->channel_list->count;
for (index = 0; index < count; index++) for (index = 0; index < count; index++)
+28
View File
@@ -492,6 +492,10 @@ lxrdp_set_param(struct mod *mod, const char *name, const char *value)
{ {
settings->nla_security = g_text2bool(value); settings->nla_security = g_text2bool(value);
} }
else if (g_strcmp(name, "enable_dynamic_resizing") == 0)
{
settings->desktop_resize = g_text2bool(value);
}
else else
{ {
LOG(LOG_LEVEL_WARNING, "lxrdp_set_param: unknown name [%s] value [%s]", name, value); LOG(LOG_LEVEL_WARNING, "lxrdp_set_param: unknown name [%s] value [%s]", name, value);
@@ -599,6 +603,27 @@ lxrdp_suppress_output(struct mod *mod, int suppress,
return 0; return 0;
} }
/******************************************************************************/
static int
lxrdp_server_version_message(struct mod *mod)
{
return 0;
}
/******************************************************************************/
static int
lxrdp_server_monitor_resize(struct mod *mod, int width, int height)
{
return 0;
}
/******************************************************************************/
static int
lxrdp_server_monitor_full_invalidate(struct mod *mod, int width, int height)
{
return 0;
}
/******************************************************************************/ /******************************************************************************/
static void static void
lfreerdp_begin_paint(rdpContext *context) lfreerdp_begin_paint(rdpContext *context)
@@ -2074,6 +2099,9 @@ mod_init(void)
mod->mod_check_wait_objs = lxrdp_check_wait_objs; mod->mod_check_wait_objs = lxrdp_check_wait_objs;
mod->mod_frame_ack = lxrdp_frame_ack; mod->mod_frame_ack = lxrdp_frame_ack;
mod->mod_suppress_output = lxrdp_suppress_output; mod->mod_suppress_output = lxrdp_suppress_output;
mod->mod_server_version_message = lxrdp_server_version_message;
mod->mod_server_monitor_resize = lxrdp_server_monitor_resize;
mod->mod_server_monitor_full_invalidate = lxrdp_server_monitor_full_invalidate;
mod->inst = freerdp_new(); mod->inst = freerdp_new();
mod->inst->PreConnect = lfreerdp_pre_connect; mod->inst->PreConnect = lfreerdp_pre_connect;
+7 -2
View File
@@ -82,8 +82,13 @@ struct mod
int (*mod_frame_ack)(struct mod *mod, int flags, int frame_id); int (*mod_frame_ack)(struct mod *mod, int flags, int frame_id);
int (*mod_suppress_output)(struct mod *mod, int suppress, int (*mod_suppress_output)(struct mod *mod, int suppress,
int left, int top, int right, int bottom); int left, int top, int right, int bottom);
tintptr mod_dumby[100 - 11]; /* align, 100 minus the number of mod int (*mod_server_monitor_resize)(struct mod *mod,
functions above */ int width, int height);
int (*mod_server_monitor_full_invalidate)(struct mod *mod,
int width, int height);
int (*mod_server_version_message)(struct mod *mod);
tintptr mod_dumby[100 - 14]; /* align, 100 minus the number of mod
functions above */
/* server functions */ /* server functions */
int (*server_begin_update)(struct mod *v); int (*server_begin_update)(struct mod *v);
int (*server_end_update)(struct mod *v); int (*server_end_update)(struct mod *v);
+38 -7
View File
@@ -1224,7 +1224,7 @@ send_update_request_for_resize_status(struct vnc *v)
make_stream(s); make_stream(s);
init_stream(s, 8192); init_stream(s, 8192);
switch (v->initial_resize_status) switch (v->resize_status)
{ {
case VRS_WAITING_FOR_FIRST_UPDATE: case VRS_WAITING_FOR_FIRST_UPDATE:
/* /*
@@ -1364,14 +1364,14 @@ lib_framebuffer_first_update(struct vnc *v)
{ {
LOG(LOG_LEVEL_DEBUG, "Server layout is the same " LOG(LOG_LEVEL_DEBUG, "Server layout is the same "
"as the client layout"); "as the client layout");
v->initial_resize_status = VRS_DONE; v->resize_status = VRS_DONE;
} }
else else
{ {
LOG(LOG_LEVEL_DEBUG, "Server layout differs from " LOG(LOG_LEVEL_DEBUG, "Server layout differs from "
"the client layout. Changing server layout"); "the client layout. Changing server layout");
error = send_set_desktop_size(v, &v->client_layout); error = send_set_desktop_size(v, &v->client_layout);
v->initial_resize_status = VRS_WAITING_FOR_RESIZE_CONFIRM; v->resize_status = VRS_WAITING_FOR_RESIZE_CONFIRM;
} }
} }
else else
@@ -1382,7 +1382,7 @@ lib_framebuffer_first_update(struct vnc *v)
LOG(LOG_LEVEL_DEBUG, "Resizing client to server %dx%d", LOG(LOG_LEVEL_DEBUG, "Resizing client to server %dx%d",
v->server_width, v->server_height); v->server_width, v->server_height);
error = resize_client(v, 0, v->server_width, v->server_height); error = resize_client(v, 0, v->server_width, v->server_height);
v->initial_resize_status = VRS_DONE; v->resize_status = VRS_DONE;
} }
g_free(layout.s); g_free(layout.s);
@@ -1437,7 +1437,7 @@ lib_framebuffer_waiting_for_resize_confirm(struct vnc *v)
v->server_width, v->server_height); v->server_width, v->server_height);
error = resize_client(v, 0, v->server_width, v->server_height); error = resize_client(v, 0, v->server_width, v->server_height);
} }
v->initial_resize_status = VRS_DONE; v->resize_status = VRS_DONE;
} }
g_free(layout.s); g_free(layout.s);
@@ -1777,7 +1777,7 @@ lib_mod_process_message(struct vnc *v, struct stream *s)
{ {
if (type == S2C_FRAMEBUFFER_UPDATE) if (type == S2C_FRAMEBUFFER_UPDATE)
{ {
switch (v->initial_resize_status) switch (v->resize_status)
{ {
case VRS_WAITING_FOR_FIRST_UPDATE: case VRS_WAITING_FOR_FIRST_UPDATE:
error = lib_framebuffer_first_update(v); error = lib_framebuffer_first_update(v);
@@ -2237,7 +2237,7 @@ lib_mod_connect(struct vnc *v)
if (error == 0) if (error == 0)
{ {
v->initial_resize_status = VRS_WAITING_FOR_FIRST_UPDATE; v->resize_status = VRS_WAITING_FOR_FIRST_UPDATE;
error = send_update_request_for_resize_status(v); error = send_update_request_for_resize_status(v);
} }
@@ -2465,6 +2465,34 @@ lib_mod_suppress_output(struct vnc *v, int suppress,
return error; return error;
} }
/******************************************************************************/
/* return error */
int
lib_mod_server_version_message(struct vnc *v)
{
return 0;
}
/******************************************************************************/
/* return error */
int
lib_mod_server_monitor_resize(struct vnc *v, int width, int height)
{
int error = 0;
set_single_screen_layout(&v->client_layout, width, height);
v->resize_status = VRS_WAITING_FOR_FIRST_UPDATE;
error = send_update_request_for_resize_status(v);
return error;
}
/******************************************************************************/
/* return error */
int
lib_mod_server_monitor_full_invalidate(struct vnc *v, int param1, int param2)
{
return 0;
}
/******************************************************************************/ /******************************************************************************/
tintptr EXPORT_CC tintptr EXPORT_CC
mod_init(void) mod_init(void)
@@ -2486,6 +2514,9 @@ mod_init(void)
v->mod_check_wait_objs = lib_mod_check_wait_objs; v->mod_check_wait_objs = lib_mod_check_wait_objs;
v->mod_frame_ack = lib_mod_frame_ack; v->mod_frame_ack = lib_mod_frame_ack;
v->mod_suppress_output = lib_mod_suppress_output; v->mod_suppress_output = lib_mod_suppress_output;
v->mod_server_monitor_resize = lib_mod_server_monitor_resize;
v->mod_server_monitor_full_invalidate = lib_mod_server_monitor_full_invalidate;
v->mod_server_version_message = lib_mod_server_version_message;
/* Member variables */ /* Member variables */
v->enabled_encodings_mask = -1; v->enabled_encodings_mask = -1;
+7 -2
View File
@@ -77,7 +77,12 @@ struct vnc
int (*mod_frame_ack)(struct vnc *v, int flags, int frame_id); int (*mod_frame_ack)(struct vnc *v, int flags, int frame_id);
int (*mod_suppress_output)(struct vnc *v, int suppress, int (*mod_suppress_output)(struct vnc *v, int suppress,
int left, int top, int right, int bottom); int left, int top, int right, int bottom);
tintptr mod_dumby[100 - 11]; /* align, 100 minus the number of mod int (*mod_server_monitor_resize)(struct vnc *v,
int width, int height);
int (*mod_server_monitor_full_invalidate)(struct vnc *v,
int width, int height);
int (*mod_server_version_message)(struct vnc *v);
tintptr mod_dumby[100 - 14]; /* align, 100 minus the number of mod
functions above */ functions above */
/* server functions */ /* server functions */
int (*server_begin_update)(struct vnc *v); int (*server_begin_update)(struct vnc *v);
@@ -152,5 +157,5 @@ struct vnc
unsigned int enabled_encodings_mask; unsigned int enabled_encodings_mask;
/* Resizeable support */ /* Resizeable support */
struct vnc_screen_layout client_layout; struct vnc_screen_layout client_layout;
enum vnc_resize_status initial_resize_status; enum vnc_resize_status resize_status;
}; };
+15
View File
@@ -367,6 +367,21 @@ xrdp_bitmap_compress(char *in_data, int width, int height,
int e); int e);
/* xrdp_mm.c */ /* xrdp_mm.c */
struct dynamic_monitor_layout
{
int flags;
int left;
int top;
int width;
int height;
int physical_width;
int physical_height;
int orientation;
int desktop_scale_factor;
int device_scale_factor;
};
int int
xrdp_mm_drdynvc_up(struct xrdp_mm *self); xrdp_mm_drdynvc_up(struct xrdp_mm *self);
int int
+3
View File
@@ -235,6 +235,9 @@ ip=ask
port=ask3389 port=ask3389
username=ask username=ask
password=ask password=ask
; Currently NeutrinoRDP doesn't support dynamic resizing. Uncomment
; this line if you're using a client which does.
#enable_dynamic_resizing=false
; You can override the common channel settings for each session type ; You can override the common channel settings for each session type
#channel.rdpdr=true #channel.rdpdr=true
+200 -2
View File
@@ -24,6 +24,8 @@
#include "xrdp.h" #include "xrdp.h"
#include "log.h" #include "log.h"
#include "string_calls.h" #include "string_calls.h"
#include "ms-rdpedisp.h"
#include "ms-rdpbcgr.h"
#ifdef USE_PAM #ifdef USE_PAM
#if defined(HAVE__PAM_TYPES_H) #if defined(HAVE__PAM_TYPES_H)
@@ -992,12 +994,208 @@ xrdp_mm_process_rail_drawing_orders(struct xrdp_mm *self, struct stream *s)
return rv; return rv;
} }
/******************************************************************************/
static int
dynamic_monitor_open_response(intptr_t id, int chan_id, int creation_status)
{
struct xrdp_process *pro;
struct xrdp_wm *wm;
struct stream *s;
int bytes;
LOG_DEVEL(LOG_LEVEL_TRACE, "dynamic_monitor_open_response: chan_id %d creation_status 0x%8.8x", chan_id, creation_status);
if (creation_status != 0)
{
LOG(LOG_LEVEL_ERROR, "dynamic_monitor_open_response: error");
return 1;
}
pro = (struct xrdp_process *) id;
wm = pro->wm;
make_stream(s);
init_stream(s, 1024);
out_uint32_le(s, 5); /* DISPLAYCONTROL_PDU_TYPE_CAPS */
out_uint32_le(s, 8 + 12);
out_uint32_le(s, CLIENT_MONITOR_DATA_MAXIMUM_MONITORS); /* MaxNumMonitors */
out_uint32_le(s, 4096); /* MaxMonitorAreaFactorA */
out_uint32_le(s, 2048); /* MaxMonitorAreaFactorB */
s_mark_end(s);
bytes = (int) (s->end - s->data);
libxrdp_drdynvc_data(wm->session, chan_id, s->data, bytes);
free_stream(s);
return 0;
}
/******************************************************************************/
static int
dynamic_monitor_close_response(intptr_t id, int chan_id)
{
LOG_DEVEL(LOG_LEVEL_TRACE, "dynamic_monitor_close_response:");
return 0;
}
/******************************************************************************/
static int
dynamic_monitor_data_first(intptr_t id, int chan_id, char *data, int bytes,
int total_bytes)
{
LOG_DEVEL(LOG_LEVEL_TRACE, "dynamic_monitor_data_first:");
return 0;
}
/******************************************************************************/
static int
dynamic_monitor_data(intptr_t id, int chan_id, char *data, int bytes)
{
struct stream ls;
struct stream *s;
int msg_type;
int msg_length;
int monitor_index;
struct xrdp_process *pro;
struct xrdp_wm *wm;
int MonitorLayoutSize;
int NumMonitor;
struct dynamic_monitor_layout monitor_layouts[CLIENT_MONITOR_DATA_MAXIMUM_MONITORS];
struct dynamic_monitor_layout *monitor_layout;
struct xrdp_rect rect;
int session_width;
int session_height;
LOG_DEVEL(LOG_LEVEL_TRACE, "dynamic_monitor_data:");
pro = (struct xrdp_process *) id;
wm = pro->wm;
g_memset(&ls, 0, sizeof(ls));
ls.data = data;
ls.p = ls.data;
ls.size = bytes;
ls.end = ls.data + bytes;
s = &ls;
in_uint32_le(s, msg_type);
in_uint32_le(s, msg_length);
LOG(LOG_LEVEL_DEBUG, "dynamic_monitor_data: msg_type %d msg_length %d",
msg_type, msg_length);
rect.left = 8192;
rect.top = 8192;
rect.right = -8192;
rect.bottom = -8192;
if (msg_type == DISPLAYCONTROL_PDU_TYPE_MONITOR_LAYOUT)
{
in_uint32_le(s, MonitorLayoutSize);
in_uint32_le(s, NumMonitor);
LOG(LOG_LEVEL_DEBUG, " MonitorLayoutSize %d NumMonitor %d",
MonitorLayoutSize, NumMonitor);
for (monitor_index = 0; monitor_index < NumMonitor; monitor_index++)
{
monitor_layout = monitor_layouts + monitor_index;
in_uint32_le(s, monitor_layout->flags);
in_uint32_le(s, monitor_layout->left);
in_uint32_le(s, monitor_layout->top);
in_uint32_le(s, monitor_layout->width);
in_uint32_le(s, monitor_layout->height);
in_uint32_le(s, monitor_layout->physical_width);
in_uint32_le(s, monitor_layout->physical_height);
in_uint32_le(s, monitor_layout->orientation);
in_uint32_le(s, monitor_layout->desktop_scale_factor);
in_uint32_le(s, monitor_layout->device_scale_factor);
LOG_DEVEL(LOG_LEVEL_DEBUG, " Flags 0x%8.8x Left %d Top %d "
"Width %d Height %d PhysicalWidth %d PhysicalHeight %d "
"Orientation %d DesktopScaleFactor %d DeviceScaleFactor %d",
monitor_layout->flags, monitor_layout->left, monitor_layout->top,
monitor_layout->width, monitor_layout->height,
monitor_layout->physical_width, monitor_layout->physical_height,
monitor_layout->orientation, monitor_layout->desktop_scale_factor,
monitor_layout->device_scale_factor);
rect.left = MIN(monitor_layout->left, rect.left);
rect.top = MIN(monitor_layout->top, rect.top);
rect.right = MAX(rect.right, monitor_layout->left + monitor_layout->width);
rect.bottom = MAX(rect.bottom, monitor_layout->top + monitor_layout->height);
}
}
session_width = rect.right - rect.left;
session_height = rect.bottom - rect.top;
if ((session_width > 0) && (session_height > 0))
{
// TODO: Unify this logic with server_reset
libxrdp_reset(wm->session, session_width, session_height, wm->screen->bpp);
/* reset cache */
xrdp_cache_reset(wm->cache, wm->client_info);
/* resize the main window */
xrdp_bitmap_resize(wm->screen, session_width, session_height);
/* load some stuff */
xrdp_wm_load_static_colors_plus(wm, 0);
xrdp_wm_load_static_pointers(wm);
/* redraw */
xrdp_bitmap_invalidate(wm->screen, 0);
struct xrdp_mod* v = wm->mm->mod;
if (v != 0) {
v->mod_server_version_message(v);
v->mod_server_monitor_resize(v, session_width, session_height);
v->mod_server_monitor_full_invalidate(v, session_width, session_height);
}
}
return 0;
}
/******************************************************************************/
int
dynamic_monitor_initialize(struct xrdp_mm *self)
{
struct xrdp_drdynvc_procs d_procs;
int flags;
int error;
LOG_DEVEL(LOG_LEVEL_TRACE, "dynamic_monitor_initialize:");
g_memset(&d_procs, 0, sizeof(d_procs));
d_procs.open_response = dynamic_monitor_open_response;
d_procs.close_response = dynamic_monitor_close_response;
d_procs.data_first = dynamic_monitor_data_first;
d_procs.data = dynamic_monitor_data;
flags = 0;
error = libxrdp_drdynvc_open(self->wm->session,
"Microsoft::Windows::RDS::DisplayControl",
flags, &d_procs,
&(self->dynamic_monitor_chanid));
if (error != 0)
{
LOG(LOG_LEVEL_ERROR, "xrdp_mm_drdynvc_up: "
"libxrdp_drdynvc_open failed %d", error);
}
return error;
}
/******************************************************************************/ /******************************************************************************/
int int
xrdp_mm_drdynvc_up(struct xrdp_mm *self) xrdp_mm_drdynvc_up(struct xrdp_mm *self)
{ {
LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_mm_drdynvc_up:"); char enable_dynamic_resize[32];
return 0; int error = 0;
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_mm_drdynvc_up:");
xrdp_mm_get_value(self, "enable_dynamic_resizing",
enable_dynamic_resize,
sizeof(enable_dynamic_resize) - 1);
/*
* User can disable dynamic resizing if necessary
*/
if (enable_dynamic_resize[0] != '\0' && !g_text2bool(enable_dynamic_resize))
{
LOG(LOG_LEVEL_INFO, "User has disabled dynamic resizing.");
}
else
{
error = dynamic_monitor_initialize(self);
}
return error;
} }
/******************************************************************************/ /******************************************************************************/
+7 -1
View File
@@ -53,7 +53,12 @@ struct xrdp_mod
int (*mod_frame_ack)(struct xrdp_mod *v, int flags, int frame_id); int (*mod_frame_ack)(struct xrdp_mod *v, int flags, int frame_id);
int (*mod_suppress_output)(struct xrdp_mod *v, int suppress, int (*mod_suppress_output)(struct xrdp_mod *v, int suppress,
int left, int top, int right, int bottom); int left, int top, int right, int bottom);
tintptr mod_dumby[100 - 11]; /* align, 100 minus the number of mod int (*mod_server_monitor_resize)(struct xrdp_mod* v,
int width, int height);
int (*mod_server_monitor_full_invalidate)(struct xrdp_mod* v,
int width, int height);
int (*mod_server_version_message)(struct xrdp_mod* v);
tintptr mod_dumby[100 - 14]; /* align, 100 minus the number of mod
functions above */ functions above */
/* server functions */ /* server functions */
int (*server_begin_update)(struct xrdp_mod *v); int (*server_begin_update)(struct xrdp_mod *v);
@@ -302,6 +307,7 @@ struct xrdp_mm
struct xrdp_encoder *encoder; struct xrdp_encoder *encoder;
int cs2xr_cid_map[256]; int cs2xr_cid_map[256];
int xr2cr_cid_map[256]; int xr2cr_cid_map[256];
int dynamic_monitor_chanid;
}; };
struct xrdp_key_info struct xrdp_key_info
+133 -46
View File
@@ -27,6 +27,15 @@
#include "trans.h" #include "trans.h"
#include "string_calls.h" #include "string_calls.h"
static int
send_server_monitor_resize(struct mod *mod, struct stream *s, int width, int height, int bpp);
static int
send_server_monitor_full_invalidate(struct mod *mod, struct stream *s, int width, int height);
static int
send_server_version_message(struct mod *v, struct stream *s);
static int static int
lib_mod_process_message(struct mod *mod, struct stream *s); lib_mod_process_message(struct mod *mod, struct stream *s);
@@ -139,7 +148,6 @@ int
lib_mod_connect(struct mod *mod) lib_mod_connect(struct mod *mod)
{ {
int error; int error;
int len;
int i; int i;
int use_uds; int use_uds;
struct stream *s; struct stream *s;
@@ -243,60 +251,18 @@ lib_mod_connect(struct mod *mod)
if (error == 0) if (error == 0)
{ {
/* send version message */ error = send_server_version_message(mod, s);
init_stream(s, 8192);
s_push_layer(s, iso_hdr, 4);
out_uint16_le(s, 103);
out_uint32_le(s, 301);
out_uint32_le(s, 0);
out_uint32_le(s, 0);
out_uint32_le(s, 0);
out_uint32_le(s, 1);
s_mark_end(s);
len = (int)(s->end - s->data);
s_pop_layer(s, iso_hdr);
out_uint32_le(s, len);
lib_send_copy(mod, s);
} }
if (error == 0) if (error == 0)
{ {
/* send screen size message */ /* send screen size message */
init_stream(s, 8192); error = send_server_monitor_resize(mod, s, mod->width, mod->height, mod->bpp);
s_push_layer(s, iso_hdr, 4);
out_uint16_le(s, 103);
out_uint32_le(s, 300);
out_uint32_le(s, mod->width);
out_uint32_le(s, mod->height);
out_uint32_le(s, mod->bpp);
out_uint32_le(s, 0);
s_mark_end(s);
len = (int)(s->end - s->data);
s_pop_layer(s, iso_hdr);
out_uint32_le(s, len);
lib_send_copy(mod, s);
} }
if (error == 0) if (error == 0)
{ {
/* send invalidate message */ error = send_server_monitor_full_invalidate(mod, s, mod->width, mod->height);
init_stream(s, 8192);
s_push_layer(s, iso_hdr, 4);
out_uint16_le(s, 103);
out_uint32_le(s, 200);
/* x and y */
i = 0;
out_uint32_le(s, i);
/* width and height */
i = ((mod->width & 0xffff) << 16) | mod->height;
out_uint32_le(s, i);
out_uint32_le(s, 0);
out_uint32_le(s, 0);
s_mark_end(s);
len = (int)(s->end - s->data);
s_pop_layer(s, iso_hdr);
out_uint32_le(s, len);
lib_send_copy(mod, s);
} }
free_stream(s); free_stream(s);
@@ -1292,6 +1258,124 @@ process_server_paint_rect_shmem_ex(struct mod *amod, struct stream *s)
return rv; return rv;
} }
/******************************************************************************/
/* return error */
static int
send_server_version_message(struct mod *mod, struct stream *s)
{
/* send version message */
init_stream(s, 8192);
s_push_layer(s, iso_hdr, 4);
out_uint16_le(s, 103);
out_uint32_le(s, 301);
out_uint32_le(s, 0);
out_uint32_le(s, 0);
out_uint32_le(s, 0);
out_uint32_le(s, 1);
s_mark_end(s);
int len = (int)(s->end - s->data);
s_pop_layer(s, iso_hdr);
out_uint32_le(s, len);
int rv = lib_send_copy(mod, s);
return rv;
}
/******************************************************************************/
/* return error */
static int
send_server_monitor_resize(struct mod *mod, struct stream *s, int width, int height, int bpp)
{
/* send screen size message */
init_stream(s, 8192);
s_push_layer(s, iso_hdr, 4);
out_uint16_le(s, 103);
out_uint32_le(s, 300);
out_uint32_le(s, width);
out_uint32_le(s, height);
/*
TODO: The bpp here is only necessary for initial creation. We should modify XUP to require this
only on server initialization, but not on resize. Microsoft's RDP protocol does not support changing
the bpp on resize.
*/
out_uint32_le(s, bpp);
out_uint32_le(s, 0);
s_mark_end(s);
int len = (int)(s->end - s->data);
s_pop_layer(s, iso_hdr);
out_uint32_le(s, len);
int rv = lib_send_copy(mod, s);
LOG_DEVEL(LOG_LEVEL_DEBUG, "send_server_monitor_resize: sent resize message with following properties to xorgxrdp backend "
"width=%d, height=%d, bpp=%d, return value=%d",
width, height, bpp, rv);
return rv;
}
static int
send_server_monitor_full_invalidate(struct mod *mod, struct stream *s, int width, int height)
{
/* send invalidate message */
init_stream(s, 8192);
s_push_layer(s, iso_hdr, 4);
out_uint16_le(s, 103);
out_uint32_le(s, 200);
/* x and y */
int i = 0;
out_uint32_le(s, i);
/* width and height */
i = ((width & 0xffff) << 16) | height;
out_uint32_le(s, i);
out_uint32_le(s, 0);
out_uint32_le(s, 0);
s_mark_end(s);
int len = (int)(s->end - s->data);
s_pop_layer(s, iso_hdr);
out_uint32_le(s, len);
int rv = lib_send_copy(mod, s);
LOG_DEVEL(LOG_LEVEL_DEBUG, "send_server_monitor_full_invalidate: sent invalidate message with following properties to xorgxrdp backend "
"width=%d, height=%d, return value=%d",
width, height, rv);
return rv;
}
/******************************************************************************/
/* return error */
static int
lib_send_server_version_message(struct mod *mod)
{
/* send server version message */
struct stream *s;
make_stream(s);
int rv = send_server_version_message(mod, s);
free_stream(s);
return rv;
}
/******************************************************************************/
/* return error */
static int
lib_send_server_monitor_resize(struct mod *mod, int width, int height)
{
/* send screen size message */
struct stream *s;
make_stream(s);
int rv = send_server_monitor_resize(mod, s, width, height, mod->bpp);
free_stream(s);
return rv;
}
/******************************************************************************/
/* return error */
static int
lib_send_server_monitor_full_invalidate(struct mod *mod, int width, int height)
{
/* send invalidate message */
struct stream *s;
make_stream(s);
int rv = send_server_monitor_full_invalidate(mod, s, width, height);
free_stream(s);
return rv;
}
/******************************************************************************/ /******************************************************************************/
/* return error */ /* return error */
static int static int
@@ -1636,6 +1720,9 @@ mod_init(void)
mod->mod_check_wait_objs = lib_mod_check_wait_objs; mod->mod_check_wait_objs = lib_mod_check_wait_objs;
mod->mod_frame_ack = lib_mod_frame_ack; mod->mod_frame_ack = lib_mod_frame_ack;
mod->mod_suppress_output = lib_mod_suppress_output; mod->mod_suppress_output = lib_mod_suppress_output;
mod->mod_server_monitor_resize = lib_send_server_monitor_resize;
mod->mod_server_monitor_full_invalidate = lib_send_server_monitor_full_invalidate;
mod->mod_server_version_message = lib_send_server_version_message;
return (tintptr) mod; return (tintptr) mod;
} }
+6 -1
View File
@@ -51,7 +51,12 @@ struct mod
int (*mod_frame_ack)(struct mod *v, int flags, int frame_id); int (*mod_frame_ack)(struct mod *v, int flags, int frame_id);
int (*mod_suppress_output)(struct mod *v, int suppress, int (*mod_suppress_output)(struct mod *v, int suppress,
int left, int top, int right, int bottom); int left, int top, int right, int bottom);
tintptr mod_dumby[100 - 11]; /* align, 100 minus the number of mod int (*mod_server_monitor_resize)(struct mod* v,
int width, int height);
int (*mod_server_monitor_full_invalidate)(struct mod* v,
int width, int height);
int (*mod_server_version_message)(struct mod* v);
tintptr mod_dumby[100 - 14]; /* align, 100 minus the number of mod
functions above */ functions above */
/* server functions */ /* server functions */
int (*server_begin_update)(struct mod *v); int (*server_begin_update)(struct mod *v);