diff --git a/common/xrdp_client_info.h b/common/xrdp_client_info.h index bf296404..e1879cef 100644 --- a/common/xrdp_client_info.h +++ b/common/xrdp_client_info.h @@ -80,8 +80,16 @@ struct xrdp_client_info int wnd_support_level; int wnd_num_icon_caches; int wnd_num_icon_cache_entries; - /* remotefx codec */ + /* codecs */ int rfx_codec_id; + int rfx_prop_len; + char rfx_prop[64]; + int ns_codec_id; + int ns_prop_len; + char ns_prop[64]; + int jpeg_codec_id; + int jpeg_prop_len; + char jpeg_prop[64]; }; #endif diff --git a/common/xrdp_constants.h b/common/xrdp_constants.h index c9e39ae8..7d31326e 100644 --- a/common/xrdp_constants.h +++ b/common/xrdp_constants.h @@ -508,8 +508,12 @@ #define SURCMDS_FRAMEMARKER 0x00000010 #define SURCMDS_STREAMSUFRACEBITS 0x00000040 +/* CODEC_GUID_NSCODEC 0xCA8D1BB9000F154F589FAE2D1A87E2D6 */ +#define XR_CODEC_GUID_NSCODEC \ + "\xb9\x1b\x8d\xca\x0f\x00\x4f\x15\x58\x9f\xae\x2d\x1a\x87\xe2\xd6" + /* CODEC_GUID_REMOTEFX 0x76772F12BD724463AFB3B73C9C6F7886 */ -#define CODEC_GUID_REMOTEFX \ +#define XR_CODEC_GUID_REMOTEFX \ "\x12\x2F\x77\x76\x72\xBD\x63\x44\xAF\xB3\xB7\x3C\x9C\x6F\x78\x86" #define RDP_CAPSET_SURFCMDS 0x1c diff --git a/libxrdp/xrdp_rdp.c b/libxrdp/xrdp_rdp.c index 07dc1023..f25108f0 100644 --- a/libxrdp/xrdp_rdp.c +++ b/libxrdp/xrdp_rdp.c @@ -684,8 +684,18 @@ xrdp_rdp_send_demand_active(struct xrdp_rdp* self) /* Output bmpcodecs capability set */ caps_count++; out_uint16_le(s, RDP_CAPSET_BMPCODECS); - out_uint16_le(s, 5); - out_uint8(s, 0); /* bitmapCodecCount (freerdp hack) TODO: list codecs here */ + out_uint16_le(s, 302); /* cap len */ + out_uint8(s, 2); /* bitmapCodecCount */ + out_uint8a(s, XR_CODEC_GUID_NSCODEC, 16); + out_uint8(s, 1); /* codec id */ + out_uint16_le(s, 3); + out_uint8(s, 0x01); /* fAllowDynamicFidelity */ + out_uint8(s, 0x01); /* fAllowSubsampling */ + out_uint8(s, 0x03); /* colorLossLevel */ + out_uint8a(s, XR_CODEC_GUID_REMOTEFX, 16); + out_uint8(s, 0); /* codec id */ + out_uint16_le(s, 256); + out_uint8s(s, 256); /* Output color cache capability set */ caps_count++; @@ -988,6 +998,48 @@ xrdp_process_capset_window(struct xrdp_rdp* self, struct stream* s, int len) return 0; } +/*****************************************************************************/ +static int APP_CC +xrdp_process_capset_codecs(struct xrdp_rdp* self, struct stream* s, int len) +{ + int codec_id; + int codec_count; + int index; + int codec_properties_length; + int i1; + char* codec_guid; + char* next_guid; + + in_uint8(s, codec_count); + for (index = 0; index < codec_count; index++) + { + codec_guid = s->p; + in_uint8s(s, 16); + in_uint8(s, codec_id); + in_uint16_le(s, codec_properties_length); + next_guid = s->p + codec_properties_length; + if (g_memcmp(codec_guid, XR_CODEC_GUID_NSCODEC, 16) == 0) + { + g_writeln("xrdp_process_capset_codecs: nscodec codec id %d prop len %d", + codec_id, codec_properties_length); + self->client_info.ns_codec_id = codec_id; + i1 = MIN(64, codec_properties_length); + g_memcpy(self->client_info.ns_prop, s->p, i1); + self->client_info.ns_prop_len = i1; + } + else if (g_memcmp(codec_guid, XR_CODEC_GUID_REMOTEFX, 16) == 0) + { + g_writeln("xrdp_process_capset_codecs: rfx codec id %d prop len %d", + codec_id, codec_properties_length); + self->client_info.rfx_codec_id = codec_id; + i1 = MIN(64, codec_properties_length); + g_memcpy(self->client_info.rfx_prop, s->p, i1); + self->client_info.rfx_prop_len = i1; + } + s->p = next_guid; + } +} + /*****************************************************************************/ int APP_CC xrdp_rdp_process_confirm_active(struct xrdp_rdp* self, struct stream* s) @@ -1087,6 +1139,9 @@ xrdp_rdp_process_confirm_active(struct xrdp_rdp* self, struct stream* s) case 26: /* 26 */ DEBUG(("--26")); break; + case RDP_CAPSET_BMPCODECS: /* 0x1d(29) */ + xrdp_process_capset_codecs(self, s, len); + break; default: g_writeln("unknown in xrdp_rdp_process_confirm_active %d", type); break;