diff --git a/constants.h b/constants.h index 7dcb6cc..0b088b9 100644 --- a/constants.h +++ b/constants.h @@ -256,8 +256,9 @@ enum RDP_INPUT_DEVICE /* Logon flags */ #define RDP_LOGON_AUTO 0x0008 #define RDP_LOGON_NORMAL 0x0033 -#define RDP_COMPRESSION 0x0080 +#define RDP_LOGON_COMPRESSION 0x0080 /* mppc compression with 8kB histroy buffer */ #define RDP_LOGON_BLOB 0x0100 +#define RDP_LOGON_COMPRESSION2 0x0200 /* rdp5 mppc compression with 64kB history buffer */ #define RDP_LOGON_LEAVE_AUDIO 0x2000 #define RDP5_DISABLE_NOTHING 0x00 @@ -269,10 +270,13 @@ enum RDP_INPUT_DEVICE #define RDP5_NO_CURSORSETTINGS 0x40 /* disables cursor blinking */ /* compression types */ +#define RDP_MPPC_BIG 0x01 #define RDP_MPPC_COMPRESSED 0x20 #define RDP_MPPC_RESET 0x40 #define RDP_MPPC_FLUSH 0x80 -#define RDP_MPPC_DICT_SIZE 8192 +#define RDP_MPPC_DICT_SIZE 65536 + +#define RDP5_COMPRESSED 0x80 /* Keymap flags */ #define MapRightShiftMask (1<<0) diff --git a/mppc.c b/mppc.c index e0facfa..9b263a3 100644 --- a/mppc.c +++ b/mppc.c @@ -155,60 +155,131 @@ mppc_expand(uint8 * data, uint32 clen, uint8 ctype, uint32 * roff, uint32 * rlen /* decode offset */ /* length pair */ walker <<= 1; - if (--walker_len < 2) + if (--walker_len < (ctype & RDP_MPPC_BIG ? 3 : 2)) { if (i >= clen) return -1; walker |= (data[i++] & 0xff) << (24 - walker_len); walker_len += 8; } - /* offset decoding where offset len is: - -63: 1111 followed by the lower 6 bits of the value - 64-319: 1110 followed by the lower 8 bits of the value ( value - 64 ) - 320-8191: 110 followed by the lower 13 bits of the value ( value - 320 ) - */ - switch (((uint32) walker) >> ((uint32) 30)) + + if (ctype & RDP_MPPC_BIG) { - case 3: /* - 63 */ - if (walker_len < 8) - { - if (i >= clen) - return -1; - walker |= (data[i++] & 0xff) << (24 - walker_len); - walker_len += 8; - } - walker <<= 2; - match_off = ((uint32) walker) >> ((uint32) 26); - walker <<= 6; - walker_len -= 8; - break; + /* offset decoding where offset len is: + -63: 11111 followed by the lower 6 bits of the value + 64-319: 11110 followed by the lower 8 bits of the value ( value - 64 ) + 320-2367: 1110 followed by lower 11 bits of the value ( value - 320 ) + 2368-65535: 110 followed by lower 16 bits of the value ( value - 2368 ) + */ + switch (((uint32) walker) >> ((uint32) 29)) + { + case 7: /* - 63 */ + for (; walker_len < 9; walker_len += 8) + { + if (i >= clen) + return -1; + walker |= (data[i++] & 0xff) << (24 - walker_len); + } + walker <<= 3; + match_off = ((uint32) walker) >> ((uint32) 26); + walker <<= 6; + walker_len -= 9; + break; - case 2: /* 64 - 319 */ - for (; walker_len < 10; walker_len += 8) - { - if (i >= clen) - return -1; - walker |= (data[i++] & 0xff) << (24 - walker_len); - } + case 6: /* 64 - 319 */ + for (; walker_len < 11; walker_len += 8) + { + if (i >= clen) + return -1; + walker |= (data[i++] & 0xff) << (24 - walker_len); + } - walker <<= 2; - match_off = (((uint32) walker) >> ((uint32) 24)) + 64; - walker <<= 8; - walker_len -= 10; - break; + walker <<= 3; + match_off = (((uint32) walker) >> ((uint32) 24)) + 64; + walker <<= 8; + walker_len -= 11; + break; - default: /* 320 - 8191 */ - for (; walker_len < 14; walker_len += 8) - { - if (i >= clen) - return -1; - walker |= (data[i++] & 0xff) << (24 - walker_len); - } + case 5: + case 4: /* 320 - 2367 */ + for (; walker_len < 13; walker_len += 8) + { + if (i >= clen) + return -1; + walker |= (data[i++] & 0xff) << (24 - walker_len); + } - match_off = (walker >> 18) + 320; - walker <<= 14; - walker_len -= 14; - break; + walker <<= 2; + match_off = (((uint32) walker) >> ((uint32) 21)) + 320; + walker <<= 11; + walker_len -= 13; + break; + + default: /* 2368 - 65535 */ + for (; walker_len < 17; walker_len += 8) + { + if (i >= clen) + return -1; + walker |= (data[i++] & 0xff) << (24 - walker_len); + } + + walker <<= 1; + match_off = (((uint32) walker) >> ((uint32) 16)) + 2368; + walker <<= 16; + walker_len -= 17; + break; + } + } + else + { + /* offset decoding where offset len is: + -63: 1111 followed by the lower 6 bits of the value + 64-319: 1110 followed by the lower 8 bits of the value ( value - 64 ) + 320-8191: 110 followed by the lower 13 bits of the value ( value - 320 ) + */ + switch (((uint32) walker) >> ((uint32) 30)) + { + case 3: /* - 63 */ + if (walker_len < 8) + { + if (i >= clen) + return -1; + walker |= (data[i++] & 0xff) << (24 - walker_len); + walker_len += 8; + } + walker <<= 2; + match_off = ((uint32) walker) >> ((uint32) 26); + walker <<= 6; + walker_len -= 8; + break; + + case 2: /* 64 - 319 */ + for (; walker_len < 10; walker_len += 8) + { + if (i >= clen) + return -1; + walker |= (data[i++] & 0xff) << (24 - walker_len); + } + + walker <<= 2; + match_off = (((uint32) walker) >> ((uint32) 24)) + 64; + walker <<= 8; + walker_len -= 10; + break; + + default: /* 320 - 8191 */ + for (; walker_len < 14; walker_len += 8) + { + if (i >= clen) + return -1; + walker |= (data[i++] & 0xff) << (24 - walker_len); + } + + match_off = (walker >> 18) + 320; + walker <<= 14; + walker_len -= 14; + break; + } } if (walker_len == 0) { @@ -289,7 +360,7 @@ mppc_expand(uint8 * data, uint32 clen, uint8 ctype, uint32 * roff, uint32 * rlen return -1; } /* memory areas can overlap - meaning we can't use memXXX functions */ - k = (next_offset - match_off) & (RDP_MPPC_DICT_SIZE - 1); + k = (next_offset - match_off) & (ctype & RDP_MPPC_BIG ? 65535 : 8191); do { dict[next_offset++] = dict[k++]; diff --git a/rdesktop.c b/rdesktop.c index aa3df35..173667f 100644 --- a/rdesktop.c +++ b/rdesktop.c @@ -85,7 +85,6 @@ BOOL g_console_session = False; BOOL g_numlock_sync = False; BOOL g_owncolmap = False; BOOL g_ownbackstore = True; /* We can't rely on external BackingStore */ -BOOL g_rdp_compression = False; uint32 g_embed_wnd; uint32 g_rdp5_performanceflags = RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG | RDP5_NO_MENUANIMATIONS; @@ -575,8 +574,7 @@ main(int argc, char *argv[]) case 'z': DEBUG(("rdp compression enabled\n")); - flags |= RDP_COMPRESSION; - g_rdp_compression = True; + flags |= (RDP_LOGON_COMPRESSION | RDP_LOGON_COMPRESSION2); break; case 'x': diff --git a/rdp.c b/rdp.c index 8c41bd2..cc3304a 100644 --- a/rdp.c +++ b/rdp.c @@ -298,12 +298,6 @@ rdp_send_logon_info(uint32 flags, char *domain, char *user, time_t t = time(NULL); time_t tzone; -#if 0 - /* enable rdp compression */ - /* some problems still exist with rdp5 */ - flags |= RDP_COMPRESSION; -#endif - if (!g_use_rdp5 || 1 == g_server_rdp_version) { DEBUG_RDP5(("Sending RDP4-style Logon packet\n")); @@ -660,34 +654,14 @@ rdp_out_bmpcache_caps(STREAM s) static void rdp_out_bmpcache2_caps(STREAM s) { - uint16 cellsize; - out_uint16_le(s, RDP_CAPSET_BMPCACHE2); out_uint16_le(s, RDP_CAPLEN_BMPCACHE2); out_uint16_le(s, g_bitmap_cache_persist_enable ? 2 : 0); /* version */ - /* Cellsize: - 01 = 16x16, 02 = 32x32, 03 = 64x64 - log2(cell size) - 3 - */ - - cellsize = 0x03; - - if (g_rdp_compression) - { - switch (g_server_bpp) - { - case 24: - case 16: - case 15: - cellsize = 0x02; - break; - } - } - - out_uint16_le(s, (0x0000 | (cellsize << 8))); /* flags? number of caches? */ + out_uint16_be(s, 3); /* number of caches in this set */ + /* max cell size for cache 0 is 16x16, 1 = 32x32, 2 = 64x64, etc */ out_uint32_le(s, BMPCACHE2_C0_CELLS); out_uint32_le(s, BMPCACHE2_C1_CELLS); if (pstcache_init(2)) diff --git a/rdp5.c b/rdp5.c index 554214b..6d08ba0 100644 --- a/rdp5.c +++ b/rdp5.c @@ -45,11 +45,11 @@ rdp5_process(STREAM s) while (s->p < s->end) { in_uint8(s, type); - if (type & RDP_COMPRESSION) + if (type & RDP5_COMPRESSED) { in_uint8(s, ctype); in_uint16_le(s, length); - type ^= RDP_COMPRESSION; + type ^= RDP5_COMPRESSED; } else { @@ -60,8 +60,6 @@ rdp5_process(STREAM s) if (ctype & RDP_MPPC_COMPRESSED) { - if (length > RDP_MPPC_DICT_SIZE) - error("error decompressed packet size exceeds max\n"); if (mppc_expand(s->p, length, ctype, &roff, &rlen) == -1) error("error while decompressing packet\n");