--- sourceforge.net/trunk/rdesktop/rdp.c 2005/04/03 18:08:05 879 +++ sourceforge.net/trunk/rdesktop/rdp.c 2006/04/07 14:41:34 1217 @@ -44,17 +44,28 @@ extern BOOL g_use_rdp5; extern uint16 g_server_rdp_version; extern uint32 g_rdp5_performanceflags; -extern int g_server_bpp; +extern int g_server_depth; extern int g_width; extern int g_height; extern BOOL g_bitmap_cache; extern BOOL g_bitmap_cache_persist_enable; +extern BOOL g_numlock_sync; uint8 *g_next_packet; uint32 g_rdp_shareid; extern RDPCOMP g_mppc_dict; +/* Session Directory support */ +extern BOOL g_redirect; +extern char g_redirect_server[64]; +extern char g_redirect_domain[16]; +extern char g_redirect_password[64]; +extern char g_redirect_username[64]; +extern char g_redirect_cookie[128]; +extern uint32 g_redirect_flags; +/* END Session Directory support */ + #if WITH_DEBUG static uint32 g_packetno; #endif @@ -71,7 +82,7 @@ uint16 length, pdu_type; uint8 rdpver; - if ((rdp_s == NULL) || (g_next_packet >= rdp_s->end)) + if ((rdp_s == NULL) || (g_next_packet >= rdp_s->end) || (g_next_packet == NULL)) { rdp_s = sec_recv(&rdpver); if (rdp_s == NULL) @@ -260,6 +271,10 @@ g_iconv_works = False; return rdp_in_unistr(s, string, uni_len); } + + /* we must update the location of the current STREAM for future reads of s->p */ + s->p += uni_len; + return pout - string; } else @@ -297,12 +312,6 @@ 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")); @@ -487,7 +496,38 @@ rdp_send_data(s, RDP_DATA_PDU_INPUT); } -/* Inform the server on the contents of the persistent bitmap cache */ +/* Send a client window information PDU */ +void +rdp_send_client_window_status(int status) +{ + STREAM s; + static int current_status = 1; + + if (current_status == status) + return; + + s = rdp_init_data(12); + + out_uint32_le(s, status); + + switch (status) + { + case 0: /* shut the server up */ + break; + + case 1: /* receive data again */ + out_uint32_le(s, 0); /* unknown */ + out_uint16_le(s, g_width); + out_uint16_le(s, g_height); + break; + } + + s_mark_end(s); + rdp_send_data(s, RDP_DATA_PDU_CLIENT_WINDOW_STATUS); + current_status = status; +} + +/* Send persistent bitmap cache enumeration PDU's */ static void rdp_enum_bmpcache2(void) { @@ -581,7 +621,7 @@ out_uint16_le(s, RDP_CAPSET_BITMAP); out_uint16_le(s, RDP_CAPLEN_BITMAP); - out_uint16_le(s, g_server_bpp); /* Preferred BPP */ + out_uint16_le(s, g_server_depth); /* Preferred colour depth */ out_uint16_le(s, 1); /* Receive 1 BPP */ out_uint16_le(s, 1); /* Receive 4 BPP */ out_uint16_le(s, 1); /* Receive 8 BPP */ @@ -645,7 +685,7 @@ out_uint16_le(s, RDP_CAPSET_BMPCACHE); out_uint16_le(s, RDP_CAPLEN_BMPCACHE); - Bpp = (g_server_bpp + 7) / 8; + Bpp = (g_server_depth + 7) / 8; /* bytes per pixel */ out_uint8s(s, 24); /* unused */ out_uint16_le(s, 0x258); /* entries */ out_uint16_le(s, 0x100 * Bpp); /* max cell size */ @@ -664,8 +704,9 @@ out_uint16_le(s, g_bitmap_cache_persist_enable ? 2 : 0); /* version */ - out_uint16_le(s, 0x0300); /* 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)) @@ -841,28 +882,29 @@ static void rdp_process_bitmap_caps(STREAM s) { - uint16 width, height, bpp; + uint16 width, height, depth; - in_uint16_le(s, bpp); + in_uint16_le(s, depth); 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)); + DEBUG(("setting desktop size and depth to: %dx%dx%d\n", width, height, depth)); /* - * The server may limit bpp and change the size of the desktop (for + * The server may limit depth and change the size of the desktop (for * example when shadowing another session). */ - if (g_server_bpp != bpp) + if (g_server_depth != depth) { - warning("colour depth changed from %d to %d\n", g_server_bpp, bpp); - g_server_bpp = bpp; + warning("Remote desktop does not support colour depth %d; falling back to %d\n", + g_server_depth, depth); + g_server_depth = depth; } if (g_width != width || g_height != height) { - warning("screen size changed from %dx%d to %dx%d\n", g_width, g_height, + warning("Remote desktop changed from %dx%d to %dx%d.\n", g_width, g_height, width, height); g_width = width; g_height = height; @@ -871,7 +913,7 @@ } /* Process server capabilities */ -void +static void rdp_process_server_caps(STREAM s, uint16 length) { int n; @@ -930,7 +972,8 @@ rdp_recv(&type); /* RDP_PDU_SYNCHRONIZE */ 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_input(0, RDP_INPUT_SYNCHRONIZE, 0, + g_numlock_sync ? ui_get_numlock_state(read_keyboard_state()) : 0, 0); if (g_use_rdp5) { @@ -1258,6 +1301,54 @@ return False; } +/* Process redirect PDU from Session Directory */ +static BOOL +process_redirect_pdu(STREAM s /*, uint32 * ext_disc_reason */ ) +{ + uint32 len; + + /* these 2 bytes are unknown, seem to be zeros */ + in_uint8s(s, 2); + + /* read connection flags */ + in_uint32_le(s, g_redirect_flags); + + /* read length of ip string */ + in_uint32_le(s, len); + + /* read ip string */ + rdp_in_unistr(s, g_redirect_server, len); + + /* read length of cookie string */ + in_uint32_le(s, len); + + /* read cookie string (plain ASCII) */ + in_uint8a(s, g_redirect_cookie, len); + g_redirect_cookie[len] = 0; + + /* read length of username string */ + in_uint32_le(s, len); + + /* read username string */ + rdp_in_unistr(s, g_redirect_username, len); + + /* read length of domain string */ + in_uint32_le(s, len); + + /* read domain string */ + rdp_in_unistr(s, g_redirect_domain, len); + + /* read length of password string */ + in_uint32_le(s, len); + + /* read password string */ + rdp_in_unistr(s, g_redirect_password, len); + + g_redirect = True; + + return True; +} + /* Process incoming packets */ /* nevers gets out of here till app is done */ void @@ -1291,6 +1382,9 @@ DEBUG(("RDP_PDU_DEACTIVATE\n")); *deactivated = True; break; + case RDP_PDU_REDIRECT: + return process_redirect_pdu(s); + break; case RDP_PDU_DATA: disc = process_data_pdu(s, ext_disc_reason); break; @@ -1318,6 +1412,27 @@ return True; } +/* Establish a reconnection up to the RDP layer */ +BOOL +rdp_reconnect(char *server, uint32 flags, char *domain, char *password, + char *command, char *directory, char *cookie) +{ + if (!sec_reconnect(server)) + return False; + + rdp_send_logon_info(flags, domain, g_username, password, command, directory); + return True; +} + +/* Called during redirection to reset the state to support redirection */ +void +rdp_reset_state(void) +{ + g_next_packet = NULL; /* reset the packet information */ + g_rdp_shareid = 0; + sec_reset_state(); +} + /* Disconnect from the RDP layer */ void rdp_disconnect(void)