From c250529e8e67ac437b835034f8141a62fa7b41ae Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Thu, 14 Jul 2022 01:46:38 -0700 Subject: [PATCH] add large cursor support, posix shm --- common/ms-rdpbcgr.h | 4 ++ common/os_calls.c | 32 ++++++++++++++++ common/os_calls.h | 4 ++ common/xrdp_client_info.h | 5 ++- libxrdp/libxrdp.c | 77 +++++++++++++++++++++------------------ libxrdp/libxrdpinc.h | 3 +- libxrdp/xrdp_caps.c | 63 ++++++++++++++++++++++++++++++++ xrdp/xrdp.h | 9 ++++- xrdp/xrdp_cache.c | 26 ++++++++----- xrdp/xrdp_mm.c | 18 ++++++++- xrdp/xrdp_types.h | 13 +++++-- xrdp/xrdp_wm.c | 28 ++++++++------ xup/xup.c | 60 ++++++++++++++++++++++++++++++ xup/xup.h | 8 +++- 14 files changed, 282 insertions(+), 68 deletions(-) diff --git a/common/ms-rdpbcgr.h b/common/ms-rdpbcgr.h index 0cbe03a7..5e88be35 100644 --- a/common/ms-rdpbcgr.h +++ b/common/ms-rdpbcgr.h @@ -567,4 +567,8 @@ #define RDP_MPPC_FLUSH 0x80 #define RDP_MPPC_DICT_SIZE 8192 /* RDP 4.0 | MS-RDPBCGR 3.1.8 */ +/* largePointerSupprtFlags (2.2.7.2.7) */ +#define LARGE_POINTER_FLAG_96x96 0x00000001 +#define LARGE_POINTER_FLAG_384x384 0x00000002 + #endif /* MS_RDPBCGR_H */ diff --git a/common/os_calls.c b/common/os_calls.c index 53dcf4a1..68687f95 100644 --- a/common/os_calls.c +++ b/common/os_calls.c @@ -56,6 +56,7 @@ #if defined(HAVE_SYS_PRCTL_H) #include #endif +#include #include #include #include @@ -2353,6 +2354,37 @@ nomem: return NULL; } +/*****************************************************************************/ +int +g_file_map(int fd, int aread, int awrite, size_t length, void **addr) +{ + int prot = 0; + void *laddr; + + if (aread) + { + prot |= PROT_READ; + } + if (awrite) + { + prot |= PROT_WRITE; + } + laddr = mmap(NULL, length, prot, MAP_SHARED, fd, 0); + if (laddr == MAP_FAILED) + { + return 1; + } + *addr = laddr; + return 0; +} + +/*****************************************************************************/ +int +g_munmap(void *addr, size_t length) +{ + return munmap(addr, length); +} + /*****************************************************************************/ /* Converts a hex mask to a mode_t value */ #if !defined(_WIN32) diff --git a/common/os_calls.h b/common/os_calls.h index 8e095d32..2374df3e 100644 --- a/common/os_calls.h +++ b/common/os_calls.h @@ -221,6 +221,10 @@ int g_file_read(int fd, char *ptr, int len); int g_file_write(int fd, const char *ptr, int len); int g_file_seek(int fd, int offset); int g_file_lock(int fd, int start, int len); +int +g_file_map(int fd, int aread, int awrite, size_t length, void **addr); +int +g_munmap(void *addr, size_t length); int g_file_duplicate_on(int fd, int target_fd); int g_file_get_cloexec(int fd); int g_file_set_cloexec(int fd, int status); diff --git a/common/xrdp_client_info.h b/common/xrdp_client_info.h index 6ba13d3f..f2d91ad7 100644 --- a/common/xrdp_client_info.h +++ b/common/xrdp_client_info.h @@ -213,9 +213,12 @@ struct xrdp_client_info * data */ unsigned int session_physical_width; /* in mm */ unsigned int session_physical_height; /* in mm */ + + int large_pointer_support_flags; }; /* yyyymmdd of last incompatible change to xrdp_client_info */ -#define CLIENT_INFO_CURRENT_VERSION 20220428 +/* also used for changes to all the xrdp installed headers */ +#define CLIENT_INFO_CURRENT_VERSION 20230425 #endif diff --git a/libxrdp/libxrdp.c b/libxrdp/libxrdp.c index a4dcc866..358a4418 100644 --- a/libxrdp/libxrdp.c +++ b/libxrdp/libxrdp.c @@ -705,7 +705,8 @@ libxrdp_send_bitmap(struct xrdp_session *session, int width, int height, /*****************************************************************************/ int EXPORT_CC libxrdp_send_pointer(struct xrdp_session *session, int cache_idx, - char *data, char *mask, int x, int y, int bpp) + char *data, char *mask, int x, int y, int bpp, + int width, int height) { struct stream *s; char *p; @@ -714,12 +715,21 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx, int i; int j; int data_bytes; + int mask_bytes; LOG_DEVEL(LOG_LEVEL_DEBUG, "sending cursor"); if (bpp == 0) { bpp = 24; } + if (width == 0) + { + width = 32; + } + if (height == 0) + { + height = 32; + } /* error check */ if ((session->client_info->pointer_flags & 1) == 0) { @@ -731,16 +741,17 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx, } } - if ((bpp != 16) && (bpp != 24) && (bpp != 32)) + if ((bpp != 15) && (bpp != 16) && (bpp != 24) && (bpp != 32)) { LOG(LOG_LEVEL_ERROR, - "Send pointer: invalid bpp value. Expected 16 or 24 or 32, " + "Send pointer: invalid bpp value. Expected 15, 16, 24 or 32, " "received %d", bpp); return 1; } make_stream(s); - init_stream(s, 8192); - + data_bytes = width * height * ((bpp + 7) / 8); + mask_bytes = width * height / 8; + init_stream(s, data_bytes + mask_bytes + 8192); if (session->client_info->use_fast_path & 1) /* fastpath output supported */ { LOG_DEVEL(LOG_LEVEL_DEBUG, "libxrdp_send_pointer: fastpath"); @@ -751,13 +762,8 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx, return 1; } - if ((session->client_info->pointer_flags & 1) == 0) + if ((session->client_info->pointer_flags & 1) != 0) { - data_bytes = 3072; - } - else - { - data_bytes = ((bpp + 7) / 8) * 32 * 32; out_uint16_le(s, bpp); /* TS_FP_POINTERATTRIBUTE -> newPointerUpdateData.xorBpp */ } } @@ -769,7 +775,6 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx, { out_uint16_le(s, RDP_POINTER_COLOR); out_uint16_le(s, 0); /* pad */ - data_bytes = 3072; LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPBCGR] TS_POINTER_PDU " "messageType %d (TS_PTRMSGTYPE_COLOR), pad2Octets ", RDP_POINTER_COLOR); @@ -783,7 +788,6 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx, RDP_POINTER_POINTER); out_uint16_le(s, bpp); /* TS_POINTERATTRIBUTE -> xorBpp */ - data_bytes = ((bpp + 7) / 8) * 32 * 32; } } @@ -792,20 +796,21 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx, out_uint16_le(s, cache_idx); /* cache_idx */ out_uint16_le(s, x); /* hotSpot.xPos */ out_uint16_le(s, y); /* hotSpot.yPos */ - out_uint16_le(s, 32); /* width */ - out_uint16_le(s, 32); /* height */ - out_uint16_le(s, 128); /* lengthAndMask */ + out_uint16_le(s, width); /* width */ + out_uint16_le(s, height); /* height */ + out_uint16_le(s, mask_bytes); /* lengthAndMask */ out_uint16_le(s, data_bytes); /* lengthXorMask */ /* xorMaskData */ switch (bpp) { - //case 15: /* coverity: this is logically dead code */ + case 15: + /* fallthrough */ case 16: p16 = (tui16 *) data; - for (i = 0; i < 32; i++) + for (i = 0; i < height; i++) { - for (j = 0; j < 32; j++) + for (j = 0; j < width; j++) { out_uint16_le(s, *p16); p16++; @@ -814,9 +819,9 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx, break; case 24: p = data; - for (i = 0; i < 32; i++) + for (i = 0; i < height; i++) { - for (j = 0; j < 32; j++) + for (j = 0; j < width; j++) { out_uint8(s, *p); p++; @@ -829,9 +834,9 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx, break; case 32: p32 = (tui32 *) data; - for (i = 0; i < 32; i++) + for (i = 0; i < height; i++) { - for (j = 0; j < 32; j++) + for (j = 0; j < width; j++) { out_uint32_le(s, *p32); p32++; @@ -840,7 +845,7 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx, break; } - out_uint8a(s, mask, 128); /* andMaskData */ + out_uint8a(s, mask, mask_bytes); /* andMaskData */ out_uint8(s, 0); /* pad */ s_mark_end(s); if (session->client_info->use_fast_path & 1) /* fastpath output supported */ @@ -849,11 +854,11 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx, { LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_FP_COLORPOINTERATTRIBUTE " "cachedPointerUpdateData = { cacheIndex %d, " - "hotSpot.xPos %d, hotSpot.yPos %d, width 32, " - "height 32, lengthAndMask 128, lengthXorMask %d, " + "hotSpot.xPos %d, hotSpot.yPos %d, width %d, " + "height %d, lengthAndMask %d, lengthXorMask %d, " "xorMaskData , " "andMaskData }", - cache_idx, x, y, data_bytes); + cache_idx, x, y, width, height, mask_bytes, data_bytes); if (xrdp_rdp_send_fastpath((struct xrdp_rdp *)session->rdp, s, FASTPATH_UPDATETYPE_COLOR) != 0) { @@ -867,11 +872,11 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx, LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_FP_POINTERATTRIBUTE " "newPointerUpdateData.xorBpp %d, " "newPointerUpdateData.colorPtrAttr = { cacheIndex %d, " - "hotSpot.xPos %d, hotSpot.yPos %d, width 32, " - "height 32, lengthAndMask 128, lengthXorMask %d, " + "hotSpot.xPos %d, hotSpot.yPos %d, width %d, " + "height %d, lengthAndMask %d, lengthXorMask %d, " "xorMaskData , " "andMaskData }", - bpp, cache_idx, x, y, data_bytes); + bpp, cache_idx, x, y, width, height, mask_bytes, data_bytes); if (xrdp_rdp_send_fastpath((struct xrdp_rdp *)session->rdp, s, FASTPATH_UPDATETYPE_POINTER) != 0) { @@ -887,21 +892,21 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx, { LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_COLORPOINTERATTRIBUTE " "cacheIndex %d, " - "hotSpot.xPos %d, hotSpot.yPos %d, width 32, " - "height 32, lengthAndMask 128, lengthXorMask %d, " + "hotSpot.xPos %d, hotSpot.yPos %d, width %d, " + "height %d, lengthAndMask %d, lengthXorMask %d, " "xorMaskData , " "andMaskData ", - cache_idx, x, y, data_bytes); + cache_idx, x, y, width, height, mask_bytes, data_bytes); } else { LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_POINTERATTRIBUTE " "xorBpp %d, colorPtrAttr = { cacheIndex %d, " - "hotSpot.xPos %d, hotSpot.yPos %d, width 32, " - "height 32, lengthAndMask 128, lengthXorMask %d, " + "hotSpot.xPos %d, hotSpot.yPos %d, width %d, " + "height %d, lengthAndMask %d, lengthXorMask %d, " "xorMaskData , " "andMaskData }", - bpp, cache_idx, x, y, data_bytes); + bpp, cache_idx, x, y, width, height, mask_bytes, data_bytes); } xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s, RDP_DATA_PDU_POINTER); diff --git a/libxrdp/libxrdpinc.h b/libxrdp/libxrdpinc.h index 5e8ad869..5d1c8fff 100644 --- a/libxrdp/libxrdpinc.h +++ b/libxrdp/libxrdpinc.h @@ -122,7 +122,8 @@ libxrdp_send_bitmap(struct xrdp_session *session, int width, int height, int bpp, char *data, int x, int y, int cx, int cy); int libxrdp_send_pointer(struct xrdp_session *session, int cache_idx, - char *data, char *mask, int x, int y, int bpp); + char *data, char *mask, int x, int y, int bpp, + int width, int height); int libxrdp_set_pointer(struct xrdp_session *session, int cache_idx); int diff --git a/libxrdp/xrdp_caps.c b/libxrdp/xrdp_caps.c index 2ba9cafa..6713380d 100644 --- a/libxrdp/xrdp_caps.c +++ b/libxrdp/xrdp_caps.c @@ -630,6 +630,18 @@ xrdp_caps_process_multifragmentupdate(struct xrdp_rdp *self, struct stream *s, return 0; } +/*****************************************************************************/ +static int +xrdp_caps_process_largepointer(struct xrdp_rdp *self, struct stream *s, + int len) +{ + int largePointerSupportFlags; + + in_uint16_le(s, largePointerSupportFlags); + self->client_info.large_pointer_support_flags = largePointerSupportFlags; + return 0; +} + /*****************************************************************************/ static int xrdp_caps_process_frame_ack(struct xrdp_rdp *self, struct stream *s, int len) @@ -846,6 +858,11 @@ xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s) "capabilitySetType = CAPSSETTYPE_MULTIFRAGMENTUPDATE"); xrdp_caps_process_multifragmentupdate(self, s, len); break; + case CAPSETTYPE_LARGE_POINTER: + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSETTYPE_LARGE_POINTER"); + xrdp_caps_process_largepointer(self, s, len); + break; case CAPSETTYPE_SURFACE_COMMANDS: LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " "capabilitySetType = CAPSETTYPE_SURFACE_COMMANDS"); @@ -881,6 +898,46 @@ xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s) self->client_info.offscreen_cache_entries = 0; } + if (self->client_info.use_fast_path) + { + if ((self->client_info.large_pointer_support_flags & LARGE_POINTER_FLAG_96x96) && + (self->client_info.max_fastpath_frag_bytes < 38055)) + { + LOG(LOG_LEVEL_WARNING, "Client Capability: client requested " + "LARGE_POINTER_FLAG_96x96 but max_fastpath_frag_bytes(%d) is less then " + "the required size of 38055, 96x96 large cursor support disabled", + self->client_info.max_fastpath_frag_bytes); + self->client_info.large_pointer_support_flags &= ~LARGE_POINTER_FLAG_96x96; + } + if ((self->client_info.large_pointer_support_flags & LARGE_POINTER_FLAG_384x384) && + (self->client_info.max_fastpath_frag_bytes < 608299)) + { + LOG(LOG_LEVEL_WARNING, "Client Capability: client requested " + "LARGE_POINTER_FLAG_384x384 but max_fastpath_frag_bytes(%d) is less then " + "the required size of 608299, 384x384 large cursor support disabled", + self->client_info.max_fastpath_frag_bytes); + self->client_info.large_pointer_support_flags &= ~LARGE_POINTER_FLAG_384x384; + } + } + else + { + if (self->client_info.large_pointer_support_flags != 0) + { + LOG(LOG_LEVEL_WARNING, "Client Capability: client requested " + "large pointers but use_fast_path is false, " + "all large cursor support disabled"); + self->client_info.large_pointer_support_flags = 0; + } + } + if (self->client_info.large_pointer_support_flags & LARGE_POINTER_FLAG_96x96) + { + LOG(LOG_LEVEL_INFO, "Client Capability: LARGE_POINTER_FLAG_96x96 supported"); + } + if (self->client_info.large_pointer_support_flags & LARGE_POINTER_FLAG_384x384) + { + LOG(LOG_LEVEL_INFO, "Client Capability: LARGE_POINTER_FLAG_384x384 supported"); + } + LOG_DEVEL(LOG_LEVEL_TRACE, "Completed processing received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU"); return 0; } @@ -1225,6 +1282,12 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self) LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability " "CAPSSETTYPE_MULTIFRAGMENTUPDATE = %d", max_request_size); + /* large pointer 96x96 */ + caps_count++; + out_uint16_le(s, CAPSETTYPE_LARGE_POINTER); + out_uint16_le(s, CAPSETTYPE_LARGE_POINTER_LEN); + out_uint16_le(s, LARGE_POINTER_FLAG_96x96); + /* frame acks */ caps_count++; out_uint16_le(s, CAPSTYPE_FRAME_ACKNOWLEDGE); diff --git a/xrdp/xrdp.h b/xrdp/xrdp.h index 809a0cf1..8a855754 100644 --- a/xrdp/xrdp.h +++ b/xrdp/xrdp.h @@ -149,10 +149,11 @@ int xrdp_wm_pu(struct xrdp_wm *self, struct xrdp_bitmap *control); int xrdp_wm_send_pointer(struct xrdp_wm *self, int cache_idx, - char *data, char *mask, int x, int y, int bpp); + char *data, char *mask, int x, int y, int bpp, + int width, int height); int xrdp_wm_pointer(struct xrdp_wm *self, char *data, char *mask, int x, int y, - int bpp); + int bpp, int width, int height); int callback(intptr_t id, int msg, intptr_t param1, intptr_t param2, intptr_t param3, intptr_t param4); @@ -513,6 +514,10 @@ int server_set_pointer_ex(struct xrdp_mod *mod, int x, int y, char *data, char *mask, int bpp); int +server_set_pointer_large(struct xrdp_mod *mod, int x, int y, + char *data, char *mask, int bpp, + int width, int height); +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_cache.c b/xrdp/xrdp_cache.c index bef11113..e2aa57ac 100644 --- a/xrdp/xrdp_cache.c +++ b/xrdp/xrdp_cache.c @@ -619,10 +619,12 @@ xrdp_cache_add_pointer(struct xrdp_cache *self, if (self->pointer_items[i].x == pointer_item->x && self->pointer_items[i].y == pointer_item->y && g_memcmp(self->pointer_items[i].data, - pointer_item->data, 32 * 32 * 4) == 0 && + pointer_item->data, 96 * 96 * 4) == 0 && g_memcmp(self->pointer_items[i].mask, - pointer_item->mask, 32 * 32 / 8) == 0 && - self->pointer_items[i].bpp == pointer_item->bpp) + pointer_item->mask, 96 * 96 / 8) == 0 && + self->pointer_items[i].bpp == pointer_item->bpp && + self->pointer_items[i].width == pointer_item->width && + self->pointer_items[i].height == pointer_item->height) { self->pointer_items[i].stamp = self->pointer_stamp; xrdp_wm_set_pointer(self->wm, i); @@ -648,17 +650,21 @@ xrdp_cache_add_pointer(struct xrdp_cache *self, self->pointer_items[index].x = pointer_item->x; self->pointer_items[index].y = pointer_item->y; g_memcpy(self->pointer_items[index].data, - pointer_item->data, 32 * 32 * 4); + pointer_item->data, 96 * 96 * 4); g_memcpy(self->pointer_items[index].mask, - pointer_item->mask, 32 * 32 / 8); + pointer_item->mask, 96 * 96 / 8); self->pointer_items[index].stamp = self->pointer_stamp; self->pointer_items[index].bpp = pointer_item->bpp; + self->pointer_items[index].width = pointer_item->width; + self->pointer_items[index].height = pointer_item->height; xrdp_wm_send_pointer(self->wm, index, self->pointer_items[index].data, self->pointer_items[index].mask, self->pointer_items[index].x, self->pointer_items[index].y, - self->pointer_items[index].bpp); + self->pointer_items[index].bpp, + self->pointer_items[index].width, + self->pointer_items[index].height); self->wm->current_pointer = index; LOG_DEVEL(LOG_LEVEL_TRACE, "adding pointer at %d", index); return index; @@ -680,9 +686,9 @@ xrdp_cache_add_pointer_static(struct xrdp_cache *self, self->pointer_items[index].x = pointer_item->x; self->pointer_items[index].y = pointer_item->y; g_memcpy(self->pointer_items[index].data, - pointer_item->data, 32 * 32 * 4); + pointer_item->data, 96 * 96 * 4); g_memcpy(self->pointer_items[index].mask, - pointer_item->mask, 32 * 32 / 8); + pointer_item->mask, 96 * 96 / 8); self->pointer_items[index].stamp = self->pointer_stamp; self->pointer_items[index].bpp = pointer_item->bpp; xrdp_wm_send_pointer(self->wm, index, @@ -690,7 +696,9 @@ xrdp_cache_add_pointer_static(struct xrdp_cache *self, self->pointer_items[index].mask, self->pointer_items[index].x, self->pointer_items[index].y, - self->pointer_items[index].bpp); + self->pointer_items[index].bpp, + self->pointer_items[index].width, + self->pointer_items[index].height); self->wm->current_pointer = index; LOG_DEVEL(LOG_LEVEL_TRACE, "adding pointer at %d", index); return index; diff --git a/xrdp/xrdp_mm.c b/xrdp/xrdp_mm.c index 4fc2c97e..b43ccf53 100644 --- a/xrdp/xrdp_mm.c +++ b/xrdp/xrdp_mm.c @@ -422,6 +422,7 @@ xrdp_mm_setup_mod1(struct xrdp_mm *self) self->mod->server_composite = server_composite; 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->si = &(self->wm->session->si); } } @@ -3463,7 +3464,7 @@ server_set_pointer(struct xrdp_mod *mod, int x, int y, struct xrdp_wm *wm; wm = (struct xrdp_wm *)(mod->wm); - xrdp_wm_pointer(wm, data, mask, x, y, 0); + xrdp_wm_pointer(wm, data, mask, x, y, 0, 32, 32); return 0; } @@ -3475,7 +3476,20 @@ server_set_pointer_ex(struct xrdp_mod *mod, int x, int y, struct xrdp_wm *wm; wm = (struct xrdp_wm *)(mod->wm); - xrdp_wm_pointer(wm, data, mask, x, y, bpp); + xrdp_wm_pointer(wm, data, mask, x, y, bpp, 32, 32); + return 0; +} + +/*****************************************************************************/ +int +server_set_pointer_large(struct xrdp_mod *mod, int x, int y, + char *data, char *mask, int bpp, + int width, int height) +{ + struct xrdp_wm *wm; + + wm = (struct xrdp_wm *)(mod->wm); + xrdp_wm_pointer(wm, data, mask, x, y, bpp, width, height); return 0; } diff --git a/xrdp/xrdp_types.h b/xrdp/xrdp_types.h index bb6994a6..55677fcf 100644 --- a/xrdp/xrdp_types.h +++ b/xrdp/xrdp_types.h @@ -171,7 +171,10 @@ struct xrdp_mod int flags, int frame_id); int (*server_session_info)(struct xrdp_mod *v, const char *data, int data_bytes); - tintptr server_dumby[100 - 46]; /* align, 100 minus the number of server + 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 functions above */ /* common */ tintptr handle; /* pointer to self as int */ @@ -242,9 +245,13 @@ struct xrdp_pointer_item int stamp; int x; /* hotspot */ int y; - char data[32 * 32 * 4]; - char mask[32 * 32 / 8]; + int pad0; + char data[96 * 96 * 4]; + char mask[96 * 96 / 8]; int bpp; + int width; + int height; + int pad1; }; struct xrdp_brush_item diff --git a/xrdp/xrdp_wm.c b/xrdp/xrdp_wm.c index b2c9dc6a..f71a0578 100644 --- a/xrdp/xrdp_wm.c +++ b/xrdp/xrdp_wm.c @@ -199,23 +199,26 @@ xrdp_wm_get_pixel(char *data, int x, int y, int width, int bpp) /*****************************************************************************/ int xrdp_wm_pointer(struct xrdp_wm *self, char *data, char *mask, int x, int y, - int bpp) + int bpp, int width, int height) { int bytes; - struct xrdp_pointer_item pointer_item; + struct xrdp_pointer_item *pointer_item; if (bpp == 0) { bpp = 24; } - bytes = ((bpp + 7) / 8) * 32 * 32; - g_memset(&pointer_item, 0, sizeof(struct xrdp_pointer_item)); - pointer_item.x = x; - pointer_item.y = y; - pointer_item.bpp = bpp; - g_memcpy(pointer_item.data, data, bytes); - g_memcpy(pointer_item.mask, mask, 32 * 32 / 8); - self->screen->pointer = xrdp_cache_add_pointer(self->cache, &pointer_item); + bytes = ((bpp + 7) / 8) * width * height; + pointer_item = g_new0(struct xrdp_pointer_item, 1); + pointer_item->x = x; + pointer_item->y = y; + pointer_item->bpp = bpp; + pointer_item->width = width; + pointer_item->height = height; + g_memcpy(pointer_item->data, data, bytes); + g_memcpy(pointer_item->mask, mask, width * height / 8); + self->screen->pointer = xrdp_cache_add_pointer(self->cache, pointer_item); + g_free(pointer_item); return 0; } @@ -334,10 +337,11 @@ xrdp_wm_load_pointer(struct xrdp_wm *self, char *file_name, char *data, /*****************************************************************************/ int xrdp_wm_send_pointer(struct xrdp_wm *self, int cache_idx, - char *data, char *mask, int x, int y, int bpp) + char *data, char *mask, int x, int y, int bpp, + int width, int height) { return libxrdp_send_pointer(self->session, cache_idx, data, mask, - x, y, bpp); + x, y, bpp, width, height); } /*****************************************************************************/ diff --git a/xup/xup.c b/xup/xup.c index 8d472c77..3fb1a421 100644 --- a/xup/xup.c +++ b/xup/xup.c @@ -1247,6 +1247,63 @@ process_server_paint_rect_shmem_ex(struct mod *amod, struct stream *s) return rv; } +/******************************************************************************/ +/* return error */ +static int +process_server_set_pointer_shmfd(struct mod *amod, struct stream *s) +{ + int rv; + int x; + int y; + int bpp; + int Bpp; + int width; + int height; + int fd; + int recv_bytes; + int shmembytes; + unsigned int num_fds; + void *shmemptr; + char *cur_data; + char *cur_mask; + char msg[4]; + + rv = 0; + in_sint16_le(s, x); + in_sint16_le(s, y); + in_uint16_le(s, bpp); + in_uint16_le(s, width); + in_uint16_le(s, height); + fd = -1; + num_fds = -1; + if (g_tcp_can_recv(amod->trans->sck, 5000) == 0) + { + return 1; + } + recv_bytes = g_sck_recv_fd_set(amod->trans->sck, msg, 4, &fd, 1, &num_fds); + LOG_DEVEL(LOG_LEVEL_DEBUG, "process_server_set_pointer_shmfd: " + "g_sck_recv_fd_set rv %d fd %d", recv_bytes, fd); + if (recv_bytes == 4) + { + if (num_fds == 1) + { + Bpp = (bpp == 0) ? 3 : (bpp + 7) / 8; + shmembytes = width * height * Bpp + width * height / 8; + if (g_file_map(fd, 1, 1, shmembytes, &shmemptr) == 0) + { + cur_data = (char *)shmemptr; + cur_mask = cur_data + width * height * Bpp; + rv = amod->server_set_pointer_large(amod, x, y, + cur_data, cur_mask, + bpp, width, height); + g_munmap(shmemptr, shmembytes); + } + g_file_close(fd); + } + } + return rv; +} + /******************************************************************************/ /* return error */ static int @@ -1472,6 +1529,9 @@ lib_mod_process_orders(struct mod *mod, int type, struct stream *s) case 61: /* server_paint_rect_shmem_ex */ rv = process_server_paint_rect_shmem_ex(mod, s); break; + case 63: /* server_set_pointer_shmfd */ + rv = process_server_set_pointer_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 f8c64221..6a14206a 100644 --- a/xup/xup.h +++ b/xup/xup.h @@ -155,8 +155,12 @@ struct mod int num_crects, short *crects, char *data, int width, int height, int flags, int frame_id); - - tintptr server_dumby[100 - 45]; /* align, 100 minus the number of server + int (*server_session_info)(struct mod *v, const char *data, + int data_bytes); + 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 functions above */ /* common */ tintptr handle; /* pointer to self as long */