diff --git a/proto.h b/proto.h index 9c0bb61..879b75e 100644 --- a/proto.h +++ b/proto.h @@ -157,6 +157,7 @@ BOOL get_key_state(unsigned int state, uint32 keysym); BOOL ui_init(void); void ui_deinit(void); BOOL ui_create_window(void); +void ui_resize_window(void); void ui_destroy_window(void); void xwin_toggle_fullscreen(void); int ui_select(int rdp_socket); diff --git a/rdp.c b/rdp.c index 488de50..ed2eef4 100644 --- a/rdp.c +++ b/rdp.c @@ -31,6 +31,8 @@ extern BOOL g_use_rdp5; extern uint16 g_server_rdp_version; extern uint32 g_rdp5_performanceflags; extern int g_server_bpp; +extern int g_width; +extern int g_height; uint8 *g_next_packet; uint32 g_rdp_shareid; @@ -368,7 +370,7 @@ rdp_send_fonts(uint16 seq) s = rdp_init_data(8); out_uint16(s, 0); /* number of fonts */ - out_uint16_le(s, 0x3e); /* unknown */ + out_uint16_le(s, 0); /* pad? */ out_uint16_le(s, seq); /* unknown */ out_uint16_le(s, 0x32); /* entry size */ @@ -416,7 +418,7 @@ rdp_out_bitmap_caps(STREAM s) out_uint16_le(s, 800); /* Desktop width */ out_uint16_le(s, 600); /* Desktop height */ out_uint16(s, 0); /* Pad */ - out_uint16(s, 0); /* Allow resize */ + out_uint16(s, 1); /* Allow resize */ out_uint16_le(s, g_bitmap_compression ? 1 : 0); /* Support compression */ out_uint16(s, 0); /* Unknown */ out_uint16_le(s, 1); /* Unknown */ @@ -613,43 +615,83 @@ rdp_send_confirm_active(void) sec_send(s, sec_flags); } +/* Process a general capability set */ +static void +rdp_process_general_caps(STREAM s) +{ + uint16 pad2octetsB; /* rdp5 flags? */ + + in_uint8s(s, 10); + in_uint16_le(s, pad2octetsB); + + if (!pad2octetsB) + g_use_rdp5 = False; +} + +/* Process a bitmap capability set */ +static void +rdp_process_bitmap_caps(STREAM s) +{ + uint16 width, height, bpp; + + in_uint16_le(s, bpp); + in_uint8s(s, 6); + + in_uint16_le(s, width); + in_uint16_le(s, height); + + DEBUG(("setting desktop size and bpp to: %dx%dx%d\n", width, height, bpp)); + + /* + * The server may limit bpp and change the size of the desktop (for + * example when shadowing another session). + */ + g_server_bpp = bpp; + g_width = width; + g_height = height; + + ui_resize_window(); +} + /* Respond to a demand active PDU */ static void process_demand_active(STREAM s) { - uint8 type; - uint16 i; - uint16 p_bpp; + int n; + uint8 type, *next; + uint16 len_src_descriptor, len_combined_caps, num_capsets, capset_type, capset_length; in_uint32_le(s, g_rdp_shareid); + in_uint16_le(s, len_src_descriptor); + in_uint16_le(s, len_combined_caps); + in_uint8s(s, len_src_descriptor); - /* scan for prefered bpp */ - while (s_check_rem(s, 6)) + in_uint16_le(s, num_capsets); + in_uint8s(s, 2); /* pad */ + + DEBUG(("DEMAND_ACTIVE(id=0x%x,num_caps=%d)\n", g_rdp_shareid, num_capsets)); + + for (n = 0; n < num_capsets; n++) { - in_uint16_le(s, i); - if (i == RDP_CAPSET_BITMAP) + in_uint16_le(s, capset_type); + in_uint16_le(s, capset_length); + + next = s->p + capset_length - 4; + + switch (capset_type) { - in_uint16_le(s, i); - if (i == RDP_CAPLEN_BITMAP) - { - in_uint16_le(s, p_bpp); - if (p_bpp == 8 || p_bpp == 15 || p_bpp == 16 || p_bpp == 24) - { - if (p_bpp < g_server_bpp) - { - warning("Server limited colour depth to %d bits\n", - p_bpp); - g_server_bpp = p_bpp; - } - break; - } - } + case RDP_CAPSET_GENERAL: + rdp_process_general_caps(s); + break; + + case RDP_CAPSET_BITMAP: + rdp_process_bitmap_caps(s); + break; } + + s->p = next; } - - DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", g_rdp_shareid)); - rdp_send_confirm_active(); rdp_send_synchronise(); rdp_send_control(RDP_CTL_COOPERATE); @@ -658,9 +700,18 @@ process_demand_active(STREAM s) rdp_recv(&type); /* RDP_CTL_COOPERATE */ rdp_recv(&type); /* RDP_CTL_GRANT_CONTROL */ rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, ui_get_numlock_state(read_keyboard_state()), 0); - rdp_send_fonts(1); - rdp_send_fonts(2); - rdp_recv(&type); /* RDP_PDU_UNKNOWN 0x28 */ + + if (g_use_rdp5) + { + rdp_send_fonts(3); + } + else + { + rdp_send_fonts(1); + rdp_send_fonts(2); + } + + rdp_recv(&type); /* RDP_PDU_UNKNOWN 0x28 (Fonts?) */ reset_order_state(); } @@ -997,6 +1048,7 @@ rdp_main_loop(BOOL * deactivated, uint32 * ext_disc_reason) break; case RDP_PDU_DEACTIVATE: + DEBUG(("RDP_PDU_DEACTIVATE\n")); *deactivated = True; break; diff --git a/secure.c b/secure.c index bc49647..7c9136f 100644 --- a/secure.c +++ b/secure.c @@ -449,22 +449,7 @@ sec_out_mcs_data(STREAM s) out_uint32(s, 0); out_uint32_le(s, 12); out_uint8s(s, 64); /* reserved? 4 + 12 doublewords */ - - switch (g_server_bpp) - { - case 8: - out_uint16_le(s, 0xca01); - break; - case 15: - out_uint16_le(s, 0xca02); - break; - case 16: - out_uint16_le(s, 0xca03); - break; - case 24: - out_uint16_le(s, 0xca04); - break; - } + out_uint16_le(s, 0xca01); /* colour depth? */ out_uint16_le(s, 1); out_uint32(s, 0); @@ -771,7 +756,10 @@ sec_process_srv_info(STREAM s) in_uint16_le(s, g_server_rdp_version); DEBUG_RDP5(("Server RDP version is %d\n", g_server_rdp_version)); if (1 == g_server_rdp_version) + { g_use_rdp5 = 0; + g_server_bpp = 8; + } } diff --git a/xwin.c b/xwin.c index 4a1dba2..f955346 100644 --- a/xwin.c +++ b/xwin.c @@ -1008,6 +1008,27 @@ ui_create_window(void) return True; } +void +ui_resize_window() +{ + XSizeHints *sizehints; + + sizehints = XAllocSizeHints(); + if (sizehints) + { + sizehints->flags = PMinSize | PMaxSize; + sizehints->min_width = sizehints->max_width = g_width; + sizehints->min_height = sizehints->max_height = g_height; + XSetWMNormalHints(g_display, g_wnd, sizehints); + XFree(sizehints); + } + + if (!(g_fullscreen || g_embed_wnd)) + { + XResizeWindow(g_display, g_wnd, g_width, g_height); + } +} + void ui_destroy_window(void) {