From b3a188920087bbc0293ee4e61bf8eb8e03a1c752 Mon Sep 17 00:00:00 2001 From: daixj Date: Thu, 25 Oct 2018 10:34:00 +0800 Subject: [PATCH 1/2] Support Cache Glyph Revison 2, issue #367 --- common/xrdp_client_info.h | 1 + libxrdp/xrdp_caps.c | 30 +++++++- libxrdp/xrdp_orders.c | 152 +++++++++++++++++++++++++++++++++++++- libxrdp/xrdp_rdp.c | 6 +- xrdp/xrdp.ini.in | 2 + 5 files changed, 185 insertions(+), 6 deletions(-) diff --git a/common/xrdp_client_info.h b/common/xrdp_client_info.h index e8e91da4..b57b1949 100644 --- a/common/xrdp_client_info.h +++ b/common/xrdp_client_info.h @@ -154,6 +154,7 @@ struct xrdp_client_info int client_os_minor; int no_orders_supported; + int use_cache_glyph_v2; }; #endif diff --git a/libxrdp/xrdp_caps.c b/libxrdp/xrdp_caps.c index dddf6d23..46810c18 100644 --- a/libxrdp/xrdp_caps.c +++ b/libxrdp/xrdp_caps.c @@ -360,6 +360,33 @@ xrdp_caps_process_brushcache(struct xrdp_rdp *self, struct stream *s, return 0; } +/*****************************************************************************/ +static int +xrdp_caps_process_glyphcache(struct xrdp_rdp *self, struct stream *s, + int len) +{ + int glyph_support_level; + + if (len < 40 + 4 + 2 + 2) + { + g_writeln("xrdp_caps_process_glyphcache: error"); + return 1; + } + + in_uint8s(s, 40); /* glyph cache */ + in_uint8s(s, 4); /* frag cache */ + in_uint16_le(s, glyph_support_level); + in_uint8s(s, 2); /* pad */ + + if (self->client_info.use_cache_glyph_v2 && (glyph_support_level != 3)) + { + self->client_info.use_cache_glyph_v2 = 0; + } + g_writeln("xrdp_caps_process_glyphcache: support level %d ", + glyph_support_level); + return 0; +} + /*****************************************************************************/ int xrdp_caps_process_offscreen_bmpcache(struct xrdp_rdp *self, struct stream *s, @@ -657,7 +684,8 @@ xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s) xrdp_caps_process_brushcache(self, s, len); break; case RDP_CAPSET_GLYPHCACHE: - DEBUG(("--0x11")); + DEBUG(("RDP_CAPSET_GLYPHCACHE")); + xrdp_caps_process_glyphcache(self, s, len); break; case RDP_CAPSET_OFFSCREENCACHE: DEBUG(("CAPSET_TYPE_OFFSCREEN_CACHE")); diff --git a/libxrdp/xrdp_orders.c b/libxrdp/xrdp_orders.c index 52d043c9..5790a675 100644 --- a/libxrdp/xrdp_orders.c +++ b/libxrdp/xrdp_orders.c @@ -2444,10 +2444,10 @@ xrdp_orders_send_bitmap(struct xrdp_orders *self, /* returns error */ /* max size datasize + 18*/ /* todo, only sends one for now */ -int -xrdp_orders_send_font(struct xrdp_orders *self, - struct xrdp_font_char *font_char, - int font_index, int char_index) +static int +xrdp_orders_cache_glyph(struct xrdp_orders *self, + struct xrdp_font_char *font_char, + int font_index, int char_index) { int order_flags = 0; int datasize = 0; @@ -2486,6 +2486,150 @@ xrdp_orders_send_font(struct xrdp_orders *self, return 0; } +/*****************************************************************************/ +/* returns error */ +static int write_2byte_signed(struct stream * s, int value) +{ + unsigned char byte; + int negative = 0; + + if (value < 0) + { + negative = 1; + value *= -1; + } + + if (value > 0x3FFF) + { + return 1; + } + + if (value >= 0x3F) + { + byte = ((value & 0x3F00) >> 8); + + if (negative) + { + byte |= 0x40; + } + + out_uint8(s, byte | 0x80); + byte = (value & 0xFF); + out_uint8(s, byte); + } + else + { + byte = (value & 0x3F); + + if (negative) + { + byte |= 0x40; + } + + out_uint8(s, byte); + } + + return 0; +} + +/*****************************************************************************/ +/* returns error */ +static int write_2byte_unsigned(struct stream * s, unsigned int value) +{ + unsigned char byte; + + if (value > 0x7FFF) + { + return 1; + } + + if (value >= 0x7F) + { + byte = ((value & 0x7F00) >> 8); + out_uint8(s, byte | 0x80); + byte = (value & 0xFF); + out_uint8(s, byte); + } + else + { + byte = (value & 0x7F); + out_uint8(s, byte); + } + + return 0; +} + +/*****************************************************************************/ +/* returns error */ +/* max size datasize + 15*/ +/* todo, only sends one for now */ +static int +xrdp_orders_cache_glyph_v2(struct xrdp_orders *self, + struct xrdp_font_char *font_char, + int font_index, int char_index) +{ + int order_flags = 0; + int datasize = 0; + int len = 0; + int extra_flags; + char *len_ptr; + + if (font_char->bpp == 8) /* alpha font */ + { + datasize = ((font_char->width + 3) & ~3) * font_char->height; + } + else + { + datasize = FONT_DATASIZE(font_char); + } + + /* cacheId, flags(GLYPH_ORDER_REV2), cGlyphs */ + extra_flags = (font_index & 0x000F) | (0x2 << 4) | (1 << 8); + + if (xrdp_orders_check(self, datasize + 15) != 0) + { + return 1; + } + self->order_count++; + order_flags = RDP_ORDER_STANDARD | RDP_ORDER_SECONDARY; + out_uint8(self->out_s, order_flags); + len_ptr = self->out_s->p; + out_uint16_le(self->out_s, 0); /* set later */ + out_uint16_le(self->out_s, extra_flags); + out_uint8(self->out_s, RDP_ORDER_FONTCACHE); /* type */ + + out_uint8(self->out_s, char_index); + if (write_2byte_signed(self->out_s, font_char->offset) || + write_2byte_signed(self->out_s, font_char->baseline) || + write_2byte_unsigned(self->out_s, font_char->width) || + write_2byte_unsigned(self->out_s, font_char->height)) + { + return 1; + } + + out_uint8a(self->out_s, font_char->data, datasize); + len = (self->out_s->p - len_ptr) + 1 - 13; + len_ptr[0] = len & 0xFF; + len_ptr[1] = (len >> 8) & 0xFF; + + return 0; +} + +/*****************************************************************************/ +/* returns error */ +int +xrdp_orders_send_font(struct xrdp_orders *self, + struct xrdp_font_char *font_char, + int font_index, int char_index) +{ + if (self->rdp_layer->client_info.use_cache_glyph_v2) + { + return xrdp_orders_cache_glyph_v2(self, font_char, font_index, char_index); + } + + return xrdp_orders_cache_glyph(self, font_char, font_index, char_index); +} + /*****************************************************************************/ /* returns error */ /* max size width * height * Bpp + 14 */ diff --git a/libxrdp/xrdp_rdp.c b/libxrdp/xrdp_rdp.c index 494d23e8..928c1610 100644 --- a/libxrdp/xrdp_rdp.c +++ b/libxrdp/xrdp_rdp.c @@ -269,12 +269,16 @@ xrdp_rdp_read_config(struct xrdp_client_info *client_info) g_strncpy(client_info->key_file, value, 1023); } - if (!g_file_readable(client_info->key_file)) + if (!g_file_readable(client_info->key_file)) { log_message(LOG_LEVEL_ERROR, "Cannot read private key file %s: %s", client_info->key_file, g_get_strerror()); } } + else if (g_strcasecmp(item, "use_cache_glyph_v2") == 0) + { + client_info->use_cache_glyph_v2 = g_text2bool(value); + } } diff --git a/xrdp/xrdp.ini.in b/xrdp/xrdp.ini.in index c73e271c..0b24012d 100644 --- a/xrdp/xrdp.ini.in +++ b/xrdp/xrdp.ini.in @@ -53,6 +53,8 @@ use_fastpath=both #require_credentials=true ; You can set the PAM error text in a gateway setup (MAX 256 chars) #pamerrortxt=change your password according to policy at http://url +; Cache Glyph Revison 2. default: false +use_cache_glyph_v2=true ; ; colors used by windows in RGB format From bc150c2e56245ec3637d59915600fc65bc3c83a7 Mon Sep 17 00:00:00 2001 From: daixj Date: Thu, 25 Oct 2018 17:02:43 +0800 Subject: [PATCH 2/2] set use_cache_glyph_v2 on if the client support --- libxrdp/xrdp_caps.c | 6 +++--- libxrdp/xrdp_rdp.c | 4 ---- xrdp/xrdp.ini.in | 2 -- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/libxrdp/xrdp_caps.c b/libxrdp/xrdp_caps.c index 46810c18..ff9b4484 100644 --- a/libxrdp/xrdp_caps.c +++ b/libxrdp/xrdp_caps.c @@ -367,7 +367,7 @@ xrdp_caps_process_glyphcache(struct xrdp_rdp *self, struct stream *s, { int glyph_support_level; - if (len < 40 + 4 + 2 + 2) + if (len < 40 + 4 + 2 + 2) /* MS-RDPBCGR 2.2.7.1.8 */ { g_writeln("xrdp_caps_process_glyphcache: error"); return 1; @@ -378,9 +378,9 @@ xrdp_caps_process_glyphcache(struct xrdp_rdp *self, struct stream *s, in_uint16_le(s, glyph_support_level); in_uint8s(s, 2); /* pad */ - if (self->client_info.use_cache_glyph_v2 && (glyph_support_level != 3)) + if (glyph_support_level == GLYPH_SUPPORT_ENCODE) { - self->client_info.use_cache_glyph_v2 = 0; + self->client_info.use_cache_glyph_v2 = 1; } g_writeln("xrdp_caps_process_glyphcache: support level %d ", glyph_support_level); diff --git a/libxrdp/xrdp_rdp.c b/libxrdp/xrdp_rdp.c index 928c1610..ff099da9 100644 --- a/libxrdp/xrdp_rdp.c +++ b/libxrdp/xrdp_rdp.c @@ -275,10 +275,6 @@ xrdp_rdp_read_config(struct xrdp_client_info *client_info) client_info->key_file, g_get_strerror()); } } - else if (g_strcasecmp(item, "use_cache_glyph_v2") == 0) - { - client_info->use_cache_glyph_v2 = g_text2bool(value); - } } diff --git a/xrdp/xrdp.ini.in b/xrdp/xrdp.ini.in index 0b24012d..c73e271c 100644 --- a/xrdp/xrdp.ini.in +++ b/xrdp/xrdp.ini.in @@ -53,8 +53,6 @@ use_fastpath=both #require_credentials=true ; You can set the PAM error text in a gateway setup (MAX 256 chars) #pamerrortxt=change your password according to policy at http://url -; Cache Glyph Revison 2. default: false -use_cache_glyph_v2=true ; ; colors used by windows in RGB format