diff --git a/common/Makefile.am b/common/Makefile.am index 915796be..b59a69d6 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -17,6 +17,7 @@ include_HEADERS = \ ms-rdperp.h \ ms-rdpedisp.h \ ms-smb2.h \ + xup_client_info.h \ xrdp_client_info.h \ xrdp_constants.h \ xrdp_rail.h \ diff --git a/common/ms-rdpbcgr.h b/common/ms-rdpbcgr.h index 38c5393f..c92ad625 100644 --- a/common/ms-rdpbcgr.h +++ b/common/ms-rdpbcgr.h @@ -338,6 +338,8 @@ /* Order Capability Set: orderSupportExFlags (2.2.7.1.3) */ /* NOTE: XR_ prefixed to avoid conflict with FreeRDP */ +/* XR_PRIMARY_ORDER_COUNT is not an official definition */ +#define XR_PRIMARY_ORDER_COUNT 32 #define XR_ORDERFLAGS_EX_CACHE_BITMAP_REV3_SUPPORT 0x0002 #define XR_ORDERFLAGS_EX_ALTSEC_FRAME_MARKER_SUPPORT 0x0004 diff --git a/common/xrdp_client_info.h b/common/xrdp_client_info.h index 71ffca7d..d699039d 100644 --- a/common/xrdp_client_info.h +++ b/common/xrdp_client_info.h @@ -99,18 +99,31 @@ enum unicode_input_state UIS_SUPPORTED, ///< Client supports Unicode, but it's not active UIS_ACTIVE ///< Unicode input is active }; + +enum xrdp_encoder_flags +{ + NONE = 0, + ENCODE_COMPLETE = 1 << 0, + GFX_PROGRESSIVE_RFX = 1 << 1, + GFX_H264 = 1 << 2, + KEY_FRAME_REQUESTED = 1 << 3 +}; + +/* Size definitions for some arrays in xrdp_client_info */ +enum +{ + CI_KBD_MODEL_SIZE = 16, + CI_KBD_LAYOUT_SIZE = 16, + CI_KBD_VARIANT_SIZE = 16, + CI_KBD_OPTIONS_SIZE = 256, + CI_KBD_XKB_RULES_SIZE = 32 +}; + /** * Information about the xrdp client - * - * @note This structure is shared with xorgxrdp. If you change anything - * above the 'private to xrdp below this line' comment, you MUST - * bump the CLIENT_INFO_CURRENT_VERSION number so that the mismatch - * can be detected. */ struct xrdp_client_info { - int size; /* bytes for this structure */ - int version; /* Should be CLIENT_INFO_CURRENT_VERSION */ int bpp; /* bitmap cache info */ int cache1_entries; @@ -173,7 +186,7 @@ struct xrdp_client_info char jpeg_prop[64]; int v3_codec_id; int rfx_min_pixel; - char orders[32]; + char orders[XR_PRIMARY_ORDER_COUNT]; int order_flags_ex; int use_bulk_comp; int pointer_flags; /* 0 color, 1 new, 2 no new */ @@ -197,18 +210,17 @@ struct xrdp_client_info int mcs_early_capability_flags; int max_fastpath_frag_bytes; - int pad0; /* unused */ int capture_format; char certificate[1024]; char key_file[1024]; /* X11 keyboard layout - inferred from keyboard type/subtype */ - char model[16]; - char layout[16]; - char variant[16]; - char options[256]; - char xkb_rules[32]; + char model[CI_KBD_MODEL_SIZE]; + char layout[CI_KBD_LAYOUT_SIZE]; + char variant[CI_KBD_VARIANT_SIZE]; + char options[CI_KBD_OPTIONS_SIZE]; + char xkb_rules[CI_KBD_XKB_RULES_SIZE]; // A few x11 keycodes are needed by the xup module int x11_keycode_caps_lock; int x11_keycode_num_lock; @@ -219,10 +231,6 @@ struct xrdp_client_info int h264_frame_interval; int normal_frame_interval; - /* ==================================================================== */ - /* Private to xrdp below this line */ - /* ==================================================================== */ - /* codec */ int h264_codec_id; int h264_prop_len; @@ -270,23 +278,10 @@ struct xrdp_client_info enum xrdp_capture_code capture_code; }; -enum xrdp_encoder_flags -{ - NONE = 0, - ENCODE_COMPLETE = 1 << 0, - GFX_PROGRESSIVE_RFX = 1 << 1, - GFX_H264 = 1 << 2, - KEY_FRAME_REQUESTED = 1 << 3 -}; - /* * Return true if output is suppressed for a particular reason */ #define OUTPUT_SUPPRESSED_FOR_REASON(ci,reason) \ (((ci)->suppress_output_mask & (unsigned int)reason) != 0) -/* yyyymmdd of last incompatible change to xrdp_client_info */ -/* also used for changes to all the xrdp installed headers */ -#define CLIENT_INFO_CURRENT_VERSION 20241118 - #endif diff --git a/common/xup_client_info.h b/common/xup_client_info.h new file mode 100644 index 00000000..fa8d6bae --- /dev/null +++ b/common/xup_client_info.h @@ -0,0 +1,78 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2004-2025 + * + * 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. + */ + +/** + * @file common/xup_client_info.h + * @brief Data shared with xorgxrdp + */ + +#if !defined(XUP_CLIENT_INFO_H) +#define XUP_CLIENT_INFO_H + +#include "xrdp_client_info.h" + +/** + * Information about the xrdp client which is passed to xorgxrdp + * + * This is a subset of 'struct xrdp_client_info' + * + * @note If you change this structure, you MUST bump the + * XUP_CLIENT_INFO_CURRENT_VERSION number so that the mismatch + * can be detected. + */ +struct xup_client_info +{ + int size; /* bytes for this structure */ + int version; /* Should be XUP_CLIENT_INFO_CURRENT_VERSION */ + int bpp; + int jpeg; /* non standard bitmap cache v2 cap */ + int offscreen_support_level; + int offscreen_cache_size; + int offscreen_cache_entries; + + char orders[XR_PRIMARY_ORDER_COUNT]; + int order_flags_ex; + int pointer_flags; /* 0 color, 1 new, 2 no new */ + int large_pointer_support_flags; + + struct display_size_description display_sizes; + + enum xrdp_capture_code capture_code; + int capture_format; + + /* X11 keyboard layout - inferred from keyboard type/subtype */ + char model[CI_KBD_MODEL_SIZE]; + char layout[CI_KBD_LAYOUT_SIZE]; + char variant[CI_KBD_VARIANT_SIZE]; + char options[CI_KBD_OPTIONS_SIZE]; + char xkb_rules[CI_KBD_XKB_RULES_SIZE]; + // A few x11 keycodes are needed by the xup module + int x11_keycode_caps_lock; + int x11_keycode_num_lock; + int x11_keycode_scroll_lock; + + /* xorgxrdp: frame capture interval (milliseconds) */ + int rfx_frame_interval; + int h264_frame_interval; + int normal_frame_interval; +}; + +/* yyyymmdd of last incompatible change to xup_client_info */ +#define XUP_CLIENT_INFO_CURRENT_VERSION 20250528 + +#endif // XUP_CLIENT_INFO_H diff --git a/libxrdp/xrdp_caps.c b/libxrdp/xrdp_caps.c index 3eab5b7c..b9851644 100644 --- a/libxrdp/xrdp_caps.c +++ b/libxrdp/xrdp_caps.c @@ -168,7 +168,7 @@ xrdp_caps_process_order(struct xrdp_rdp *self, struct stream *s, int len) { int i; - char order_caps[32]; + char order_caps[XR_PRIMARY_ORDER_COUNT]; int ex_flags; int cap_flags; @@ -185,8 +185,8 @@ xrdp_caps_process_order(struct xrdp_rdp *self, struct stream *s, in_uint8s(s, 2); /* Max order level */ in_uint8s(s, 2); /* Number of fonts */ in_uint16_le(s, cap_flags); /* Capability flags */ - in_uint8a(s, order_caps, 32); /* Orders supported */ - g_memcpy(self->client_info.orders, order_caps, 32); + in_uint8a(s, order_caps, XR_PRIMARY_ORDER_COUNT); /* Orders supported */ + g_memcpy(self->client_info.orders, order_caps, XR_PRIMARY_ORDER_COUNT); LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: terminalDescriptor (ignored as per protocol spec)"); LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: desktopSaveXGranularity (ignored as per protocol spec)"); @@ -220,7 +220,7 @@ xrdp_caps_process_order(struct xrdp_rdp *self, struct stream *s, LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 26: EllipseCB %d", order_caps[26]); LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 27: GlyphIndex %d", order_caps[27]); LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 28-31: unused index"); - LOG_DEVEL_HEXDUMP(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: order_caps", order_caps, 32); + LOG_DEVEL_HEXDUMP(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: order_caps", order_caps, XR_PRIMARY_ORDER_COUNT); in_uint8s(s, 2); /* Text capability flags */ LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: textFlags (ignored as per protocol spec)"); @@ -228,7 +228,7 @@ xrdp_caps_process_order(struct xrdp_rdp *self, struct stream *s, in_uint16_le(s, ex_flags); /* Ex flags */ LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupportExFlags 0x%4.4x", ex_flags); - if (cap_flags & 0x80) /* ORDER_FLAGS_EXTRA_SUPPORT */ + if (cap_flags & ORDERFLAGS_EXTRA_FLAGS) { self->client_info.order_flags_ex = ex_flags; if (ex_flags & XR_ORDERFLAGS_EX_CACHE_BITMAP_REV3_SUPPORT) diff --git a/libxrdp/xrdp_rdp.c b/libxrdp/xrdp_rdp.c index bc18a9ff..97fe7ffd 100644 --- a/libxrdp/xrdp_rdp.c +++ b/libxrdp/xrdp_rdp.c @@ -389,8 +389,6 @@ xrdp_rdp_create(struct xrdp_session *session, struct trans *trans) self->rfx_enc = rfx_context_new(); rfx_context_set_cpu_opt(self->rfx_enc, xrdp_rdp_detect_cpu()); #endif - self->client_info.size = sizeof(self->client_info); - self->client_info.version = CLIENT_INFO_CURRENT_VERSION; LOG_DEVEL(LOG_LEVEL_TRACE, "out xrdp_rdp_create"); return self; } diff --git a/xup/xup.c b/xup/xup.c index 5bcfcc13..de37fa7f 100644 --- a/xup/xup.c +++ b/xup/xup.c @@ -23,6 +23,7 @@ #endif #include "xup.h" +#include "xup_client_info.h" #include "log.h" #include "trans.h" #include "string_calls.h" @@ -188,6 +189,47 @@ wait_for_module_caps_message(struct mod *mod) return (mod->caps_processing_status == E_CAPS_OK) ? 0 : 1; } +/******************************************************************************/ +/* Convert the internal xrdp_client_info structure to an + * external xup_client_info structure */ +static void +convert_xrdp_client_info_to_xup_client_info( + const struct xrdp_client_info *src, + struct xup_client_info *dst) +{ + dst->size = sizeof(*dst); + dst->version = XUP_CLIENT_INFO_CURRENT_VERSION; + dst->bpp = src->bpp; + dst->jpeg = src->jpeg; + dst->offscreen_support_level = src->offscreen_support_level; + dst->offscreen_cache_size = src->offscreen_cache_size; + dst->offscreen_cache_entries = src->offscreen_cache_entries; + + memcpy(dst->orders, src->orders, XR_PRIMARY_ORDER_COUNT); + dst->order_flags_ex = src->order_flags_ex; + dst->pointer_flags = src->pointer_flags; + dst->large_pointer_support_flags = src->large_pointer_support_flags; + + dst->display_sizes = src->display_sizes; + + dst->capture_code = src->capture_code; + dst->capture_format = src->capture_format; + + memcpy(dst->model, src->model, CI_KBD_MODEL_SIZE); + memcpy(dst->layout, src->layout, CI_KBD_LAYOUT_SIZE); + memcpy(dst->variant, src->variant, CI_KBD_VARIANT_SIZE); + memcpy(dst->options, src->options, CI_KBD_OPTIONS_SIZE); + memcpy(dst->xkb_rules, src->xkb_rules, CI_KBD_XKB_RULES_SIZE); + + dst->x11_keycode_caps_lock = src->x11_keycode_caps_lock; + dst->x11_keycode_num_lock = src->x11_keycode_num_lock; + dst->x11_keycode_scroll_lock = src->x11_keycode_scroll_lock; + + dst->rfx_frame_interval = src->rfx_frame_interval; + dst->h264_frame_interval = src->h264_frame_interval; + dst->normal_frame_interval = src->normal_frame_interval; +} + /******************************************************************************/ /* return error */ static int @@ -195,14 +237,18 @@ lib_send_client_info(struct mod *mod) { struct stream *s; int len; + struct xup_client_info xup_client_info; LOG_DEVEL(LOG_LEVEL_TRACE, "lib_send_client_info:"); + + convert_xrdp_client_info_to_xup_client_info(&mod->client_info, + &xup_client_info); make_stream(s); - init_stream(s, 8192); + init_stream(s, (int)sizeof(xup_client_info) + 64); s_push_layer(s, iso_hdr, 4); out_uint16_le(s, 104); - g_memcpy(s->p, &(mod->client_info), sizeof(mod->client_info)); - s->p += sizeof(mod->client_info); + g_memcpy(s->p, &xup_client_info, sizeof(xup_client_info)); + s->p += sizeof(xup_client_info); s_mark_end(s); len = (int)(s->end - s->data); s_pop_layer(s, iso_hdr); @@ -1864,12 +1910,12 @@ lib_mod_process_message(struct mod *mod, struct stream *s) { case 100: in_uint32_le(s, version); - if (version != CLIENT_INFO_CURRENT_VERSION) + if (version != XUP_CLIENT_INFO_CURRENT_VERSION) { char msg[128]; g_snprintf(msg, sizeof(msg), "Xorg module has version %d, expected %d", - version, CLIENT_INFO_CURRENT_VERSION); + version, XUP_CLIENT_INFO_CURRENT_VERSION); LOG(LOG_LEVEL_ERROR, "%s", msg); mod->server_msg(mod, msg, 0); mod->caps_processing_status = E_CAPS_NOT_OK;