20#include <freerdp/config.h> 
   22#include <winpr/assert.h> 
   27#include <winpr/cast.h> 
   29#include <winpr/synch.h> 
   30#include <winpr/thread.h> 
   31#include <winpr/stream.h> 
   33#include <freerdp/freerdp.h> 
   34#include <freerdp/codec/color.h> 
   36#include <freerdp/channels/wtsvc.h> 
   37#include <freerdp/channels/log.h> 
   39#include "rdpgfx_common.h" 
   40#include "rdpgfx_main.h" 
   42#define TAG CHANNELS_TAG("rdpgfx.server") 
   43#define RDPGFX_RESET_GRAPHICS_PDU_SIZE 340 
   45#define checkCapsAreExchanged(context) \ 
   46  checkCapsAreExchangedInt(context, __FILE__, __func__, __LINE__) 
   47static BOOL checkCapsAreExchangedInt(RdpgfxServerContext* context, 
const char* file,
 
   48                                     const char* fkt, 
size_t line)
 
   50  WINPR_ASSERT(context);
 
   51  WINPR_ASSERT(context->priv);
 
   53  const DWORD level = WLOG_TRACE;
 
   54  if (WLog_IsLevelActive(context->priv->log, level))
 
   56    WLog_PrintTextMessage(context->priv->log, level, line, file, fkt,
 
   57                          "activeCapSet{Version=0x%08" PRIx32 
", flags=0x%08" PRIx32 
"}",
 
   58                          context->priv->activeCapSet.version,
 
   59                          context->priv->activeCapSet.flags);
 
   61  return context->priv->activeCapSet.version > 0;
 
   73static inline UINT32 rdpgfx_pdu_length(UINT32 dataLen)
 
   75  return RDPGFX_HEADER_SIZE + dataLen;
 
   78static inline UINT rdpgfx_server_packet_init_header(
wStream* s, UINT16 cmdId, UINT32 pduLength)
 
   83  header.pduLength = pduLength;
 
   86  return rdpgfx_write_header(s, &header);
 
   96static inline BOOL rdpgfx_server_packet_complete_header(
wStream* s, 
size_t start)
 
   98  const size_t current = Stream_GetPosition(s);
 
   99  const size_t cap = Stream_Capacity(s);
 
  100  if (cap < start + RDPGFX_HEADER_SIZE)
 
  102  if ((start > UINT32_MAX) || (current < start))
 
  105  Stream_SetPosition(s, start + RDPGFX_HEADER_SIZE - 
sizeof(UINT32));
 
  106  Stream_Write_UINT32(s, (UINT32)(current - start)); 
 
  107  Stream_SetPosition(s, current);
 
  118static UINT rdpgfx_server_packet_send(RdpgfxServerContext* context, 
wStream* s)
 
  123  BYTE* pSrcData = Stream_Buffer(s);
 
  124  const size_t SrcSize = Stream_GetPosition(s);
 
  125  if (SrcSize > UINT32_MAX)
 
  126    return ERROR_INTERNAL_ERROR;
 
  132  fs = Stream_New(NULL, SrcSize + 7 + (SrcSize / ZGFX_SEGMENTED_MAXSIZE + 1) * 4);
 
  136    WLog_Print(context->priv->log, WLOG_ERROR, 
"Stream_New failed!");
 
  137    error = CHANNEL_RC_NO_MEMORY;
 
  141  if (zgfx_compress_to_stream(context->priv->zgfx, fs, pSrcData, (UINT32)SrcSize, &flags) < 0)
 
  143    WLog_Print(context->priv->log, WLOG_ERROR, 
"zgfx_compress_to_stream failed!");
 
  144    error = ERROR_INTERNAL_ERROR;
 
  148  const size_t pos = Stream_GetPosition(fs);
 
  150  WINPR_ASSERT(pos <= UINT32_MAX);
 
  151  if (!WTSVirtualChannelWrite(context->priv->rdpgfx_channel, Stream_BufferAs(fs, 
char),
 
  152                              (UINT32)pos, &written))
 
  154    WLog_Print(context->priv->log, WLOG_ERROR, 
"WTSVirtualChannelWrite failed!");
 
  155    error = ERROR_INTERNAL_ERROR;
 
  159  if (written < Stream_GetPosition(fs))
 
  161    WLog_Print(context->priv->log, WLOG_WARN,
 
  162               "Unexpected bytes written: %" PRIu32 
"/%" PRIuz 
"", written,
 
  163               Stream_GetPosition(fs));
 
  166  error = CHANNEL_RC_OK;
 
  168  Stream_Free(fs, TRUE);
 
  169  Stream_Free(s, TRUE);
 
  185static wStream* rdpgfx_server_single_packet_new(wLog* log, UINT16 cmdId, UINT32 dataLen)
 
  189  UINT32 pduLength = rdpgfx_pdu_length(dataLen);
 
  190  s = Stream_New(NULL, pduLength);
 
  194    WLog_Print(log, WLOG_ERROR, 
"Stream_New failed!");
 
  198  if ((error = rdpgfx_server_packet_init_header(s, cmdId, pduLength)))
 
  200    WLog_Print(log, WLOG_ERROR, 
"Failed to init header with error %" PRIu32 
"!", error);
 
  206  Stream_Free(s, TRUE);
 
  218static inline UINT rdpgfx_server_single_packet_send(RdpgfxServerContext* context, 
wStream* s)
 
  221  rdpgfx_server_packet_complete_header(s, 0);
 
  222  return rdpgfx_server_packet_send(context, s);
 
  230static UINT rdpgfx_send_caps_confirm_pdu(RdpgfxServerContext* context,
 
  236  WINPR_ASSERT(context);
 
  237  WINPR_ASSERT(capsConfirm);
 
  239  capsSet = capsConfirm->capsSet;
 
  240  WINPR_ASSERT(capsSet);
 
  242  s = rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_CAPSCONFIRM,
 
  243                                      RDPGFX_CAPSET_BASE_SIZE + capsSet->length);
 
  247    WLog_Print(context->priv->log, WLOG_ERROR, 
"rdpgfx_server_single_packet_new failed!");
 
  248    return CHANNEL_RC_NO_MEMORY;
 
  251  WLog_DBG(TAG, 
"CAPS version=0x%04" PRIx32 
", flags=0x%04" PRIx32 
", length=%" PRIu32,
 
  252           capsSet->version, capsSet->flags, capsSet->length);
 
  253  Stream_Write_UINT32(s, capsSet->version); 
 
  254  Stream_Write_UINT32(s, capsSet->length);  
 
  256  if (capsSet->length >= 4)
 
  258    Stream_Write_UINT32(s, capsSet->flags); 
 
  259    Stream_Zero(s, capsSet->length - 4);
 
  262    Stream_Zero(s, capsSet->length);
 
  264  context->priv->activeCapSet = *capsSet;
 
  265  return rdpgfx_server_single_packet_send(context, s);
 
  273static UINT rdpgfx_send_reset_graphics_pdu(RdpgfxServerContext* context,
 
  276  if (!checkCapsAreExchanged(context))
 
  277    return CHANNEL_RC_NOT_INITIALIZED;
 
  282  if (pdu->monitorCount >= 16)
 
  284    WLog_Print(context->priv->log, WLOG_ERROR,
 
  285               "Monitor count MUST be less than or equal to 16: %" PRIu32 
"",
 
  287    return ERROR_INVALID_DATA;
 
  290  s = rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_RESETGRAPHICS,
 
  291                                      RDPGFX_RESET_GRAPHICS_PDU_SIZE - RDPGFX_HEADER_SIZE);
 
  295    WLog_Print(context->priv->log, WLOG_ERROR, 
"rdpgfx_server_single_packet_new failed!");
 
  296    return CHANNEL_RC_NO_MEMORY;
 
  299  Stream_Write_UINT32(s, pdu->width);        
 
  300  Stream_Write_UINT32(s, pdu->height);       
 
  301  Stream_Write_UINT32(s, pdu->monitorCount); 
 
  303  for (UINT32 index = 0; index < pdu->monitorCount; index++)
 
  305    const MONITOR_DEF* monitor = &(pdu->monitorDefArray[index]);
 
  306    Stream_Write_INT32(s, monitor->left);    
 
  307    Stream_Write_INT32(s, monitor->top);     
 
  308    Stream_Write_INT32(s, monitor->right);   
 
  309    Stream_Write_INT32(s, monitor->bottom);  
 
  310    Stream_Write_UINT32(s, monitor->flags);  
 
  314  Stream_SetPosition(s, RDPGFX_RESET_GRAPHICS_PDU_SIZE);
 
  315  return rdpgfx_server_single_packet_send(context, s);
 
  323static UINT rdpgfx_send_evict_cache_entry_pdu(RdpgfxServerContext* context,
 
  326  if (!checkCapsAreExchanged(context))
 
  327    return CHANNEL_RC_NOT_INITIALIZED;
 
  329      rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_EVICTCACHEENTRY, 2);
 
  333    WLog_Print(context->priv->log, WLOG_ERROR, 
"rdpgfx_server_single_packet_new failed!");
 
  334    return CHANNEL_RC_NO_MEMORY;
 
  337  Stream_Write_UINT16(s, pdu->cacheSlot); 
 
  338  return rdpgfx_server_single_packet_send(context, s);
 
  346static UINT rdpgfx_send_cache_import_reply_pdu(RdpgfxServerContext* context,
 
  349  if (!checkCapsAreExchanged(context))
 
  350    return CHANNEL_RC_NOT_INITIALIZED;
 
  351  WINPR_ASSERT(context);
 
  354  WLog_DBG(TAG, 
"reply with %" PRIu16 
" entries", pdu->importedEntriesCount);
 
  355  wStream* s = rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_CACHEIMPORTREPLY,
 
  356                                               2 + 2 * pdu->importedEntriesCount);
 
  360    WLog_Print(context->priv->log, WLOG_ERROR, 
"rdpgfx_server_single_packet_new failed!");
 
  361    return CHANNEL_RC_NO_MEMORY;
 
  365  Stream_Write_UINT16(s, pdu->importedEntriesCount);
 
  367  for (UINT16 index = 0; index < pdu->importedEntriesCount; index++)
 
  369    Stream_Write_UINT16(s, pdu->cacheSlots[index]); 
 
  372  return rdpgfx_server_single_packet_send(context, s);
 
  376rdpgfx_process_cache_import_offer_pdu(RdpgfxServerContext* context,
 
  379  if (!checkCapsAreExchanged(context))
 
  380    return CHANNEL_RC_NOT_INITIALIZED;
 
  381  WINPR_ASSERT(context);
 
  382  WINPR_ASSERT(cacheImportOffer);
 
  385  WLog_DBG(TAG, 
"received %" PRIu16 
" entries, reply with %" PRIu16 
" entries",
 
  386           cacheImportOffer->cacheEntriesCount, reply.importedEntriesCount);
 
  387  return IFCALLRESULT(CHANNEL_RC_OK, context->CacheImportReply, context, &reply);
 
  395static UINT rdpgfx_send_create_surface_pdu(RdpgfxServerContext* context,
 
  398  if (!checkCapsAreExchanged(context))
 
  399    return CHANNEL_RC_NOT_INITIALIZED;
 
  400  wStream* s = rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_CREATESURFACE, 7);
 
  402  WINPR_ASSERT(context);
 
  404  WINPR_ASSERT((pdu->pixelFormat == GFX_PIXEL_FORMAT_XRGB_8888) ||
 
  405               (pdu->pixelFormat == GFX_PIXEL_FORMAT_ARGB_8888));
 
  409    WLog_Print(context->priv->log, WLOG_ERROR, 
"rdpgfx_server_single_packet_new failed!");
 
  410    return CHANNEL_RC_NO_MEMORY;
 
  413  Stream_Write_UINT16(s, pdu->surfaceId);  
 
  414  Stream_Write_UINT16(s, pdu->width);      
 
  415  Stream_Write_UINT16(s, pdu->height);     
 
  416  Stream_Write_UINT8(s, pdu->pixelFormat); 
 
  417  return rdpgfx_server_single_packet_send(context, s);
 
  425static UINT rdpgfx_send_delete_surface_pdu(RdpgfxServerContext* context,
 
  428  if (!checkCapsAreExchanged(context))
 
  429    return CHANNEL_RC_NOT_INITIALIZED;
 
  430  wStream* s = rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_DELETESURFACE, 2);
 
  434    WLog_Print(context->priv->log, WLOG_ERROR, 
"rdpgfx_server_single_packet_new failed!");
 
  435    return CHANNEL_RC_NO_MEMORY;
 
  438  Stream_Write_UINT16(s, pdu->surfaceId); 
 
  439  return rdpgfx_server_single_packet_send(context, s);
 
  444  if (!Stream_EnsureRemainingCapacity(s, 8))
 
  446  Stream_Write_UINT32(s, pdu->timestamp); 
 
  447  Stream_Write_UINT32(s, pdu->frameId);   
 
  453  if (!Stream_EnsureRemainingCapacity(s, 4))
 
  455  Stream_Write_UINT32(s, pdu->frameId); 
 
  464static UINT rdpgfx_send_start_frame_pdu(RdpgfxServerContext* context,
 
  467  if (!checkCapsAreExchanged(context))
 
  468    return CHANNEL_RC_NOT_INITIALIZED;
 
  469  wStream* s = rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_STARTFRAME,
 
  470                                               RDPGFX_START_FRAME_PDU_SIZE);
 
  474    WLog_Print(context->priv->log, WLOG_ERROR, 
"rdpgfx_server_single_packet_new failed!");
 
  475    return CHANNEL_RC_NO_MEMORY;
 
  478  rdpgfx_write_start_frame_pdu(s, pdu);
 
  479  return rdpgfx_server_single_packet_send(context, s);
 
  487static UINT rdpgfx_send_end_frame_pdu(RdpgfxServerContext* context, 
const RDPGFX_END_FRAME_PDU* pdu)
 
  489  if (!checkCapsAreExchanged(context))
 
  490    return CHANNEL_RC_NOT_INITIALIZED;
 
  491  wStream* s = rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_ENDFRAME,
 
  492                                               RDPGFX_END_FRAME_PDU_SIZE);
 
  496    WLog_Print(context->priv->log, WLOG_ERROR, 
"rdpgfx_server_single_packet_new failed!");
 
  497    return CHANNEL_RC_NO_MEMORY;
 
  500  rdpgfx_write_end_frame_pdu(s, pdu);
 
  501  return rdpgfx_server_single_packet_send(context, s);
 
  513  return sizeof(UINT32) 
 
  515               * havc420->meta.numRegionRects +
 
  532  switch (cmd->codecId)
 
  534    case RDPGFX_CODECID_CAPROGRESSIVE:
 
  535    case RDPGFX_CODECID_CAPROGRESSIVE_V2:
 
  536      return RDPGFX_WIRE_TO_SURFACE_PDU_2_SIZE + cmd->length;
 
  538    case RDPGFX_CODECID_AVC420:
 
  540      h264Size = rdpgfx_estimate_h264_avc420(havc420);
 
  541      return RDPGFX_WIRE_TO_SURFACE_PDU_1_SIZE + h264Size;
 
  543    case RDPGFX_CODECID_AVC444:
 
  545      h264Size = 
sizeof(UINT32); 
 
  547      havc420 = &(havc444->bitstream[0]);
 
  548      h264Size += rdpgfx_estimate_h264_avc420(havc420);
 
  551      if (havc444->LC == 0)
 
  553        havc420 = &(havc444->bitstream[1]);
 
  554        h264Size += rdpgfx_estimate_h264_avc420(havc420);
 
  557      return RDPGFX_WIRE_TO_SURFACE_PDU_1_SIZE + h264Size;
 
  560      return RDPGFX_WIRE_TO_SURFACE_PDU_1_SIZE + cmd->length;
 
  573  if (cmd->codecId == RDPGFX_CODECID_CAPROGRESSIVE ||
 
  574      cmd->codecId == RDPGFX_CODECID_CAPROGRESSIVE_V2)
 
  576    return RDPGFX_CMDID_WIRETOSURFACE_2;
 
  579  return RDPGFX_CMDID_WIRETOSURFACE_1;
 
  591  UINT error = CHANNEL_RC_OK;
 
  593  if (!Stream_EnsureRemainingCapacity(s, 4 + meta->numRegionRects * 10))
 
  594    return ERROR_OUTOFMEMORY;
 
  596  Stream_Write_UINT32(s, meta->numRegionRects); 
 
  598  for (UINT32 index = 0; index < meta->numRegionRects; index++)
 
  600    regionRect = &(meta->regionRects[index]);
 
  602    if ((error = rdpgfx_write_rect16(s, regionRect)))
 
  604      WLog_Print(log, WLOG_ERROR, 
"rdpgfx_write_rect16 failed with error %" PRIu32 
"!",
 
  610  for (UINT32 index = 0; index < meta->numRegionRects; index++)
 
  612    quantQualityVal = &(meta->quantQualityVals[index]);
 
  613    Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(
 
  614                              uint8_t, quantQualityVal->qp | (quantQualityVal->r << 6) |
 
  615                                           (quantQualityVal->p << 7))); 
 
  617    Stream_Write_UINT8(s, quantQualityVal->qualityVal);
 
  629static inline UINT rdpgfx_write_h264_avc420(wLog* log, 
wStream* s,
 
  632  UINT error = CHANNEL_RC_OK;
 
  634  if ((error = rdpgfx_write_h264_metablock(log, s, &(havc420->meta))))
 
  636    WLog_Print(log, WLOG_ERROR, 
"rdpgfx_write_h264_metablock failed with error %" PRIu32 
"!",
 
  641  if (!Stream_EnsureRemainingCapacity(s, havc420->length))
 
  642    return ERROR_OUTOFMEMORY;
 
  644  Stream_Write(s, havc420->data, havc420->length);
 
  657  UINT error = CHANNEL_RC_OK;
 
  660  UINT8 pixelFormat = 0;
 
  664    case PIXEL_FORMAT_BGRX32:
 
  665      pixelFormat = GFX_PIXEL_FORMAT_XRGB_8888;
 
  668    case PIXEL_FORMAT_BGRA32:
 
  669      pixelFormat = GFX_PIXEL_FORMAT_ARGB_8888;
 
  673      WLog_Print(log, WLOG_ERROR, 
"Format %s not supported!",
 
  674                 FreeRDPGetColorFormatName(cmd->format));
 
  675      return ERROR_INVALID_DATA;
 
  678  if (cmd->codecId == RDPGFX_CODECID_CAPROGRESSIVE ||
 
  679      cmd->codecId == RDPGFX_CODECID_CAPROGRESSIVE_V2)
 
  681    if (!Stream_EnsureRemainingCapacity(s, 13 + cmd->length))
 
  682      return ERROR_INTERNAL_ERROR;
 
  685        s, WINPR_ASSERTING_INT_CAST(uint16_t, cmd->surfaceId)); 
 
  687        s, WINPR_ASSERTING_INT_CAST(uint16_t, cmd->codecId)); 
 
  688    Stream_Write_UINT32(s, cmd->contextId); 
 
  689    Stream_Write_UINT8(s, pixelFormat);     
 
  690    Stream_Write_UINT32(s, cmd->length);    
 
  691    Stream_Write(s, cmd->data, cmd->length);
 
  696    if (!Stream_EnsureRemainingCapacity(s, 17))
 
  697      return ERROR_INTERNAL_ERROR;
 
  699        s, WINPR_ASSERTING_INT_CAST(uint16_t, cmd->surfaceId)); 
 
  701        s, WINPR_ASSERTING_INT_CAST(uint16_t, cmd->codecId)); 
 
  702    Stream_Write_UINT8(s, pixelFormat);     
 
  703    Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, cmd->left)); 
 
  704    Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, cmd->top));  
 
  705    Stream_Write_UINT16(s,
 
  706                        WINPR_ASSERTING_INT_CAST(uint16_t, cmd->right)); 
 
  707    Stream_Write_UINT16(s,
 
  708                        WINPR_ASSERTING_INT_CAST(uint16_t, cmd->bottom)); 
 
  709    Stream_Write_UINT32(s, cmd->length);    
 
  710    const size_t bitmapDataStart = Stream_GetPosition(s);
 
  712    if (cmd->codecId == RDPGFX_CODECID_AVC420)
 
  715      error = rdpgfx_write_h264_avc420(log, s, havc420);
 
  717      if (error != CHANNEL_RC_OK)
 
  719        WLog_Print(log, WLOG_ERROR, 
"rdpgfx_write_h264_avc420 failed!");
 
  723    else if ((cmd->codecId == RDPGFX_CODECID_AVC444) ||
 
  724             (cmd->codecId == RDPGFX_CODECID_AVC444v2))
 
  727      havc420 = &(havc444->bitstream[0]); 
 
  728      if (!Stream_EnsureRemainingCapacity(s, 4))
 
  729        return ERROR_INTERNAL_ERROR;
 
  730      Stream_Write_UINT32(s, havc444->cbAvc420EncodedBitstream1 |
 
  731                                 ((uint32_t)havc444->LC << 30UL));
 
  733      error = rdpgfx_write_h264_avc420(log, s, havc420);
 
  735      if (error != CHANNEL_RC_OK)
 
  737        WLog_Print(log, WLOG_ERROR, 
"rdpgfx_write_h264_avc420 failed!");
 
  742      if (havc444->LC == 0)
 
  744        havc420 = &(havc444->bitstream[1]);
 
  745        error = rdpgfx_write_h264_avc420(log, s, havc420);
 
  747        if (error != CHANNEL_RC_OK)
 
  749          WLog_Print(log, WLOG_ERROR, 
"rdpgfx_write_h264_avc420 failed!");
 
  756      if (!Stream_EnsureRemainingCapacity(s, cmd->length))
 
  757        return ERROR_INTERNAL_ERROR;
 
  758      Stream_Write(s, cmd->data, cmd->length);
 
  762    const size_t bitmapDataLength = Stream_GetPosition(s) - bitmapDataStart;
 
  763    if (bitmapDataLength > UINT32_MAX)
 
  764      return ERROR_INTERNAL_ERROR;
 
  766    Stream_SetPosition(s, bitmapDataStart - 
sizeof(UINT32));
 
  767    if (!Stream_EnsureRemainingCapacity(s, 4))
 
  768      return ERROR_INTERNAL_ERROR;
 
  769    Stream_Write_UINT32(s, (UINT32)bitmapDataLength); 
 
  770    if (!Stream_SafeSeek(s, bitmapDataLength))
 
  771      return ERROR_INTERNAL_ERROR;
 
  784static UINT rdpgfx_send_surface_command(RdpgfxServerContext* context,
 
  787  if (!checkCapsAreExchanged(context))
 
  788    return CHANNEL_RC_NOT_INITIALIZED;
 
  789  UINT error = CHANNEL_RC_OK;
 
  791  s = rdpgfx_server_single_packet_new(context->priv->log, rdpgfx_surface_command_cmdid(cmd),
 
  792                                      rdpgfx_estimate_surface_command(cmd));
 
  796    WLog_Print(context->priv->log, WLOG_ERROR, 
"rdpgfx_server_single_packet_new failed!");
 
  797    return CHANNEL_RC_NO_MEMORY;
 
  800  error = rdpgfx_write_surface_command(context->priv->log, s, cmd);
 
  802  if (error != CHANNEL_RC_OK)
 
  804    WLog_Print(context->priv->log, WLOG_ERROR, 
"rdpgfx_write_surface_command failed!");
 
  808  return rdpgfx_server_single_packet_send(context, s);
 
  810  Stream_Free(s, TRUE);
 
  822static UINT rdpgfx_send_surface_frame_command(RdpgfxServerContext* context,
 
  828  if (!checkCapsAreExchanged(context))
 
  829    return CHANNEL_RC_NOT_INITIALIZED;
 
  830  UINT error = CHANNEL_RC_OK;
 
  831  UINT32 size = rdpgfx_pdu_length(rdpgfx_estimate_surface_command(cmd));
 
  835    size += rdpgfx_pdu_length(RDPGFX_START_FRAME_PDU_SIZE);
 
  840    size += rdpgfx_pdu_length(RDPGFX_END_FRAME_PDU_SIZE);
 
  843  wStream* s = Stream_New(NULL, size);
 
  847    WLog_Print(context->priv->log, WLOG_ERROR, 
"Stream_New failed!");
 
  848    return CHANNEL_RC_NO_MEMORY;
 
  854    const size_t position = Stream_GetPosition(s);
 
  855    error = rdpgfx_server_packet_init_header(s, RDPGFX_CMDID_STARTFRAME, 0);
 
  857    if (error != CHANNEL_RC_OK)
 
  859      WLog_Print(context->priv->log, WLOG_ERROR,
 
  860                 "Failed to init header with error %" PRIu32 
"!", error);
 
  864    if (!rdpgfx_write_start_frame_pdu(s, startFrame) ||
 
  865        !rdpgfx_server_packet_complete_header(s, position))
 
  870  const size_t pos = Stream_GetPosition(s);
 
  871  error = rdpgfx_server_packet_init_header(s, rdpgfx_surface_command_cmdid(cmd),
 
  874  if (error != CHANNEL_RC_OK)
 
  876    WLog_Print(context->priv->log, WLOG_ERROR, 
"Failed to init header with error %" PRIu32 
"!",
 
  881  error = rdpgfx_write_surface_command(context->priv->log, s, cmd);
 
  883  if (error != CHANNEL_RC_OK)
 
  885    WLog_Print(context->priv->log, WLOG_ERROR, 
"rdpgfx_write_surface_command failed!");
 
  889  if (!rdpgfx_server_packet_complete_header(s, pos))
 
  895    const size_t position = Stream_GetPosition(s);
 
  896    error = rdpgfx_server_packet_init_header(s, RDPGFX_CMDID_ENDFRAME, 0);
 
  898    if (error != CHANNEL_RC_OK)
 
  900      WLog_Print(context->priv->log, WLOG_ERROR,
 
  901                 "Failed to init header with error %" PRIu32 
"!", error);
 
  905    if (!rdpgfx_write_end_frame_pdu(s, endFrame) ||
 
  906        !rdpgfx_server_packet_complete_header(s, position))
 
  910  return rdpgfx_server_packet_send(context, s);
 
  912  Stream_Free(s, TRUE);
 
  921static UINT rdpgfx_send_delete_encoding_context_pdu(RdpgfxServerContext* context,
 
  924  if (!checkCapsAreExchanged(context))
 
  925    return CHANNEL_RC_NOT_INITIALIZED;
 
  927      rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_DELETEENCODINGCONTEXT, 6);
 
  931    WLog_Print(context->priv->log, WLOG_ERROR, 
"rdpgfx_server_single_packet_new failed!");
 
  932    return CHANNEL_RC_NO_MEMORY;
 
  935  Stream_Write_UINT16(s, pdu->surfaceId);      
 
  936  Stream_Write_UINT32(s, pdu->codecContextId); 
 
  937  return rdpgfx_server_single_packet_send(context, s);
 
  945static UINT rdpgfx_send_solid_fill_pdu(RdpgfxServerContext* context,
 
  948  if (!checkCapsAreExchanged(context))
 
  949    return CHANNEL_RC_NOT_INITIALIZED;
 
  950  UINT error = CHANNEL_RC_OK;
 
  952  wStream* s = rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_SOLIDFILL,
 
  953                                               8 + 8 * pdu->fillRectCount);
 
  957    WLog_Print(context->priv->log, WLOG_ERROR, 
"rdpgfx_server_single_packet_new failed!");
 
  958    return CHANNEL_RC_NO_MEMORY;
 
  961  Stream_Write_UINT16(s, pdu->surfaceId); 
 
  964  if ((error = rdpgfx_write_color32(s, &(pdu->fillPixel))))
 
  966    WLog_Print(context->priv->log, WLOG_ERROR,
 
  967               "rdpgfx_write_color32 failed with error %" PRIu32 
"!", error);
 
  971  Stream_Write_UINT16(s, pdu->fillRectCount); 
 
  973  for (UINT16 index = 0; index < pdu->fillRectCount; index++)
 
  975    fillRect = &(pdu->fillRects[index]);
 
  977    if ((error = rdpgfx_write_rect16(s, fillRect)))
 
  979      WLog_Print(context->priv->log, WLOG_ERROR,
 
  980                 "rdpgfx_write_rect16 failed with error %" PRIu32 
"!", error);
 
  985  return rdpgfx_server_single_packet_send(context, s);
 
  987  Stream_Free(s, TRUE);
 
  996static UINT rdpgfx_send_surface_to_surface_pdu(RdpgfxServerContext* context,
 
  999  if (!checkCapsAreExchanged(context))
 
 1000    return CHANNEL_RC_NOT_INITIALIZED;
 
 1001  UINT error = CHANNEL_RC_OK;
 
 1003  wStream* s = rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_SURFACETOSURFACE,
 
 1004                                               14 + 4 * pdu->destPtsCount);
 
 1008    WLog_Print(context->priv->log, WLOG_ERROR, 
"rdpgfx_server_single_packet_new failed!");
 
 1009    return CHANNEL_RC_NO_MEMORY;
 
 1012  Stream_Write_UINT16(s, pdu->surfaceIdSrc);  
 
 1013  Stream_Write_UINT16(s, pdu->surfaceIdDest); 
 
 1016  if ((error = rdpgfx_write_rect16(s, &(pdu->rectSrc))))
 
 1018    WLog_Print(context->priv->log, WLOG_ERROR,
 
 1019               "rdpgfx_write_rect16 failed with error %" PRIu32 
"!", error);
 
 1023  Stream_Write_UINT16(s, pdu->destPtsCount); 
 
 1025  for (UINT16 index = 0; index < pdu->destPtsCount; index++)
 
 1027    destPt = &(pdu->destPts[index]);
 
 1029    if ((error = rdpgfx_write_point16(s, destPt)))
 
 1031      WLog_Print(context->priv->log, WLOG_ERROR,
 
 1032                 "rdpgfx_write_point16 failed with error %" PRIu32 
"!", error);
 
 1037  return rdpgfx_server_single_packet_send(context, s);
 
 1039  Stream_Free(s, TRUE);
 
 1048static UINT rdpgfx_send_surface_to_cache_pdu(RdpgfxServerContext* context,
 
 1051  if (!checkCapsAreExchanged(context))
 
 1052    return CHANNEL_RC_NOT_INITIALIZED;
 
 1053  UINT error = CHANNEL_RC_OK;
 
 1055      rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_SURFACETOCACHE, 20);
 
 1059    WLog_Print(context->priv->log, WLOG_ERROR, 
"rdpgfx_server_single_packet_new failed!");
 
 1060    return CHANNEL_RC_NO_MEMORY;
 
 1063  Stream_Write_UINT16(s, pdu->surfaceId); 
 
 1064  Stream_Write_UINT64(s, pdu->cacheKey);  
 
 1065  Stream_Write_UINT16(s, pdu->cacheSlot); 
 
 1068  if ((error = rdpgfx_write_rect16(s, &(pdu->rectSrc))))
 
 1070    WLog_Print(context->priv->log, WLOG_ERROR,
 
 1071               "rdpgfx_write_rect16 failed with error %" PRIu32 
"!", error);
 
 1075  return rdpgfx_server_single_packet_send(context, s);
 
 1077  Stream_Free(s, TRUE);
 
 1086static UINT rdpgfx_send_cache_to_surface_pdu(RdpgfxServerContext* context,
 
 1089  if (!checkCapsAreExchanged(context))
 
 1090    return CHANNEL_RC_NOT_INITIALIZED;
 
 1091  UINT error = CHANNEL_RC_OK;
 
 1093  wStream* s = rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_CACHETOSURFACE,
 
 1094                                               6 + 4 * pdu->destPtsCount);
 
 1098    WLog_Print(context->priv->log, WLOG_ERROR, 
"rdpgfx_server_single_packet_new failed!");
 
 1099    return CHANNEL_RC_NO_MEMORY;
 
 1102  Stream_Write_UINT16(s, pdu->cacheSlot);    
 
 1103  Stream_Write_UINT16(s, pdu->surfaceId);    
 
 1104  Stream_Write_UINT16(s, pdu->destPtsCount); 
 
 1106  for (UINT16 index = 0; index < pdu->destPtsCount; index++)
 
 1108    destPt = &(pdu->destPts[index]);
 
 1110    if ((error = rdpgfx_write_point16(s, destPt)))
 
 1112      WLog_Print(context->priv->log, WLOG_ERROR,
 
 1113                 "rdpgfx_write_point16 failed with error %" PRIu32 
"", error);
 
 1118  return rdpgfx_server_single_packet_send(context, s);
 
 1120  Stream_Free(s, TRUE);
 
 1129static UINT rdpgfx_send_map_surface_to_output_pdu(RdpgfxServerContext* context,
 
 1132  if (!checkCapsAreExchanged(context))
 
 1133    return CHANNEL_RC_NOT_INITIALIZED;
 
 1135      rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_MAPSURFACETOOUTPUT, 12);
 
 1139    WLog_Print(context->priv->log, WLOG_ERROR, 
"rdpgfx_server_single_packet_new failed!");
 
 1140    return CHANNEL_RC_NO_MEMORY;
 
 1143  Stream_Write_UINT16(s, pdu->surfaceId);     
 
 1144  Stream_Write_UINT16(s, 0);                  
 
 1145  Stream_Write_UINT32(s, pdu->outputOriginX); 
 
 1146  Stream_Write_UINT32(s, pdu->outputOriginY); 
 
 1147  return rdpgfx_server_single_packet_send(context, s);
 
 1155static UINT rdpgfx_send_map_surface_to_window_pdu(RdpgfxServerContext* context,
 
 1158  if (!checkCapsAreExchanged(context))
 
 1159    return CHANNEL_RC_NOT_INITIALIZED;
 
 1161      rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_MAPSURFACETOWINDOW, 18);
 
 1165    WLog_Print(context->priv->log, WLOG_ERROR, 
"rdpgfx_server_single_packet_new failed!");
 
 1166    return CHANNEL_RC_NO_MEMORY;
 
 1169  Stream_Write_UINT16(s, pdu->surfaceId);    
 
 1170  Stream_Write_UINT64(s, pdu->windowId);     
 
 1171  Stream_Write_UINT32(s, pdu->mappedWidth);  
 
 1172  Stream_Write_UINT32(s, pdu->mappedHeight); 
 
 1173  return rdpgfx_server_single_packet_send(context, s);
 
 1177rdpgfx_send_map_surface_to_scaled_window_pdu(RdpgfxServerContext* context,
 
 1180  if (!checkCapsAreExchanged(context))
 
 1181    return CHANNEL_RC_NOT_INITIALIZED;
 
 1182  wStream* s = rdpgfx_server_single_packet_new(context->priv->log,
 
 1183                                               RDPGFX_CMDID_MAPSURFACETOSCALEDWINDOW, 26);
 
 1187    WLog_Print(context->priv->log, WLOG_ERROR, 
"rdpgfx_server_single_packet_new failed!");
 
 1188    return CHANNEL_RC_NO_MEMORY;
 
 1191  Stream_Write_UINT16(s, pdu->surfaceId);    
 
 1192  Stream_Write_UINT64(s, pdu->windowId);     
 
 1193  Stream_Write_UINT32(s, pdu->mappedWidth);  
 
 1194  Stream_Write_UINT32(s, pdu->mappedHeight); 
 
 1195  Stream_Write_UINT32(s, pdu->targetWidth);  
 
 1196  Stream_Write_UINT32(s, pdu->targetHeight); 
 
 1197  return rdpgfx_server_single_packet_send(context, s);
 
 1205static UINT rdpgfx_recv_frame_acknowledge_pdu(RdpgfxServerContext* context, 
wStream* s)
 
 1207  if (!checkCapsAreExchanged(context))
 
 1208    return CHANNEL_RC_NOT_INITIALIZED;
 
 1210  UINT error = CHANNEL_RC_OK;
 
 1212  if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
 
 1213    return ERROR_INVALID_DATA;
 
 1215  Stream_Read_UINT32(s, pdu.queueDepth);         
 
 1216  Stream_Read_UINT32(s, pdu.frameId);            
 
 1217  Stream_Read_UINT32(s, pdu.totalFramesDecoded); 
 
 1221    IFCALLRET(context->FrameAcknowledge, error, context, &pdu);
 
 1224      WLog_Print(context->priv->log, WLOG_ERROR,
 
 1225                 "context->FrameAcknowledge failed with error %" PRIu32 
"", error);
 
 1236static UINT rdpgfx_recv_cache_import_offer_pdu(RdpgfxServerContext* context, 
wStream* s)
 
 1238  if (!checkCapsAreExchanged(context))
 
 1239    return CHANNEL_RC_NOT_INITIALIZED;
 
 1243  UINT error = CHANNEL_RC_OK;
 
 1245  if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
 
 1246    return ERROR_INVALID_DATA;
 
 1249  Stream_Read_UINT16(s, pdu.cacheEntriesCount);
 
 1252  if (pdu.cacheEntriesCount >= 5462)
 
 1254    WLog_Print(context->priv->log, WLOG_ERROR, 
"Invalid cacheEntriesCount: %" PRIu16 
"",
 
 1255               pdu.cacheEntriesCount);
 
 1256    return ERROR_INVALID_DATA;
 
 1259  if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, pdu.cacheEntriesCount, 12ull))
 
 1260    return ERROR_INVALID_DATA;
 
 1262  for (UINT16 index = 0; index < pdu.cacheEntriesCount; index++)
 
 1264    cacheEntry = &(pdu.cacheEntries[index]);
 
 1265    Stream_Read_UINT64(s, cacheEntry->cacheKey);     
 
 1266    Stream_Read_UINT32(s, cacheEntry->bitmapLength); 
 
 1271    IFCALLRET(context->CacheImportOffer, error, context, &pdu);
 
 1274      WLog_Print(context->priv->log, WLOG_ERROR,
 
 1275                 "context->CacheImportOffer failed with error %" PRIu32 
"", error);
 
 1286static UINT rdpgfx_recv_caps_advertise_pdu(RdpgfxServerContext* context, 
wStream* s)
 
 1290  UINT error = ERROR_INVALID_DATA;
 
 1293    return ERROR_BAD_ARGUMENTS;
 
 1295  if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
 
 1296    return ERROR_INVALID_DATA;
 
 1298  Stream_Read_UINT16(s, pdu.capsSetCount); 
 
 1299  if (pdu.capsSetCount > 0)
 
 1301    capsSets = calloc(pdu.capsSetCount, (RDPGFX_CAPSET_BASE_SIZE + 4));
 
 1303      return ERROR_OUTOFMEMORY;
 
 1306  pdu.capsSets = capsSets;
 
 1308  for (UINT16 index = 0; index < pdu.capsSetCount; index++)
 
 1312    if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
 
 1315    Stream_Read_UINT32(s, capsSet->version); 
 
 1316    Stream_Read_UINT32(s, capsSet->length);  
 
 1318    if (capsSet->length >= 4)
 
 1320      if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
 
 1323      Stream_Peek_UINT32(s, capsSet->flags); 
 
 1326    if (!Stream_SafeSeek(s, capsSet->length))
 
 1330  error = ERROR_BAD_CONFIGURATION;
 
 1331  IFCALLRET(context->CapsAdvertise, error, context, &pdu);
 
 1334    WLog_Print(context->priv->log, WLOG_ERROR,
 
 1335               "context->CapsAdvertise failed with error %" PRIu32 
"", error);
 
 1347static UINT rdpgfx_recv_qoe_frame_acknowledge_pdu(RdpgfxServerContext* context, 
wStream* s)
 
 1349  if (!checkCapsAreExchanged(context))
 
 1350    return CHANNEL_RC_NOT_INITIALIZED;
 
 1352  UINT error = CHANNEL_RC_OK;
 
 1354  if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
 
 1355    return ERROR_INVALID_DATA;
 
 1357  Stream_Read_UINT32(s, pdu.frameId);     
 
 1358  Stream_Read_UINT32(s, pdu.timestamp);   
 
 1359  Stream_Read_UINT16(s, pdu.timeDiffSE);  
 
 1360  Stream_Read_UINT16(s, pdu.timeDiffEDR); 
 
 1364    IFCALLRET(context->QoeFrameAcknowledge, error, context, &pdu);
 
 1367      WLog_Print(context->priv->log, WLOG_ERROR,
 
 1368                 "context->QoeFrameAcknowledge failed with error %" PRIu32 
"", error);
 
 1375rdpgfx_send_map_surface_to_scaled_output_pdu(RdpgfxServerContext* context,
 
 1378  if (!checkCapsAreExchanged(context))
 
 1379    return CHANNEL_RC_NOT_INITIALIZED;
 
 1380  wStream* s = rdpgfx_server_single_packet_new(context->priv->log,
 
 1381                                               RDPGFX_CMDID_MAPSURFACETOSCALEDOUTPUT, 20);
 
 1385    WLog_Print(context->priv->log, WLOG_ERROR, 
"rdpgfx_server_single_packet_new failed!");
 
 1386    return CHANNEL_RC_NO_MEMORY;
 
 1389  Stream_Write_UINT16(s, pdu->surfaceId);     
 
 1390  Stream_Write_UINT16(s, 0);                  
 
 1391  Stream_Write_UINT32(s, pdu->outputOriginX); 
 
 1392  Stream_Write_UINT32(s, pdu->outputOriginY); 
 
 1393  Stream_Write_UINT32(s, pdu->targetWidth);   
 
 1394  Stream_Write_UINT32(s, pdu->targetHeight);  
 
 1395  return rdpgfx_server_single_packet_send(context, s);
 
 1403static UINT rdpgfx_server_receive_pdu(RdpgfxServerContext* context, 
wStream* s)
 
 1408  UINT error = CHANNEL_RC_OK;
 
 1409  beg = Stream_GetPosition(s);
 
 1411  if ((error = rdpgfx_read_header(s, &header)))
 
 1413    WLog_Print(context->priv->log, WLOG_ERROR,
 
 1414               "rdpgfx_read_header failed with error %" PRIu32 
"!", error);
 
 1418#ifdef WITH_DEBUG_RDPGFX 
 1419  WLog_DBG(TAG, 
"cmdId: %s (0x%04" PRIX16 
") flags: 0x%04" PRIX16 
" pduLength: %" PRIu32 
"",
 
 1420           rdpgfx_get_cmd_id_string(header.cmdId), header.cmdId, header.flags, header.pduLength);
 
 1423  switch (header.cmdId)
 
 1425    case RDPGFX_CMDID_FRAMEACKNOWLEDGE:
 
 1426      if ((error = rdpgfx_recv_frame_acknowledge_pdu(context, s)))
 
 1427        WLog_Print(context->priv->log, WLOG_ERROR,
 
 1428                   "rdpgfx_recv_frame_acknowledge_pdu " 
 1429                   "failed with error %" PRIu32 
"!",
 
 1434    case RDPGFX_CMDID_CACHEIMPORTOFFER:
 
 1435      if ((error = rdpgfx_recv_cache_import_offer_pdu(context, s)))
 
 1436        WLog_Print(context->priv->log, WLOG_ERROR,
 
 1437                   "rdpgfx_recv_cache_import_offer_pdu " 
 1438                   "failed with error %" PRIu32 
"!",
 
 1443    case RDPGFX_CMDID_CAPSADVERTISE:
 
 1444      if ((error = rdpgfx_recv_caps_advertise_pdu(context, s)))
 
 1445        WLog_Print(context->priv->log, WLOG_ERROR,
 
 1446                   "rdpgfx_recv_caps_advertise_pdu " 
 1447                   "failed with error %" PRIu32 
"!",
 
 1452    case RDPGFX_CMDID_QOEFRAMEACKNOWLEDGE:
 
 1453      if ((error = rdpgfx_recv_qoe_frame_acknowledge_pdu(context, s)))
 
 1454        WLog_Print(context->priv->log, WLOG_ERROR,
 
 1455                   "rdpgfx_recv_qoe_frame_acknowledge_pdu " 
 1456                   "failed with error %" PRIu32 
"!",
 
 1462      error = CHANNEL_RC_BAD_PROC;
 
 1468    WLog_Print(context->priv->log, WLOG_ERROR,
 
 1469               "Error while parsing GFX cmdId: %s (0x%04" PRIX16 
")",
 
 1470               rdpgfx_get_cmd_id_string(header.cmdId), header.cmdId);
 
 1474  end = Stream_GetPosition(s);
 
 1476  if (end != (beg + header.pduLength))
 
 1478    WLog_Print(context->priv->log, WLOG_ERROR,
 
 1479               "Unexpected gfx pdu end: Actual: %" PRIuz 
", Expected: %" PRIuz 
"", end,
 
 1480               (beg + header.pduLength));
 
 1481    Stream_SetPosition(s, (beg + header.pduLength));
 
 1487static BOOL rdpgfx_server_close(RdpgfxServerContext* context);
 
 1489static DWORD WINAPI rdpgfx_server_thread_func(LPVOID arg)
 
 1491  RdpgfxServerContext* context = (RdpgfxServerContext*)arg;
 
 1492  WINPR_ASSERT(context);
 
 1494  RdpgfxServerPrivate* priv = context->priv;
 
 1497  HANDLE events[8] = { 0 };
 
 1498  UINT error = CHANNEL_RC_OK;
 
 1502  if (priv->ownThread)
 
 1504    WINPR_ASSERT(priv->stopEvent);
 
 1505    events[nCount++] = priv->stopEvent;
 
 1508  WINPR_ASSERT(priv->channelEvent);
 
 1509  events[nCount++] = priv->channelEvent;
 
 1514    status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
 
 1516    if (status == WAIT_FAILED)
 
 1518      error = GetLastError();
 
 1519      WLog_Print(context->priv->log, WLOG_ERROR,
 
 1520                 "WaitForMultipleObjects failed with error %" PRIu32 
"", error);
 
 1525    if (status == WAIT_OBJECT_0)
 
 1528    if ((error = rdpgfx_server_handle_messages(context)))
 
 1530      WLog_Print(context->priv->log, WLOG_ERROR,
 
 1531                 "rdpgfx_server_handle_messages failed with error %" PRIu32 
"", error);
 
 1536  if (error && context->rdpcontext)
 
 1537    setChannelError(context->rdpcontext, error, 
"rdpgfx_server_thread_func reported an error");
 
 1543static BOOL rdpgfx_server_open(RdpgfxServerContext* context)
 
 1545  WINPR_ASSERT(context);
 
 1546  RdpgfxServerPrivate* priv = context->priv;
 
 1547  void* buffer = NULL;
 
 1551  if (!priv->isOpened)
 
 1553    PULONG pSessionId = NULL;
 
 1554    DWORD BytesReturned = 0;
 
 1555    priv->SessionId = WTS_CURRENT_SESSION;
 
 1556    UINT32 channelId = 0;
 
 1559    if (WTSQuerySessionInformationA(context->vcm, WTS_CURRENT_SESSION, WTSSessionId,
 
 1560                                    (LPSTR*)&pSessionId, &BytesReturned) == FALSE)
 
 1562      WLog_Print(context->priv->log, WLOG_ERROR, 
"WTSQuerySessionInformationA failed!");
 
 1566    priv->SessionId = (DWORD)*pSessionId;
 
 1567    WTSFreeMemory(pSessionId);
 
 1568    priv->rdpgfx_channel = WTSVirtualChannelOpenEx(priv->SessionId, RDPGFX_DVC_CHANNEL_NAME,
 
 1569                                                   WTS_CHANNEL_OPTION_DYNAMIC);
 
 1571    if (!priv->rdpgfx_channel)
 
 1573      WLog_Print(context->priv->log, WLOG_ERROR, 
"WTSVirtualChannelOpenEx failed!");
 
 1577    channelId = WTSChannelGetIdByHandle(priv->rdpgfx_channel);
 
 1579    IFCALLRET(context->ChannelIdAssigned, status, context, channelId);
 
 1582      WLog_Print(context->priv->log, WLOG_ERROR, 
"context->ChannelIdAssigned failed!");
 
 1587    if (!WTSVirtualChannelQuery(priv->rdpgfx_channel, WTSVirtualEventHandle, &buffer,
 
 1589        (BytesReturned != 
sizeof(HANDLE)))
 
 1591      WLog_Print(context->priv->log, WLOG_ERROR,
 
 1592                 "WTSVirtualChannelQuery failed " 
 1593                 "or invalid returned size(%" PRIu32 
")",
 
 1597        WTSFreeMemory(buffer);
 
 1602    priv->channelEvent = *(HANDLE*)buffer;
 
 1603    WTSFreeMemory(buffer);
 
 1605    if (!(priv->zgfx = zgfx_context_new(TRUE)))
 
 1607      WLog_Print(context->priv->log, WLOG_ERROR, 
"Create zgfx context failed!");
 
 1611    priv->isReady = FALSE;
 
 1613    priv->activeCapSet = empty;
 
 1614    if (priv->ownThread)
 
 1616      if (!(priv->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
 
 1618        WLog_Print(context->priv->log, WLOG_ERROR, 
"CreateEvent failed!");
 
 1622      if (!(priv->thread =
 
 1623                CreateThread(NULL, 0, rdpgfx_server_thread_func, (
void*)context, 0, NULL)))
 
 1625        WLog_Print(context->priv->log, WLOG_ERROR, 
"CreateThread failed!");
 
 1630    priv->isOpened = TRUE;
 
 1634  WLog_Print(context->priv->log, WLOG_ERROR, 
"RDPGFX channel is already opened!");
 
 1637  rdpgfx_server_close(context);
 
 1641BOOL rdpgfx_server_close(RdpgfxServerContext* context)
 
 1643  WINPR_ASSERT(context);
 
 1645  RdpgfxServerPrivate* priv = context->priv;
 
 1648  if (priv->ownThread && priv->thread)
 
 1650    (void)SetEvent(priv->stopEvent);
 
 1652    if (WaitForSingleObject(priv->thread, INFINITE) == WAIT_FAILED)
 
 1654      WLog_ERR(TAG, 
"WaitForSingleObject failed with error %" PRIu32 
"", GetLastError());
 
 1658    (void)CloseHandle(priv->thread);
 
 1659    (void)CloseHandle(priv->stopEvent);
 
 1660    priv->thread = NULL;
 
 1661    priv->stopEvent = NULL;
 
 1664  zgfx_context_free(priv->zgfx);
 
 1667  if (priv->rdpgfx_channel)
 
 1669    (void)WTSVirtualChannelClose(priv->rdpgfx_channel);
 
 1670    priv->rdpgfx_channel = NULL;
 
 1673  priv->channelEvent = NULL;
 
 1674  priv->isOpened = FALSE;
 
 1675  priv->isReady = FALSE;
 
 1677  priv->activeCapSet = empty;
 
 1681static BOOL rdpgfx_server_initialize(RdpgfxServerContext* context, BOOL externalThread)
 
 1683  WINPR_ASSERT(context);
 
 1684  WINPR_ASSERT(context->priv);
 
 1686  if (context->priv->isOpened)
 
 1688    WLog_Print(context->priv->log, WLOG_WARN,
 
 1689               "Application error: RDPEGFX channel already initialized, " 
 1690               "calling in this state is not possible!");
 
 1694  context->priv->ownThread = !externalThread;
 
 1698RdpgfxServerContext* rdpgfx_server_context_new(HANDLE vcm)
 
 1700  RdpgfxServerContext* context = (RdpgfxServerContext*)calloc(1, 
sizeof(RdpgfxServerContext));
 
 1704    WLog_ERR(TAG, 
"calloc failed!");
 
 1709  context->Initialize = rdpgfx_server_initialize;
 
 1710  context->Open = rdpgfx_server_open;
 
 1711  context->Close = rdpgfx_server_close;
 
 1712  context->ResetGraphics = rdpgfx_send_reset_graphics_pdu;
 
 1713  context->StartFrame = rdpgfx_send_start_frame_pdu;
 
 1714  context->EndFrame = rdpgfx_send_end_frame_pdu;
 
 1715  context->SurfaceCommand = rdpgfx_send_surface_command;
 
 1716  context->SurfaceFrameCommand = rdpgfx_send_surface_frame_command;
 
 1717  context->DeleteEncodingContext = rdpgfx_send_delete_encoding_context_pdu;
 
 1718  context->CreateSurface = rdpgfx_send_create_surface_pdu;
 
 1719  context->DeleteSurface = rdpgfx_send_delete_surface_pdu;
 
 1720  context->SolidFill = rdpgfx_send_solid_fill_pdu;
 
 1721  context->SurfaceToSurface = rdpgfx_send_surface_to_surface_pdu;
 
 1722  context->SurfaceToCache = rdpgfx_send_surface_to_cache_pdu;
 
 1723  context->CacheToSurface = rdpgfx_send_cache_to_surface_pdu;
 
 1724  context->CacheImportOffer = rdpgfx_process_cache_import_offer_pdu;
 
 1725  context->CacheImportReply = rdpgfx_send_cache_import_reply_pdu;
 
 1726  context->EvictCacheEntry = rdpgfx_send_evict_cache_entry_pdu;
 
 1727  context->MapSurfaceToOutput = rdpgfx_send_map_surface_to_output_pdu;
 
 1728  context->MapSurfaceToWindow = rdpgfx_send_map_surface_to_window_pdu;
 
 1729  context->MapSurfaceToScaledOutput = rdpgfx_send_map_surface_to_scaled_output_pdu;
 
 1730  context->MapSurfaceToScaledWindow = rdpgfx_send_map_surface_to_scaled_window_pdu;
 
 1731  context->CapsAdvertise = NULL;
 
 1732  context->CapsConfirm = rdpgfx_send_caps_confirm_pdu;
 
 1733  context->FrameAcknowledge = NULL;
 
 1734  context->QoeFrameAcknowledge = NULL;
 
 1735  RdpgfxServerPrivate* priv = context->priv =
 
 1736      (RdpgfxServerPrivate*)calloc(1, 
sizeof(RdpgfxServerPrivate));
 
 1740    WLog_ERR(TAG, 
"calloc failed!");
 
 1744  priv->log = WLog_Get(TAG);
 
 1749  priv->input_stream = Stream_New(NULL, 4);
 
 1751  if (!priv->input_stream)
 
 1753    WLog_Print(context->priv->log, WLOG_ERROR, 
"Stream_New failed!");
 
 1757  priv->isOpened = FALSE;
 
 1758  priv->isReady = FALSE;
 
 1759  priv->ownThread = TRUE;
 
 1762  priv->activeCapSet = empty;
 
 1765  WINPR_PRAGMA_DIAG_PUSH
 
 1766  WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
 
 1767  rdpgfx_server_context_free(context);
 
 1768  WINPR_PRAGMA_DIAG_POP
 
 1772void rdpgfx_server_context_free(RdpgfxServerContext* context)
 
 1777  rdpgfx_server_close(context);
 
 1780    Stream_Free(context->priv->input_stream, TRUE);
 
 1782  free(context->priv);
 
 1786HANDLE rdpgfx_server_get_event_handle(RdpgfxServerContext* context)
 
 1792  return context->priv->channelEvent;
 
 1804UINT rdpgfx_server_handle_messages(RdpgfxServerContext* context)
 
 1806  DWORD BytesReturned = 0;
 
 1807  void* buffer = NULL;
 
 1808  UINT ret = CHANNEL_RC_OK;
 
 1810  WINPR_ASSERT(context);
 
 1811  WINPR_ASSERT(context->priv);
 
 1813  RdpgfxServerPrivate* priv = context->priv;
 
 1814  wStream* s = priv->input_stream;
 
 1819    if (WTSVirtualChannelQuery(priv->rdpgfx_channel, WTSVirtualChannelReady, &buffer,
 
 1820                               &BytesReturned) == FALSE)
 
 1822      if (GetLastError() == ERROR_NO_DATA)
 
 1823        return ERROR_NO_DATA;
 
 1825      WLog_Print(context->priv->log, WLOG_ERROR, 
"WTSVirtualChannelQuery failed");
 
 1826      return ERROR_INTERNAL_ERROR;
 
 1829    priv->isReady = *((BOOL*)buffer);
 
 1830    WTSFreeMemory(buffer);
 
 1836    Stream_SetPosition(s, 0);
 
 1838    if (!WTSVirtualChannelRead(priv->rdpgfx_channel, 0, NULL, 0, &BytesReturned))
 
 1840      if (GetLastError() == ERROR_NO_DATA)
 
 1841        return ERROR_NO_DATA;
 
 1843      WLog_Print(context->priv->log, WLOG_ERROR, 
"WTSVirtualChannelRead failed!");
 
 1844      return ERROR_INTERNAL_ERROR;
 
 1847    if (BytesReturned < 1)
 
 1848      return CHANNEL_RC_OK;
 
 1850    if (!Stream_EnsureRemainingCapacity(s, BytesReturned))
 
 1852      WLog_Print(context->priv->log, WLOG_ERROR, 
"Stream_EnsureRemainingCapacity failed!");
 
 1853      return CHANNEL_RC_NO_MEMORY;
 
 1856    const size_t len = Stream_Capacity(s);
 
 1857    if (len > UINT32_MAX)
 
 1858      return ERROR_INTERNAL_ERROR;
 
 1859    if (WTSVirtualChannelRead(priv->rdpgfx_channel, 0, Stream_BufferAs(s, 
char), (UINT32)len,
 
 1860                              &BytesReturned) == FALSE)
 
 1862      WLog_Print(context->priv->log, WLOG_ERROR, 
"WTSVirtualChannelRead failed!");
 
 1863      return ERROR_INTERNAL_ERROR;
 
 1866    Stream_SetLength(s, BytesReturned);
 
 1867    Stream_SetPosition(s, 0);
 
 1869    while (Stream_GetPosition(s) < Stream_Length(s))
 
 1871      if ((ret = rdpgfx_server_receive_pdu(context, s)))
 
 1873        WLog_Print(context->priv->log, WLOG_ERROR,
 
 1874                   "rdpgfx_server_receive_pdu " 
 1875                   "failed with error %" PRIu32 
"!",