diff --git a/xrdp/xrdp.h b/xrdp/xrdp.h index f06eb1a90c..03bcd254e3 100644 --- a/xrdp/xrdp.h +++ b/xrdp/xrdp.h @@ -524,6 +524,12 @@ server_set_pointer_large(struct xrdp_mod *mod, int x, int y, char *data, char *mask, int bpp, int width, int height); int +server_paint_rects_ex(struct xrdp_mod *mod, int num_drects, short *drects, + int num_crects, short *crects, + char *data, int left, int top, + int width, int height, + int flags, int frame_id); +int server_palette(struct xrdp_mod *mod, int *palette); int server_msg(struct xrdp_mod *mod, const char *msg, int code); diff --git a/xrdp/xrdp_encoder.h b/xrdp/xrdp_encoder.h index 2598bcb523..ce8c128a06 100644 --- a/xrdp/xrdp_encoder.h +++ b/xrdp/xrdp_encoder.h @@ -38,6 +38,8 @@ struct xrdp_enc_data int num_crects; short *crects; /* 4 * num_crects */ char *data; + int left; + int top; int width; int height; int flags; diff --git a/xrdp/xrdp_mm.c b/xrdp/xrdp_mm.c index b43ccf53a9..573c1e3317 100644 --- a/xrdp/xrdp_mm.c +++ b/xrdp/xrdp_mm.c @@ -423,6 +423,7 @@ xrdp_mm_setup_mod1(struct xrdp_mm *self) self->mod->server_paint_rects = server_paint_rects; self->mod->server_session_info = server_session_info; self->mod->server_set_pointer_large = server_set_pointer_large; + self->mod->server_paint_rects_ex = server_paint_rects_ex; self->mod->si = &(self->wm->session->si); } } @@ -3357,6 +3358,17 @@ int server_paint_rects(struct xrdp_mod *mod, int num_drects, short *drects, int num_crects, short *crects, char *data, int width, int height, int flags, int frame_id) +{ + return server_paint_rects_ex(mod, num_drects, drects, num_crects, crects, + data, 0, 0, width, height, flags, frame_id); +} + +/*****************************************************************************/ +int +server_paint_rects_ex(struct xrdp_mod *mod, int num_drects, short *drects, + int num_crects, short *crects, char *data, + int left, int top, int width, int height, + int flags, int frame_id) { struct xrdp_wm *wm; struct xrdp_mm *mm; @@ -3404,6 +3416,8 @@ server_paint_rects(struct xrdp_mod *mod, int num_drects, short *drects, enc_data->num_drects = num_drects; enc_data->num_crects = num_crects; enc_data->data = data; + enc_data->left = left; + enc_data->top = top; enc_data->width = width; enc_data->height = height; enc_data->flags = flags; diff --git a/xrdp/xrdp_types.h b/xrdp/xrdp_types.h index 55677fcf35..f75193460a 100644 --- a/xrdp/xrdp_types.h +++ b/xrdp/xrdp_types.h @@ -174,7 +174,13 @@ struct xrdp_mod int (*server_set_pointer_large)(struct xrdp_mod *v, int x, int y, char *data, char *mask, int bpp, int width, int height); - tintptr server_dumby[100 - 47]; /* align, 100 minus the number of server + int (*server_paint_rects_ex)(struct xrdp_mod *v, + int num_drects, short *drects, + int num_crects, short *crects, + char *data, int left, int top, + int width, int height, + int flags, int frame_id); + tintptr server_dumby[100 - 48]; /* align, 100 minus the number of server functions above */ /* common */ tintptr handle; /* pointer to self as int */ diff --git a/xup/xup.c b/xup/xup.c index 3fb1a421ad..cbd912c850 100644 --- a/xup/xup.c +++ b/xup/xup.c @@ -1304,6 +1304,102 @@ process_server_set_pointer_shmfd(struct mod *amod, struct stream *s) return rv; } +/******************************************************************************/ +/* return error */ +static int +process_server_paint_rect_shmfd(struct mod *amod, struct stream *s) +{ + int num_drects; + int num_crects; + int flags; + int frame_id; + int shmem_bytes; + int shmem_offset; + int left; + int top; + int width; + int height; + int index; + int rv; + int16_t *ldrects; + int16_t *ldrects1; + int16_t *lcrects; + int16_t *lcrects1; + char *bmpdata; + int fd; + int recv_bytes; + unsigned int num_fds; + void *shmem_ptr; + char msg[4]; + + /* dirty pixels */ + in_uint16_le(s, num_drects); + ldrects = g_new(int16_t, 2 * 4 * num_drects); + ldrects1 = ldrects; + for (index = 0; index < num_drects; index++) + { + in_sint16_le(s, ldrects1[0]); + in_sint16_le(s, ldrects1[1]); + in_sint16_le(s, ldrects1[2]); + in_sint16_le(s, ldrects1[3]); + ldrects1 += 4; + } + + /* copied pixels */ + in_uint16_le(s, num_crects); + lcrects = g_new(int16_t, 2 * 4 * num_crects); + lcrects1 = lcrects; + for (index = 0; index < num_crects; index++) + { + in_sint16_le(s, lcrects1[0]); + in_sint16_le(s, lcrects1[1]); + in_sint16_le(s, lcrects1[2]); + in_sint16_le(s, lcrects1[3]); + lcrects1 += 4; + } + + in_uint32_le(s, flags); + in_uint32_le(s, frame_id); + in_uint32_le(s, shmem_bytes); + in_uint32_le(s, shmem_offset); + + in_uint16_le(s, left); + in_uint16_le(s, top); + in_uint16_le(s, width); + in_uint16_le(s, height); + + if (g_tcp_can_recv(amod->trans->sck, 5000) == 0) + { + g_free(ldrects); + g_free(lcrects); + return 1; + } + rv = 1; + recv_bytes = g_sck_recv_fd_set(amod->trans->sck, msg, 4, &fd, 1, &num_fds); + LOG_DEVEL(LOG_LEVEL_DEBUG, "process_server_paint_rect_shmfd: " + "g_sck_recv_fd_set rv %d fd %d", recv_bytes, fd); + if (recv_bytes == 4) + { + if (num_fds == 1) + { + if (g_file_map(fd, 1, 1, shmem_bytes, &shmem_ptr) == 0) + { + bmpdata = (char *)shmem_ptr; + bmpdata += shmem_offset; + rv = amod->server_paint_rects_ex(amod, num_drects, ldrects, + num_crects, lcrects, bmpdata, + left, top, width, height, + flags, frame_id); + g_munmap(shmem_ptr, shmem_bytes); + } + g_file_close(fd); + } + } + g_free(ldrects); + g_free(lcrects); + return rv; +} + /******************************************************************************/ /* return error */ static int @@ -1532,6 +1628,9 @@ lib_mod_process_orders(struct mod *mod, int type, struct stream *s) case 63: /* server_set_pointer_shmfd */ rv = process_server_set_pointer_shmfd(mod, s); break; + case 64: /* server_paint_rect_shmfd */ + rv = process_server_paint_rect_shmfd(mod, s); + break; default: LOG_DEVEL(LOG_LEVEL_WARNING, "lib_mod_process_orders: unknown order type %d", type); diff --git a/xup/xup.h b/xup/xup.h index 6a14206aa3..fc3e8ef507 100644 --- a/xup/xup.h +++ b/xup/xup.h @@ -160,7 +160,13 @@ struct mod int (*server_set_pointer_large)(struct mod *v, int x, int y, char *data, char *mask, int bpp, int width, int height); - tintptr server_dumby[100 - 47]; /* align, 100 minus the number of server + int (*server_paint_rects_ex)(struct mod *v, + int num_drects, short *drects, + int num_crects, short *crects, + char *data, int left, int top, + int width, int height, + int flags, int frame_id); + tintptr server_dumby[100 - 48]; /* align, 100 minus the number of server functions above */ /* common */ tintptr handle; /* pointer to self as long */