20#include <freerdp/config.h> 
   25#include <winpr/assert.h> 
   26#include <winpr/stream.h> 
   28#include <freerdp/log.h> 
   33#define TAG FREERDP_TAG("cache.pointer") 
   35static BOOL pointer_cache_put(rdpPointerCache* pointer_cache, UINT32 index, rdpPointer* pointer,
 
   37static rdpPointer* pointer_cache_get(rdpPointerCache* pointer_cache, UINT32 index);
 
   39static void pointer_clear(rdpPointer* pointer)
 
   43    pointer->lengthAndMask = 0;
 
   44    free(pointer->andMaskData);
 
   45    pointer->andMaskData = NULL;
 
   47    pointer->lengthXorMask = 0;
 
   48    free(pointer->xorMaskData);
 
   49    pointer->xorMaskData = NULL;
 
   53static void pointer_free(rdpContext* context, rdpPointer* pointer)
 
   57    IFCALL(pointer->Free, context, pointer);
 
   58    pointer_clear(pointer);
 
   63static BOOL update_pointer_position(rdpContext* context,
 
   66  if (!context || !context->graphics || !context->graphics->Pointer_Prototype ||
 
   74  const rdpPointer* pointer = context->graphics->Pointer_Prototype;
 
   75  WINPR_ASSERT(pointer);
 
   77  return IFCALLRESULT(TRUE, pointer->SetPosition, context, pointer_position->xPos,
 
   78                      pointer_position->yPos);
 
   83  rdpPointer* pointer = NULL;
 
   85  if (!context || !context->graphics || !context->graphics->Pointer_Prototype || !pointer_system)
 
   88  pointer = context->graphics->Pointer_Prototype;
 
   90  switch (pointer_system->type)
 
   93      return IFCALLRESULT(TRUE, pointer->SetNull, context);
 
   96      return IFCALLRESULT(TRUE, pointer->SetDefault, context);
 
   99      WLog_ERR(TAG, 
"Unknown system pointer type (0x%08" PRIX32 
")", pointer_system->type);
 
  104static BOOL upate_pointer_copy_andxor(rdpPointer* pointer, 
const BYTE* andMaskData,
 
  105                                      size_t lengthAndMask, 
const BYTE* xorMaskData,
 
  106                                      size_t lengthXorMask)
 
  108  WINPR_ASSERT(pointer);
 
  110  pointer_clear(pointer);
 
  111  if (lengthAndMask && andMaskData)
 
  113    if (lengthAndMask > UINT32_MAX)
 
  115    pointer->lengthAndMask = (UINT32)lengthAndMask;
 
  116    pointer->andMaskData = (BYTE*)malloc(lengthAndMask);
 
  117    if (!pointer->andMaskData)
 
  120    CopyMemory(pointer->andMaskData, andMaskData, lengthAndMask);
 
  123  if (lengthXorMask && xorMaskData)
 
  125    if (lengthXorMask > UINT32_MAX)
 
  127    pointer->lengthXorMask = (UINT32)lengthXorMask;
 
  128    pointer->xorMaskData = (BYTE*)malloc(lengthXorMask);
 
  129    if (!pointer->xorMaskData)
 
  132    CopyMemory(pointer->xorMaskData, xorMaskData, lengthXorMask);
 
  140  rdpPointer* pointer = NULL;
 
  141  rdpCache* cache = NULL;
 
  143  WINPR_ASSERT(context);
 
  144  WINPR_ASSERT(pointer_color);
 
  146  cache = context->cache;
 
  149  pointer = Pointer_Alloc(context);
 
  153  pointer->xorBpp = 24;
 
  154  pointer->xPos = pointer_color->hotSpotX;
 
  155  pointer->yPos = pointer_color->hotSpotY;
 
  156  pointer->width = pointer_color->width;
 
  157  pointer->height = pointer_color->height;
 
  159  if (!upate_pointer_copy_andxor(pointer, pointer_color->andMaskData,
 
  160                                 pointer_color->lengthAndMask, pointer_color->xorMaskData,
 
  161                                 pointer_color->lengthXorMask))
 
  164  if (!IFCALLRESULT(TRUE, pointer->New, context, pointer))
 
  167  if (!pointer_cache_put(cache->pointer, pointer_color->cacheIndex, pointer, TRUE))
 
  170  return IFCALLRESULT(TRUE, pointer->Set, context, pointer);
 
  173  pointer_free(context, pointer);
 
  179  rdpPointer* pointer = NULL;
 
  180  rdpCache* cache = NULL;
 
  182  WINPR_ASSERT(context);
 
  183  WINPR_ASSERT(pointer_large);
 
  185  cache = context->cache;
 
  188  pointer = Pointer_Alloc(context);
 
  191  pointer->xorBpp = pointer_large->xorBpp;
 
  192  pointer->xPos = pointer_large->hotSpotX;
 
  193  pointer->yPos = pointer_large->hotSpotY;
 
  194  pointer->width = pointer_large->width;
 
  195  pointer->height = pointer_large->height;
 
  197  if (!upate_pointer_copy_andxor(pointer, pointer_large->andMaskData,
 
  198                                 pointer_large->lengthAndMask, pointer_large->xorMaskData,
 
  199                                 pointer_large->lengthXorMask))
 
  202  if (!IFCALLRESULT(TRUE, pointer->New, context, pointer))
 
  205  if (!pointer_cache_put(cache->pointer, pointer_large->cacheIndex, pointer, FALSE))
 
  208  return IFCALLRESULT(TRUE, pointer->Set, context, pointer);
 
  211  pointer_free(context, pointer);
 
  215static BOOL update_pointer_new(rdpContext* context, 
const POINTER_NEW_UPDATE* pointer_new)
 
  217  if (!context || !pointer_new)
 
  220  rdpCache* cache = context->cache;
 
  221  rdpPointer* pointer = Pointer_Alloc(context);
 
  226  pointer->xorBpp = pointer_new->xorBpp;
 
  227  pointer->xPos = pointer_new->colorPtrAttr.hotSpotX;
 
  228  pointer->yPos = pointer_new->colorPtrAttr.hotSpotY;
 
  229  pointer->width = pointer_new->colorPtrAttr.width;
 
  230  pointer->height = pointer_new->colorPtrAttr.height;
 
  231  if (!upate_pointer_copy_andxor(
 
  232          pointer, pointer_new->colorPtrAttr.andMaskData, pointer_new->colorPtrAttr.lengthAndMask,
 
  233          pointer_new->colorPtrAttr.xorMaskData, pointer_new->colorPtrAttr.lengthXorMask))
 
  236  if (!IFCALLRESULT(TRUE, pointer->New, context, pointer))
 
  239  if (!pointer_cache_put(cache->pointer, pointer_new->colorPtrAttr.cacheIndex, pointer, FALSE))
 
  242  return IFCALLRESULT(TRUE, pointer->Set, context, pointer);
 
  245  pointer_free(context, pointer);
 
  251  rdpPointer* pointer = NULL;
 
  252  rdpCache* cache = NULL;
 
  254  WINPR_ASSERT(context);
 
  255  WINPR_ASSERT(pointer_cached);
 
  257  cache = context->cache;
 
  260  pointer = pointer_cache_get(cache->pointer, pointer_cached->cacheIndex);
 
  263    return IFCALLRESULT(TRUE, pointer->Set, context, pointer);
 
  268rdpPointer* pointer_cache_get(rdpPointerCache* pointer_cache, UINT32 index)
 
  270  rdpPointer* pointer = NULL;
 
  272  WINPR_ASSERT(pointer_cache);
 
  274  if (index >= pointer_cache->cacheSize)
 
  276    WLog_ERR(TAG, 
"invalid pointer index:%" PRIu32 
" [%" PRIu32 
"]", index,
 
  277             pointer_cache->cacheSize);
 
  281  WINPR_ASSERT(pointer_cache->entries);
 
  282  pointer = pointer_cache->entries[index];
 
  286BOOL pointer_cache_put(rdpPointerCache* pointer_cache, UINT32 index, rdpPointer* pointer,
 
  289  rdpPointer* prevPointer = NULL;
 
  290  const FreeRDP_Settings_Keys_UInt32 
id =
 
  291      colorCache ? FreeRDP_ColorPointerCacheSize : FreeRDP_PointerCacheSize;
 
  293  WINPR_ASSERT(pointer_cache);
 
  294  WINPR_ASSERT(pointer_cache->context);
 
  297  if (index >= pointer_cache->cacheSize)
 
  300             "invalid pointer index:%" PRIu32 
" [allocated %" PRIu32 
", %s size %" PRIu32 
"]",
 
  301             index, pointer_cache->cacheSize,
 
  302             colorCache ? 
"color-pointer-cache" : 
"pointer-cache", size);
 
  308              "suspicious pointer index:%" PRIu32 
" [allocated %" PRIu32 
", %s size %" PRIu32
 
  310              index, pointer_cache->cacheSize,
 
  311              colorCache ? 
"color-pointer-cache" : 
"pointer-cache", size);
 
  314  WINPR_ASSERT(pointer_cache->entries);
 
  315  prevPointer = pointer_cache->entries[index];
 
  316  pointer_free(pointer_cache->context, prevPointer);
 
  317  pointer_cache->entries[index] = pointer;
 
  321void pointer_cache_register_callbacks(rdpUpdate* update)
 
  323  rdpPointerUpdate* pointer = NULL;
 
  325  WINPR_ASSERT(update);
 
  326  WINPR_ASSERT(update->context);
 
  328  pointer = update->pointer;
 
  329  WINPR_ASSERT(pointer);
 
  333    pointer->PointerPosition = update_pointer_position;
 
  334    pointer->PointerSystem = update_pointer_system;
 
  335    pointer->PointerColor = update_pointer_color;
 
  336    pointer->PointerLarge = update_pointer_large;
 
  337    pointer->PointerNew = update_pointer_new;
 
  338    pointer->PointerCached = update_pointer_cached;
 
  342rdpPointerCache* pointer_cache_new(rdpContext* context)
 
  344  rdpPointerCache* pointer_cache = NULL;
 
  345  rdpSettings* settings = NULL;
 
  347  WINPR_ASSERT(context);
 
  349  settings = context->settings;
 
  350  WINPR_ASSERT(settings);
 
  352  pointer_cache = (rdpPointerCache*)calloc(1, 
sizeof(rdpPointerCache));
 
  357  pointer_cache->context = context;
 
  363  pointer_cache->cacheSize = MAX(size, colorSize) + 1;
 
  365  pointer_cache->entries = (rdpPointer**)calloc(pointer_cache->cacheSize, 
sizeof(rdpPointer*));
 
  367  if (!pointer_cache->entries)
 
  373  return pointer_cache;
 
  376void pointer_cache_free(rdpPointerCache* pointer_cache)
 
  378  if (pointer_cache != NULL)
 
  380    if (pointer_cache->entries)
 
  382      for (UINT32 i = 0; i < pointer_cache->cacheSize; i++)
 
  384        rdpPointer* pointer = pointer_cache->entries[i];
 
  385        pointer_free(pointer_cache->context, pointer);
 
  389    free((
void*)pointer_cache->entries);
 
  404  if (src->lengthAndMask > 0)
 
  406    dst->andMaskData = calloc(src->lengthAndMask, 
sizeof(BYTE));
 
  408    if (!dst->andMaskData)
 
  411    memcpy(dst->andMaskData, src->andMaskData, src->lengthAndMask);
 
  414  if (src->lengthXorMask > 0)
 
  416    dst->xorMaskData = calloc(src->lengthXorMask, 
sizeof(BYTE));
 
  418    if (!dst->xorMaskData)
 
  421    memcpy(dst->xorMaskData, src->xorMaskData, src->lengthXorMask);
 
  426  free_pointer_color_update(context, dst);
 
  432  WINPR_UNUSED(context);
 
  437  free(pointer->xorMaskData);
 
  438  free(pointer->andMaskData);
 
  452  if (src->lengthAndMask > 0)
 
  454    dst->andMaskData = calloc(src->lengthAndMask, 
sizeof(BYTE));
 
  456    if (!dst->andMaskData)
 
  459    memcpy(dst->andMaskData, src->andMaskData, src->lengthAndMask);
 
  462  if (src->lengthXorMask > 0)
 
  464    dst->xorMaskData = calloc(src->lengthXorMask, 
sizeof(BYTE));
 
  466    if (!dst->xorMaskData)
 
  469    memcpy(dst->xorMaskData, src->xorMaskData, src->lengthXorMask);
 
  474  free_pointer_large_update(context, dst);
 
  480  WINPR_UNUSED(context);
 
  484  free(pointer->xorMaskData);
 
  485  free(pointer->andMaskData);
 
  498  if (src->colorPtrAttr.lengthAndMask > 0)
 
  500    dst->colorPtrAttr.andMaskData = calloc(src->colorPtrAttr.lengthAndMask, 
sizeof(BYTE));
 
  502    if (!dst->colorPtrAttr.andMaskData)
 
  505    memcpy(dst->colorPtrAttr.andMaskData, src->colorPtrAttr.andMaskData,
 
  506           src->colorPtrAttr.lengthAndMask);
 
  509  if (src->colorPtrAttr.lengthXorMask > 0)
 
  511    dst->colorPtrAttr.xorMaskData = calloc(src->colorPtrAttr.lengthXorMask, 
sizeof(BYTE));
 
  513    if (!dst->colorPtrAttr.xorMaskData)
 
  516    memcpy(dst->colorPtrAttr.xorMaskData, src->colorPtrAttr.xorMaskData,
 
  517           src->colorPtrAttr.lengthXorMask);
 
  522  free_pointer_new_update(context, dst);
 
  526void free_pointer_new_update(WINPR_ATTR_UNUSED rdpContext* context, 
POINTER_NEW_UPDATE* pointer)
 
  531  free(pointer->colorPtrAttr.xorMaskData);
 
  532  free(pointer->colorPtrAttr.andMaskData);
 
  547  free_pointer_cached_update(context, dst);
 
  553  WINPR_UNUSED(context);
 
  559  WINPR_UNUSED(context);
 
  568  if (!dst || !pointer)
 
  574  free_pointer_position_update(context, dst);
 
  580  WINPR_UNUSED(context);
 
  589  if (!dst || !pointer)
 
  595  free_pointer_system_update(context, dst);
 
FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.