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
"!",