summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordaixj <daixj@shterm.com>2018-10-25 10:34:00 +0800
committerdaixj <daixj@shterm.com>2018-10-25 10:34:00 +0800
commitb3a188920087bbc0293ee4e61bf8eb8e03a1c752 (patch)
tree3975d0f73e48d16ac279a2ed1684025a4ab34444
parentc2ade7a1f7318527bd8cb5aedc4ed127c5546c94 (diff)
downloadxrdp-proprietary-b3a188920087bbc0293ee4e61bf8eb8e03a1c752.tar.gz
xrdp-proprietary-b3a188920087bbc0293ee4e61bf8eb8e03a1c752.zip
Support Cache Glyph Revison 2, issue #367
-rw-r--r--common/xrdp_client_info.h1
-rw-r--r--libxrdp/xrdp_caps.c30
-rw-r--r--libxrdp/xrdp_orders.c152
-rw-r--r--libxrdp/xrdp_rdp.c6
-rw-r--r--xrdp/xrdp.ini.in2
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
@@ -361,6 +361,33 @@ xrdp_caps_process_brushcache(struct xrdp_rdp *self, struct stream *s,
}
/*****************************************************************************/
+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,
int len)
@@ -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;
@@ -2488,6 +2488,150 @@ xrdp_orders_send_font(struct xrdp_orders *self,
/*****************************************************************************/
/* 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 */
int
xrdp_orders_send_raw_bitmap2(struct xrdp_orders *self,
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