mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-15 00:44:19 +09:00
Added RDP 10.7 large pointer support
* Implements [MS-RDPBCGR] version 51 large pointer support. * Logs unknown large pointer capability flags as warning. Signed-off-by: Armin Novak <armin.novak@thincast.com>
This commit is contained in:
@@ -36,7 +36,6 @@
|
||||
#include <freerdp/client/channels.h>
|
||||
#include <freerdp/crypto/crypto.h>
|
||||
#include <freerdp/locale/keyboard.h>
|
||||
|
||||
#include <freerdp/utils/passphrase.h>
|
||||
|
||||
#include <freerdp/client/cmdline.h>
|
||||
@@ -3136,7 +3135,8 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
|
||||
if (settings->RemoteFxCodec || settings->NSCodec || settings->SupportGraphicsPipeline)
|
||||
{
|
||||
settings->FastPathOutput = TRUE;
|
||||
settings->LargePointerFlag = TRUE;
|
||||
settings->LargePointerFlag =
|
||||
0x0002; /* (LARGE_POINTER_FLAG_96x96 | LARGE_POINTER_FLAG_384x384); */
|
||||
settings->FrameMarkerCommandEnabled = TRUE;
|
||||
settings->ColorDepth = 32;
|
||||
}
|
||||
|
||||
@@ -212,12 +212,14 @@
|
||||
#define PointerUpdate_PointerColor 3
|
||||
#define PointerUpdate_PointerNew 4
|
||||
#define PointerUpdate_PointerCached 5
|
||||
#define PointerUpdate_PointerLarge 6
|
||||
|
||||
#define FREERDP_POINTER_UPDATE_ POINTER_POSITION MakeMessageId(PointerUpdate, PointerPosition)
|
||||
#define FREERDP_POINTER_UPDATE_POINTER_SYSTEM MakeMessageId(PointerUpdate, PointerSystem)
|
||||
#define FREERDP_POINTER_UPDATE_POINTER_COLOR MakeMessageId(PointerUpdate, PointerColor)
|
||||
#define FREERDP_POINTER_UPDATE_POINTER_NEW MakeMessageId(PointerUpdate, PointerNew)
|
||||
#define FREERDP_POINTER_UPDATE_POINTER_CACHED MakeMessageId(PointerUpdate, PointerCached)
|
||||
#define FREERDP_POINTER_UPDATE_POINTER_LARGE MakeMessageId(PointerUpdate, PointerLarge)
|
||||
|
||||
/**
|
||||
* Input Message Queue
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#define PTR_MSG_TYPE_COLOR 0x0006
|
||||
#define PTR_MSG_TYPE_CACHED 0x0007
|
||||
#define PTR_MSG_TYPE_POINTER 0x0008
|
||||
#define PTR_MSG_TYPE_POINTER_LARGE 0x0009
|
||||
|
||||
#define SYSPTR_NULL 0x00000000
|
||||
#define SYSPTR_DEFAULT 0x00007F00
|
||||
@@ -58,6 +59,21 @@ struct _POINTER_COLOR_UPDATE
|
||||
};
|
||||
typedef struct _POINTER_COLOR_UPDATE POINTER_COLOR_UPDATE;
|
||||
|
||||
struct _POINTER_LARGE_UPDATE
|
||||
{
|
||||
UINT16 xorBpp;
|
||||
UINT16 cacheIndex;
|
||||
UINT16 hotSpotX;
|
||||
UINT16 hotSpotY;
|
||||
UINT16 width;
|
||||
UINT16 height;
|
||||
UINT32 lengthAndMask;
|
||||
UINT32 lengthXorMask;
|
||||
BYTE* xorMaskData;
|
||||
BYTE* andMaskData;
|
||||
};
|
||||
typedef struct _POINTER_LARGE_UPDATE POINTER_LARGE_UPDATE;
|
||||
|
||||
struct _POINTER_NEW_UPDATE
|
||||
{
|
||||
UINT32 xorBpp;
|
||||
@@ -77,6 +93,7 @@ typedef BOOL (*pPointerSystem)(rdpContext* context, const POINTER_SYSTEM_UPDATE*
|
||||
typedef BOOL (*pPointerColor)(rdpContext* context, const POINTER_COLOR_UPDATE* pointer_color);
|
||||
typedef BOOL (*pPointerNew)(rdpContext* context, const POINTER_NEW_UPDATE* pointer_new);
|
||||
typedef BOOL (*pPointerCached)(rdpContext* context, const POINTER_CACHED_UPDATE* pointer_cached);
|
||||
typedef BOOL (*pPointerLarge)(rdpContext* context, const POINTER_LARGE_UPDATE* pointer_large);
|
||||
|
||||
struct rdp_pointer_update
|
||||
{
|
||||
@@ -88,7 +105,8 @@ struct rdp_pointer_update
|
||||
pPointerColor PointerColor; /* 18 */
|
||||
pPointerNew PointerNew; /* 19 */
|
||||
pPointerCached PointerCached; /* 20 */
|
||||
UINT32 paddingB[32 - 21]; /* 21 */
|
||||
pPointerLarge PointerLarge; /* 21 */
|
||||
UINT32 paddingB[32 - 22]; /* 22 */
|
||||
};
|
||||
typedef struct rdp_pointer_update rdpPointerUpdate;
|
||||
|
||||
|
||||
99
libfreerdp/cache/pointer.c
vendored
99
libfreerdp/cache/pointer.c
vendored
@@ -147,6 +147,57 @@ out_fail:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOL update_pointer_large(rdpContext* context, const POINTER_LARGE_UPDATE* pointer_large)
|
||||
{
|
||||
rdpPointer* pointer;
|
||||
rdpCache* cache = context->cache;
|
||||
pointer = Pointer_Alloc(context);
|
||||
|
||||
if (pointer != NULL)
|
||||
{
|
||||
pointer->xorBpp = pointer_large->xorBpp;
|
||||
pointer->xPos = pointer_large->hotSpotX;
|
||||
pointer->yPos = pointer_large->hotSpotY;
|
||||
pointer->width = pointer_large->width;
|
||||
pointer->height = pointer_large->height;
|
||||
pointer->lengthAndMask = pointer_large->lengthAndMask;
|
||||
pointer->lengthXorMask = pointer_large->lengthXorMask;
|
||||
|
||||
if (pointer->lengthAndMask && pointer_large->andMaskData)
|
||||
{
|
||||
pointer->andMaskData = (BYTE*)malloc(pointer->lengthAndMask);
|
||||
|
||||
if (!pointer->andMaskData)
|
||||
goto out_fail;
|
||||
|
||||
CopyMemory(pointer->andMaskData, pointer_large->andMaskData, pointer->lengthAndMask);
|
||||
}
|
||||
|
||||
if (pointer->lengthXorMask && pointer_large->xorMaskData)
|
||||
{
|
||||
pointer->xorMaskData = (BYTE*)malloc(pointer->lengthXorMask);
|
||||
|
||||
if (!pointer->xorMaskData)
|
||||
goto out_fail;
|
||||
|
||||
CopyMemory(pointer->xorMaskData, pointer_large->xorMaskData, pointer->lengthXorMask);
|
||||
}
|
||||
|
||||
if (!IFCALLRESULT(TRUE, pointer->New, context, pointer))
|
||||
goto out_fail;
|
||||
|
||||
if (!pointer_cache_put(cache->pointer, pointer_large->cacheIndex, pointer))
|
||||
goto out_fail;
|
||||
|
||||
return IFCALLRESULT(TRUE, pointer->Set, context, pointer);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
out_fail:
|
||||
pointer_free(context, pointer);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOL update_pointer_new(rdpContext* context, const POINTER_NEW_UPDATE* pointer_new)
|
||||
{
|
||||
rdpPointer* pointer;
|
||||
@@ -251,6 +302,7 @@ void pointer_cache_register_callbacks(rdpUpdate* update)
|
||||
pointer->PointerPosition = update_pointer_position;
|
||||
pointer->PointerSystem = update_pointer_system;
|
||||
pointer->PointerColor = update_pointer_color;
|
||||
pointer->PointerLarge = update_pointer_large;
|
||||
pointer->PointerNew = update_pointer_new;
|
||||
pointer->PointerCached = update_pointer_cached;
|
||||
}
|
||||
@@ -341,6 +393,53 @@ void free_pointer_color_update(rdpContext* context, POINTER_COLOR_UPDATE* pointe
|
||||
free(pointer);
|
||||
}
|
||||
|
||||
POINTER_LARGE_UPDATE* copy_pointer_large_update(rdpContext* context,
|
||||
const POINTER_LARGE_UPDATE* src)
|
||||
{
|
||||
POINTER_LARGE_UPDATE* dst = calloc(1, sizeof(POINTER_LARGE_UPDATE));
|
||||
|
||||
if (!dst || !src)
|
||||
goto fail;
|
||||
|
||||
*dst = *src;
|
||||
|
||||
if (src->lengthAndMask > 0)
|
||||
{
|
||||
dst->andMaskData = calloc(src->lengthAndMask, sizeof(BYTE));
|
||||
|
||||
if (!dst->andMaskData)
|
||||
goto fail;
|
||||
|
||||
memcpy(dst->andMaskData, src->andMaskData, src->lengthAndMask);
|
||||
}
|
||||
|
||||
if (src->lengthXorMask > 0)
|
||||
{
|
||||
dst->xorMaskData = calloc(src->lengthXorMask, sizeof(BYTE));
|
||||
|
||||
if (!dst->xorMaskData)
|
||||
goto fail;
|
||||
|
||||
memcpy(dst->xorMaskData, src->xorMaskData, src->lengthXorMask);
|
||||
}
|
||||
|
||||
return dst;
|
||||
fail:
|
||||
free_pointer_large_update(context, dst);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void free_pointer_large_update(rdpContext* context, POINTER_LARGE_UPDATE* pointer)
|
||||
{
|
||||
WINPR_UNUSED(context);
|
||||
if (!pointer)
|
||||
return;
|
||||
|
||||
free(pointer->xorMaskData);
|
||||
free(pointer->andMaskData);
|
||||
free(pointer);
|
||||
}
|
||||
|
||||
POINTER_NEW_UPDATE* copy_pointer_new_update(rdpContext* context, const POINTER_NEW_UPDATE* src)
|
||||
{
|
||||
POINTER_NEW_UPDATE* dst = calloc(1, sizeof(POINTER_NEW_UPDATE));
|
||||
|
||||
4
libfreerdp/cache/pointer.h
vendored
4
libfreerdp/cache/pointer.h
vendored
@@ -28,6 +28,10 @@ FREERDP_LOCAL POINTER_COLOR_UPDATE* copy_pointer_color_update(rdpContext* contex
|
||||
const POINTER_COLOR_UPDATE* pointer);
|
||||
FREERDP_LOCAL void free_pointer_color_update(rdpContext* context, POINTER_COLOR_UPDATE* pointer);
|
||||
|
||||
FREERDP_LOCAL POINTER_LARGE_UPDATE* copy_pointer_large_update(rdpContext* context,
|
||||
const POINTER_LARGE_UPDATE* pointer);
|
||||
FREERDP_LOCAL void free_pointer_large_update(rdpContext* context, POINTER_LARGE_UPDATE* pointer);
|
||||
|
||||
FREERDP_LOCAL POINTER_NEW_UPDATE* copy_pointer_new_update(rdpContext* context,
|
||||
const POINTER_NEW_UPDATE* pointer);
|
||||
FREERDP_LOCAL void free_pointer_new_update(rdpContext* context, POINTER_NEW_UPDATE* pointer);
|
||||
|
||||
@@ -2479,7 +2479,16 @@ static BOOL rdp_read_large_pointer_capability_set(wStream* s, UINT16 length, rdp
|
||||
return FALSE;
|
||||
|
||||
Stream_Read_UINT16(s, largePointerSupportFlags); /* largePointerSupportFlags (2 bytes) */
|
||||
settings->LargePointerFlag = (largePointerSupportFlags & LARGE_POINTER_FLAG_96x96) ? 1 : 0;
|
||||
settings->LargePointerFlag =
|
||||
largePointerSupportFlags & (LARGE_POINTER_FLAG_96x96 | LARGE_POINTER_FLAG_384x384);
|
||||
if ((largePointerSupportFlags & ~(LARGE_POINTER_FLAG_96x96 | LARGE_POINTER_FLAG_384x384)) != 0)
|
||||
{
|
||||
WLog_WARN(
|
||||
TAG,
|
||||
"TS_LARGE_POINTER_CAPABILITYSET with unsupported flags %04X (all flags %04X) received",
|
||||
largePointerSupportFlags & ~(LARGE_POINTER_FLAG_96x96 | LARGE_POINTER_FLAG_384x384),
|
||||
largePointerSupportFlags);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -2499,7 +2508,8 @@ static BOOL rdp_write_large_pointer_capability_set(wStream* s, const rdpSettings
|
||||
return FALSE;
|
||||
|
||||
header = rdp_capability_set_start(s);
|
||||
largePointerSupportFlags = (settings->LargePointerFlag) ? LARGE_POINTER_FLAG_96x96 : 0;
|
||||
largePointerSupportFlags =
|
||||
settings->LargePointerFlag & (LARGE_POINTER_FLAG_96x96 | LARGE_POINTER_FLAG_384x384);
|
||||
Stream_Write_UINT16(s, largePointerSupportFlags); /* largePointerSupportFlags (2 bytes) */
|
||||
rdp_capability_set_finish(s, header, CAPSET_TYPE_LARGE_POINTER);
|
||||
return TRUE;
|
||||
|
||||
@@ -146,6 +146,7 @@
|
||||
|
||||
/* Large Pointer Support Flags */
|
||||
#define LARGE_POINTER_FLAG_96x96 0x00000001
|
||||
#define LARGE_POINTER_FLAG_384x384 0x00000002
|
||||
|
||||
/* Surface Commands Flags */
|
||||
#define SURFCMDS_SET_SURFACE_BITS 0x00000002
|
||||
|
||||
@@ -470,6 +470,17 @@ static int fastpath_recv_update(rdpFastPath* fastpath, BYTE updateCode, wStream*
|
||||
}
|
||||
break;
|
||||
|
||||
case FASTPATH_UPDATETYPE_LARGE_POINTER:
|
||||
{
|
||||
POINTER_LARGE_UPDATE* pointer_large = update_read_pointer_large(update, s);
|
||||
|
||||
if (pointer_large)
|
||||
{
|
||||
rc = IFCALLRESULT(FALSE, pointer->PointerLarge, context, pointer_large);
|
||||
free_pointer_large_update(context, pointer_large);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -79,7 +79,8 @@ enum FASTPATH_UPDATETYPE
|
||||
FASTPATH_UPDATETYPE_PTR_POSITION = 0x8,
|
||||
FASTPATH_UPDATETYPE_COLOR = 0x9,
|
||||
FASTPATH_UPDATETYPE_CACHED = 0xA,
|
||||
FASTPATH_UPDATETYPE_POINTER = 0xB
|
||||
FASTPATH_UPDATETYPE_POINTER = 0xB,
|
||||
FASTPATH_UPDATETYPE_LARGE_POINTER = 0xC
|
||||
};
|
||||
|
||||
enum FASTPATH_FRAGMENT
|
||||
|
||||
@@ -1440,6 +1440,22 @@ static BOOL update_message_PointerColor(rdpContext* context,
|
||||
MakeMessageId(PointerUpdate, PointerColor), (void*)wParam, NULL);
|
||||
}
|
||||
|
||||
static BOOL update_message_PointerLarge(rdpContext* context, const POINTER_LARGE_UPDATE* pointer)
|
||||
{
|
||||
POINTER_LARGE_UPDATE* wParam;
|
||||
|
||||
if (!context || !context->update || !pointer)
|
||||
return FALSE;
|
||||
|
||||
wParam = copy_pointer_large_update(context, pointer);
|
||||
|
||||
if (!wParam)
|
||||
return FALSE;
|
||||
|
||||
return MessageQueue_Post(context->update->queue, (void*)context,
|
||||
MakeMessageId(PointerUpdate, PointerLarge), (void*)wParam, NULL);
|
||||
}
|
||||
|
||||
static BOOL update_message_PointerNew(rdpContext* context, const POINTER_NEW_UPDATE* pointerNew)
|
||||
{
|
||||
POINTER_NEW_UPDATE* wParam;
|
||||
@@ -2640,11 +2656,13 @@ static BOOL update_message_register_interface(rdpUpdateProxy* message, rdpUpdate
|
||||
message->PointerPosition = pointer->PointerPosition;
|
||||
message->PointerSystem = pointer->PointerSystem;
|
||||
message->PointerColor = pointer->PointerColor;
|
||||
message->PointerLarge = pointer->PointerLarge;
|
||||
message->PointerNew = pointer->PointerNew;
|
||||
message->PointerCached = pointer->PointerCached;
|
||||
pointer->PointerPosition = update_message_PointerPosition;
|
||||
pointer->PointerSystem = update_message_PointerSystem;
|
||||
pointer->PointerColor = update_message_PointerColor;
|
||||
pointer->PointerLarge = update_message_PointerLarge;
|
||||
pointer->PointerNew = update_message_PointerNew;
|
||||
pointer->PointerCached = update_message_PointerCached;
|
||||
return TRUE;
|
||||
|
||||
@@ -123,6 +123,7 @@ struct rdp_update_proxy
|
||||
pPointerColor PointerColor;
|
||||
pPointerNew PointerNew;
|
||||
pPointerCached PointerCached;
|
||||
pPointerLarge PointerLarge;
|
||||
|
||||
HANDLE thread;
|
||||
};
|
||||
|
||||
@@ -421,7 +421,7 @@ rdpSettings* freerdp_settings_new(DWORD flags)
|
||||
gethostname(settings->ClientHostname, 31);
|
||||
settings->ClientHostname[31] = 0;
|
||||
settings->ColorPointerFlag = TRUE;
|
||||
settings->LargePointerFlag = TRUE;
|
||||
settings->LargePointerFlag = (LARGE_POINTER_FLAG_96x96 | LARGE_POINTER_FLAG_384x384);
|
||||
settings->PointerCacheSize = 20;
|
||||
settings->SoundBeepsEnabled = TRUE;
|
||||
settings->DrawGdiPlusEnabled = FALSE;
|
||||
|
||||
@@ -489,6 +489,130 @@ fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static BOOL _update_read_pointer_large(wStream* s, POINTER_LARGE_UPDATE* pointer)
|
||||
{
|
||||
BYTE* newMask;
|
||||
UINT32 scanlineSize;
|
||||
|
||||
if (!pointer)
|
||||
goto fail;
|
||||
|
||||
if (Stream_GetRemainingLength(s) < 14)
|
||||
goto fail;
|
||||
|
||||
Stream_Read_UINT16(s, pointer->xorBpp);
|
||||
Stream_Read_UINT16(s, pointer->cacheIndex); /* cacheIndex (2 bytes) */
|
||||
Stream_Read_UINT16(s, pointer->hotSpotX); /* xPos (2 bytes) */
|
||||
Stream_Read_UINT16(s, pointer->hotSpotY); /* yPos (2 bytes) */
|
||||
|
||||
Stream_Read_UINT16(s, pointer->width); /* width (2 bytes) */
|
||||
Stream_Read_UINT16(s, pointer->height); /* height (2 bytes) */
|
||||
|
||||
if ((pointer->width > 384) || (pointer->height > 384))
|
||||
goto fail;
|
||||
|
||||
Stream_Read_UINT16(s, pointer->lengthAndMask); /* lengthAndMask (2 bytes) */
|
||||
Stream_Read_UINT16(s, pointer->lengthXorMask); /* lengthXorMask (2 bytes) */
|
||||
|
||||
if (pointer->hotSpotX >= pointer->width)
|
||||
pointer->hotSpotX = 0;
|
||||
|
||||
if (pointer->hotSpotY >= pointer->height)
|
||||
pointer->hotSpotY = 0;
|
||||
|
||||
if (pointer->lengthXorMask > 0)
|
||||
{
|
||||
/**
|
||||
* Spec states that:
|
||||
*
|
||||
* xorMaskData (variable): A variable-length array of bytes. Contains the 24-bpp, bottom-up
|
||||
* XOR mask scan-line data. The XOR mask is padded to a 2-byte boundary for each encoded
|
||||
* scan-line. For example, if a 3x3 pixel cursor is being sent, then each scan-line will
|
||||
* consume 10 bytes (3 pixels per scan-line multiplied by 3 bytes per pixel, rounded up to
|
||||
* the next even number of bytes).
|
||||
*
|
||||
* In fact instead of 24-bpp, the bpp parameter is given by the containing packet.
|
||||
*/
|
||||
if (Stream_GetRemainingLength(s) < pointer->lengthXorMask)
|
||||
goto fail;
|
||||
|
||||
scanlineSize = (7 + pointer->xorBpp * pointer->width) / 8;
|
||||
scanlineSize = ((scanlineSize + 1) / 2) * 2;
|
||||
|
||||
if (scanlineSize * pointer->height != pointer->lengthXorMask)
|
||||
{
|
||||
WLog_ERR(TAG,
|
||||
"invalid lengthXorMask: width=%" PRIu32 " height=%" PRIu32 ", %" PRIu32
|
||||
" instead of %" PRIu32 "",
|
||||
pointer->width, pointer->height, pointer->lengthXorMask,
|
||||
scanlineSize * pointer->height);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
newMask = realloc(pointer->xorMaskData, pointer->lengthXorMask);
|
||||
|
||||
if (!newMask)
|
||||
goto fail;
|
||||
|
||||
pointer->xorMaskData = newMask;
|
||||
Stream_Read(s, pointer->xorMaskData, pointer->lengthXorMask);
|
||||
}
|
||||
|
||||
if (pointer->lengthAndMask > 0)
|
||||
{
|
||||
/**
|
||||
* andMaskData (variable): A variable-length array of bytes. Contains the 1-bpp, bottom-up
|
||||
* AND mask scan-line data. The AND mask is padded to a 2-byte boundary for each encoded
|
||||
* scan-line. For example, if a 7x7 pixel cursor is being sent, then each scan-line will
|
||||
* consume 2 bytes (7 pixels per scan-line multiplied by 1 bpp, rounded up to the next even
|
||||
* number of bytes).
|
||||
*/
|
||||
if (Stream_GetRemainingLength(s) < pointer->lengthAndMask)
|
||||
goto fail;
|
||||
|
||||
scanlineSize = ((7 + pointer->width) / 8);
|
||||
scanlineSize = ((1 + scanlineSize) / 2) * 2;
|
||||
|
||||
if (scanlineSize * pointer->height != pointer->lengthAndMask)
|
||||
{
|
||||
WLog_ERR(TAG, "invalid lengthAndMask: %" PRIu32 " instead of %" PRIu32 "",
|
||||
pointer->lengthAndMask, scanlineSize * pointer->height);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
newMask = realloc(pointer->andMaskData, pointer->lengthAndMask);
|
||||
|
||||
if (!newMask)
|
||||
goto fail;
|
||||
|
||||
pointer->andMaskData = newMask;
|
||||
Stream_Read(s, pointer->andMaskData, pointer->lengthAndMask);
|
||||
}
|
||||
|
||||
if (Stream_GetRemainingLength(s) > 0)
|
||||
Stream_Seek_UINT8(s); /* pad (1 byte) */
|
||||
|
||||
return TRUE;
|
||||
fail:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
POINTER_LARGE_UPDATE* update_read_pointer_large(rdpUpdate* update, wStream* s)
|
||||
{
|
||||
POINTER_LARGE_UPDATE* pointer = calloc(1, sizeof(POINTER_LARGE_UPDATE));
|
||||
|
||||
if (!pointer)
|
||||
goto fail;
|
||||
|
||||
if (!_update_read_pointer_large(s, pointer))
|
||||
goto fail;
|
||||
|
||||
return pointer;
|
||||
fail:
|
||||
free_pointer_large_update(update->context, pointer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
POINTER_NEW_UPDATE* update_read_pointer_new(rdpUpdate* update, wStream* s)
|
||||
{
|
||||
POINTER_NEW_UPDATE* pointer_new = calloc(1, sizeof(POINTER_NEW_UPDATE));
|
||||
@@ -585,6 +709,18 @@ BOOL update_recv_pointer(rdpUpdate* update, wStream* s)
|
||||
}
|
||||
break;
|
||||
|
||||
case PTR_MSG_TYPE_POINTER_LARGE:
|
||||
{
|
||||
POINTER_LARGE_UPDATE* pointer_large = update_read_pointer_large(update, s);
|
||||
|
||||
if (pointer_large)
|
||||
{
|
||||
rc = IFCALLRESULT(FALSE, pointer->PointerLarge, context, pointer_large);
|
||||
free_pointer_large_update(context, pointer_large);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PTR_MSG_TYPE_POINTER:
|
||||
{
|
||||
POINTER_NEW_UPDATE* pointer_new = update_read_pointer_new(update, s);
|
||||
@@ -1888,6 +2024,44 @@ out_fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL update_write_pointer_large(wStream* s, const POINTER_LARGE_UPDATE* pointer)
|
||||
{
|
||||
if (!Stream_EnsureRemainingCapacity(s, 32 + pointer->lengthAndMask + pointer->lengthXorMask))
|
||||
return FALSE;
|
||||
|
||||
Stream_Write_UINT16(s, pointer->xorBpp);
|
||||
Stream_Write_UINT16(s, pointer->cacheIndex);
|
||||
Stream_Write_UINT16(s, pointer->hotSpotX);
|
||||
Stream_Write_UINT16(s, pointer->hotSpotY);
|
||||
Stream_Write_UINT16(s, pointer->width);
|
||||
Stream_Write_UINT16(s, pointer->height);
|
||||
Stream_Write_UINT32(s, pointer->lengthAndMask);
|
||||
Stream_Write_UINT32(s, pointer->lengthXorMask);
|
||||
Stream_Write(s, pointer->xorMaskData, pointer->lengthXorMask);
|
||||
Stream_Write(s, pointer->andMaskData, pointer->lengthAndMask);
|
||||
Stream_Write_UINT8(s, 0); /* pad (1 byte) */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL update_send_pointer_large(rdpContext* context, const POINTER_LARGE_UPDATE* pointer)
|
||||
{
|
||||
wStream* s;
|
||||
rdpRdp* rdp = context->rdp;
|
||||
BOOL ret = FALSE;
|
||||
s = fastpath_update_pdu_init(rdp->fastpath);
|
||||
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
if (!update_write_pointer_large(s, pointer))
|
||||
goto out_fail;
|
||||
|
||||
ret = fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_LARGE_POINTER, s, FALSE);
|
||||
out_fail:
|
||||
Stream_Release(s);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL update_send_pointer_new(rdpContext* context, const POINTER_NEW_UPDATE* pointer_new)
|
||||
{
|
||||
wStream* s;
|
||||
@@ -2635,6 +2809,7 @@ void update_register_server_callbacks(rdpUpdate* update)
|
||||
update->pointer->PointerSystem = update_send_pointer_system;
|
||||
update->pointer->PointerPosition = update_send_pointer_position;
|
||||
update->pointer->PointerColor = update_send_pointer_color;
|
||||
update->pointer->PointerLarge = update_send_pointer_large;
|
||||
update->pointer->PointerNew = update_send_pointer_new;
|
||||
update->pointer->PointerCached = update_send_pointer_cached;
|
||||
update->window->WindowCreate = update_send_window_create;
|
||||
|
||||
@@ -55,6 +55,8 @@ FREERDP_LOCAL POINTER_SYSTEM_UPDATE* update_read_pointer_system(rdpUpdate* updat
|
||||
FREERDP_LOCAL POINTER_POSITION_UPDATE* update_read_pointer_position(rdpUpdate* update, wStream* s);
|
||||
FREERDP_LOCAL POINTER_COLOR_UPDATE* update_read_pointer_color(rdpUpdate* update, wStream* s,
|
||||
BYTE xorBpp);
|
||||
FREERDP_LOCAL POINTER_LARGE_UPDATE* update_read_pointer_large(rdpUpdate* update, wStream* s);
|
||||
|
||||
FREERDP_LOCAL POINTER_NEW_UPDATE* update_read_pointer_new(rdpUpdate* update, wStream* s);
|
||||
FREERDP_LOCAL POINTER_CACHED_UPDATE* update_read_pointer_cached(rdpUpdate* update, wStream* s);
|
||||
|
||||
|
||||
@@ -152,6 +152,16 @@ static BOOL pf_client_send_pointer_color(rdpContext* context,
|
||||
return ps->update->pointer->PointerColor(ps, pointer_color);
|
||||
}
|
||||
|
||||
static BOOL pf_client_send_pointer_large(rdpContext* context,
|
||||
const POINTER_LARGE_UPDATE* pointer_large)
|
||||
{
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
proxyData* pdata = pc->pdata;
|
||||
rdpContext* ps = (rdpContext*)pdata->ps;
|
||||
WLog_DBG(TAG, __FUNCTION__);
|
||||
return ps->update->pointer->PointerLarge(ps, pointer_large);
|
||||
}
|
||||
|
||||
static BOOL pf_client_send_pointer_new(rdpContext* context, const POINTER_NEW_UPDATE* pointer_new)
|
||||
{
|
||||
pClientContext* pc = (pClientContext*)context;
|
||||
@@ -324,6 +334,7 @@ void pf_client_register_update_callbacks(rdpUpdate* update)
|
||||
update->pointer->PointerSystem = pf_client_send_pointer_system;
|
||||
update->pointer->PointerPosition = pf_client_send_pointer_position;
|
||||
update->pointer->PointerColor = pf_client_send_pointer_color;
|
||||
update->pointer->PointerLarge = pf_client_send_pointer_large;
|
||||
update->pointer->PointerNew = pf_client_send_pointer_new;
|
||||
update->pointer->PointerCached = pf_client_send_pointer_cached;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user