21#include <freerdp/config.h> 
   24#include <winpr/assert.h> 
   25#include <winpr/cast.h> 
   26#include <winpr/file.h> 
   27#include <winpr/path.h> 
   28#include <winpr/synch.h> 
   29#include <winpr/thread.h> 
   30#include <winpr/sysinfo.h> 
   31#include <winpr/interlocked.h> 
   33#include <freerdp/log.h> 
   34#include <freerdp/channels/drdynvc.h> 
   38#define TAG CLIENT_TAG("shadow") 
   43  BOOL gfxSurfaceCreated;
 
   53#define BitmapUpdateProxy(client, bitmap) \ 
   54  BitmapUpdateProxyEx((client), (bitmap), __FILE__, __LINE__, __func__) 
   55static BOOL BitmapUpdateProxyEx(rdpShadowClient* client, 
const BITMAP_UPDATE* bitmap,
 
   56                                const char* file, 
size_t line, 
const char* fkt)
 
   61  rdpShadowServer* server = client->server;
 
   64  rdpContext* context = (rdpContext*)client;
 
   66  rdpUpdate* update = context->update;
 
   69  if (server->SupportMultiRectBitmapUpdates)
 
   71    const BOOL rc = IFCALLRESULT(FALSE, update->BitmapUpdate, context, bitmap);
 
   74      const DWORD log_level = WLOG_ERROR;
 
   75      wLog* log = WLog_Get(TAG);
 
   76      if (WLog_IsLevelActive(log, log_level))
 
   78        WLog_PrintTextMessage(log, log_level, line, file, fkt,
 
   79                              "BitmapUpdate[count %" PRIu32 
"] failed", bitmap->number);
 
   86    for (UINT32 x = 0; x < bitmap->number; x++)
 
   92      cur.skipCompression = bitmap->skipCompression;
 
   93      const BOOL rc = IFCALLRESULT(FALSE, update->BitmapUpdate, context, &cur);
 
   96        const DWORD log_level = WLOG_ERROR;
 
   97        wLog* log = WLog_Get(TAG);
 
   98        if (WLog_IsLevelActive(log, log_level))
 
  100          WLog_PrintTextMessage(log, log_level, line, file, fkt,
 
  101                                "BitmapUpdate[count 1, at %" PRIu32 
"] failed", x);
 
  111static inline BOOL shadow_client_rdpgfx_new_surface(rdpShadowClient* client)
 
  113  UINT error = CHANNEL_RC_OK;
 
  116  RdpgfxServerContext* context = NULL;
 
  117  rdpSettings* settings = NULL;
 
  119  WINPR_ASSERT(client);
 
  120  context = client->rdpgfx;
 
  121  WINPR_ASSERT(context);
 
  122  settings = ((rdpContext*)client)->settings;
 
  123  WINPR_ASSERT(settings);
 
  129  createSurface.pixelFormat = GFX_PIXEL_FORMAT_XRGB_8888;
 
  130  createSurface.surfaceId = client->surfaceId;
 
  131  surfaceToOutput.outputOriginX = 0;
 
  132  surfaceToOutput.outputOriginY = 0;
 
  133  surfaceToOutput.surfaceId = client->surfaceId;
 
  134  surfaceToOutput.reserved = 0;
 
  135  IFCALLRET(context->CreateSurface, error, context, &createSurface);
 
  139    WLog_ERR(TAG, 
"CreateSurface failed with error %" PRIu32 
"", error);
 
  143  IFCALLRET(context->MapSurfaceToOutput, error, context, &surfaceToOutput);
 
  147    WLog_ERR(TAG, 
"MapSurfaceToOutput failed with error %" PRIu32 
"", error);
 
  154static inline BOOL shadow_client_rdpgfx_release_surface(rdpShadowClient* client)
 
  156  UINT error = CHANNEL_RC_OK;
 
  158  RdpgfxServerContext* context = NULL;
 
  160  WINPR_ASSERT(client);
 
  162  context = client->rdpgfx;
 
  163  WINPR_ASSERT(context);
 
  165  pdu.surfaceId = client->surfaceId++;
 
  166  IFCALLRET(context->DeleteSurface, error, context, &pdu);
 
  170    WLog_ERR(TAG, 
"DeleteSurface failed with error %" PRIu32 
"", error);
 
  177static inline BOOL shadow_client_rdpgfx_reset_graphic(rdpShadowClient* client)
 
  179  UINT error = CHANNEL_RC_OK;
 
  181  RdpgfxServerContext* context = NULL;
 
  182  rdpSettings* settings = NULL;
 
  184  WINPR_ASSERT(client);
 
  185  WINPR_ASSERT(client->rdpgfx);
 
  187  context = client->rdpgfx;
 
  188  WINPR_ASSERT(context);
 
  190  settings = client->context.settings;
 
  191  WINPR_ASSERT(settings);
 
  195  pdu.monitorCount = client->subsystem->numMonitors;
 
  196  pdu.monitorDefArray = client->subsystem->monitors;
 
  197  IFCALLRET(context->ResetGraphics, error, context, &pdu);
 
  201    WLog_ERR(TAG, 
"ResetGraphics failed with error %" PRIu32 
"", error);
 
  205  client->first_frame = TRUE;
 
  209static inline void shadow_client_free_queued_message(
void* obj)
 
  211  wMessage* message = (wMessage*)obj;
 
  213  WINPR_ASSERT(message);
 
  216    message->Free(message);
 
  217    message->Free = NULL;
 
  221static void shadow_client_context_free(freerdp_peer* peer, rdpContext* context)
 
  223  rdpShadowClient* client = (rdpShadowClient*)context;
 
  224  rdpShadowServer* server = NULL;
 
  230  server = client->server;
 
  231  if (server && server->clients)
 
  232    ArrayList_Remove(server->clients, (
void*)client);
 
  234  shadow_encoder_free(client->encoder);
 
  237  MessageQueue_Free(client->MsgQueue);
 
  238  WTSCloseServer(client->vcm);
 
  239  region16_uninit(&(client->invalidRegion));
 
  240  DeleteCriticalSection(&(client->lock));
 
  242  client->MsgQueue = NULL;
 
  243  client->encoder = NULL;
 
  247static BOOL shadow_client_context_new(freerdp_peer* peer, rdpContext* context)
 
  250  const char bind_address[] = 
"bind-address,";
 
  251  rdpShadowClient* client = (rdpShadowClient*)context;
 
  252  rdpSettings* settings = NULL;
 
  253  const rdpSettings* srvSettings = NULL;
 
  254  rdpShadowServer* server = NULL;
 
  255  const wObject cb = { NULL, NULL, NULL, shadow_client_free_queued_message, NULL };
 
  257  WINPR_ASSERT(client);
 
  259  WINPR_ASSERT(peer->context);
 
  261  server = (rdpShadowServer*)peer->ContextExtra;
 
  262  WINPR_ASSERT(server);
 
  264  srvSettings = server->settings;
 
  265  WINPR_ASSERT(srvSettings);
 
  267  client->surfaceId = 1;
 
  268  client->server = server;
 
  269  client->subsystem = server->subsystem;
 
  270  WINPR_ASSERT(client->subsystem);
 
  272  settings = peer->context->settings;
 
  273  WINPR_ASSERT(settings);
 
  285          settings, FreeRDP_RemoteFxRlgrMode,
 
  295          settings, FreeRDP_SupportGraphicsPipeline,
 
  310  if (server->ipcSocket && (strncmp(bind_address, server->ipcSocket,
 
  311                                    strnlen(bind_address, 
sizeof(bind_address))) != 0))
 
  319  client->inLobby = TRUE;
 
  320  client->mayView = server->mayView;
 
  321  client->mayInteract = server->mayInteract;
 
  323  if (!InitializeCriticalSectionAndSpinCount(&(client->lock), 4000))
 
  326  region16_init(&(client->invalidRegion));
 
  327  client->vcm = WTSOpenServerA((LPSTR)peer->context);
 
  329  if (!client->vcm || client->vcm == INVALID_HANDLE_VALUE)
 
  332  if (!(client->MsgQueue = MessageQueue_New(&cb)))
 
  335  if (!(client->encoder = shadow_encoder_new(client)))
 
  338  if (!ArrayList_Append(server->clients, (
void*)client))
 
  344  shadow_client_context_free(peer, context);
 
  348static inline void shadow_client_mark_invalid(rdpShadowClient* client, UINT32 numRects,
 
  352  rdpSettings* settings = NULL;
 
  354  WINPR_ASSERT(client);
 
  355  WINPR_ASSERT(rects || (numRects == 0));
 
  357  settings = client->context.settings;
 
  358  WINPR_ASSERT(settings);
 
  360  EnterCriticalSection(&(client->lock));
 
  365    for (UINT32 index = 0; index < numRects; index++)
 
  367      region16_union_rect(&(client->invalidRegion), &(client->invalidRegion), &rects[index]);
 
  372    screenRegion.left = 0;
 
  373    screenRegion.top = 0;
 
  378    region16_union_rect(&(client->invalidRegion), &(client->invalidRegion), &screenRegion);
 
  381  LeaveCriticalSection(&(client->lock));
 
  390static inline BOOL shadow_client_recalc_desktop_size(rdpShadowClient* client)
 
  394  rdpShadowServer* server = NULL;
 
  395  rdpSettings* settings = NULL;
 
  398  WINPR_ASSERT(client);
 
  399  server = client->server;
 
  400  settings = client->context.settings;
 
  402  WINPR_ASSERT(server);
 
  403  WINPR_ASSERT(server->surface);
 
  404  WINPR_ASSERT(settings);
 
  406  WINPR_ASSERT(server->surface->width <= UINT16_MAX);
 
  407  WINPR_ASSERT(server->surface->height <= UINT16_MAX);
 
  408  viewport.right = (UINT16)server->surface->width;
 
  409  viewport.bottom = (UINT16)server->surface->height;
 
  411  if (server->shareSubRect)
 
  413    rectangles_intersection(&viewport, &(server->subRect), &viewport);
 
  416  width = viewport.right - viewport.left;
 
  417  height = viewport.bottom - viewport.top;
 
  419  WINPR_ASSERT(width >= 0);
 
  420  WINPR_ASSERT(width <= UINT16_MAX);
 
  421  WINPR_ASSERT(height >= 0);
 
  422  WINPR_ASSERT(height <= UINT16_MAX);
 
  430static BOOL shadow_client_capabilities(freerdp_peer* peer)
 
  432  rdpShadowSubsystem* subsystem = NULL;
 
  433  rdpShadowClient* client = NULL;
 
  438  client = (rdpShadowClient*)peer->context;
 
  439  WINPR_ASSERT(client);
 
  440  WINPR_ASSERT(client->server);
 
  442  subsystem = client->server->subsystem;
 
  443  WINPR_ASSERT(subsystem);
 
  445  IFCALLRET(subsystem->ClientCapabilities, ret, subsystem, client);
 
  448    WLog_WARN(TAG, 
"subsystem->ClientCapabilities failed");
 
  453static void shadow_reset_desktop_resize(rdpShadowClient* client)
 
  455  WINPR_ASSERT(client);
 
  456  client->resizeRequested = FALSE;
 
  459static BOOL shadow_send_desktop_resize(rdpShadowClient* client)
 
  462  rdpUpdate* update = NULL;
 
  463  rdpSettings* settings = NULL;
 
  464  const freerdp_peer* peer = NULL;
 
  466  WINPR_ASSERT(client);
 
  468  settings = client->context.settings;
 
  469  peer = client->context.peer;
 
  471  WINPR_ASSERT(client->server);
 
  472  WINPR_ASSERT(client->server->surface);
 
  474  const UINT32 resizeWidth = client->server->surface->width;
 
  475  const UINT32 resizeHeight = client->server->surface->height;
 
  477  if (client->resizeRequested)
 
  479    if ((resizeWidth == client->resizeWidth) && (resizeHeight == client->resizeHeight))
 
  484                "detected previous resize request for resolution %" PRIu32 
"x%" PRIu32
 
  485                ", still have %" PRIu32 
"x%" PRIu32 
", disconnecting peer",
 
  486                resizeWidth, resizeHeight, w, h);
 
  491  update = client->context.update;
 
  492  WINPR_ASSERT(update);
 
  493  WINPR_ASSERT(update->DesktopResize);
 
  501  rc = update->DesktopResize(update->context);
 
  502  WLog_INFO(TAG, 
"Client %s resize requested (%" PRIu32 
"x%" PRIu32 
"@%" PRIu32 
")",
 
  503            peer->hostname, resizeWidth, resizeHeight,
 
  505  client->resizeRequested = TRUE;
 
  506  client->resizeWidth = resizeWidth;
 
  507  client->resizeHeight = resizeHeight;
 
  512static BOOL shadow_client_post_connect(freerdp_peer* peer)
 
  515  rdpSettings* settings = NULL;
 
  516  rdpShadowClient* client = NULL;
 
  517  rdpShadowServer* server = NULL;
 
  518  rdpShadowSubsystem* subsystem = NULL;
 
  522  client = (rdpShadowClient*)peer->context;
 
  523  WINPR_ASSERT(client);
 
  525  settings = peer->context->settings;
 
  526  WINPR_ASSERT(settings);
 
  528  server = client->server;
 
  529  WINPR_ASSERT(server);
 
  531  subsystem = server->subsystem;
 
  532  WINPR_ASSERT(subsystem);
 
  540  const UINT32 MultifragMaxRequestSize =
 
  542  if (MultifragMaxRequestSize < 0x3F0000)
 
  545        settings, FreeRDP_NSCodec,
 
  551  WLog_INFO(TAG, 
"Client from %s is activated (%" PRIu32 
"x%" PRIu32 
"@%" PRIu32 
")",
 
  556  if (shadow_client_channels_post_connect(client) != CHANNEL_RC_OK)
 
  559  shadow_client_mark_invalid(client, 0, NULL);
 
  566  if (Username && Password)
 
  574    if (subsystem->Authenticate)
 
  576      authStatus = subsystem->Authenticate(subsystem, client, Username, Domain, Password);
 
  581      WLog_ERR(TAG, 
"client authentication failure: %d", authStatus);
 
  586  if (subsystem->ClientConnect)
 
  588    return subsystem->ClientConnect(subsystem, client);
 
  595static inline void shadow_client_convert_rects(rdpShadowClient* client, 
RECTANGLE_16* dst,
 
  598  WINPR_ASSERT(client);
 
  599  WINPR_ASSERT(client->server);
 
  601  WINPR_ASSERT(src || (numRects == 0));
 
  603  if (client->server->shareSubRect)
 
  605    UINT16 offsetX = client->server->subRect.left;
 
  606    UINT16 offsetY = client->server->subRect.top;
 
  608    for (UINT32 i = 0; i < numRects; i++)
 
  613      d->left = s->left + offsetX;
 
  614      d->right = s->right + offsetX;
 
  615      d->top = s->top + offsetY;
 
  616      d->bottom = s->bottom + offsetY;
 
  628static BOOL shadow_client_refresh_request(rdpShadowClient* client)
 
  630  wMessage message = { 0 };
 
  633  WINPR_ASSERT(client);
 
  634  WINPR_ASSERT(client->subsystem);
 
  636  MsgPipe = client->subsystem->MsgPipe;
 
  637  WINPR_ASSERT(MsgPipe);
 
  639  message.id = SHADOW_MSG_IN_REFRESH_REQUEST_ID;
 
  640  message.wParam = NULL;
 
  641  message.lParam = NULL;
 
  642  message.context = (
void*)client;
 
  644  return MessageQueue_Dispatch(MsgPipe->In, &message);
 
  647static BOOL shadow_client_refresh_rect(rdpContext* context, BYTE count, 
const RECTANGLE_16* areas)
 
  649  rdpShadowClient* client = (rdpShadowClient*)context;
 
  665    shadow_client_convert_rects(client, rects, areas, count);
 
  666    shadow_client_mark_invalid(client, count, rects);
 
  671    shadow_client_mark_invalid(client, 0, NULL);
 
  674  return shadow_client_refresh_request(client);
 
  677static BOOL shadow_client_suppress_output(rdpContext* context, BYTE allow, 
const RECTANGLE_16* area)
 
  679  rdpShadowClient* client = (rdpShadowClient*)context;
 
  682  WINPR_ASSERT(client);
 
  684  client->suppressOutput = allow ? FALSE : TRUE;
 
  690      shadow_client_convert_rects(client, ®ion, area, 1);
 
  691      shadow_client_mark_invalid(client, 1, ®ion);
 
  695      shadow_client_mark_invalid(client, 0, NULL);
 
  699  return shadow_client_refresh_request(client);
 
  702static BOOL shadow_client_activate(freerdp_peer* peer)
 
  706  rdpShadowClient* client = (rdpShadowClient*)peer->context;
 
  707  WINPR_ASSERT(client);
 
  710  if (shadow_client_recalc_desktop_size(client))
 
  711    return shadow_send_desktop_resize(client);
 
  713  shadow_reset_desktop_resize(client);
 
  714  client->activated = TRUE;
 
  715  client->inLobby = client->mayView ? FALSE : TRUE;
 
  717  if (shadow_encoder_reset(client->encoder) < 0)
 
  719    WLog_ERR(TAG, 
"Failed to reset encoder");
 
  724  return shadow_client_refresh_rect(&client->context, 0, NULL);
 
  727static BOOL shadow_client_logon(freerdp_peer* peer, 
const SEC_WINNT_AUTH_IDENTITY* identity,
 
  733  char* password = NULL;
 
  734  rdpSettings* settings = NULL;
 
  736  WINPR_UNUSED(automatic);
 
  739  WINPR_ASSERT(identity);
 
  741  WINPR_ASSERT(peer->context);
 
  743  settings = peer->context->settings;
 
  744  WINPR_ASSERT(settings);
 
  746  if (identity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE)
 
  749      user = ConvertWCharNToUtf8Alloc(identity->User, identity->UserLength, NULL);
 
  751    if (identity->Domain)
 
  752      domain = ConvertWCharNToUtf8Alloc(identity->Domain, identity->DomainLength, NULL);
 
  754    if (identity->Password)
 
  755      password = ConvertWCharNToUtf8Alloc(identity->Password, identity->PasswordLength, NULL);
 
  760      user = _strdup((
char*)identity->User);
 
  762    if (identity->Domain)
 
  763      domain = _strdup((
char*)identity->Domain);
 
  765    if (identity->Password)
 
  766      password = _strdup((
char*)identity->Password);
 
  769  if ((identity->User && !user) || (identity->Domain && !domain) ||
 
  770      (identity->Password && !password))
 
  797static inline void shadow_client_common_frame_acknowledge(rdpShadowClient* client, UINT32 frameId)
 
  807  WINPR_ASSERT(client);
 
  808  WINPR_ASSERT(client->encoder);
 
  809  client->encoder->lastAckframeId = frameId;
 
  812static BOOL shadow_client_surface_frame_acknowledge(rdpContext* context, UINT32 frameId)
 
  814  rdpShadowClient* client = (rdpShadowClient*)context;
 
  815  shadow_client_common_frame_acknowledge(client, frameId);
 
  819  WINPR_ASSERT(client);
 
  820  WINPR_ASSERT(client->encoder);
 
  821  client->encoder->queueDepth = QUEUE_DEPTH_UNAVAILABLE;
 
  826shadow_client_rdpgfx_frame_acknowledge(RdpgfxServerContext* context,
 
  829  rdpShadowClient* client = NULL;
 
  831  WINPR_ASSERT(context);
 
  832  WINPR_ASSERT(frameAcknowledge);
 
  834  client = (rdpShadowClient*)context->custom;
 
  835  shadow_client_common_frame_acknowledge(client, frameAcknowledge->frameId);
 
  837  WINPR_ASSERT(client);
 
  838  WINPR_ASSERT(client->encoder);
 
  839  client->encoder->queueDepth = frameAcknowledge->queueDepth;
 
  840  return CHANNEL_RC_OK;
 
  843static BOOL shadow_are_caps_filtered(
const rdpSettings* settings, UINT32 caps)
 
  845  const UINT32 capList[] = { RDPGFX_CAPVERSION_8,   RDPGFX_CAPVERSION_81,
 
  846                           RDPGFX_CAPVERSION_10,  RDPGFX_CAPVERSION_101,
 
  847                           RDPGFX_CAPVERSION_102, RDPGFX_CAPVERSION_103,
 
  848                           RDPGFX_CAPVERSION_104, RDPGFX_CAPVERSION_105,
 
  849                           RDPGFX_CAPVERSION_106, RDPGFX_CAPVERSION_106_ERR,
 
  850                           RDPGFX_CAPVERSION_107 };
 
  852  WINPR_ASSERT(settings);
 
  855  for (UINT32 x = 0; x < ARRAYSIZE(capList); x++)
 
  857    if (caps == capList[x])
 
  858      return (filter & (1 << x)) != 0;
 
  864static UINT shadow_client_send_caps_confirm(RdpgfxServerContext* context, rdpShadowClient* client,
 
  867  WINPR_ASSERT(context);
 
  868  WINPR_ASSERT(client);
 
  871  WINPR_ASSERT(context->CapsConfirm);
 
  872  UINT rc = context->CapsConfirm(context, pdu);
 
  873  client->areGfxCapsReady = (rc == CHANNEL_RC_OK);
 
  877static BOOL shadow_client_caps_test_version(RdpgfxServerContext* context, rdpShadowClient* client,
 
  879                                            UINT32 capsSetCount, UINT32 capsVersion, UINT* rc)
 
  881  const rdpSettings* srvSettings = NULL;
 
  882  rdpSettings* clientSettings = NULL;
 
  884  WINPR_ASSERT(context);
 
  885  WINPR_ASSERT(client);
 
  886  WINPR_ASSERT(capsSets || (capsSetCount == 0));
 
  889  WINPR_ASSERT(context->rdpcontext);
 
  890  srvSettings = context->rdpcontext->settings;
 
  891  WINPR_ASSERT(srvSettings);
 
  893  clientSettings = client->context.settings;
 
  894  WINPR_ASSERT(clientSettings);
 
  896  if (shadow_are_caps_filtered(srvSettings, capsVersion))
 
  899  for (UINT32 index = 0; index < capsSetCount; index++)
 
  903    if (currentCaps->version == capsVersion)
 
  908      BOOL avc444v2 = FALSE;
 
  911      BOOL progressive = FALSE;
 
  916      flags = pdu.capsSet->flags;
 
  919                                     (flags & RDPGFX_CAPS_FLAG_SMALL_CACHE) ? TRUE : FALSE))
 
  922      avc444v2 = avc444 = !(flags & RDPGFX_CAPS_FLAG_AVC_DISABLED);
 
  951      if (!avc444v2 && !avc444 && !avc420)
 
  952        pdu.capsSet->flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED;
 
  954      *rc = shadow_client_send_caps_confirm(context, client, &pdu);
 
  967static UINT shadow_client_rdpgfx_caps_advertise(RdpgfxServerContext* context,
 
  970  UINT rc = ERROR_INTERNAL_ERROR;
 
  971  const rdpSettings* srvSettings = NULL;
 
  972  rdpSettings* clientSettings = NULL;
 
  977  WINPR_ASSERT(context);
 
  978  WINPR_ASSERT(capsAdvertise);
 
  980  rdpShadowClient* client = (rdpShadowClient*)context->custom;
 
  981  WINPR_ASSERT(client);
 
  982  WINPR_ASSERT(context->rdpcontext);
 
  984  srvSettings = context->rdpcontext->settings;
 
  985  WINPR_ASSERT(srvSettings);
 
  987  clientSettings = client->context.settings;
 
  988  WINPR_ASSERT(clientSettings);
 
  992      (shadow_encoder_prepare(client->encoder, FREERDP_CODEC_AVC420 | FREERDP_CODEC_AVC444) >= 0);
 
 1003  if (!shadow_client_refresh_rect(&client->context, 0, NULL))
 
 1006  if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
 
 1007                                      capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_107, &rc))
 
 1010  if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
 
 1011                                      capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_106, &rc))
 
 1014  if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
 
 1015                                      capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_106_ERR,
 
 1019  if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
 
 1020                                      capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_105, &rc))
 
 1023  if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
 
 1024                                      capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_104, &rc))
 
 1027  if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
 
 1028                                      capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_103, &rc))
 
 1031  if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
 
 1032                                      capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_102, &rc))
 
 1035  if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
 
 1036                                      capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_101, &rc))
 
 1039  if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
 
 1040                                      capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_10, &rc))
 
 1043  if (!shadow_are_caps_filtered(srvSettings, RDPGFX_CAPVERSION_81))
 
 1045    for (UINT32 index = 0; index < capsAdvertise->capsSetCount; index++)
 
 1047      const RDPGFX_CAPSET* currentCaps = &capsAdvertise->capsSets[index];
 
 1049      if (currentCaps->version == RDPGFX_CAPVERSION_81)
 
 1053        pdu.capsSet = ∩︀
 
 1055        flags = pdu.capsSet->flags;
 
 1063                                       (flags & RDPGFX_CAPS_FLAG_THINCLIENT) ? TRUE
 
 1067                                       (flags & RDPGFX_CAPS_FLAG_SMALL_CACHE) ? TRUE
 
 1071#ifndef WITH_GFX_H264 
 1074        pdu.capsSet->flags &= ~RDPGFX_CAPS_FLAG_AVC420_ENABLED;
 
 1080                  clientSettings, FreeRDP_GfxH264,
 
 1081                  (flags & RDPGFX_CAPS_FLAG_AVC420_ENABLED) ? TRUE : FALSE))
 
 1091        return shadow_client_send_caps_confirm(context, client, &pdu);
 
 1096  if (!shadow_are_caps_filtered(srvSettings, RDPGFX_CAPVERSION_8))
 
 1098    for (UINT32 index = 0; index < capsAdvertise->capsSetCount; index++)
 
 1100      const RDPGFX_CAPSET* currentCaps = &capsAdvertise->capsSets[index];
 
 1102      if (currentCaps->version == RDPGFX_CAPVERSION_8)
 
 1106        pdu.capsSet = ∩︀
 
 1107        flags = pdu.capsSet->flags;
 
 1117                                       (flags & RDPGFX_CAPS_FLAG_THINCLIENT) ? TRUE
 
 1121                                       (flags & RDPGFX_CAPS_FLAG_SMALL_CACHE) ? TRUE
 
 1125        return shadow_client_send_caps_confirm(context, client, &pdu);
 
 1130  return CHANNEL_RC_UNSUPPORTED_VERSION;
 
 1136  WINPR_ASSERT(havc420);
 
 1137  return sizeof(UINT32) 
 
 1139               * havc420->meta.numRegionRects +
 
 1148static BOOL shadow_client_send_surface_gfx(rdpShadowClient* client, 
const BYTE* pSrcData,
 
 1149                                           UINT32 nSrcStep, UINT32 SrcFormat, UINT16 nXSrc,
 
 1150                                           UINT16 nYSrc, UINT16 nWidth, UINT16 nHeight)
 
 1153  UINT error = CHANNEL_RC_OK;
 
 1154  const rdpContext* context = (
const rdpContext*)client;
 
 1155  const rdpSettings* settings = NULL;
 
 1156  rdpShadowEncoder* encoder = NULL;
 
 1162  if (!context || !pSrcData)
 
 1165  settings = context->settings;
 
 1166  encoder = client->encoder;
 
 1168  if (!settings || !encoder)
 
 1171  if (client->first_frame)
 
 1173    rfx_context_reset(encoder->rfx, nWidth, nHeight);
 
 1174    client->first_frame = FALSE;
 
 1177  cmdstart.frameId = shadow_encoder_create_frame_id(encoder);
 
 1178  GetSystemTime(&sTime);
 
 1179  cmdstart.timestamp = (UINT32)(sTime.wHour << 22U | sTime.wMinute << 16U | sTime.wSecond << 10U |
 
 1180                                sTime.wMilliseconds);
 
 1181  cmdend.frameId = cmdstart.frameId;
 
 1182  cmd.surfaceId = client->surfaceId;
 
 1183  cmd.format = PIXEL_FORMAT_BGRX32;
 
 1186  cmd.right = cmd.left + nWidth;
 
 1187  cmd.bottom = cmd.top + nHeight;
 
 1189  cmd.height = nHeight;
 
 1196  if (GfxAVC444 || GfxAVC444v2)
 
 1201    BYTE version = GfxAVC444v2 ? 2 : 1;
 
 1203    if (shadow_encoder_prepare(encoder, FREERDP_CODEC_AVC444) < 0)
 
 1205      WLog_ERR(TAG, 
"Failed to prepare encoder FREERDP_CODEC_AVC444");
 
 1209    WINPR_ASSERT(cmd.left <= UINT16_MAX);
 
 1210    WINPR_ASSERT(cmd.top <= UINT16_MAX);
 
 1211    WINPR_ASSERT(cmd.right <= UINT16_MAX);
 
 1212    WINPR_ASSERT(cmd.bottom <= UINT16_MAX);
 
 1213    regionRect.left = (UINT16)cmd.left;
 
 1214    regionRect.top = (UINT16)cmd.top;
 
 1215    regionRect.right = (UINT16)cmd.right;
 
 1216    regionRect.bottom = (UINT16)cmd.bottom;
 
 1217    rc = avc444_compress(encoder->h264, pSrcData, cmd.format, nSrcStep, nWidth, nHeight,
 
 1218                         version, ®ionRect, &avc444.LC, &avc444.bitstream[0].data,
 
 1219                         &avc444.bitstream[0].length, &avc444.bitstream[1].data,
 
 1220                         &avc444.bitstream[1].length, &avc444.bitstream[0].meta,
 
 1221                         &avc444.bitstream[1].meta);
 
 1224      WLog_ERR(TAG, 
"avc420_compress failed for avc444");
 
 1231      avc444.cbAvc420EncodedBitstream1 = rdpgfx_estimate_h264_avc420(&avc444.bitstream[0]);
 
 1232      cmd.codecId = GfxAVC444v2 ? RDPGFX_CODECID_AVC444v2 : RDPGFX_CODECID_AVC444;
 
 1233      cmd.extra = (
void*)&avc444;
 
 1234      IFCALLRET(client->rdpgfx->SurfaceFrameCommand, error, client->rdpgfx, &cmd, &cmdstart,
 
 1238    free_h264_metablock(&avc444.bitstream[0].meta);
 
 1239    free_h264_metablock(&avc444.bitstream[1].meta);
 
 1242      WLog_ERR(TAG, 
"SurfaceFrameCommand failed with error %" PRIu32 
"", error);
 
 1252    if (shadow_encoder_prepare(encoder, FREERDP_CODEC_AVC420) < 0)
 
 1254      WLog_ERR(TAG, 
"Failed to prepare encoder FREERDP_CODEC_AVC420");
 
 1258    WINPR_ASSERT(cmd.left <= UINT16_MAX);
 
 1259    WINPR_ASSERT(cmd.top <= UINT16_MAX);
 
 1260    WINPR_ASSERT(cmd.right <= UINT16_MAX);
 
 1261    WINPR_ASSERT(cmd.bottom <= UINT16_MAX);
 
 1262    regionRect.left = (UINT16)cmd.left;
 
 1263    regionRect.top = (UINT16)cmd.top;
 
 1264    regionRect.right = (UINT16)cmd.right;
 
 1265    regionRect.bottom = (UINT16)cmd.bottom;
 
 1266    rc = avc420_compress(encoder->h264, pSrcData, cmd.format, nSrcStep, nWidth, nHeight,
 
 1267                         ®ionRect, &avc420.data, &avc420.length, &avc420.meta);
 
 1270      WLog_ERR(TAG, 
"avc420_compress failed");
 
 1277      cmd.codecId = RDPGFX_CODECID_AVC420;
 
 1278      cmd.extra = (
void*)&avc420;
 
 1280      IFCALLRET(client->rdpgfx->SurfaceFrameCommand, error, client->rdpgfx, &cmd, &cmdstart,
 
 1283    free_h264_metablock(&avc420.meta);
 
 1287      WLog_ERR(TAG, 
"SurfaceFrameCommand failed with error %" PRIu32 
"", error);
 
 1299    if (shadow_encoder_prepare(encoder, FREERDP_CODEC_REMOTEFX) < 0)
 
 1301      WLog_ERR(TAG, 
"Failed to prepare encoder FREERDP_CODEC_REMOTEFX");
 
 1305    s = Stream_New(NULL, 1024);
 
 1308    WINPR_ASSERT(cmd.left <= UINT16_MAX);
 
 1309    WINPR_ASSERT(cmd.top <= UINT16_MAX);
 
 1310    WINPR_ASSERT(cmd.right <= UINT16_MAX);
 
 1311    WINPR_ASSERT(cmd.bottom <= UINT16_MAX);
 
 1312    rect.x = (UINT16)cmd.left;
 
 1313    rect.y = (UINT16)cmd.top;
 
 1314    rect.width = WINPR_ASSERTING_INT_CAST(UINT16, cmd.right - cmd.left);
 
 1315    rect.height = WINPR_ASSERTING_INT_CAST(UINT16, cmd.bottom - cmd.top);
 
 1317    rc = rfx_compose_message(encoder->rfx, s, &rect, 1, pSrcData, nWidth, nHeight, nSrcStep);
 
 1321      WLog_ERR(TAG, 
"rfx_compose_message failed");
 
 1322      Stream_Free(s, TRUE);
 
 1329      const size_t pos = Stream_GetPosition(s);
 
 1330      WINPR_ASSERT(pos <= UINT32_MAX);
 
 1332      cmd.codecId = RDPGFX_CODECID_CAVIDEO;
 
 1333      cmd.data = Stream_Buffer(s);
 
 1334      cmd.length = (UINT32)pos;
 
 1336      IFCALLRET(client->rdpgfx->SurfaceFrameCommand, error, client->rdpgfx, &cmd, &cmdstart,
 
 1340    Stream_Free(s, TRUE);
 
 1343      WLog_ERR(TAG, 
"SurfaceFrameCommand failed with error %" PRIu32 
"", error);
 
 1353    if (shadow_encoder_prepare(encoder, FREERDP_CODEC_PROGRESSIVE) < 0)
 
 1355      WLog_ERR(TAG, 
"Failed to prepare encoder FREERDP_CODEC_PROGRESSIVE");
 
 1359    WINPR_ASSERT(cmd.left <= UINT16_MAX);
 
 1360    WINPR_ASSERT(cmd.top <= UINT16_MAX);
 
 1361    WINPR_ASSERT(cmd.right <= UINT16_MAX);
 
 1362    WINPR_ASSERT(cmd.bottom <= UINT16_MAX);
 
 1363    regionRect.left = (UINT16)cmd.left;
 
 1364    regionRect.top = (UINT16)cmd.top;
 
 1365    regionRect.right = (UINT16)cmd.right;
 
 1366    regionRect.bottom = (UINT16)cmd.bottom;
 
 1367    region16_init(®ion);
 
 1368    region16_union_rect(®ion, ®ion, ®ionRect);
 
 1369    rc = progressive_compress(encoder->progressive, pSrcData, nSrcStep * nHeight, cmd.format,
 
 1370                              nWidth, nHeight, nSrcStep, ®ion, &cmd.data, &cmd.length);
 
 1371    region16_uninit(®ion);
 
 1374      WLog_ERR(TAG, 
"progressive_compress failed");
 
 1381      cmd.codecId = RDPGFX_CODECID_CAPROGRESSIVE;
 
 1383      IFCALLRET(client->rdpgfx->SurfaceFrameCommand, error, client->rdpgfx, &cmd, &cmdstart,
 
 1389      WLog_ERR(TAG, 
"SurfaceFrameCommand failed with error %" PRIu32 
"", error);
 
 1395    const UINT32 w = cmd.right - cmd.left;
 
 1396    const UINT32 h = cmd.bottom - cmd.top;
 
 1398        &pSrcData[cmd.top * nSrcStep + cmd.left * FreeRDPGetBytesPerPixel(SrcFormat)];
 
 1399    if (shadow_encoder_prepare(encoder, FREERDP_CODEC_PLANAR) < 0)
 
 1401      WLog_ERR(TAG, 
"Failed to prepare encoder FREERDP_CODEC_PLANAR");
 
 1405    const BOOL rc = freerdp_bitmap_planar_context_reset(encoder->planar, w, h);
 
 1409    freerdp_planar_topdown_image(encoder->planar, TRUE);
 
 1411    cmd.data = freerdp_bitmap_compress_planar(encoder->planar, src, SrcFormat, w, h, nSrcStep,
 
 1413    WINPR_ASSERT(cmd.data || (cmd.length == 0));
 
 1415    cmd.codecId = RDPGFX_CODECID_PLANAR;
 
 1417    IFCALLRET(client->rdpgfx->SurfaceFrameCommand, error, client->rdpgfx, &cmd, &cmdstart,
 
 1422      WLog_ERR(TAG, 
"SurfaceFrameCommand failed with error %" PRIu32 
"", error);
 
 1428    const UINT32 w = cmd.right - cmd.left;
 
 1429    const UINT32 h = cmd.bottom - cmd.top;
 
 1430    const UINT32 length = w * 4 * h;
 
 1432    BYTE* data = malloc(length);
 
 1436    BOOL rc = freerdp_image_copy_no_overlap(data, PIXEL_FORMAT_BGRA32, 0, 0, 0, w, h, pSrcData,
 
 1437                                            SrcFormat, nSrcStep, cmd.left, cmd.top, NULL, 0);
 
 1445    cmd.length = length;
 
 1446    cmd.codecId = RDPGFX_CODECID_UNCOMPRESSED;
 
 1448    IFCALLRET(client->rdpgfx->SurfaceFrameCommand, error, client->rdpgfx, &cmd, &cmdstart,
 
 1453      WLog_ERR(TAG, 
"SurfaceFrameCommand failed with error %" PRIu32 
"", error);
 
 1460static BOOL stream_surface_bits_supported(
const rdpSettings* settings)
 
 1462  const UINT32 supported =
 
 1464  return ((supported & SURFCMDS_STREAM_SURFACE_BITS) != 0);
 
 1467static BOOL set_surface_bits_supported(
const rdpSettings* settings)
 
 1469  const UINT32 supported =
 
 1471  return ((supported & SURFCMDS_SET_SURFACE_BITS) != 0);
 
 1474static BOOL is_surface_command_supported(
const rdpSettings* settings)
 
 1476  if (stream_surface_bits_supported(settings))
 
 1480    if (supported && (rfxID != 0))
 
 1483  if (set_surface_bits_supported(settings))
 
 1487    if (supported && (nsID != 0))
 
 1498static BOOL shadow_client_send_surface_bits(rdpShadowClient* client, BYTE* pSrcData,
 
 1499                                            UINT32 nSrcStep, UINT16 nXSrc, UINT16 nYSrc,
 
 1500                                            UINT16 nWidth, UINT16 nHeight)
 
 1506  size_t numMessages = 0;
 
 1508  rdpUpdate* update = NULL;
 
 1509  rdpContext* context = (rdpContext*)client;
 
 1510  rdpSettings* settings = NULL;
 
 1511  rdpShadowEncoder* encoder = NULL;
 
 1514  if (!context || !pSrcData)
 
 1517  update = context->update;
 
 1518  settings = context->settings;
 
 1519  encoder = client->encoder;
 
 1521  if (!update || !settings || !encoder)
 
 1524  if (encoder->frameAck)
 
 1525    frameId = shadow_encoder_create_frame_id(encoder);
 
 1530  if (stream_surface_bits_supported(settings) &&
 
 1535    if (shadow_encoder_prepare(encoder, FREERDP_CODEC_REMOTEFX) < 0)
 
 1537      WLog_ERR(TAG, 
"Failed to prepare encoder FREERDP_CODEC_REMOTEFX");
 
 1544    rect.width = nWidth;
 
 1545    rect.height = nHeight;
 
 1547    const UINT32 MultifragMaxRequestSize =
 
 1549    RFX_MESSAGE_LIST* messages =
 
 1550        rfx_encode_messages(encoder->rfx, &rect, 1, pSrcData,
 
 1553                            nSrcStep, &numMessages, MultifragMaxRequestSize);
 
 1556      WLog_ERR(TAG, 
"rfx_encode_messages failed");
 
 1560    cmd.cmdType = CMDTYPE_STREAM_SURFACE_BITS;
 
 1561    WINPR_ASSERT(rfxID <= UINT16_MAX);
 
 1562    cmd.bmp.codecID = (UINT16)rfxID;
 
 1573    cmd.skipCompression = TRUE;
 
 1575    for (
size_t i = 0; i < numMessages; i++)
 
 1577      Stream_SetPosition(s, 0);
 
 1579      const RFX_MESSAGE* msg = rfx_message_list_get(messages, i);
 
 1580      if (!rfx_write_message(encoder->rfx, s, msg))
 
 1582        WLog_ERR(TAG, 
"rfx_write_message failed");
 
 1587      WINPR_ASSERT(Stream_GetPosition(s) <= UINT32_MAX);
 
 1588      cmd.bmp.bitmapDataLength = (UINT32)Stream_GetPosition(s);
 
 1589      cmd.bmp.bitmapData = Stream_Buffer(s);
 
 1590      first = (i == 0) ? TRUE : FALSE;
 
 1591      last = ((i + 1) == numMessages) ? TRUE : FALSE;
 
 1593      if (!encoder->frameAck)
 
 1594        IFCALLRET(update->SurfaceBits, ret, update->context, &cmd);
 
 1596        IFCALLRET(update->SurfaceFrameBits, ret, update->context, &cmd, first, last,
 
 1601        WLog_ERR(TAG, 
"Send surface bits(RemoteFxCodec) failed");
 
 1606    rfx_message_list_free(messages);
 
 1608  else if (set_surface_bits_supported(settings) &&
 
 1611    if (shadow_encoder_prepare(encoder, FREERDP_CODEC_NSCODEC) < 0)
 
 1613      WLog_ERR(TAG, 
"Failed to prepare encoder FREERDP_CODEC_NSCODEC");
 
 1618    Stream_SetPosition(s, 0);
 
 1619    pSrcData = &pSrcData[(nYSrc * nSrcStep) + (nXSrc * 4)];
 
 1620    nsc_compose_message(encoder->nsc, s, pSrcData, nWidth, nHeight, nSrcStep);
 
 1621    cmd.cmdType = CMDTYPE_SET_SURFACE_BITS;
 
 1623    WINPR_ASSERT(nsID <= UINT16_MAX);
 
 1624    cmd.bmp.codecID = (UINT16)nsID;
 
 1625    cmd.destLeft = nXSrc;
 
 1626    cmd.destTop = nYSrc;
 
 1627    cmd.destRight = cmd.destLeft + nWidth;
 
 1628    cmd.destBottom = cmd.destTop + nHeight;
 
 1629    cmd.bmp.width = nWidth;
 
 1630    cmd.bmp.height = nHeight;
 
 1631    WINPR_ASSERT(Stream_GetPosition(s) <= UINT32_MAX);
 
 1632    cmd.bmp.bitmapDataLength = (UINT32)Stream_GetPosition(s);
 
 1633    cmd.bmp.bitmapData = Stream_Buffer(s);
 
 1637    if (!encoder->frameAck)
 
 1638      IFCALLRET(update->SurfaceBits, ret, update->context, &cmd);
 
 1640      IFCALLRET(update->SurfaceFrameBits, ret, update->context, &cmd, first, last, frameId);
 
 1644      WLog_ERR(TAG, 
"Send surface bits(NSCodec) failed");
 
 1656static BOOL shadow_client_send_bitmap_update(rdpShadowClient* client, BYTE* pSrcData,
 
 1657                                             UINT32 nSrcStep, UINT16 nXSrc, UINT16 nYSrc,
 
 1658                                             UINT16 nWidth, UINT16 nHeight)
 
 1662  BYTE* buffer = NULL;
 
 1669  UINT32 SrcFormat = 0;
 
 1671  rdpContext* context = (rdpContext*)client;
 
 1672  UINT32 totalBitmapSize = 0;
 
 1673  UINT32 updateSizeEstimate = 0;
 
 1677  if (!context || !pSrcData)
 
 1680  rdpUpdate* update = context->update;
 
 1681  rdpSettings* settings = context->settings;
 
 1682  rdpShadowEncoder* encoder = client->encoder;
 
 1684  if (!update || !settings || !encoder)
 
 1687  const UINT32 maxUpdateSize =
 
 1691    if (shadow_encoder_prepare(encoder, FREERDP_CODEC_INTERLEAVED) < 0)
 
 1693      WLog_ERR(TAG, 
"Failed to prepare encoder FREERDP_CODEC_INTERLEAVED");
 
 1699    if (shadow_encoder_prepare(encoder, FREERDP_CODEC_PLANAR) < 0)
 
 1701      WLog_ERR(TAG, 
"Failed to prepare encoder FREERDP_CODEC_PLANAR");
 
 1706  SrcFormat = PIXEL_FORMAT_BGRX32;
 
 1708  if ((nXSrc % 4) != 0)
 
 1710    nWidth += (nXSrc % 4);
 
 1711    nXSrc -= (nXSrc % 4);
 
 1714  if ((nYSrc % 4) != 0)
 
 1716    nHeight += (nYSrc % 4);
 
 1717    nYSrc -= (nYSrc % 4);
 
 1720  rows = (nHeight / 64) + ((nHeight % 64) ? 1 : 0);
 
 1721  cols = (nWidth / 64) + ((nWidth % 64) ? 1 : 0);
 
 1723  totalBitmapSize = 0;
 
 1724  bitmapUpdate.number = rows * cols;
 
 1729  bitmapUpdate.rectangles = bitmapData;
 
 1731  if ((nWidth % 4) != 0)
 
 1733    nWidth += (4 - (nWidth % 4));
 
 1736  if ((nHeight % 4) != 0)
 
 1738    nHeight += (4 - (nHeight % 4));
 
 1741  for (yIdx = 0; yIdx < rows; yIdx++)
 
 1743    for (xIdx = 0; xIdx < cols; xIdx++)
 
 1745      bitmap = &bitmapData[k];
 
 1747      bitmap->height = 64;
 
 1748      bitmap->destLeft = nXSrc + (xIdx * 64);
 
 1749      bitmap->destTop = nYSrc + (yIdx * 64);
 
 1751      if (((INT64)bitmap->destLeft + bitmap->width) > (nXSrc + nWidth))
 
 1752        bitmap->width = (UINT32)(nXSrc + nWidth) - bitmap->destLeft;
 
 1754      if (((INT64)bitmap->destTop + bitmap->height) > (nYSrc + nHeight))
 
 1755        bitmap->height = (UINT32)(nYSrc + nHeight) - bitmap->destTop;
 
 1757      bitmap->destRight = bitmap->destLeft + bitmap->width - 1;
 
 1758      bitmap->destBottom = bitmap->destTop + bitmap->height - 1;
 
 1759      bitmap->compressed = TRUE;
 
 1761      if ((bitmap->width < 4) || (bitmap->height < 4))
 
 1767        UINT32 bytesPerPixel = (bitsPerPixel + 7) / 8;
 
 1768        DstSize = 64 * 64 * 4;
 
 1769        buffer = encoder->grid[k];
 
 1770        interleaved_compress(encoder->interleaved, buffer, &DstSize, bitmap->width,
 
 1771                             bitmap->height, pSrcData, SrcFormat, nSrcStep,
 
 1772                             bitmap->destLeft, bitmap->destTop, NULL, bitsPerPixel);
 
 1773        bitmap->bitmapDataStream = buffer;
 
 1774        bitmap->bitmapLength = DstSize;
 
 1775        bitmap->bitsPerPixel = bitsPerPixel;
 
 1776        bitmap->cbScanWidth = bitmap->width * bytesPerPixel;
 
 1777        bitmap->cbUncompressedSize = bitmap->width * bitmap->height * bytesPerPixel;
 
 1782        buffer = encoder->grid[k];
 
 1783        data = &pSrcData[(bitmap->destTop * nSrcStep) + (bitmap->destLeft * 4)];
 
 1786            freerdp_bitmap_compress_planar(encoder->planar, data, SrcFormat, bitmap->width,
 
 1787                                           bitmap->height, nSrcStep, buffer, &dstSize);
 
 1788        bitmap->bitmapDataStream = buffer;
 
 1789        bitmap->bitmapLength = dstSize;
 
 1790        bitmap->bitsPerPixel = 32;
 
 1791        bitmap->cbScanWidth = bitmap->width * 4;
 
 1792        bitmap->cbUncompressedSize = bitmap->width * bitmap->height * 4;
 
 1795      bitmap->cbCompFirstRowSize = 0;
 
 1796      bitmap->cbCompMainBodySize = bitmap->bitmapLength;
 
 1797      totalBitmapSize += bitmap->bitmapLength;
 
 1802  bitmapUpdate.number = k;
 
 1803  updateSizeEstimate = totalBitmapSize + (k * bitmapUpdate.number) + 16;
 
 1805  if (updateSizeEstimate > maxUpdateSize)
 
 1809    UINT32 updateSize = 0;
 
 1810    UINT32 newUpdateSize = 0;
 
 1816    if (!fragBitmapData)
 
 1818      WLog_ERR(TAG, 
"Failed to allocate memory for fragBitmapData");
 
 1823    bitmapUpdate.rectangles = fragBitmapData;
 
 1829      newUpdateSize = updateSize + (bitmapData[i].bitmapLength + 16);
 
 1831      if (newUpdateSize < maxUpdateSize)
 
 1833        CopyMemory(&fragBitmapData[j++], &bitmapData[i++], 
sizeof(
BITMAP_DATA));
 
 1834        updateSize = newUpdateSize;
 
 1837      if ((newUpdateSize >= maxUpdateSize) || (i + 1) >= k)
 
 1839        bitmapUpdate.number = j;
 
 1840        ret = BitmapUpdateProxy(client, &bitmapUpdate);
 
 1850    free(fragBitmapData);
 
 1854    ret = BitmapUpdateProxy(client, &bitmapUpdate);
 
 1867static BOOL shadow_client_send_surface_update(rdpShadowClient* client, SHADOW_GFX_STATUS* pStatus)
 
 1874  rdpContext* context = (rdpContext*)client;
 
 1875  rdpSettings* settings = NULL;
 
 1876  rdpShadowServer* server = NULL;
 
 1877  rdpShadowSurface* surface = NULL;
 
 1881  BYTE* pSrcData = NULL;
 
 1882  UINT32 nSrcStep = 0;
 
 1883  UINT32 SrcFormat = 0;
 
 1884  UINT32 numRects = 0;
 
 1887  if (!context || !pStatus)
 
 1890  settings = context->settings;
 
 1891  server = client->server;
 
 1893  if (!settings || !server)
 
 1896  surface = client->inLobby ? server->lobby : server->surface;
 
 1901  EnterCriticalSection(&(client->lock));
 
 1902  region16_init(&invalidRegion);
 
 1903  region16_copy(&invalidRegion, &(client->invalidRegion));
 
 1904  region16_clear(&(client->invalidRegion));
 
 1905  LeaveCriticalSection(&(client->lock));
 
 1907  EnterCriticalSection(&surface->lock);
 
 1908  rects = region16_rects(&(surface->invalidRegion), &numRects);
 
 1910  for (UINT32 index = 0; index < numRects; index++)
 
 1911    region16_union_rect(&invalidRegion, &invalidRegion, &rects[index]);
 
 1913  surfaceRect.left = 0;
 
 1914  surfaceRect.top = 0;
 
 1915  WINPR_ASSERT(surface->width <= UINT16_MAX);
 
 1916  WINPR_ASSERT(surface->height <= UINT16_MAX);
 
 1917  surfaceRect.right = (UINT16)surface->width;
 
 1918  surfaceRect.bottom = (UINT16)surface->height;
 
 1919  region16_intersect_rect(&invalidRegion, &invalidRegion, &surfaceRect);
 
 1921  if (server->shareSubRect)
 
 1923    region16_intersect_rect(&invalidRegion, &invalidRegion, &(server->subRect));
 
 1926  if (region16_is_empty(&invalidRegion))
 
 1932  extents = region16_extents(&invalidRegion);
 
 1933  nXSrc = extents->left;
 
 1934  nYSrc = extents->top;
 
 1935  nWidth = extents->right - extents->left;
 
 1936  nHeight = extents->bottom - extents->top;
 
 1937  pSrcData = surface->data;
 
 1938  nSrcStep = surface->scanline;
 
 1939  SrcFormat = surface->format;
 
 1942  if (server->shareSubRect)
 
 1946    subX = server->subRect.left;
 
 1947    subY = server->subRect.top;
 
 1950    WINPR_ASSERT(nXSrc >= 0);
 
 1951    WINPR_ASSERT(nXSrc <= UINT16_MAX);
 
 1952    WINPR_ASSERT(nYSrc >= 0);
 
 1953    WINPR_ASSERT(nYSrc <= UINT16_MAX);
 
 1954    pSrcData = &pSrcData[((UINT16)subY * nSrcStep) + ((UINT16)subX * 4U)];
 
 1963    if (pStatus->gfxOpened && client->areGfxCapsReady)
 
 1970      if (!pStatus->gfxSurfaceCreated)
 
 1973        if (!(ret = shadow_client_rdpgfx_reset_graphic(client)))
 
 1976        if (!(ret = shadow_client_rdpgfx_new_surface(client)))
 
 1979        pStatus->gfxSurfaceCreated = TRUE;
 
 1982      WINPR_ASSERT(nWidth >= 0);
 
 1983      WINPR_ASSERT(nWidth <= UINT16_MAX);
 
 1984      WINPR_ASSERT(nHeight >= 0);
 
 1985      WINPR_ASSERT(nHeight <= UINT16_MAX);
 
 1986      ret = shadow_client_send_surface_gfx(client, pSrcData, nSrcStep, SrcFormat, 0, 0,
 
 1987                                           (UINT16)nWidth, (UINT16)nHeight);
 
 1994  else if (is_surface_command_supported(settings))
 
 1996    WINPR_ASSERT(nXSrc >= 0);
 
 1997    WINPR_ASSERT(nXSrc <= UINT16_MAX);
 
 1998    WINPR_ASSERT(nYSrc >= 0);
 
 1999    WINPR_ASSERT(nYSrc <= UINT16_MAX);
 
 2000    WINPR_ASSERT(nWidth >= 0);
 
 2001    WINPR_ASSERT(nWidth <= UINT16_MAX);
 
 2002    WINPR_ASSERT(nHeight >= 0);
 
 2003    WINPR_ASSERT(nHeight <= UINT16_MAX);
 
 2004    ret = shadow_client_send_surface_bits(client, pSrcData, nSrcStep, (UINT16)nXSrc,
 
 2005                                          (UINT16)nYSrc, (UINT16)nWidth, (UINT16)nHeight);
 
 2009    WINPR_ASSERT(nXSrc >= 0);
 
 2010    WINPR_ASSERT(nXSrc <= UINT16_MAX);
 
 2011    WINPR_ASSERT(nYSrc >= 0);
 
 2012    WINPR_ASSERT(nYSrc <= UINT16_MAX);
 
 2013    WINPR_ASSERT(nWidth >= 0);
 
 2014    WINPR_ASSERT(nWidth <= UINT16_MAX);
 
 2015    WINPR_ASSERT(nHeight >= 0);
 
 2016    WINPR_ASSERT(nHeight <= UINT16_MAX);
 
 2017    ret = shadow_client_send_bitmap_update(client, pSrcData, nSrcStep, (UINT16)nXSrc,
 
 2018                                           (UINT16)nYSrc, (UINT16)nWidth, (UINT16)nHeight);
 
 2022  LeaveCriticalSection(&surface->lock);
 
 2023  region16_uninit(&invalidRegion);
 
 2034static BOOL shadow_client_send_resize(rdpShadowClient* client, SHADOW_GFX_STATUS* pStatus)
 
 2036  rdpContext* context = (rdpContext*)client;
 
 2037  rdpSettings* settings = NULL;
 
 2038  freerdp_peer* peer = NULL;
 
 2040  if (!context || !pStatus)
 
 2043  peer = context->peer;
 
 2044  settings = context->settings;
 
 2046  if (!peer || !settings)
 
 2054  client->activated = FALSE;
 
 2057  if (pStatus->gfxSurfaceCreated)
 
 2059    if (!shadow_client_rdpgfx_release_surface(client))
 
 2062    pStatus->gfxSurfaceCreated = FALSE;
 
 2066  if (!shadow_send_desktop_resize(client))
 
 2068  shadow_reset_desktop_resize(client);
 
 2071  EnterCriticalSection(&(client->lock));
 
 2072  region16_clear(&(client->invalidRegion));
 
 2073  LeaveCriticalSection(&(client->lock));
 
 2083static BOOL shadow_client_surface_update(rdpShadowClient* client, 
REGION16* region)
 
 2085  UINT32 numRects = 0;
 
 2087  rects = region16_rects(region, &numRects);
 
 2088  shadow_client_mark_invalid(client, numRects, rects);
 
 2098static inline BOOL shadow_client_no_surface_update(rdpShadowClient* client,
 
 2099                                                   SHADOW_GFX_STATUS* pStatus)
 
 2101  rdpShadowServer* server = NULL;
 
 2102  rdpShadowSurface* surface = NULL;
 
 2103  WINPR_UNUSED(pStatus);
 
 2104  WINPR_ASSERT(client);
 
 2105  server = client->server;
 
 2106  WINPR_ASSERT(server);
 
 2107  surface = client->inLobby ? server->lobby : server->surface;
 
 2108  EnterCriticalSection(&surface->lock);
 
 2109  const BOOL rc = shadow_client_surface_update(client, &(surface->invalidRegion));
 
 2110  LeaveCriticalSection(&surface->lock);
 
 2114static int shadow_client_subsystem_process_message(rdpShadowClient* client, wMessage* message)
 
 2116  rdpContext* context = (rdpContext*)client;
 
 2117  rdpUpdate* update = NULL;
 
 2119  WINPR_ASSERT(message);
 
 2120  WINPR_ASSERT(context);
 
 2121  update = context->update;
 
 2122  WINPR_ASSERT(update);
 
 2126  switch (message->id)
 
 2128    case SHADOW_MSG_OUT_POINTER_POSITION_UPDATE_ID:
 
 2133      pointerPosition.xPos = msg->xPos;
 
 2134      pointerPosition.yPos = msg->yPos;
 
 2136      WINPR_ASSERT(client->server);
 
 2137      if (client->server->shareSubRect)
 
 2139        pointerPosition.xPos -= client->server->subRect.left;
 
 2140        pointerPosition.yPos -= client->server->subRect.top;
 
 2143      if (client->activated)
 
 2145        if ((msg->xPos != client->pointerX) || (msg->yPos != client->pointerY))
 
 2147          WINPR_ASSERT(update->pointer);
 
 2148          IFCALL(update->pointer->PointerPosition, context, &pointerPosition);
 
 2149          client->pointerX = msg->xPos;
 
 2150          client->pointerY = msg->yPos;
 
 2157    case SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE_ID:
 
 2166      pointerNew.xorBpp = 24;
 
 2167      pointerColor = &(pointerNew.colorPtrAttr);
 
 2168      pointerColor->cacheIndex = 0;
 
 2169      pointerColor->hotSpotX = WINPR_ASSERTING_INT_CAST(UINT16, msg->xHot);
 
 2170      pointerColor->hotSpotY = WINPR_ASSERTING_INT_CAST(UINT16, msg->yHot);
 
 2171      pointerColor->width = WINPR_ASSERTING_INT_CAST(UINT16, msg->width);
 
 2172      pointerColor->height = WINPR_ASSERTING_INT_CAST(UINT16, msg->height);
 
 2173      pointerColor->lengthAndMask = WINPR_ASSERTING_INT_CAST(UINT16, msg->lengthAndMask);
 
 2174      pointerColor->lengthXorMask = WINPR_ASSERTING_INT_CAST(UINT16, msg->lengthXorMask);
 
 2175      pointerColor->xorMaskData = msg->xorMaskData;
 
 2176      pointerColor->andMaskData = msg->andMaskData;
 
 2177      pointerCached.cacheIndex = pointerColor->cacheIndex;
 
 2179      if (client->activated)
 
 2181        IFCALL(update->pointer->PointerNew, context, &pointerNew);
 
 2182        if (client->server->ShowMouseCursor)
 
 2184          IFCALL(update->pointer->PointerCached, context, &pointerCached);
 
 2189          pointer_system.type = SYSPTR_NULL;
 
 2190          IFCALL(update->pointer->PointerSystem, context, &pointer_system);
 
 2197    case SHADOW_MSG_OUT_AUDIO_OUT_SAMPLES_ID:
 
 2204      if (client->activated && client->rdpsnd && client->rdpsnd->Activated)
 
 2206        client->rdpsnd->src_format = msg->audio_format;
 
 2207        IFCALL(client->rdpsnd->SendSamples, client->rdpsnd, msg->buf, msg->nFrames,
 
 2214    case SHADOW_MSG_OUT_AUDIO_OUT_VOLUME_ID:
 
 2219      if (client->activated && client->rdpsnd && client->rdpsnd->Activated)
 
 2221        IFCALL(client->rdpsnd->SetVolume, client->rdpsnd, msg->left, msg->right);
 
 2228      WLog_ERR(TAG, 
"Unknown message id: %" PRIu32 
"", message->id);
 
 2232  shadow_client_free_queued_message(message);
 
 2236static DWORD WINAPI shadow_client_thread(LPVOID arg)
 
 2238  rdpShadowClient* client = (rdpShadowClient*)arg;
 
 2241  wMessage message = { 0 };
 
 2242  wMessage pointerPositionMsg = { 0 };
 
 2243  wMessage pointerAlphaMsg = { 0 };
 
 2244  wMessage audioVolumeMsg = { 0 };
 
 2245  HANDLE ChannelEvent = 0;
 
 2246  void* UpdateSubscriber = NULL;
 
 2247  HANDLE UpdateEvent = 0;
 
 2248  freerdp_peer* peer = NULL;
 
 2249  rdpContext* context = NULL;
 
 2250  rdpSettings* settings = NULL;
 
 2251  rdpShadowServer* server = NULL;
 
 2252  rdpShadowSubsystem* subsystem = NULL;
 
 2253  wMessageQueue* MsgQueue = NULL;
 
 2255  SHADOW_GFX_STATUS gfxstatus = { 0 };
 
 2256  rdpUpdate* update = NULL;
 
 2258  WINPR_ASSERT(client);
 
 2260  MsgQueue = client->MsgQueue;
 
 2261  WINPR_ASSERT(MsgQueue);
 
 2263  server = client->server;
 
 2264  WINPR_ASSERT(server);
 
 2265  subsystem = server->subsystem;
 
 2266  context = (rdpContext*)client;
 
 2267  peer = context->peer;
 
 2269  WINPR_ASSERT(peer->context);
 
 2271  settings = peer->context->settings;
 
 2272  WINPR_ASSERT(settings);
 
 2274  peer->Capabilities = shadow_client_capabilities;
 
 2275  peer->PostConnect = shadow_client_post_connect;
 
 2276  peer->Activate = shadow_client_activate;
 
 2277  peer->Logon = shadow_client_logon;
 
 2278  shadow_input_register_callbacks(peer->context->input);
 
 2280  rc = peer->Initialize(peer);
 
 2284  update = peer->context->update;
 
 2285  WINPR_ASSERT(update);
 
 2287  update->RefreshRect = shadow_client_refresh_rect;
 
 2288  update->SuppressOutput = shadow_client_suppress_output;
 
 2289  update->SurfaceFrameAcknowledge = shadow_client_surface_frame_acknowledge;
 
 2291  if ((!client->vcm) || (!subsystem->updateEvent))
 
 2294  UpdateSubscriber = shadow_multiclient_get_subscriber(subsystem->updateEvent);
 
 2296  if (!UpdateSubscriber)
 
 2299  UpdateEvent = shadow_multiclient_getevent(UpdateSubscriber);
 
 2300  WINPR_ASSERT(UpdateEvent);
 
 2302  ChannelEvent = WTSVirtualChannelManagerGetEventHandle(client->vcm);
 
 2303  WINPR_ASSERT(ChannelEvent);
 
 2315    HANDLE events[MAXIMUM_WAIT_OBJECTS] = { 0 };
 
 2317    events[nCount++] = UpdateEvent;
 
 2319      DWORD tmp = peer->GetEventHandles(peer, &events[nCount], 64 - nCount);
 
 2323        WLog_ERR(TAG, 
"Failed to get FreeRDP transport event handles");
 
 2329    events[nCount++] = ChannelEvent;
 
 2330    events[nCount++] = MessageQueue_Event(MsgQueue);
 
 2332#if defined(CHANNEL_RDPGFX_SERVER) 
 2333    HANDLE gfxevent = rdpgfx_server_get_event_handle(client->rdpgfx);
 
 2336      events[nCount++] = gfxevent;
 
 2339    status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
 
 2341    if (status == WAIT_FAILED)
 
 2344    if (WaitForSingleObject(UpdateEvent, 0) == WAIT_OBJECT_0)
 
 2353      if (client->activated && !client->suppressOutput)
 
 2358        if (shadow_client_recalc_desktop_size(client))
 
 2361          if (!shadow_client_send_resize(client, &gfxstatus))
 
 2363            WLog_ERR(TAG, 
"Failed to send resize message");
 
 2370          if (!shadow_client_send_surface_update(client, &gfxstatus))
 
 2372            WLog_ERR(TAG, 
"Failed to send surface update");
 
 2380        if (!shadow_client_no_surface_update(client, &gfxstatus))
 
 2382          WLog_ERR(TAG, 
"Failed to handle surface update");
 
 2391      (void)shadow_multiclient_consume(UpdateSubscriber);
 
 2394    WINPR_ASSERT(peer->CheckFileDescriptor);
 
 2395    if (!peer->CheckFileDescriptor(peer))
 
 2397      WLog_ERR(TAG, 
"Failed to check FreeRDP file descriptor");
 
 2401    if (client->activated &&
 
 2402        WTSVirtualChannelManagerIsChannelJoined(client->vcm, DRDYNVC_SVC_CHANNEL_NAME))
 
 2404      switch (WTSVirtualChannelManagerGetDrdynvcState(client->vcm))
 
 2407        case DRDYNVC_STATE_NONE:
 
 2410          if (!WTSVirtualChannelManagerCheckFileDescriptor(client->vcm))
 
 2412            WLog_ERR(TAG, 
"Failed to initialize drdynvc channel");
 
 2418        case DRDYNVC_STATE_READY:
 
 2419#if defined(CHANNEL_AUDIN_SERVER) 
 2420          if (client->audin && !IFCALLRESULT(TRUE, client->audin->IsOpen, client->audin))
 
 2422            if (!IFCALLRESULT(FALSE, client->audin->Open, client->audin))
 
 2424              WLog_ERR(TAG, 
"Failed to initialize audin channel");
 
 2432              client->rdpgfx && !gfxstatus.gfxOpened)
 
 2434            client->rdpgfx->FrameAcknowledge = shadow_client_rdpgfx_frame_acknowledge;
 
 2435            client->rdpgfx->CapsAdvertise = shadow_client_rdpgfx_caps_advertise;
 
 2437            if (!client->rdpgfx->Open(client->rdpgfx))
 
 2439              WLog_WARN(TAG, 
"Failed to open GraphicsPipeline");
 
 2441                                             FreeRDP_SupportGraphicsPipeline, FALSE))
 
 2446              gfxstatus.gfxOpened = TRUE;
 
 2447              WLog_INFO(TAG, 
"Gfx Pipeline Opened");
 
 2458    if (WaitForSingleObject(ChannelEvent, 0) == WAIT_OBJECT_0)
 
 2460      if (!WTSVirtualChannelManagerCheckFileDescriptor(client->vcm))
 
 2462        WLog_ERR(TAG, 
"WTSVirtualChannelManagerCheckFileDescriptor failure");
 
 2467#if defined(CHANNEL_RDPGFX_SERVER) 
 2470      if (WaitForSingleObject(gfxevent, 0) == WAIT_OBJECT_0)
 
 2472        rdpgfx_server_handle_messages(client->rdpgfx);
 
 2477    if (WaitForSingleObject(MessageQueue_Event(MsgQueue), 0) == WAIT_OBJECT_0)
 
 2480      pointerPositionMsg.id = 0;
 
 2481      pointerPositionMsg.Free = NULL;
 
 2482      pointerAlphaMsg.id = 0;
 
 2483      pointerAlphaMsg.Free = NULL;
 
 2484      audioVolumeMsg.id = 0;
 
 2485      audioVolumeMsg.Free = NULL;
 
 2487      while (MessageQueue_Peek(MsgQueue, &message, TRUE))
 
 2489        if (message.id == WMQ_QUIT)
 
 2496          case SHADOW_MSG_OUT_POINTER_POSITION_UPDATE_ID:
 
 2498            shadow_client_free_queued_message(&pointerPositionMsg);
 
 2499            pointerPositionMsg = message;
 
 2502          case SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE_ID:
 
 2504            shadow_client_free_queued_message(&pointerAlphaMsg);
 
 2505            pointerAlphaMsg = message;
 
 2508          case SHADOW_MSG_OUT_AUDIO_OUT_VOLUME_ID:
 
 2510            shadow_client_free_queued_message(&audioVolumeMsg);
 
 2511            audioVolumeMsg = message;
 
 2515            shadow_client_subsystem_process_message(client, &message);
 
 2520      if (message.id == WMQ_QUIT)
 
 2523        shadow_client_free_queued_message(&pointerPositionMsg);
 
 2524        shadow_client_free_queued_message(&pointerAlphaMsg);
 
 2525        shadow_client_free_queued_message(&audioVolumeMsg);
 
 2531        if (pointerPositionMsg.id)
 
 2533          shadow_client_subsystem_process_message(client, &pointerPositionMsg);
 
 2536        if (pointerAlphaMsg.id)
 
 2538          shadow_client_subsystem_process_message(client, &pointerAlphaMsg);
 
 2541        if (audioVolumeMsg.id)
 
 2543          shadow_client_subsystem_process_message(client, &audioVolumeMsg);
 
 2552#if defined(CHANNEL_AUDIN_SERVER) 
 2553  if (client->audin && !IFCALLRESULT(TRUE, client->audin->IsOpen, client->audin))
 
 2555    if (!IFCALLRESULT(FALSE, client->audin->Close, client->audin))
 
 2557      WLog_WARN(TAG, 
"AUDIN shutdown failure!");
 
 2562  if (gfxstatus.gfxOpened)
 
 2564    if (gfxstatus.gfxSurfaceCreated)
 
 2566      if (!shadow_client_rdpgfx_release_surface(client))
 
 2567        WLog_WARN(TAG, 
"GFX release surface failure!");
 
 2570    WINPR_ASSERT(client->rdpgfx);
 
 2571    WINPR_ASSERT(client->rdpgfx->Close);
 
 2572    rc = client->rdpgfx->Close(client->rdpgfx);
 
 2576  shadow_client_channels_free(client);
 
 2578  if (UpdateSubscriber)
 
 2580    shadow_multiclient_release_subscriber(UpdateSubscriber);
 
 2581    UpdateSubscriber = NULL;
 
 2584  if (peer->connected && subsystem->ClientDisconnect)
 
 2586    subsystem->ClientDisconnect(subsystem, client);
 
 2590  WINPR_ASSERT(peer->Disconnect);
 
 2591  peer->Disconnect(peer);
 
 2592  freerdp_peer_context_free(peer);
 
 2593  freerdp_peer_free(peer);
 
 2598BOOL shadow_client_accepted(freerdp_listener* listener, freerdp_peer* peer)
 
 2600  rdpShadowClient* client = NULL;
 
 2601  rdpShadowServer* server = NULL;
 
 2603  if (!listener || !peer)
 
 2606  server = (rdpShadowServer*)listener->info;
 
 2607  WINPR_ASSERT(server);
 
 2609  peer->ContextExtra = (
void*)server;
 
 2610  peer->ContextSize = 
sizeof(rdpShadowClient);
 
 2611  peer->ContextNew = shadow_client_context_new;
 
 2612  peer->ContextFree = shadow_client_context_free;
 
 2614  if (!freerdp_peer_context_new_ex(peer, server->settings))
 
 2617  client = (rdpShadowClient*)peer->context;
 
 2618  WINPR_ASSERT(client);
 
 2620  if (!(client->thread = CreateThread(NULL, 0, shadow_client_thread, client, 0, NULL)))
 
 2622    freerdp_peer_context_free(peer);
 
 2628    (void)CloseHandle(client->thread);
 
 2629    client->thread = NULL;
 
 2635static void shadow_msg_out_addref(wMessage* message)
 
 2637  SHADOW_MSG_OUT* msg = NULL;
 
 2639  WINPR_ASSERT(message);
 
 2640  msg = (SHADOW_MSG_OUT*)message->wParam;
 
 2643  InterlockedIncrement(&(msg->refCount));
 
 2646static void shadow_msg_out_release(wMessage* message)
 
 2648  SHADOW_MSG_OUT* msg = NULL;
 
 2650  WINPR_ASSERT(message);
 
 2651  msg = (SHADOW_MSG_OUT*)message->wParam;
 
 2654  if (InterlockedDecrement(&(msg->refCount)) <= 0)
 
 2656    IFCALL(msg->Free, message->id, msg);
 
 2660static BOOL shadow_client_dispatch_msg(rdpShadowClient* client, wMessage* message)
 
 2662  if (!client || !message)
 
 2666  shadow_msg_out_addref(message);
 
 2668  WINPR_ASSERT(client->MsgQueue);
 
 2669  if (MessageQueue_Dispatch(client->MsgQueue, message))
 
 2674    shadow_msg_out_release(message);
 
 2679BOOL shadow_client_post_msg(rdpShadowClient* client, 
void* context, UINT32 type,
 
 2680                            SHADOW_MSG_OUT* msg, 
void* lParam)
 
 2682  wMessage message = { 0 };
 
 2683  message.context = context;
 
 2685  message.wParam = (
void*)msg;
 
 2686  message.lParam = lParam;
 
 2687  message.Free = shadow_msg_out_release;
 
 2688  return shadow_client_dispatch_msg(client, &message);
 
 2691int shadow_client_boardcast_msg(rdpShadowServer* server, 
void* context, UINT32 type,
 
 2692                                SHADOW_MSG_OUT* msg, 
void* lParam)
 
 2694  wMessage message = { 0 };
 
 2695  rdpShadowClient* client = NULL;
 
 2698  WINPR_ASSERT(server);
 
 2701  message.context = context;
 
 2703  message.wParam = (
void*)msg;
 
 2704  message.lParam = lParam;
 
 2705  message.Free = shadow_msg_out_release;
 
 2708  shadow_msg_out_addref(&message);
 
 2710  WINPR_ASSERT(server->clients);
 
 2711  ArrayList_Lock(server->clients);
 
 2713  for (
size_t index = 0; index < ArrayList_Count(server->clients); index++)
 
 2715    client = (rdpShadowClient*)ArrayList_GetItem(server->clients, index);
 
 2717    if (shadow_client_dispatch_msg(client, &message))
 
 2723  ArrayList_Unlock(server->clients);
 
 2725  shadow_msg_out_release(&message);
 
 2729int shadow_client_boardcast_quit(rdpShadowServer* server, 
int nExitCode)
 
 2731  wMessageQueue* queue = NULL;
 
 2734  WINPR_ASSERT(server);
 
 2735  WINPR_ASSERT(server->clients);
 
 2737  ArrayList_Lock(server->clients);
 
 2739  for (
size_t index = 0; index < ArrayList_Count(server->clients); index++)
 
 2741    queue = ((rdpShadowClient*)ArrayList_GetItem(server->clients, index))->MsgQueue;
 
 2743    if (MessageQueue_PostQuit(queue, nExitCode))
 
 2749  ArrayList_Unlock(server->clients);
 
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_set_string(rdpSettings *settings, FreeRDP_Settings_Keys_String id, const char *param)
Sets a string settings value. The param is copied.
FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.
FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 param)
Sets a UINT32 settings value.
FREERDP_API const char * freerdp_settings_get_string(const rdpSettings *settings, FreeRDP_Settings_Keys_String id)
Returns a immutable string settings value.
FREERDP_API BOOL freerdp_settings_set_bool(rdpSettings *settings, FreeRDP_Settings_Keys_Bool id, BOOL param)
Sets a BOOL settings value.
This struct contains function pointer to initialize/free objects.