Merge pull request #1820 from Nexarian/dynamic_monitor_xrdp_master

Resolution switching without reconnecting.
This commit is contained in:
metalefty 2021-04-24 21:56:57 +09:00 committed by GitHub
commit 5f618207dd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 499 additions and 69 deletions

View File

@ -9,9 +9,15 @@
## Overview
**xrdp** provides a graphical login to remote machines using Microsoft
Remote Desktop Protocol (RDP). xrdp accepts connections from a variety of
RDP clients: FreeRDP, rdesktop, KRDC, NeutrinoRDP and Microsoft Remote Desktop
Client (for Windows, Mac OS, iOS and Android).
Remote Desktop Protocol (RDP). xrdp accepts connections from a variety of RDP clients:
- FreeRDP
- 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.
@ -24,7 +30,7 @@ RDP transport is encrypted using TLS by default.
* Connect to a Linux desktop using RDP from anywhere (requires
[xorgxrdp](https://github.com/neutrinolabs/xorgxrdp) Xorg module)
* 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)
### Access to Remote Resources

View File

@ -14,6 +14,7 @@ include_HEADERS = \
ms-rdpegdi.h \
ms-rdpele.h \
ms-rdperp.h \
ms-rdpedisp.h \
ms-smb2.h \
xrdp_client_info.h \
xrdp_constants.h \

View File

@ -78,7 +78,12 @@
/* This isn't explicitly named in MS-RDPBCGR */
#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 */
#define XR_CHANNEL_OPTION_INITIALIZED 0x80000000
#define XR_CHANNEL_OPTION_ENCRYPT_RDP 0x40000000

29
common/ms-rdpedisp.h Normal file
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 */

View File

@ -19,6 +19,7 @@
*/
#include "xrdp_constants.h"
#include "ms-rdpbcgr.h"
#if !defined(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 multimon; /* 0 = deny , 1 = allow */
int monitorCount; /* number of monitors detected (max = 16) */
struct monitor_info minfo[16]; /* client monitor data */
struct monitor_info minfo_wm[16]; /* client monitor data, non-negative values */
struct monitor_info minfo[CLIENT_MONITOR_DATA_MAXIMUM_MONITORS]; /* client monitor data */
struct monitor_info minfo_wm[CLIENT_MONITOR_DATA_MAXIMUM_MONITORS]; /* client monitor data, non-negative values */
int keyboard_type;
int keyboard_subtype;

View File

@ -776,7 +776,12 @@ xrdp_channel_drdynvc_start(struct xrdp_channel *self)
struct mcs_channel_item *ci;
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;
count = self->mcs_layer->channel_list->count;
for (index = 0; index < count; index++)

View File

@ -492,6 +492,10 @@ lxrdp_set_param(struct mod *mod, const char *name, const char *value)
{
settings->nla_security = g_text2bool(value);
}
else if (g_strcmp(name, "enable_dynamic_resizing") == 0)
{
settings->desktop_resize = g_text2bool(value);
}
else
{
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;
}
/******************************************************************************/
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
lfreerdp_begin_paint(rdpContext *context)
@ -2074,6 +2099,9 @@ mod_init(void)
mod->mod_check_wait_objs = lxrdp_check_wait_objs;
mod->mod_frame_ack = lxrdp_frame_ack;
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->PreConnect = lfreerdp_pre_connect;

View File

@ -82,8 +82,13 @@ struct mod
int (*mod_frame_ack)(struct mod *mod, int flags, int frame_id);
int (*mod_suppress_output)(struct mod *mod, int suppress,
int left, int top, int right, int bottom);
tintptr mod_dumby[100 - 11]; /* align, 100 minus the number of mod
functions above */
int (*mod_server_monitor_resize)(struct mod *mod,
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 */
int (*server_begin_update)(struct mod *v);
int (*server_end_update)(struct mod *v);

View File

@ -1224,7 +1224,7 @@ send_update_request_for_resize_status(struct vnc *v)
make_stream(s);
init_stream(s, 8192);
switch (v->initial_resize_status)
switch (v->resize_status)
{
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 "
"as the client layout");
v->initial_resize_status = VRS_DONE;
v->resize_status = VRS_DONE;
}
else
{
LOG(LOG_LEVEL_DEBUG, "Server layout differs from "
"the client layout. Changing server 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
@ -1382,7 +1382,7 @@ lib_framebuffer_first_update(struct vnc *v)
LOG(LOG_LEVEL_DEBUG, "Resizing client to server %dx%d",
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);
@ -1437,7 +1437,7 @@ lib_framebuffer_waiting_for_resize_confirm(struct vnc *v)
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);
@ -1777,7 +1777,7 @@ lib_mod_process_message(struct vnc *v, struct stream *s)
{
if (type == S2C_FRAMEBUFFER_UPDATE)
{
switch (v->initial_resize_status)
switch (v->resize_status)
{
case VRS_WAITING_FOR_FIRST_UPDATE:
error = lib_framebuffer_first_update(v);
@ -2237,7 +2237,7 @@ lib_mod_connect(struct vnc *v)
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);
}
@ -2465,6 +2465,34 @@ lib_mod_suppress_output(struct vnc *v, int suppress,
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
mod_init(void)
@ -2486,6 +2514,9 @@ mod_init(void)
v->mod_check_wait_objs = lib_mod_check_wait_objs;
v->mod_frame_ack = lib_mod_frame_ack;
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 */
v->enabled_encodings_mask = -1;

View File

@ -77,7 +77,12 @@ struct vnc
int (*mod_frame_ack)(struct vnc *v, int flags, int frame_id);
int (*mod_suppress_output)(struct vnc *v, int suppress,
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 */
/* server functions */
int (*server_begin_update)(struct vnc *v);
@ -152,5 +157,5 @@ struct vnc
unsigned int enabled_encodings_mask;
/* Resizeable support */
struct vnc_screen_layout client_layout;
enum vnc_resize_status initial_resize_status;
enum vnc_resize_status resize_status;
};

View File

@ -367,6 +367,21 @@ xrdp_bitmap_compress(char *in_data, int width, int height,
int e);
/* 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
xrdp_mm_drdynvc_up(struct xrdp_mm *self);
int

View File

@ -235,6 +235,9 @@ ip=ask
port=ask3389
username=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
#channel.rdpdr=true

View File

@ -24,6 +24,8 @@
#include "xrdp.h"
#include "log.h"
#include "string_calls.h"
#include "ms-rdpedisp.h"
#include "ms-rdpbcgr.h"
#ifdef USE_PAM
#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;
}
/******************************************************************************/
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
xrdp_mm_drdynvc_up(struct xrdp_mm *self)
{
LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_mm_drdynvc_up:");
return 0;
char enable_dynamic_resize[32];
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;
}
/******************************************************************************/

View File

@ -53,7 +53,12 @@ struct xrdp_mod
int (*mod_frame_ack)(struct xrdp_mod *v, int flags, int frame_id);
int (*mod_suppress_output)(struct xrdp_mod *v, int suppress,
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 */
/* server functions */
int (*server_begin_update)(struct xrdp_mod *v);
@ -302,6 +307,7 @@ struct xrdp_mm
struct xrdp_encoder *encoder;
int cs2xr_cid_map[256];
int xr2cr_cid_map[256];
int dynamic_monitor_chanid;
};
struct xrdp_key_info

179
xup/xup.c
View File

@ -27,6 +27,15 @@
#include "trans.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
lib_mod_process_message(struct mod *mod, struct stream *s);
@ -139,7 +148,6 @@ int
lib_mod_connect(struct mod *mod)
{
int error;
int len;
int i;
int use_uds;
struct stream *s;
@ -243,60 +251,18 @@ lib_mod_connect(struct mod *mod)
if (error == 0)
{
/* 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);
len = (int)(s->end - s->data);
s_pop_layer(s, iso_hdr);
out_uint32_le(s, len);
lib_send_copy(mod, s);
error = send_server_version_message(mod, s);
}
if (error == 0)
{
/* 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, 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);
error = send_server_monitor_resize(mod, s, mod->width, mod->height, mod->bpp);
}
if (error == 0)
{
/* 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 */
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);
error = send_server_monitor_full_invalidate(mod, s, mod->width, mod->height);
}
free_stream(s);
@ -1292,6 +1258,124 @@ process_server_paint_rect_shmem_ex(struct mod *amod, struct stream *s)
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 */
static int
@ -1636,6 +1720,9 @@ mod_init(void)
mod->mod_check_wait_objs = lib_mod_check_wait_objs;
mod->mod_frame_ack = lib_mod_frame_ack;
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;
}

View File

@ -51,7 +51,12 @@ struct mod
int (*mod_frame_ack)(struct mod *v, int flags, int frame_id);
int (*mod_suppress_output)(struct mod *v, int suppress,
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 */
/* server functions */
int (*server_begin_update)(struct mod *v);