From 7d891a1bde2f8287f333fda9acc88310d783da73 Mon Sep 17 00:00:00 2001 From: jsorg71 Date: Wed, 24 Aug 2005 01:09:33 +0000 Subject: [PATCH] added server_reset(which uses demand_active) for resizing the rdp client --- libxrdp/libxrdp.c | 68 +++++++++++++++++++++++++++++++++++++------ libxrdp/libxrdp.h | 4 +++ libxrdp/libxrdpinc.h | 4 +++ libxrdp/xrdp_orders.c | 35 +++++++++++++++++++++- libxrdp/xrdp_rdp.c | 45 +++++++++++++++++++++++----- vnc/vnc.c | 4 +++ vnc/vnc.h | 1 + xrdp/xrdp.h | 11 +++++++ xrdp/xrdp_bitmap.c | 13 +++++++-- xrdp/xrdp_cache.c | 48 ++++++++++++++++++++++++++++-- xrdp/xrdp_interface.c | 39 +++++++++++++++++++++++++ xrdp/xrdp_login_wnd.c | 1 + xrdp/xrdp_types.h | 1 + xrdp/xrdp_wm.c | 23 ++++++++++++--- 14 files changed, 269 insertions(+), 28 deletions(-) diff --git a/libxrdp/libxrdp.c b/libxrdp/libxrdp.c index 5a8f3837..c7af956e 100644 --- a/libxrdp/libxrdp.c +++ b/libxrdp/libxrdp.c @@ -33,6 +33,8 @@ libxrdp_init(long id, int sck) session->rdp = xrdp_rdp_create(session, sck); session->orders = xrdp_orders_create(session, (struct xrdp_rdp*)session->rdp); session->client_info = &(((struct xrdp_rdp*)session->rdp)->client_info); + make_stream(session->s); + init_stream(session->s, 8192 * 2); return session; } @@ -46,6 +48,7 @@ libxrdp_exit(struct xrdp_session* session) } xrdp_orders_delete((struct xrdp_orders*)session->orders); xrdp_rdp_delete((struct xrdp_rdp*)session->rdp); + free_stream(session->s); g_free(session); return 0; } @@ -68,19 +71,16 @@ libxrdp_process_incomming(struct xrdp_session* session) int EXPORT_CC libxrdp_process_data(struct xrdp_session* session) { - struct stream* s; int cont; int rv; int code; cont = 1; rv = 0; - make_stream(s); - init_stream(s, 8192); - while (cont && !session->term) + while ((cont || !session->up_and_running) && !session->term) { code = 0; - if (xrdp_rdp_recv((struct xrdp_rdp*)session->rdp, s, &code) != 0) + if (xrdp_rdp_recv((struct xrdp_rdp*)session->rdp, session->s, &code) != 0) { rv = 1; break; @@ -90,14 +90,17 @@ libxrdp_process_data(struct xrdp_session* session) { case -1: xrdp_rdp_send_demand_active((struct xrdp_rdp*)session->rdp); + session->up_and_running = 0; break; case 0: break; case RDP_PDU_CONFIRM_ACTIVE: /* 3 */ - xrdp_rdp_process_confirm_active((struct xrdp_rdp*)session->rdp, s); + xrdp_rdp_process_confirm_active((struct xrdp_rdp*)session->rdp, + session->s); break; case RDP_PDU_DATA: /* 7 */ - if (xrdp_rdp_process_data((struct xrdp_rdp*)session->rdp, s) != 0) + if (xrdp_rdp_process_data((struct xrdp_rdp*)session->rdp, + session->s) != 0) { DEBUG(("libxrdp_process_data returned non zero\n\r")); cont = 0; @@ -110,10 +113,9 @@ libxrdp_process_data(struct xrdp_session* session) } if (cont) { - cont = s->next_packet < s->end; + cont = session->s->next_packet < session->s->end; } } - free_stream(s); return rv; } @@ -528,3 +530,51 @@ libxrdp_orders_send_font(struct xrdp_session* session, return xrdp_orders_send_font((struct xrdp_orders*)session->orders, font_char, font_index, char_index); } + +/*****************************************************************************/ +int EXPORT_CC +libxrdp_reset(struct xrdp_session* session, + int width, int height, int bpp) +{ + if (session->client_info != 0) + { + /* older client can't resize */ + if (session->client_info->build <= 419) + { + return 0; + } + /* if same, don't need to do anything */ + if (session->client_info->width == width && + session->client_info->height == height && + session->client_info->bpp == bpp) + { + return 0; + } + session->client_info->width = width; + session->client_info->height = height; + session->client_info->bpp = bpp; + } + else + { + return 1; + } + /* this will send any lingering orders */ + if (xrdp_orders_reset((struct xrdp_orders*)session->orders) != 0) + { + return 1; + } + /* shut down the rdp client */ + if (xrdp_rdp_send_deactive((struct xrdp_rdp*)session->rdp) != 0) + { + return 1; + } + /* this should do the resizing */ + if (xrdp_rdp_send_demand_active((struct xrdp_rdp*)session->rdp) != 0) + { + return 1; + } + /* process till up and running */ + session->up_and_running = 0; + libxrdp_process_data(session); + return 0; +} diff --git a/libxrdp/libxrdp.h b/libxrdp/libxrdp.h index 29c2bdb6..67f325e4 100644 --- a/libxrdp/libxrdp.h +++ b/libxrdp/libxrdp.h @@ -266,6 +266,8 @@ int APP_CC xrdp_rdp_process_data(struct xrdp_rdp* self, struct stream* s); int APP_CC xrdp_rdp_disconnect(struct xrdp_rdp* self); +int APP_CC +xrdp_rdp_send_deactive(struct xrdp_rdp* self); /* xrdp_orders.c */ struct xrdp_orders* APP_CC @@ -274,6 +276,8 @@ xrdp_orders_create(struct xrdp_session* session, void APP_CC xrdp_orders_delete(struct xrdp_orders* self); int APP_CC +xrdp_orders_reset(struct xrdp_orders* self); +int APP_CC xrdp_orders_init(struct xrdp_orders* self); int APP_CC xrdp_orders_send(struct xrdp_orders* self); diff --git a/libxrdp/libxrdpinc.h b/libxrdp/libxrdpinc.h index 626b7bbd..68a1873e 100644 --- a/libxrdp/libxrdpinc.h +++ b/libxrdp/libxrdpinc.h @@ -90,6 +90,7 @@ struct xrdp_session void* orders; struct xrdp_client_info* client_info; int up_and_running; + struct stream* s; }; struct xrdp_session* DEFAULT_CC @@ -170,5 +171,8 @@ int DEFAULT_CC libxrdp_orders_send_font(struct xrdp_session* session, struct xrdp_font_char* font_char, int font_index, int char_index); +int DEFAULT_CC +libxrdp_reset(struct xrdp_session* session, + int width, int height, int bpp); #endif diff --git a/libxrdp/xrdp_orders.c b/libxrdp/xrdp_orders.c index c81899d2..6289858f 100644 --- a/libxrdp/xrdp_orders.c +++ b/libxrdp/xrdp_orders.c @@ -50,6 +50,38 @@ xrdp_orders_delete(struct xrdp_orders* self) g_free(self); } +/*****************************************************************************/ +/* set all values to zero */ +/* returns error */ +int APP_CC +xrdp_orders_reset(struct xrdp_orders* self) +{ + struct stream* out_s; + struct xrdp_rdp* rdp_layer; + struct xrdp_session* session; + struct xrdp_wm* wm; + + if (xrdp_orders_force_send(self) != 0) + { + return 1; + } + /* save these */ + out_s = self->out_s; + rdp_layer = self->rdp_layer; + session = self->session; + wm = self->wm; + /* set whole struct to zero */ + g_memset(self, 0, sizeof(struct xrdp_orders)); + /* set some stuff back */ + self->out_s = out_s; + self->rdp_layer = rdp_layer; + self->session = session; + self->wm = wm; + self->clip_right = 1; /* silly rdp right clip */ + self->clip_bottom = 1; /* silly rdp bottom clip */ + return 0; +} + /*****************************************************************************/ /* returns error */ int APP_CC @@ -90,6 +122,7 @@ xrdp_orders_send(struct xrdp_orders* self) DEBUG(("xrdp_orders_send sending %d orders\n\r", self->order_count)); self->order_count_ptr[0] = self->order_count; self->order_count_ptr[1] = self->order_count >> 8; + self->order_count = 0; if (xrdp_rdp_send_data(self->rdp_layer, self->out_s, RDP_DATA_PDU_UPDATE) != 0) { @@ -105,7 +138,7 @@ xrdp_orders_send(struct xrdp_orders* self) int APP_CC xrdp_orders_force_send(struct xrdp_orders* self) { - if (self->order_count > 0) + if (self->order_count > 0 && self->order_count > 0) { s_mark_end(self->out_s); DEBUG(("xrdp_orders_force_send sending %d orders\n\r", self->order_count)); diff --git a/libxrdp/xrdp_rdp.c b/libxrdp/xrdp_rdp.c index a9256cbf..8a883f56 100644 --- a/libxrdp/xrdp_rdp.c +++ b/libxrdp/xrdp_rdp.c @@ -321,12 +321,17 @@ xrdp_rdp_send_demand_active(struct xrdp_rdp* self) } out_uint32_le(s, self->share_id); - out_uint32_be(s, 0x04000401); - out_uint32_be(s, 0x524e5300); - out_uint32_be(s, 0x08000000); - out_uint32_be(s, 0x09000800); + + out_uint16_le(s, 4); /* 4 chars for RDP\0 */ + out_uint16_le(s, 0x0104); /* size after num caps */ + out_uint8a(s, "RDP", 4); + out_uint32_le(s, 8); /* num caps 8 */ + + /* Output share capability set */ + out_uint16_le(s, RDP_CAPSET_SHARE); + out_uint16_le(s, RDP_CAPLEN_SHARE); out_uint16_le(s, self->mcs_channel); - out_uint16_be(s, 0xb5e2); + out_uint16_be(s, 0xb5e2); /* 0x73e1 */ /* Output general capability set */ out_uint16_le(s, RDP_CAPSET_GENERAL); /* 1 */ @@ -336,7 +341,7 @@ xrdp_rdp_send_demand_active(struct xrdp_rdp* self) out_uint16_le(s, 0x200); /* Protocol version */ out_uint16_le(s, 0); /* pad */ out_uint16_le(s, 0); /* Compression types */ - out_uint16_le(s, 0); /* pad */ + out_uint16_le(s, 0); /* pad use 0x40d for rdp packets */ out_uint16_le(s, 0); /* Update capability */ out_uint16_le(s, 0); /* Remote unshare capability */ out_uint16_le(s, 0); /* Compression level */ @@ -407,9 +412,10 @@ xrdp_rdp_send_demand_active(struct xrdp_rdp* self) out_uint8(s, 0); out_uint8(s, 0); out_uint16_le(s, 0x6a1); - out_uint8s(s, 6); /* ? */ + out_uint8s(s, 2); /* ? */ out_uint32_le(s, 0x0f4240); /* desk save */ - out_uint32_le(s, 0); /* ? */ + out_uint32_le(s, 0x0f4240); /* desk save */ + out_uint32_le(s, 1); /* ? */ out_uint32_le(s, 0); /* ? */ /* Output color cache capability set */ @@ -849,3 +855,26 @@ xrdp_rdp_disconnect(struct xrdp_rdp* self) { return xrdp_sec_disconnect(self->sec_layer); } + +/*****************************************************************************/ +int APP_CC +xrdp_rdp_send_deactive(struct xrdp_rdp* self) +{ + struct stream* s; + + make_stream(s); + init_stream(s, 8192); + if (xrdp_rdp_init(self, s) != 0) + { + free_stream(s); + return 1; + } + s_mark_end(s); + if (xrdp_rdp_send(self, s, RDP_PDU_DEACTIVATE) != 0) + { + free_stream(s); + return 1; + } + free_stream(s); + return 0; +} diff --git a/vnc/vnc.c b/vnc/vnc.c index 8f69d6c6..1d90483d 100644 --- a/vnc/vnc.c +++ b/vnc/vnc.c @@ -1014,6 +1014,10 @@ lib_mod_connect(struct vnc* v) error = lib_send(v, s->data, 4 + 3 * 4); } if (error == 0) + { + error = v->server_reset(v, v->mod_width, v->mod_height, v->mod_bpp); + } + if (error == 0) { /* FrambufferUpdateRequest */ init_stream(s, 8192); diff --git a/vnc/vnc.h b/vnc/vnc.h index 72929050..b4dd237c 100644 --- a/vnc/vnc.h +++ b/vnc/vnc.h @@ -69,6 +69,7 @@ struct vnc int box_left, int box_top, int box_right, int box_bottom, int x, int y, char* data, int data_len); + int (*server_reset)(struct vnc* v, int width, int height, int bpp); /* common */ long handle; /* pointer to self as long */ long wm; diff --git a/xrdp/xrdp.h b/xrdp/xrdp.h index 18850579..5f76af0d 100644 --- a/xrdp/xrdp.h +++ b/xrdp/xrdp.h @@ -55,6 +55,9 @@ xrdp_cache_create(struct xrdp_wm* owner, struct xrdp_session* session, void APP_CC xrdp_cache_delete(struct xrdp_cache* self); int APP_CC +xrdp_cache_reset(struct xrdp_cache* self, + struct xrdp_client_info* client_info); +int APP_CC xrdp_cache_add_bitmap(struct xrdp_cache* self, struct xrdp_bitmap* bitmap); int APP_CC xrdp_cache_add_palette(struct xrdp_cache* self, int* palette); @@ -78,6 +81,10 @@ xrdp_wm_delete(struct xrdp_wm* self); int APP_CC xrdp_wm_send_palette(struct xrdp_wm* self); int APP_CC +xrdp_wm_load_static_colors(struct xrdp_wm* self); +int APP_CC +xrdp_wm_load_static_pointers(struct xrdp_wm* self); +int APP_CC xrdp_wm_init(struct xrdp_wm* self); int APP_CC xrdp_wm_send_bitmap(struct xrdp_wm* self, struct xrdp_bitmap* bitmap, @@ -160,6 +167,8 @@ xrdp_bitmap_get_child_by_id(struct xrdp_bitmap* self, int id); int APP_CC xrdp_bitmap_set_focus(struct xrdp_bitmap* self, int focused); int APP_CC +xrdp_bitmap_resize(struct xrdp_bitmap* self, int width, int height); +int APP_CC xrdp_bitmap_load(struct xrdp_bitmap* self, char* filename, int* palette); int APP_CC xrdp_bitmap_get_pixel(struct xrdp_bitmap* self, int x, int y); @@ -343,3 +352,5 @@ server_draw_text(struct xrdp_mod* mod, int font, int box_left, int box_top, int box_right, int box_bottom, int x, int y, char* data, int data_len); +int DEFAULT_CC +server_reset(struct xrdp_mod* mod, int width, int height, int bpp); diff --git a/xrdp/xrdp_bitmap.c b/xrdp/xrdp_bitmap.c index bc1a2c46..17d38f01 100644 --- a/xrdp/xrdp_bitmap.c +++ b/xrdp/xrdp_bitmap.c @@ -98,7 +98,7 @@ xrdp_bitmap_create(int width, int height, int bpp, case 15: Bpp = 2; break; case 16: Bpp = 2; break; } - if (self->type == WND_TYPE_SCREEN || self->type == WND_TYPE_BITMAP) + if (self->type == WND_TYPE_BITMAP || self->type == WND_TYPE_IMAGE) { self->data = (char*)g_malloc(width * height * Bpp, 0); } @@ -303,7 +303,10 @@ xrdp_bitmap_resize(struct xrdp_bitmap* self, int width, int height) { int Bpp; - g_free(self->data); + if (width == self->width && height == self->height) + { + return 0; + } self->width = width; self->height = height; Bpp = 4; @@ -313,7 +316,11 @@ xrdp_bitmap_resize(struct xrdp_bitmap* self, int width, int height) case 15: Bpp = 2; break; case 16: Bpp = 2; break; } - self->data = (char*)g_malloc(width * height * Bpp, 1); + if (self->data != 0) + { + g_free(self->data); + self->data = (char*)g_malloc(width * height * Bpp, 1); + } self->line_size = width * Bpp; return 0; } diff --git a/xrdp/xrdp_cache.c b/xrdp/xrdp_cache.c index 99cc8f31..57ec1f72 100644 --- a/xrdp/xrdp_cache.c +++ b/xrdp/xrdp_cache.c @@ -74,6 +74,51 @@ xrdp_cache_delete(struct xrdp_cache* self) g_free(self); } +/*****************************************************************************/ +int APP_CC +xrdp_cache_reset(struct xrdp_cache* self, + struct xrdp_client_info* client_info) +{ + struct xrdp_wm* wm; + struct xrdp_session* session; + int i; + int j; + + /* free all the cached bitmaps */ + for (i = 0; i < 3; i++) + { + for (j = 0; j < 600; j++) + { + xrdp_bitmap_delete(self->bitmap_items[i][j].bitmap); + } + } + /* free all the cached font items */ + for (i = 0; i < 12; i++) + { + for (j = 0; j < 256; j++) + { + g_free(self->char_items[i][j].font_item.data); + } + } + /* save these */ + wm = self->wm; + session = self->session; + /* set whole struct to zero */ + g_memset(self, 0, sizeof(struct xrdp_cache)); + /* set some stuff back */ + self->wm = wm; + self->session = session; + self->use_bitmap_comp = client_info->use_bitmap_comp; + self->cache1_entries = client_info->cache1_entries; + self->cache1_size = client_info->cache1_size; + self->cache2_entries = client_info->cache2_entries; + self->cache2_size = client_info->cache2_size; + self->cache3_entries = client_info->cache3_entries; + self->cache3_size = client_info->cache3_size; + self->pointer_cache_entries = client_info->pointer_cache_entries; + return 0; +} + /*****************************************************************************/ /* returns cache id */ int APP_CC @@ -110,7 +155,6 @@ xrdp_cache_add_bitmap(struct xrdp_cache* self, struct xrdp_bitmap* bitmap) { self->bitmap_items[i][j].stamp = self->bitmap_stamp; DEBUG(("found bitmap at %d %d\n\r", i, j)); - //g_printf("found bitmap at %d %d\n\r", i, j); xrdp_bitmap_delete(bitmap); return MAKELONG(i, j); } @@ -129,7 +173,6 @@ xrdp_cache_add_bitmap(struct xrdp_cache* self, struct xrdp_bitmap* bitmap) { self->bitmap_items[i][j].stamp = self->bitmap_stamp; DEBUG(("found bitmap at %d %d\n\r", i, j)); - //g_printf("found bitmap at %d %d\n\r", i, j); xrdp_bitmap_delete(bitmap); return MAKELONG(i, j); } @@ -148,7 +191,6 @@ xrdp_cache_add_bitmap(struct xrdp_cache* self, struct xrdp_bitmap* bitmap) { self->bitmap_items[i][j].stamp = self->bitmap_stamp; DEBUG(("found bitmap at %d %d\n\r", i, j)); - //g_printf("found bitmap at %d %d\n\r", i, j); xrdp_bitmap_delete(bitmap); return MAKELONG(i, j); } diff --git a/xrdp/xrdp_interface.c b/xrdp/xrdp_interface.c index b7cd1760..0d1264b8 100644 --- a/xrdp/xrdp_interface.c +++ b/xrdp/xrdp_interface.c @@ -372,3 +372,42 @@ server_draw_text(struct xrdp_mod* mod, int font, box_right, box_bottom, x, y, data, data_len); } + +/*****************************************************************************/ +int DEFAULT_CC +server_reset(struct xrdp_mod* mod, int width, int height, int bpp) +{ + struct xrdp_wm* wm; + + wm = (struct xrdp_wm*)mod->wm; + if (wm->client_info == 0) + { + return 1; + } + /* older client can't resize */ + if (wm->client_info->build <= 419) + { + return 0; + } + /* if same, don't need to do anything */ + if (wm->client_info->width == width && + wm->client_info->height == height && + wm->client_info->bpp == bpp) + { + return 0; + } + /* reset lib, client_info gets updated in libxrdp_reset */ + if (libxrdp_reset(wm->session, width, height, bpp) != 0) + { + return 1; + } + /* reset cache */ + xrdp_cache_reset(wm->cache, wm->client_info); + /* resize the main window */ + xrdp_bitmap_resize(wm->screen, wm->client_info->width, + wm->client_info->height); + /* load some stuff */ + xrdp_wm_load_static_colors(wm); + xrdp_wm_load_static_pointers(wm); + return 0; +} diff --git a/xrdp/xrdp_login_wnd.c b/xrdp/xrdp_login_wnd.c index c2c43d30..be2f6451 100644 --- a/xrdp/xrdp_login_wnd.c +++ b/xrdp/xrdp_login_wnd.c @@ -161,6 +161,7 @@ xrdp_wm_setup_mod(struct xrdp_wm* self, self->mod->server_draw_line = server_draw_line; self->mod->server_add_char = server_add_char; self->mod->server_draw_text = server_draw_text; + self->mod->server_reset = server_reset; } } /* id self->mod is null, there must be a problem */ diff --git a/xrdp/xrdp_types.h b/xrdp/xrdp_types.h index 2821c257..c0f04e62 100644 --- a/xrdp/xrdp_types.h +++ b/xrdp/xrdp_types.h @@ -64,6 +64,7 @@ struct xrdp_mod int box_left, int box_top, int box_right, int box_bottom, int x, int y, char* data, int data_len); + int (*server_reset)(struct xrdp_mod* v, int width, int height, int bpp); /* common */ long handle; /* pointer to self as int */ long wm; /* struct xrdp_wm* */ diff --git a/xrdp/xrdp_wm.c b/xrdp/xrdp_wm.c index 50f7caf3..fdd5a6c7 100644 --- a/xrdp/xrdp_wm.c +++ b/xrdp/xrdp_wm.c @@ -268,12 +268,11 @@ xrdp_wm_set_pointer(struct xrdp_wm* self, int cache_idx) /*****************************************************************************/ int APP_CC -xrdp_wm_init(struct xrdp_wm* self) +xrdp_wm_load_static_colors(struct xrdp_wm* self) { int bindex; int gindex; int rindex; - struct xrdp_pointer_item pointer_item; if (self->screen->bpp == 8) { @@ -334,6 +333,15 @@ xrdp_wm_init(struct xrdp_wm* self) self->red = COLOR24(0xff, 0x00, 0x00); self->green = COLOR24(0x00, 0xff, 0x00); } + return 0; +} + +/*****************************************************************************/ +int APP_CC +xrdp_wm_load_static_pointers(struct xrdp_wm* self) +{ + struct xrdp_pointer_item pointer_item; + DEBUG(("sending cursor\n\r")); xrdp_wm_load_pointer(self, "cursor1.cur", pointer_item.data, pointer_item.mask, &pointer_item.x, &pointer_item.y); @@ -342,13 +350,20 @@ xrdp_wm_init(struct xrdp_wm* self) xrdp_wm_load_pointer(self, "cursor0.cur", pointer_item.data, pointer_item.mask, &pointer_item.x, &pointer_item.y); xrdp_cache_add_pointer_static(self->cache, &pointer_item, 0); + return 0; +} + +/*****************************************************************************/ +int APP_CC +xrdp_wm_init(struct xrdp_wm* self) +{ + xrdp_wm_load_static_colors(self); + xrdp_wm_load_static_pointers(self); xrdp_login_wnd_create(self); /* clear screen */ self->screen->bg_color = self->black; xrdp_bitmap_invalidate(self->screen, 0); - xrdp_wm_set_focused(self, self->login_window); - return 0; }