20 #include <freerdp/config.h>
22 #include <winpr/assert.h>
27 #include <winpr/cast.h>
28 #include <winpr/crt.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__)
47 static 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_PrintMessage(context->priv->log, WLOG_MESSAGE_TEXT, level, line, file, fkt,
57 "activeCapSet{Version=0x%08" PRIx32
", flags=0x%08" PRIx32
"}",
58 context->priv->activeCapSet.version, context->priv->activeCapSet.flags);
60 return context->priv->activeCapSet.version > 0;
72 static INLINE UINT32 rdpgfx_pdu_length(UINT32 dataLen)
74 return RDPGFX_HEADER_SIZE + dataLen;
77 static INLINE UINT rdpgfx_server_packet_init_header(
wStream* s, UINT16 cmdId, UINT32 pduLength)
82 header.pduLength = pduLength;
85 return rdpgfx_write_header(s, &header);
95 static INLINE BOOL rdpgfx_server_packet_complete_header(
wStream* s,
size_t start)
97 const size_t current = Stream_GetPosition(s);
98 const size_t cap = Stream_Capacity(s);
99 if (cap < start + RDPGFX_HEADER_SIZE)
101 if ((start > UINT32_MAX) || (current < start))
104 Stream_SetPosition(s, start + RDPGFX_HEADER_SIZE -
sizeof(UINT32));
105 Stream_Write_UINT32(s, (UINT32)(current - start));
106 Stream_SetPosition(s, current);
117 static UINT rdpgfx_server_packet_send(RdpgfxServerContext* context,
wStream* s)
122 BYTE* pSrcData = Stream_Buffer(s);
123 const size_t SrcSize = Stream_GetPosition(s);
124 if (SrcSize > UINT32_MAX)
125 return ERROR_INTERNAL_ERROR;
131 fs = Stream_New(NULL, SrcSize + 7 + (SrcSize / ZGFX_SEGMENTED_MAXSIZE + 1) * 4);
135 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_New failed!");
136 error = CHANNEL_RC_NO_MEMORY;
140 if (zgfx_compress_to_stream(context->priv->zgfx, fs, pSrcData, (UINT32)SrcSize, &flags) < 0)
142 WLog_Print(context->priv->log, WLOG_ERROR,
"zgfx_compress_to_stream failed!");
143 error = ERROR_INTERNAL_ERROR;
147 const size_t pos = Stream_GetPosition(fs);
149 WINPR_ASSERT(pos <= UINT32_MAX);
150 if (!WTSVirtualChannelWrite(context->priv->rdpgfx_channel, Stream_BufferAs(fs,
char),
151 (UINT32)pos, &written))
153 WLog_Print(context->priv->log, WLOG_ERROR,
"WTSVirtualChannelWrite failed!");
154 error = ERROR_INTERNAL_ERROR;
158 if (written < Stream_GetPosition(fs))
160 WLog_Print(context->priv->log, WLOG_WARN,
161 "Unexpected bytes written: %" PRIu32
"/%" PRIuz
"", written,
162 Stream_GetPosition(fs));
165 error = CHANNEL_RC_OK;
167 Stream_Free(fs, TRUE);
168 Stream_Free(s, TRUE);
184 static wStream* rdpgfx_server_single_packet_new(wLog* log, UINT16 cmdId, UINT32 dataLen)
188 UINT32 pduLength = rdpgfx_pdu_length(dataLen);
189 s = Stream_New(NULL, pduLength);
193 WLog_Print(log, WLOG_ERROR,
"Stream_New failed!");
197 if ((error = rdpgfx_server_packet_init_header(s, cmdId, pduLength)))
199 WLog_Print(log, WLOG_ERROR,
"Failed to init header with error %" PRIu32
"!", error);
205 Stream_Free(s, TRUE);
217 static INLINE UINT rdpgfx_server_single_packet_send(RdpgfxServerContext* context,
wStream* s)
220 rdpgfx_server_packet_complete_header(s, 0);
221 return rdpgfx_server_packet_send(context, s);
229 static UINT rdpgfx_send_caps_confirm_pdu(RdpgfxServerContext* context,
235 WINPR_ASSERT(context);
236 WINPR_ASSERT(capsConfirm);
238 capsSet = capsConfirm->capsSet;
239 WINPR_ASSERT(capsSet);
241 s = rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_CAPSCONFIRM,
242 RDPGFX_CAPSET_BASE_SIZE + capsSet->length);
246 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpgfx_server_single_packet_new failed!");
247 return CHANNEL_RC_NO_MEMORY;
250 WLog_DBG(TAG,
"CAPS version=0x%04" PRIx32
", flags=0x%04" PRIx32
", length=%" PRIu32,
251 capsSet->version, capsSet->flags, capsSet->length);
252 Stream_Write_UINT32(s, capsSet->version);
253 Stream_Write_UINT32(s, capsSet->length);
255 if (capsSet->length >= 4)
257 Stream_Write_UINT32(s, capsSet->flags);
258 Stream_Zero(s, capsSet->length - 4);
261 Stream_Zero(s, capsSet->length);
263 context->priv->activeCapSet = *capsSet;
264 return rdpgfx_server_single_packet_send(context, s);
272 static UINT rdpgfx_send_reset_graphics_pdu(RdpgfxServerContext* context,
275 if (!checkCapsAreExchanged(context))
276 return CHANNEL_RC_NOT_INITIALIZED;
281 if (pdu->monitorCount >= 16)
283 WLog_Print(context->priv->log, WLOG_ERROR,
284 "Monitor count MUST be less than or equal to 16: %" PRIu32
"",
286 return ERROR_INVALID_DATA;
289 s = rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_RESETGRAPHICS,
290 RDPGFX_RESET_GRAPHICS_PDU_SIZE - RDPGFX_HEADER_SIZE);
294 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpgfx_server_single_packet_new failed!");
295 return CHANNEL_RC_NO_MEMORY;
298 Stream_Write_UINT32(s, pdu->width);
299 Stream_Write_UINT32(s, pdu->height);
300 Stream_Write_UINT32(s, pdu->monitorCount);
302 for (UINT32 index = 0; index < pdu->monitorCount; index++)
304 const MONITOR_DEF* monitor = &(pdu->monitorDefArray[index]);
305 Stream_Write_INT32(s, monitor->left);
306 Stream_Write_INT32(s, monitor->top);
307 Stream_Write_INT32(s, monitor->right);
308 Stream_Write_INT32(s, monitor->bottom);
309 Stream_Write_UINT32(s, monitor->flags);
313 Stream_SetPosition(s, RDPGFX_RESET_GRAPHICS_PDU_SIZE);
314 return rdpgfx_server_single_packet_send(context, s);
322 static UINT rdpgfx_send_evict_cache_entry_pdu(RdpgfxServerContext* context,
325 if (!checkCapsAreExchanged(context))
326 return CHANNEL_RC_NOT_INITIALIZED;
328 rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_EVICTCACHEENTRY, 2);
332 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpgfx_server_single_packet_new failed!");
333 return CHANNEL_RC_NO_MEMORY;
336 Stream_Write_UINT16(s, pdu->cacheSlot);
337 return rdpgfx_server_single_packet_send(context, s);
345 static UINT rdpgfx_send_cache_import_reply_pdu(RdpgfxServerContext* context,
348 if (!checkCapsAreExchanged(context))
349 return CHANNEL_RC_NOT_INITIALIZED;
350 WINPR_ASSERT(context);
353 WLog_DBG(TAG,
"reply with %" PRIu16
" entries", pdu->importedEntriesCount);
354 wStream* s = rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_CACHEIMPORTREPLY,
355 2 + 2 * pdu->importedEntriesCount);
359 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpgfx_server_single_packet_new failed!");
360 return CHANNEL_RC_NO_MEMORY;
364 Stream_Write_UINT16(s, pdu->importedEntriesCount);
366 for (UINT16 index = 0; index < pdu->importedEntriesCount; index++)
368 Stream_Write_UINT16(s, pdu->cacheSlots[index]);
371 return rdpgfx_server_single_packet_send(context, s);
375 rdpgfx_process_cache_import_offer_pdu(RdpgfxServerContext* context,
378 if (!checkCapsAreExchanged(context))
379 return CHANNEL_RC_NOT_INITIALIZED;
380 WINPR_ASSERT(context);
381 WINPR_ASSERT(cacheImportOffer);
384 WLog_DBG(TAG,
"received %" PRIu16
" entries, reply with %" PRIu16
" entries",
385 cacheImportOffer->cacheEntriesCount, reply.importedEntriesCount);
386 return IFCALLRESULT(CHANNEL_RC_OK, context->CacheImportReply, context, &reply);
394 static UINT rdpgfx_send_create_surface_pdu(RdpgfxServerContext* context,
397 if (!checkCapsAreExchanged(context))
398 return CHANNEL_RC_NOT_INITIALIZED;
399 wStream* s = rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_CREATESURFACE, 7);
401 WINPR_ASSERT(context);
403 WINPR_ASSERT((pdu->pixelFormat == GFX_PIXEL_FORMAT_XRGB_8888) ||
404 (pdu->pixelFormat == GFX_PIXEL_FORMAT_ARGB_8888));
408 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpgfx_server_single_packet_new failed!");
409 return CHANNEL_RC_NO_MEMORY;
412 Stream_Write_UINT16(s, pdu->surfaceId);
413 Stream_Write_UINT16(s, pdu->width);
414 Stream_Write_UINT16(s, pdu->height);
415 Stream_Write_UINT8(s, pdu->pixelFormat);
416 return rdpgfx_server_single_packet_send(context, s);
424 static UINT rdpgfx_send_delete_surface_pdu(RdpgfxServerContext* context,
427 if (!checkCapsAreExchanged(context))
428 return CHANNEL_RC_NOT_INITIALIZED;
429 wStream* s = rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_DELETESURFACE, 2);
433 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpgfx_server_single_packet_new failed!");
434 return CHANNEL_RC_NO_MEMORY;
437 Stream_Write_UINT16(s, pdu->surfaceId);
438 return rdpgfx_server_single_packet_send(context, s);
443 if (!Stream_EnsureRemainingCapacity(s, 8))
445 Stream_Write_UINT32(s, pdu->timestamp);
446 Stream_Write_UINT32(s, pdu->frameId);
452 if (!Stream_EnsureRemainingCapacity(s, 4))
454 Stream_Write_UINT32(s, pdu->frameId);
463 static UINT rdpgfx_send_start_frame_pdu(RdpgfxServerContext* context,
466 if (!checkCapsAreExchanged(context))
467 return CHANNEL_RC_NOT_INITIALIZED;
468 wStream* s = rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_STARTFRAME,
469 RDPGFX_START_FRAME_PDU_SIZE);
473 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpgfx_server_single_packet_new failed!");
474 return CHANNEL_RC_NO_MEMORY;
477 rdpgfx_write_start_frame_pdu(s, pdu);
478 return rdpgfx_server_single_packet_send(context, s);
486 static UINT rdpgfx_send_end_frame_pdu(RdpgfxServerContext* context,
const RDPGFX_END_FRAME_PDU* pdu)
488 if (!checkCapsAreExchanged(context))
489 return CHANNEL_RC_NOT_INITIALIZED;
490 wStream* s = rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_ENDFRAME,
491 RDPGFX_END_FRAME_PDU_SIZE);
495 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpgfx_server_single_packet_new failed!");
496 return CHANNEL_RC_NO_MEMORY;
499 rdpgfx_write_end_frame_pdu(s, pdu);
500 return rdpgfx_server_single_packet_send(context, s);
512 return sizeof(UINT32)
514 * havc420->meta.numRegionRects +
531 switch (cmd->codecId)
533 case RDPGFX_CODECID_CAPROGRESSIVE:
534 case RDPGFX_CODECID_CAPROGRESSIVE_V2:
535 return RDPGFX_WIRE_TO_SURFACE_PDU_2_SIZE + cmd->length;
537 case RDPGFX_CODECID_AVC420:
539 h264Size = rdpgfx_estimate_h264_avc420(havc420);
540 return RDPGFX_WIRE_TO_SURFACE_PDU_1_SIZE + h264Size;
542 case RDPGFX_CODECID_AVC444:
544 h264Size =
sizeof(UINT32);
546 havc420 = &(havc444->bitstream[0]);
547 h264Size += rdpgfx_estimate_h264_avc420(havc420);
550 if (havc444->LC == 0)
552 havc420 = &(havc444->bitstream[1]);
553 h264Size += rdpgfx_estimate_h264_avc420(havc420);
556 return RDPGFX_WIRE_TO_SURFACE_PDU_1_SIZE + h264Size;
559 return RDPGFX_WIRE_TO_SURFACE_PDU_1_SIZE + cmd->length;
572 if (cmd->codecId == RDPGFX_CODECID_CAPROGRESSIVE ||
573 cmd->codecId == RDPGFX_CODECID_CAPROGRESSIVE_V2)
575 return RDPGFX_CMDID_WIRETOSURFACE_2;
578 return RDPGFX_CMDID_WIRETOSURFACE_1;
590 UINT error = CHANNEL_RC_OK;
592 if (!Stream_EnsureRemainingCapacity(s, 4 + meta->numRegionRects * 10))
593 return ERROR_OUTOFMEMORY;
595 Stream_Write_UINT32(s, meta->numRegionRects);
597 for (UINT32 index = 0; index < meta->numRegionRects; index++)
599 regionRect = &(meta->regionRects[index]);
601 if ((error = rdpgfx_write_rect16(s, regionRect)))
603 WLog_Print(log, WLOG_ERROR,
"rdpgfx_write_rect16 failed with error %" PRIu32
"!",
609 for (UINT32 index = 0; index < meta->numRegionRects; index++)
611 quantQualityVal = &(meta->quantQualityVals[index]);
612 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(
613 uint8_t, quantQualityVal->qp | (quantQualityVal->r << 6) |
614 (quantQualityVal->p << 7)));
616 Stream_Write_UINT8(s, quantQualityVal->qualityVal);
628 static INLINE UINT rdpgfx_write_h264_avc420(wLog* log,
wStream* s,
631 UINT error = CHANNEL_RC_OK;
633 if ((error = rdpgfx_write_h264_metablock(log, s, &(havc420->meta))))
635 WLog_Print(log, WLOG_ERROR,
"rdpgfx_write_h264_metablock failed with error %" PRIu32
"!",
640 if (!Stream_EnsureRemainingCapacity(s, havc420->length))
641 return ERROR_OUTOFMEMORY;
643 Stream_Write(s, havc420->data, havc420->length);
656 UINT error = CHANNEL_RC_OK;
659 UINT8 pixelFormat = 0;
663 case PIXEL_FORMAT_BGRX32:
664 pixelFormat = GFX_PIXEL_FORMAT_XRGB_8888;
667 case PIXEL_FORMAT_BGRA32:
668 pixelFormat = GFX_PIXEL_FORMAT_ARGB_8888;
672 WLog_Print(log, WLOG_ERROR,
"Format %s not supported!",
673 FreeRDPGetColorFormatName(cmd->format));
674 return ERROR_INVALID_DATA;
677 if (cmd->codecId == RDPGFX_CODECID_CAPROGRESSIVE ||
678 cmd->codecId == RDPGFX_CODECID_CAPROGRESSIVE_V2)
680 if (!Stream_EnsureRemainingCapacity(s, 13 + cmd->length))
681 return ERROR_INTERNAL_ERROR;
684 s, WINPR_ASSERTING_INT_CAST(uint16_t, cmd->surfaceId));
686 s, WINPR_ASSERTING_INT_CAST(uint16_t, cmd->codecId));
687 Stream_Write_UINT32(s, cmd->contextId);
688 Stream_Write_UINT8(s, pixelFormat);
689 Stream_Write_UINT32(s, cmd->length);
690 Stream_Write(s, cmd->data, cmd->length);
695 if (!Stream_EnsureRemainingCapacity(s, 17))
696 return ERROR_INTERNAL_ERROR;
698 s, WINPR_ASSERTING_INT_CAST(uint16_t, cmd->surfaceId));
700 s, WINPR_ASSERTING_INT_CAST(uint16_t, cmd->codecId));
701 Stream_Write_UINT8(s, pixelFormat);
702 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, cmd->left));
703 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, cmd->top));
704 Stream_Write_UINT16(s,
705 WINPR_ASSERTING_INT_CAST(uint16_t, cmd->right));
706 Stream_Write_UINT16(s,
707 WINPR_ASSERTING_INT_CAST(uint16_t, cmd->bottom));
708 Stream_Write_UINT32(s, cmd->length);
709 const size_t bitmapDataStart = Stream_GetPosition(s);
711 if (cmd->codecId == RDPGFX_CODECID_AVC420)
714 error = rdpgfx_write_h264_avc420(log, s, havc420);
716 if (error != CHANNEL_RC_OK)
718 WLog_Print(log, WLOG_ERROR,
"rdpgfx_write_h264_avc420 failed!");
722 else if ((cmd->codecId == RDPGFX_CODECID_AVC444) ||
723 (cmd->codecId == RDPGFX_CODECID_AVC444v2))
726 havc420 = &(havc444->bitstream[0]);
727 if (!Stream_EnsureRemainingCapacity(s, 4))
728 return ERROR_INTERNAL_ERROR;
729 Stream_Write_UINT32(s, havc444->cbAvc420EncodedBitstream1 |
730 ((uint32_t)havc444->LC << 30UL));
732 error = rdpgfx_write_h264_avc420(log, s, havc420);
734 if (error != CHANNEL_RC_OK)
736 WLog_Print(log, WLOG_ERROR,
"rdpgfx_write_h264_avc420 failed!");
741 if (havc444->LC == 0)
743 havc420 = &(havc444->bitstream[1]);
744 error = rdpgfx_write_h264_avc420(log, s, havc420);
746 if (error != CHANNEL_RC_OK)
748 WLog_Print(log, WLOG_ERROR,
"rdpgfx_write_h264_avc420 failed!");
755 if (!Stream_EnsureRemainingCapacity(s, cmd->length))
756 return ERROR_INTERNAL_ERROR;
757 Stream_Write(s, cmd->data, cmd->length);
761 const size_t bitmapDataLength = Stream_GetPosition(s) - bitmapDataStart;
762 if (bitmapDataLength > UINT32_MAX)
763 return ERROR_INTERNAL_ERROR;
765 Stream_SetPosition(s, bitmapDataStart -
sizeof(UINT32));
766 if (!Stream_EnsureRemainingCapacity(s, 4))
767 return ERROR_INTERNAL_ERROR;
768 Stream_Write_UINT32(s, (UINT32)bitmapDataLength);
769 if (!Stream_SafeSeek(s, bitmapDataLength))
770 return ERROR_INTERNAL_ERROR;
783 static UINT rdpgfx_send_surface_command(RdpgfxServerContext* context,
786 if (!checkCapsAreExchanged(context))
787 return CHANNEL_RC_NOT_INITIALIZED;
788 UINT error = CHANNEL_RC_OK;
790 s = rdpgfx_server_single_packet_new(context->priv->log, rdpgfx_surface_command_cmdid(cmd),
791 rdpgfx_estimate_surface_command(cmd));
795 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpgfx_server_single_packet_new failed!");
796 return CHANNEL_RC_NO_MEMORY;
799 error = rdpgfx_write_surface_command(context->priv->log, s, cmd);
801 if (error != CHANNEL_RC_OK)
803 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpgfx_write_surface_command failed!");
807 return rdpgfx_server_single_packet_send(context, s);
809 Stream_Free(s, TRUE);
821 static UINT rdpgfx_send_surface_frame_command(RdpgfxServerContext* context,
827 if (!checkCapsAreExchanged(context))
828 return CHANNEL_RC_NOT_INITIALIZED;
829 UINT error = CHANNEL_RC_OK;
830 UINT32 size = rdpgfx_pdu_length(rdpgfx_estimate_surface_command(cmd));
834 size += rdpgfx_pdu_length(RDPGFX_START_FRAME_PDU_SIZE);
839 size += rdpgfx_pdu_length(RDPGFX_END_FRAME_PDU_SIZE);
842 wStream* s = Stream_New(NULL, size);
846 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_New failed!");
847 return CHANNEL_RC_NO_MEMORY;
853 const size_t position = Stream_GetPosition(s);
854 error = rdpgfx_server_packet_init_header(s, RDPGFX_CMDID_STARTFRAME, 0);
856 if (error != CHANNEL_RC_OK)
858 WLog_Print(context->priv->log, WLOG_ERROR,
859 "Failed to init header with error %" PRIu32
"!", error);
863 if (!rdpgfx_write_start_frame_pdu(s, startFrame) ||
864 !rdpgfx_server_packet_complete_header(s, position))
869 const size_t pos = Stream_GetPosition(s);
870 error = rdpgfx_server_packet_init_header(s, rdpgfx_surface_command_cmdid(cmd),
873 if (error != CHANNEL_RC_OK)
875 WLog_Print(context->priv->log, WLOG_ERROR,
"Failed to init header with error %" PRIu32
"!",
880 error = rdpgfx_write_surface_command(context->priv->log, s, cmd);
882 if (error != CHANNEL_RC_OK)
884 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpgfx_write_surface_command failed!");
888 if (!rdpgfx_server_packet_complete_header(s, pos))
894 const size_t position = Stream_GetPosition(s);
895 error = rdpgfx_server_packet_init_header(s, RDPGFX_CMDID_ENDFRAME, 0);
897 if (error != CHANNEL_RC_OK)
899 WLog_Print(context->priv->log, WLOG_ERROR,
900 "Failed to init header with error %" PRIu32
"!", error);
904 if (!rdpgfx_write_end_frame_pdu(s, endFrame) ||
905 !rdpgfx_server_packet_complete_header(s, position))
909 return rdpgfx_server_packet_send(context, s);
911 Stream_Free(s, TRUE);
920 static UINT rdpgfx_send_delete_encoding_context_pdu(RdpgfxServerContext* context,
923 if (!checkCapsAreExchanged(context))
924 return CHANNEL_RC_NOT_INITIALIZED;
926 rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_DELETEENCODINGCONTEXT, 6);
930 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpgfx_server_single_packet_new failed!");
931 return CHANNEL_RC_NO_MEMORY;
934 Stream_Write_UINT16(s, pdu->surfaceId);
935 Stream_Write_UINT32(s, pdu->codecContextId);
936 return rdpgfx_server_single_packet_send(context, s);
944 static UINT rdpgfx_send_solid_fill_pdu(RdpgfxServerContext* context,
947 if (!checkCapsAreExchanged(context))
948 return CHANNEL_RC_NOT_INITIALIZED;
949 UINT error = CHANNEL_RC_OK;
951 wStream* s = rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_SOLIDFILL,
952 8 + 8 * pdu->fillRectCount);
956 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpgfx_server_single_packet_new failed!");
957 return CHANNEL_RC_NO_MEMORY;
960 Stream_Write_UINT16(s, pdu->surfaceId);
963 if ((error = rdpgfx_write_color32(s, &(pdu->fillPixel))))
965 WLog_Print(context->priv->log, WLOG_ERROR,
966 "rdpgfx_write_color32 failed with error %" PRIu32
"!", error);
970 Stream_Write_UINT16(s, pdu->fillRectCount);
972 for (UINT16 index = 0; index < pdu->fillRectCount; index++)
974 fillRect = &(pdu->fillRects[index]);
976 if ((error = rdpgfx_write_rect16(s, fillRect)))
978 WLog_Print(context->priv->log, WLOG_ERROR,
979 "rdpgfx_write_rect16 failed with error %" PRIu32
"!", error);
984 return rdpgfx_server_single_packet_send(context, s);
986 Stream_Free(s, TRUE);
995 static UINT rdpgfx_send_surface_to_surface_pdu(RdpgfxServerContext* context,
998 if (!checkCapsAreExchanged(context))
999 return CHANNEL_RC_NOT_INITIALIZED;
1000 UINT error = CHANNEL_RC_OK;
1002 wStream* s = rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_SURFACETOSURFACE,
1003 14 + 4 * pdu->destPtsCount);
1007 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpgfx_server_single_packet_new failed!");
1008 return CHANNEL_RC_NO_MEMORY;
1011 Stream_Write_UINT16(s, pdu->surfaceIdSrc);
1012 Stream_Write_UINT16(s, pdu->surfaceIdDest);
1015 if ((error = rdpgfx_write_rect16(s, &(pdu->rectSrc))))
1017 WLog_Print(context->priv->log, WLOG_ERROR,
1018 "rdpgfx_write_rect16 failed with error %" PRIu32
"!", error);
1022 Stream_Write_UINT16(s, pdu->destPtsCount);
1024 for (UINT16 index = 0; index < pdu->destPtsCount; index++)
1026 destPt = &(pdu->destPts[index]);
1028 if ((error = rdpgfx_write_point16(s, destPt)))
1030 WLog_Print(context->priv->log, WLOG_ERROR,
1031 "rdpgfx_write_point16 failed with error %" PRIu32
"!", error);
1036 return rdpgfx_server_single_packet_send(context, s);
1038 Stream_Free(s, TRUE);
1047 static UINT rdpgfx_send_surface_to_cache_pdu(RdpgfxServerContext* context,
1050 if (!checkCapsAreExchanged(context))
1051 return CHANNEL_RC_NOT_INITIALIZED;
1052 UINT error = CHANNEL_RC_OK;
1054 rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_SURFACETOCACHE, 20);
1058 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpgfx_server_single_packet_new failed!");
1059 return CHANNEL_RC_NO_MEMORY;
1062 Stream_Write_UINT16(s, pdu->surfaceId);
1063 Stream_Write_UINT64(s, pdu->cacheKey);
1064 Stream_Write_UINT16(s, pdu->cacheSlot);
1067 if ((error = rdpgfx_write_rect16(s, &(pdu->rectSrc))))
1069 WLog_Print(context->priv->log, WLOG_ERROR,
1070 "rdpgfx_write_rect16 failed with error %" PRIu32
"!", error);
1074 return rdpgfx_server_single_packet_send(context, s);
1076 Stream_Free(s, TRUE);
1085 static UINT rdpgfx_send_cache_to_surface_pdu(RdpgfxServerContext* context,
1088 if (!checkCapsAreExchanged(context))
1089 return CHANNEL_RC_NOT_INITIALIZED;
1090 UINT error = CHANNEL_RC_OK;
1092 wStream* s = rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_CACHETOSURFACE,
1093 6 + 4 * pdu->destPtsCount);
1097 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpgfx_server_single_packet_new failed!");
1098 return CHANNEL_RC_NO_MEMORY;
1101 Stream_Write_UINT16(s, pdu->cacheSlot);
1102 Stream_Write_UINT16(s, pdu->surfaceId);
1103 Stream_Write_UINT16(s, pdu->destPtsCount);
1105 for (UINT16 index = 0; index < pdu->destPtsCount; index++)
1107 destPt = &(pdu->destPts[index]);
1109 if ((error = rdpgfx_write_point16(s, destPt)))
1111 WLog_Print(context->priv->log, WLOG_ERROR,
1112 "rdpgfx_write_point16 failed with error %" PRIu32
"", error);
1117 return rdpgfx_server_single_packet_send(context, s);
1119 Stream_Free(s, TRUE);
1128 static UINT rdpgfx_send_map_surface_to_output_pdu(RdpgfxServerContext* context,
1131 if (!checkCapsAreExchanged(context))
1132 return CHANNEL_RC_NOT_INITIALIZED;
1134 rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_MAPSURFACETOOUTPUT, 12);
1138 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpgfx_server_single_packet_new failed!");
1139 return CHANNEL_RC_NO_MEMORY;
1142 Stream_Write_UINT16(s, pdu->surfaceId);
1143 Stream_Write_UINT16(s, 0);
1144 Stream_Write_UINT32(s, pdu->outputOriginX);
1145 Stream_Write_UINT32(s, pdu->outputOriginY);
1146 return rdpgfx_server_single_packet_send(context, s);
1154 static UINT rdpgfx_send_map_surface_to_window_pdu(RdpgfxServerContext* context,
1157 if (!checkCapsAreExchanged(context))
1158 return CHANNEL_RC_NOT_INITIALIZED;
1160 rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_MAPSURFACETOWINDOW, 18);
1164 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpgfx_server_single_packet_new failed!");
1165 return CHANNEL_RC_NO_MEMORY;
1168 Stream_Write_UINT16(s, pdu->surfaceId);
1169 Stream_Write_UINT64(s, pdu->windowId);
1170 Stream_Write_UINT32(s, pdu->mappedWidth);
1171 Stream_Write_UINT32(s, pdu->mappedHeight);
1172 return rdpgfx_server_single_packet_send(context, s);
1176 rdpgfx_send_map_surface_to_scaled_window_pdu(RdpgfxServerContext* context,
1179 if (!checkCapsAreExchanged(context))
1180 return CHANNEL_RC_NOT_INITIALIZED;
1181 wStream* s = rdpgfx_server_single_packet_new(context->priv->log,
1182 RDPGFX_CMDID_MAPSURFACETOSCALEDWINDOW, 26);
1186 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpgfx_server_single_packet_new failed!");
1187 return CHANNEL_RC_NO_MEMORY;
1190 Stream_Write_UINT16(s, pdu->surfaceId);
1191 Stream_Write_UINT64(s, pdu->windowId);
1192 Stream_Write_UINT32(s, pdu->mappedWidth);
1193 Stream_Write_UINT32(s, pdu->mappedHeight);
1194 Stream_Write_UINT32(s, pdu->targetWidth);
1195 Stream_Write_UINT32(s, pdu->targetHeight);
1196 return rdpgfx_server_single_packet_send(context, s);
1204 static UINT rdpgfx_recv_frame_acknowledge_pdu(RdpgfxServerContext* context,
wStream* s)
1206 if (!checkCapsAreExchanged(context))
1207 return CHANNEL_RC_NOT_INITIALIZED;
1209 UINT error = CHANNEL_RC_OK;
1211 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
1212 return ERROR_INVALID_DATA;
1214 Stream_Read_UINT32(s, pdu.queueDepth);
1215 Stream_Read_UINT32(s, pdu.frameId);
1216 Stream_Read_UINT32(s, pdu.totalFramesDecoded);
1220 IFCALLRET(context->FrameAcknowledge, error, context, &pdu);
1223 WLog_Print(context->priv->log, WLOG_ERROR,
1224 "context->FrameAcknowledge failed with error %" PRIu32
"", error);
1235 static UINT rdpgfx_recv_cache_import_offer_pdu(RdpgfxServerContext* context,
wStream* s)
1237 if (!checkCapsAreExchanged(context))
1238 return CHANNEL_RC_NOT_INITIALIZED;
1242 UINT error = CHANNEL_RC_OK;
1244 if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
1245 return ERROR_INVALID_DATA;
1248 Stream_Read_UINT16(s, pdu.cacheEntriesCount);
1251 if (pdu.cacheEntriesCount >= 5462)
1253 WLog_Print(context->priv->log, WLOG_ERROR,
"Invalid cacheEntriesCount: %" PRIu16
"",
1254 pdu.cacheEntriesCount);
1255 return ERROR_INVALID_DATA;
1258 if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, pdu.cacheEntriesCount, 12ull))
1259 return ERROR_INVALID_DATA;
1261 for (UINT16 index = 0; index < pdu.cacheEntriesCount; index++)
1263 cacheEntry = &(pdu.cacheEntries[index]);
1264 Stream_Read_UINT64(s, cacheEntry->cacheKey);
1265 Stream_Read_UINT32(s, cacheEntry->bitmapLength);
1270 IFCALLRET(context->CacheImportOffer, error, context, &pdu);
1273 WLog_Print(context->priv->log, WLOG_ERROR,
1274 "context->CacheImportOffer failed with error %" PRIu32
"", error);
1285 static UINT rdpgfx_recv_caps_advertise_pdu(RdpgfxServerContext* context,
wStream* s)
1289 UINT error = ERROR_INVALID_DATA;
1292 return ERROR_BAD_ARGUMENTS;
1294 if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
1295 return ERROR_INVALID_DATA;
1297 Stream_Read_UINT16(s, pdu.capsSetCount);
1298 if (pdu.capsSetCount > 0)
1300 capsSets = calloc(pdu.capsSetCount, (RDPGFX_CAPSET_BASE_SIZE + 4));
1302 return ERROR_OUTOFMEMORY;
1305 pdu.capsSets = capsSets;
1307 for (UINT16 index = 0; index < pdu.capsSetCount; index++)
1311 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1314 Stream_Read_UINT32(s, capsSet->version);
1315 Stream_Read_UINT32(s, capsSet->length);
1317 if (capsSet->length >= 4)
1319 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1322 Stream_Peek_UINT32(s, capsSet->flags);
1325 if (!Stream_SafeSeek(s, capsSet->length))
1329 error = ERROR_BAD_CONFIGURATION;
1330 IFCALLRET(context->CapsAdvertise, error, context, &pdu);
1333 WLog_Print(context->priv->log, WLOG_ERROR,
1334 "context->CapsAdvertise failed with error %" PRIu32
"", error);
1346 static UINT rdpgfx_recv_qoe_frame_acknowledge_pdu(RdpgfxServerContext* context,
wStream* s)
1348 if (!checkCapsAreExchanged(context))
1349 return CHANNEL_RC_NOT_INITIALIZED;
1351 UINT error = CHANNEL_RC_OK;
1353 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
1354 return ERROR_INVALID_DATA;
1356 Stream_Read_UINT32(s, pdu.frameId);
1357 Stream_Read_UINT32(s, pdu.timestamp);
1358 Stream_Read_UINT16(s, pdu.timeDiffSE);
1359 Stream_Read_UINT16(s, pdu.timeDiffEDR);
1363 IFCALLRET(context->QoeFrameAcknowledge, error, context, &pdu);
1366 WLog_Print(context->priv->log, WLOG_ERROR,
1367 "context->QoeFrameAcknowledge failed with error %" PRIu32
"", error);
1374 rdpgfx_send_map_surface_to_scaled_output_pdu(RdpgfxServerContext* context,
1377 if (!checkCapsAreExchanged(context))
1378 return CHANNEL_RC_NOT_INITIALIZED;
1379 wStream* s = rdpgfx_server_single_packet_new(context->priv->log,
1380 RDPGFX_CMDID_MAPSURFACETOSCALEDOUTPUT, 20);
1384 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpgfx_server_single_packet_new failed!");
1385 return CHANNEL_RC_NO_MEMORY;
1388 Stream_Write_UINT16(s, pdu->surfaceId);
1389 Stream_Write_UINT16(s, 0);
1390 Stream_Write_UINT32(s, pdu->outputOriginX);
1391 Stream_Write_UINT32(s, pdu->outputOriginY);
1392 Stream_Write_UINT32(s, pdu->targetWidth);
1393 Stream_Write_UINT32(s, pdu->targetHeight);
1394 return rdpgfx_server_single_packet_send(context, s);
1402 static UINT rdpgfx_server_receive_pdu(RdpgfxServerContext* context,
wStream* s)
1407 UINT error = CHANNEL_RC_OK;
1408 beg = Stream_GetPosition(s);
1410 if ((error = rdpgfx_read_header(s, &header)))
1412 WLog_Print(context->priv->log, WLOG_ERROR,
1413 "rdpgfx_read_header failed with error %" PRIu32
"!", error);
1417 #ifdef WITH_DEBUG_RDPGFX
1418 WLog_DBG(TAG,
"cmdId: %s (0x%04" PRIX16
") flags: 0x%04" PRIX16
" pduLength: %" PRIu32
"",
1419 rdpgfx_get_cmd_id_string(header.cmdId), header.cmdId, header.flags, header.pduLength);
1422 switch (header.cmdId)
1424 case RDPGFX_CMDID_FRAMEACKNOWLEDGE:
1425 if ((error = rdpgfx_recv_frame_acknowledge_pdu(context, s)))
1426 WLog_Print(context->priv->log, WLOG_ERROR,
1427 "rdpgfx_recv_frame_acknowledge_pdu "
1428 "failed with error %" PRIu32
"!",
1433 case RDPGFX_CMDID_CACHEIMPORTOFFER:
1434 if ((error = rdpgfx_recv_cache_import_offer_pdu(context, s)))
1435 WLog_Print(context->priv->log, WLOG_ERROR,
1436 "rdpgfx_recv_cache_import_offer_pdu "
1437 "failed with error %" PRIu32
"!",
1442 case RDPGFX_CMDID_CAPSADVERTISE:
1443 if ((error = rdpgfx_recv_caps_advertise_pdu(context, s)))
1444 WLog_Print(context->priv->log, WLOG_ERROR,
1445 "rdpgfx_recv_caps_advertise_pdu "
1446 "failed with error %" PRIu32
"!",
1451 case RDPGFX_CMDID_QOEFRAMEACKNOWLEDGE:
1452 if ((error = rdpgfx_recv_qoe_frame_acknowledge_pdu(context, s)))
1453 WLog_Print(context->priv->log, WLOG_ERROR,
1454 "rdpgfx_recv_qoe_frame_acknowledge_pdu "
1455 "failed with error %" PRIu32
"!",
1461 error = CHANNEL_RC_BAD_PROC;
1467 WLog_Print(context->priv->log, WLOG_ERROR,
1468 "Error while parsing GFX cmdId: %s (0x%04" PRIX16
")",
1469 rdpgfx_get_cmd_id_string(header.cmdId), header.cmdId);
1473 end = Stream_GetPosition(s);
1475 if (end != (beg + header.pduLength))
1477 WLog_Print(context->priv->log, WLOG_ERROR,
1478 "Unexpected gfx pdu end: Actual: %" PRIuz
", Expected: %" PRIuz
"", end,
1479 (beg + header.pduLength));
1480 Stream_SetPosition(s, (beg + header.pduLength));
1486 static BOOL rdpgfx_server_close(RdpgfxServerContext* context);
1488 static DWORD WINAPI rdpgfx_server_thread_func(LPVOID arg)
1490 RdpgfxServerContext* context = (RdpgfxServerContext*)arg;
1491 WINPR_ASSERT(context);
1493 RdpgfxServerPrivate* priv = context->priv;
1496 HANDLE events[8] = { 0 };
1497 UINT error = CHANNEL_RC_OK;
1501 if (priv->ownThread)
1503 WINPR_ASSERT(priv->stopEvent);
1504 events[nCount++] = priv->stopEvent;
1507 WINPR_ASSERT(priv->channelEvent);
1508 events[nCount++] = priv->channelEvent;
1513 status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
1515 if (status == WAIT_FAILED)
1517 error = GetLastError();
1518 WLog_Print(context->priv->log, WLOG_ERROR,
1519 "WaitForMultipleObjects failed with error %" PRIu32
"", error);
1524 if (status == WAIT_OBJECT_0)
1527 if ((error = rdpgfx_server_handle_messages(context)))
1529 WLog_Print(context->priv->log, WLOG_ERROR,
1530 "rdpgfx_server_handle_messages failed with error %" PRIu32
"", error);
1535 if (error && context->rdpcontext)
1536 setChannelError(context->rdpcontext, error,
"rdpgfx_server_thread_func reported an error");
1542 static BOOL rdpgfx_server_open(RdpgfxServerContext* context)
1544 WINPR_ASSERT(context);
1545 RdpgfxServerPrivate* priv = context->priv;
1546 void* buffer = NULL;
1550 if (!priv->isOpened)
1552 PULONG pSessionId = NULL;
1553 DWORD BytesReturned = 0;
1554 priv->SessionId = WTS_CURRENT_SESSION;
1555 UINT32 channelId = 0;
1558 if (WTSQuerySessionInformationA(context->vcm, WTS_CURRENT_SESSION, WTSSessionId,
1559 (LPSTR*)&pSessionId, &BytesReturned) == FALSE)
1561 WLog_Print(context->priv->log, WLOG_ERROR,
"WTSQuerySessionInformationA failed!");
1565 priv->SessionId = (DWORD)*pSessionId;
1566 WTSFreeMemory(pSessionId);
1567 priv->rdpgfx_channel = WTSVirtualChannelOpenEx(priv->SessionId, RDPGFX_DVC_CHANNEL_NAME,
1568 WTS_CHANNEL_OPTION_DYNAMIC);
1570 if (!priv->rdpgfx_channel)
1572 WLog_Print(context->priv->log, WLOG_ERROR,
"WTSVirtualChannelOpenEx failed!");
1576 channelId = WTSChannelGetIdByHandle(priv->rdpgfx_channel);
1578 IFCALLRET(context->ChannelIdAssigned, status, context, channelId);
1581 WLog_Print(context->priv->log, WLOG_ERROR,
"context->ChannelIdAssigned failed!");
1586 if (!WTSVirtualChannelQuery(priv->rdpgfx_channel, WTSVirtualEventHandle, &buffer,
1588 (BytesReturned !=
sizeof(HANDLE)))
1590 WLog_Print(context->priv->log, WLOG_ERROR,
1591 "WTSVirtualChannelQuery failed "
1592 "or invalid returned size(%" PRIu32
")",
1596 WTSFreeMemory(buffer);
1601 priv->channelEvent = *(HANDLE*)buffer;
1602 WTSFreeMemory(buffer);
1604 if (!(priv->zgfx = zgfx_context_new(TRUE)))
1606 WLog_Print(context->priv->log, WLOG_ERROR,
"Create zgfx context failed!");
1610 priv->isReady = FALSE;
1612 priv->activeCapSet = empty;
1613 if (priv->ownThread)
1615 if (!(priv->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
1617 WLog_Print(context->priv->log, WLOG_ERROR,
"CreateEvent failed!");
1621 if (!(priv->thread =
1622 CreateThread(NULL, 0, rdpgfx_server_thread_func, (
void*)context, 0, NULL)))
1624 WLog_Print(context->priv->log, WLOG_ERROR,
"CreateThread failed!");
1629 priv->isOpened = TRUE;
1633 WLog_Print(context->priv->log, WLOG_ERROR,
"RDPGFX channel is already opened!");
1636 rdpgfx_server_close(context);
1640 BOOL rdpgfx_server_close(RdpgfxServerContext* context)
1642 WINPR_ASSERT(context);
1644 RdpgfxServerPrivate* priv = context->priv;
1647 if (priv->ownThread && priv->thread)
1649 (void)SetEvent(priv->stopEvent);
1651 if (WaitForSingleObject(priv->thread, INFINITE) == WAIT_FAILED)
1653 WLog_ERR(TAG,
"WaitForSingleObject failed with error %" PRIu32
"", GetLastError());
1657 (void)CloseHandle(priv->thread);
1658 (void)CloseHandle(priv->stopEvent);
1659 priv->thread = NULL;
1660 priv->stopEvent = NULL;
1663 zgfx_context_free(priv->zgfx);
1666 if (priv->rdpgfx_channel)
1668 (void)WTSVirtualChannelClose(priv->rdpgfx_channel);
1669 priv->rdpgfx_channel = NULL;
1672 priv->channelEvent = NULL;
1673 priv->isOpened = FALSE;
1674 priv->isReady = FALSE;
1676 priv->activeCapSet = empty;
1680 static BOOL rdpgfx_server_initialize(RdpgfxServerContext* context, BOOL externalThread)
1682 WINPR_ASSERT(context);
1683 WINPR_ASSERT(context->priv);
1685 if (context->priv->isOpened)
1687 WLog_Print(context->priv->log, WLOG_WARN,
1688 "Application error: RDPEGFX channel already initialized, "
1689 "calling in this state is not possible!");
1693 context->priv->ownThread = !externalThread;
1697 RdpgfxServerContext* rdpgfx_server_context_new(HANDLE vcm)
1699 RdpgfxServerContext* context = (RdpgfxServerContext*)calloc(1,
sizeof(RdpgfxServerContext));
1703 WLog_ERR(TAG,
"calloc failed!");
1708 context->Initialize = rdpgfx_server_initialize;
1709 context->Open = rdpgfx_server_open;
1710 context->Close = rdpgfx_server_close;
1711 context->ResetGraphics = rdpgfx_send_reset_graphics_pdu;
1712 context->StartFrame = rdpgfx_send_start_frame_pdu;
1713 context->EndFrame = rdpgfx_send_end_frame_pdu;
1714 context->SurfaceCommand = rdpgfx_send_surface_command;
1715 context->SurfaceFrameCommand = rdpgfx_send_surface_frame_command;
1716 context->DeleteEncodingContext = rdpgfx_send_delete_encoding_context_pdu;
1717 context->CreateSurface = rdpgfx_send_create_surface_pdu;
1718 context->DeleteSurface = rdpgfx_send_delete_surface_pdu;
1719 context->SolidFill = rdpgfx_send_solid_fill_pdu;
1720 context->SurfaceToSurface = rdpgfx_send_surface_to_surface_pdu;
1721 context->SurfaceToCache = rdpgfx_send_surface_to_cache_pdu;
1722 context->CacheToSurface = rdpgfx_send_cache_to_surface_pdu;
1723 context->CacheImportOffer = rdpgfx_process_cache_import_offer_pdu;
1724 context->CacheImportReply = rdpgfx_send_cache_import_reply_pdu;
1725 context->EvictCacheEntry = rdpgfx_send_evict_cache_entry_pdu;
1726 context->MapSurfaceToOutput = rdpgfx_send_map_surface_to_output_pdu;
1727 context->MapSurfaceToWindow = rdpgfx_send_map_surface_to_window_pdu;
1728 context->MapSurfaceToScaledOutput = rdpgfx_send_map_surface_to_scaled_output_pdu;
1729 context->MapSurfaceToScaledWindow = rdpgfx_send_map_surface_to_scaled_window_pdu;
1730 context->CapsAdvertise = NULL;
1731 context->CapsConfirm = rdpgfx_send_caps_confirm_pdu;
1732 context->FrameAcknowledge = NULL;
1733 context->QoeFrameAcknowledge = NULL;
1734 RdpgfxServerPrivate* priv = context->priv =
1735 (RdpgfxServerPrivate*)calloc(1,
sizeof(RdpgfxServerPrivate));
1739 WLog_ERR(TAG,
"calloc failed!");
1743 priv->log = WLog_Get(TAG);
1748 priv->input_stream = Stream_New(NULL, 4);
1750 if (!priv->input_stream)
1752 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_New failed!");
1756 priv->isOpened = FALSE;
1757 priv->isReady = FALSE;
1758 priv->ownThread = TRUE;
1761 priv->activeCapSet = empty;
1764 WINPR_PRAGMA_DIAG_PUSH
1765 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
1766 rdpgfx_server_context_free(context);
1767 WINPR_PRAGMA_DIAG_POP
1771 void rdpgfx_server_context_free(RdpgfxServerContext* context)
1776 rdpgfx_server_close(context);
1779 Stream_Free(context->priv->input_stream, TRUE);
1781 free(context->priv);
1785 HANDLE rdpgfx_server_get_event_handle(RdpgfxServerContext* context)
1791 return context->priv->channelEvent;
1803 UINT rdpgfx_server_handle_messages(RdpgfxServerContext* context)
1805 DWORD BytesReturned = 0;
1806 void* buffer = NULL;
1807 UINT ret = CHANNEL_RC_OK;
1809 WINPR_ASSERT(context);
1810 WINPR_ASSERT(context->priv);
1812 RdpgfxServerPrivate* priv = context->priv;
1813 wStream* s = priv->input_stream;
1818 if (WTSVirtualChannelQuery(priv->rdpgfx_channel, WTSVirtualChannelReady, &buffer,
1819 &BytesReturned) == FALSE)
1821 if (GetLastError() == ERROR_NO_DATA)
1822 return ERROR_NO_DATA;
1824 WLog_Print(context->priv->log, WLOG_ERROR,
"WTSVirtualChannelQuery failed");
1825 return ERROR_INTERNAL_ERROR;
1828 priv->isReady = *((BOOL*)buffer);
1829 WTSFreeMemory(buffer);
1835 Stream_SetPosition(s, 0);
1837 if (!WTSVirtualChannelRead(priv->rdpgfx_channel, 0, NULL, 0, &BytesReturned))
1839 if (GetLastError() == ERROR_NO_DATA)
1840 return ERROR_NO_DATA;
1842 WLog_Print(context->priv->log, WLOG_ERROR,
"WTSVirtualChannelRead failed!");
1843 return ERROR_INTERNAL_ERROR;
1846 if (BytesReturned < 1)
1847 return CHANNEL_RC_OK;
1849 if (!Stream_EnsureRemainingCapacity(s, BytesReturned))
1851 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_EnsureRemainingCapacity failed!");
1852 return CHANNEL_RC_NO_MEMORY;
1855 const size_t len = Stream_Capacity(s);
1856 if (len > UINT32_MAX)
1857 return ERROR_INTERNAL_ERROR;
1858 if (WTSVirtualChannelRead(priv->rdpgfx_channel, 0, Stream_BufferAs(s,
char), (UINT32)len,
1859 &BytesReturned) == FALSE)
1861 WLog_Print(context->priv->log, WLOG_ERROR,
"WTSVirtualChannelRead failed!");
1862 return ERROR_INTERNAL_ERROR;
1865 Stream_SetLength(s, BytesReturned);
1866 Stream_SetPosition(s, 0);
1868 while (Stream_GetPosition(s) < Stream_Length(s))
1870 if ((ret = rdpgfx_server_receive_pdu(context, s)))
1872 WLog_Print(context->priv->log, WLOG_ERROR,
1873 "rdpgfx_server_receive_pdu "
1874 "failed with error %" PRIu32
"!",