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;
149 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;
160 if (written < Stream_GetPosition(fs))
162 WLog_Print(context->priv->log, WLOG_WARN,
163 "Unexpected bytes written: %" PRIu32
"/%" PRIuz
"", written,
164 Stream_GetPosition(fs));
167 error = CHANNEL_RC_OK;
169 Stream_Free(fs, TRUE);
170 Stream_Free(s, TRUE);
186static wStream* rdpgfx_server_single_packet_new(wLog* log, UINT16 cmdId, UINT32 dataLen)
190 UINT32 pduLength = rdpgfx_pdu_length(dataLen);
191 s = Stream_New(NULL, pduLength);
195 WLog_Print(log, WLOG_ERROR,
"Stream_New failed!");
199 if ((error = rdpgfx_server_packet_init_header(s, cmdId, pduLength)))
201 WLog_Print(log, WLOG_ERROR,
"Failed to init header with error %" PRIu32
"!", error);
207 Stream_Free(s, TRUE);
219static inline UINT rdpgfx_server_single_packet_send(RdpgfxServerContext* context,
wStream* s)
222 rdpgfx_server_packet_complete_header(s, 0);
223 return rdpgfx_server_packet_send(context, s);
231static UINT rdpgfx_send_caps_confirm_pdu(RdpgfxServerContext* context,
237 WINPR_ASSERT(context);
238 WINPR_ASSERT(capsConfirm);
240 capsSet = capsConfirm->capsSet;
241 WINPR_ASSERT(capsSet);
243 s = rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_CAPSCONFIRM,
244 RDPGFX_CAPSET_BASE_SIZE + capsSet->length);
248 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpgfx_server_single_packet_new failed!");
249 return CHANNEL_RC_NO_MEMORY;
252 WLog_DBG(TAG,
"CAPS version=0x%04" PRIx32
", flags=0x%04" PRIx32
", length=%" PRIu32,
253 capsSet->version, capsSet->flags, capsSet->length);
254 Stream_Write_UINT32(s, capsSet->version);
255 Stream_Write_UINT32(s, capsSet->length);
257 if (capsSet->length >= 4)
259 Stream_Write_UINT32(s, capsSet->flags);
260 Stream_Zero(s, capsSet->length - 4);
263 Stream_Zero(s, capsSet->length);
265 context->priv->activeCapSet = *capsSet;
266 return rdpgfx_server_single_packet_send(context, s);
274static UINT rdpgfx_send_reset_graphics_pdu(RdpgfxServerContext* context,
277 if (!checkCapsAreExchanged(context))
278 return CHANNEL_RC_NOT_INITIALIZED;
283 if (pdu->monitorCount >= 16)
285 WLog_Print(context->priv->log, WLOG_ERROR,
286 "Monitor count MUST be less than or equal to 16: %" PRIu32
"",
288 return ERROR_INVALID_DATA;
291 s = rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_RESETGRAPHICS,
292 RDPGFX_RESET_GRAPHICS_PDU_SIZE - RDPGFX_HEADER_SIZE);
296 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpgfx_server_single_packet_new failed!");
297 return CHANNEL_RC_NO_MEMORY;
300 Stream_Write_UINT32(s, pdu->width);
301 Stream_Write_UINT32(s, pdu->height);
302 Stream_Write_UINT32(s, pdu->monitorCount);
304 for (UINT32 index = 0; index < pdu->monitorCount; index++)
306 const MONITOR_DEF* monitor = &(pdu->monitorDefArray[index]);
307 Stream_Write_INT32(s, monitor->left);
308 Stream_Write_INT32(s, monitor->top);
309 Stream_Write_INT32(s, monitor->right);
310 Stream_Write_INT32(s, monitor->bottom);
311 Stream_Write_UINT32(s, monitor->flags);
315 Stream_SetPosition(s, RDPGFX_RESET_GRAPHICS_PDU_SIZE);
316 return rdpgfx_server_single_packet_send(context, s);
324static UINT rdpgfx_send_evict_cache_entry_pdu(RdpgfxServerContext* context,
327 if (!checkCapsAreExchanged(context))
328 return CHANNEL_RC_NOT_INITIALIZED;
330 rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_EVICTCACHEENTRY, 2);
334 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpgfx_server_single_packet_new failed!");
335 return CHANNEL_RC_NO_MEMORY;
338 Stream_Write_UINT16(s, pdu->cacheSlot);
339 return rdpgfx_server_single_packet_send(context, s);
347static UINT rdpgfx_send_cache_import_reply_pdu(RdpgfxServerContext* context,
350 if (!checkCapsAreExchanged(context))
351 return CHANNEL_RC_NOT_INITIALIZED;
352 WINPR_ASSERT(context);
355 WLog_DBG(TAG,
"reply with %" PRIu16
" entries", pdu->importedEntriesCount);
356 wStream* s = rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_CACHEIMPORTREPLY,
357 2 + 2 * pdu->importedEntriesCount);
361 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpgfx_server_single_packet_new failed!");
362 return CHANNEL_RC_NO_MEMORY;
366 Stream_Write_UINT16(s, pdu->importedEntriesCount);
368 for (UINT16 index = 0; index < pdu->importedEntriesCount; index++)
370 Stream_Write_UINT16(s, pdu->cacheSlots[index]);
373 return rdpgfx_server_single_packet_send(context, s);
377rdpgfx_process_cache_import_offer_pdu(RdpgfxServerContext* context,
380 if (!checkCapsAreExchanged(context))
381 return CHANNEL_RC_NOT_INITIALIZED;
382 WINPR_ASSERT(context);
383 WINPR_ASSERT(cacheImportOffer);
386 WLog_DBG(TAG,
"received %" PRIu16
" entries, reply with %" PRIu16
" entries",
387 cacheImportOffer->cacheEntriesCount, reply.importedEntriesCount);
388 return IFCALLRESULT(CHANNEL_RC_OK, context->CacheImportReply, context, &reply);
396static UINT rdpgfx_send_create_surface_pdu(RdpgfxServerContext* context,
399 if (!checkCapsAreExchanged(context))
400 return CHANNEL_RC_NOT_INITIALIZED;
401 wStream* s = rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_CREATESURFACE, 7);
403 WINPR_ASSERT(context);
405 WINPR_ASSERT((pdu->pixelFormat == GFX_PIXEL_FORMAT_XRGB_8888) ||
406 (pdu->pixelFormat == GFX_PIXEL_FORMAT_ARGB_8888));
410 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpgfx_server_single_packet_new failed!");
411 return CHANNEL_RC_NO_MEMORY;
414 Stream_Write_UINT16(s, pdu->surfaceId);
415 Stream_Write_UINT16(s, pdu->width);
416 Stream_Write_UINT16(s, pdu->height);
417 Stream_Write_UINT8(s, pdu->pixelFormat);
418 return rdpgfx_server_single_packet_send(context, s);
426static UINT rdpgfx_send_delete_surface_pdu(RdpgfxServerContext* context,
429 if (!checkCapsAreExchanged(context))
430 return CHANNEL_RC_NOT_INITIALIZED;
431 wStream* s = rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_DELETESURFACE, 2);
435 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpgfx_server_single_packet_new failed!");
436 return CHANNEL_RC_NO_MEMORY;
439 Stream_Write_UINT16(s, pdu->surfaceId);
440 return rdpgfx_server_single_packet_send(context, s);
445 if (!Stream_EnsureRemainingCapacity(s, 8))
447 Stream_Write_UINT32(s, pdu->timestamp);
448 Stream_Write_UINT32(s, pdu->frameId);
454 if (!Stream_EnsureRemainingCapacity(s, 4))
456 Stream_Write_UINT32(s, pdu->frameId);
465static UINT rdpgfx_send_start_frame_pdu(RdpgfxServerContext* context,
468 if (!checkCapsAreExchanged(context))
469 return CHANNEL_RC_NOT_INITIALIZED;
470 wStream* s = rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_STARTFRAME,
471 RDPGFX_START_FRAME_PDU_SIZE);
475 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpgfx_server_single_packet_new failed!");
476 return CHANNEL_RC_NO_MEMORY;
479 rdpgfx_write_start_frame_pdu(s, pdu);
480 return rdpgfx_server_single_packet_send(context, s);
488static UINT rdpgfx_send_end_frame_pdu(RdpgfxServerContext* context,
const RDPGFX_END_FRAME_PDU* pdu)
490 if (!checkCapsAreExchanged(context))
491 return CHANNEL_RC_NOT_INITIALIZED;
492 wStream* s = rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_ENDFRAME,
493 RDPGFX_END_FRAME_PDU_SIZE);
497 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpgfx_server_single_packet_new failed!");
498 return CHANNEL_RC_NO_MEMORY;
501 rdpgfx_write_end_frame_pdu(s, pdu);
502 return rdpgfx_server_single_packet_send(context, s);
514 return sizeof(UINT32)
516 * havc420->meta.numRegionRects +
533 switch (cmd->codecId)
535 case RDPGFX_CODECID_CAPROGRESSIVE:
536 case RDPGFX_CODECID_CAPROGRESSIVE_V2:
537 return RDPGFX_WIRE_TO_SURFACE_PDU_2_SIZE + cmd->length;
539 case RDPGFX_CODECID_AVC420:
541 h264Size = rdpgfx_estimate_h264_avc420(havc420);
542 return RDPGFX_WIRE_TO_SURFACE_PDU_1_SIZE + h264Size;
544 case RDPGFX_CODECID_AVC444:
546 h264Size =
sizeof(UINT32);
548 havc420 = &(havc444->bitstream[0]);
549 h264Size += rdpgfx_estimate_h264_avc420(havc420);
552 if (havc444->LC == 0)
554 havc420 = &(havc444->bitstream[1]);
555 h264Size += rdpgfx_estimate_h264_avc420(havc420);
558 return RDPGFX_WIRE_TO_SURFACE_PDU_1_SIZE + h264Size;
561 return RDPGFX_WIRE_TO_SURFACE_PDU_1_SIZE + cmd->length;
574 if (cmd->codecId == RDPGFX_CODECID_CAPROGRESSIVE ||
575 cmd->codecId == RDPGFX_CODECID_CAPROGRESSIVE_V2)
577 return RDPGFX_CMDID_WIRETOSURFACE_2;
580 return RDPGFX_CMDID_WIRETOSURFACE_1;
592 UINT error = CHANNEL_RC_OK;
594 if (!Stream_EnsureRemainingCapacity(s, 4 + meta->numRegionRects * 10))
595 return ERROR_OUTOFMEMORY;
597 Stream_Write_UINT32(s, meta->numRegionRects);
599 for (UINT32 index = 0; index < meta->numRegionRects; index++)
601 regionRect = &(meta->regionRects[index]);
603 if ((error = rdpgfx_write_rect16(s, regionRect)))
605 WLog_Print(log, WLOG_ERROR,
"rdpgfx_write_rect16 failed with error %" PRIu32
"!",
611 for (UINT32 index = 0; index < meta->numRegionRects; index++)
613 quantQualityVal = &(meta->quantQualityVals[index]);
614 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(
615 uint8_t, quantQualityVal->qp | (quantQualityVal->r << 6) |
616 (quantQualityVal->p << 7)));
618 Stream_Write_UINT8(s, quantQualityVal->qualityVal);
630static inline UINT rdpgfx_write_h264_avc420(wLog* log,
wStream* s,
633 UINT error = CHANNEL_RC_OK;
635 if ((error = rdpgfx_write_h264_metablock(log, s, &(havc420->meta))))
637 WLog_Print(log, WLOG_ERROR,
"rdpgfx_write_h264_metablock failed with error %" PRIu32
"!",
642 if (!Stream_EnsureRemainingCapacity(s, havc420->length))
643 return ERROR_OUTOFMEMORY;
645 Stream_Write(s, havc420->data, havc420->length);
658 UINT error = CHANNEL_RC_OK;
661 UINT8 pixelFormat = 0;
665 case PIXEL_FORMAT_BGRX32:
666 pixelFormat = GFX_PIXEL_FORMAT_XRGB_8888;
669 case PIXEL_FORMAT_BGRA32:
670 pixelFormat = GFX_PIXEL_FORMAT_ARGB_8888;
674 WLog_Print(log, WLOG_ERROR,
"Format %s not supported!",
675 FreeRDPGetColorFormatName(cmd->format));
676 return ERROR_INVALID_DATA;
679 if (cmd->codecId == RDPGFX_CODECID_CAPROGRESSIVE ||
680 cmd->codecId == RDPGFX_CODECID_CAPROGRESSIVE_V2)
682 if (!Stream_EnsureRemainingCapacity(s, 13 + cmd->length))
683 return ERROR_INTERNAL_ERROR;
686 s, WINPR_ASSERTING_INT_CAST(uint16_t, cmd->surfaceId));
688 s, WINPR_ASSERTING_INT_CAST(uint16_t, cmd->codecId));
689 Stream_Write_UINT32(s, cmd->contextId);
690 Stream_Write_UINT8(s, pixelFormat);
691 Stream_Write_UINT32(s, cmd->length);
692 Stream_Write(s, cmd->data, cmd->length);
697 if (!Stream_EnsureRemainingCapacity(s, 17))
698 return ERROR_INTERNAL_ERROR;
700 s, WINPR_ASSERTING_INT_CAST(uint16_t, cmd->surfaceId));
702 s, WINPR_ASSERTING_INT_CAST(uint16_t, cmd->codecId));
703 Stream_Write_UINT8(s, pixelFormat);
704 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, cmd->left));
705 Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, cmd->top));
706 Stream_Write_UINT16(s,
707 WINPR_ASSERTING_INT_CAST(uint16_t, cmd->right));
708 Stream_Write_UINT16(s,
709 WINPR_ASSERTING_INT_CAST(uint16_t, cmd->bottom));
710 Stream_Write_UINT32(s, cmd->length);
711 const size_t bitmapDataStart = Stream_GetPosition(s);
713 if (cmd->codecId == RDPGFX_CODECID_AVC420)
716 error = rdpgfx_write_h264_avc420(log, s, havc420);
718 if (error != CHANNEL_RC_OK)
720 WLog_Print(log, WLOG_ERROR,
"rdpgfx_write_h264_avc420 failed!");
724 else if ((cmd->codecId == RDPGFX_CODECID_AVC444) ||
725 (cmd->codecId == RDPGFX_CODECID_AVC444v2))
728 havc420 = &(havc444->bitstream[0]);
729 if (!Stream_EnsureRemainingCapacity(s, 4))
730 return ERROR_INTERNAL_ERROR;
731 Stream_Write_UINT32(s, havc444->cbAvc420EncodedBitstream1 |
732 ((uint32_t)havc444->LC << 30UL));
734 error = rdpgfx_write_h264_avc420(log, s, havc420);
736 if (error != CHANNEL_RC_OK)
738 WLog_Print(log, WLOG_ERROR,
"rdpgfx_write_h264_avc420 failed!");
743 if (havc444->LC == 0)
745 havc420 = &(havc444->bitstream[1]);
746 error = rdpgfx_write_h264_avc420(log, s, havc420);
748 if (error != CHANNEL_RC_OK)
750 WLog_Print(log, WLOG_ERROR,
"rdpgfx_write_h264_avc420 failed!");
757 if (!Stream_EnsureRemainingCapacity(s, cmd->length))
758 return ERROR_INTERNAL_ERROR;
759 Stream_Write(s, cmd->data, cmd->length);
763 const size_t bitmapDataLength = Stream_GetPosition(s) - bitmapDataStart;
764 if (bitmapDataLength > UINT32_MAX)
765 return ERROR_INTERNAL_ERROR;
767 Stream_SetPosition(s, bitmapDataStart -
sizeof(UINT32));
768 if (!Stream_EnsureRemainingCapacity(s, 4))
769 return ERROR_INTERNAL_ERROR;
770 Stream_Write_UINT32(s, (UINT32)bitmapDataLength);
771 if (!Stream_SafeSeek(s, bitmapDataLength))
772 return ERROR_INTERNAL_ERROR;
785static UINT rdpgfx_send_surface_command(RdpgfxServerContext* context,
788 if (!checkCapsAreExchanged(context))
789 return CHANNEL_RC_NOT_INITIALIZED;
790 UINT error = CHANNEL_RC_OK;
792 s = rdpgfx_server_single_packet_new(context->priv->log, rdpgfx_surface_command_cmdid(cmd),
793 rdpgfx_estimate_surface_command(cmd));
797 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpgfx_server_single_packet_new failed!");
798 return CHANNEL_RC_NO_MEMORY;
801 error = rdpgfx_write_surface_command(context->priv->log, s, cmd);
803 if (error != CHANNEL_RC_OK)
805 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpgfx_write_surface_command failed!");
809 return rdpgfx_server_single_packet_send(context, s);
811 Stream_Free(s, TRUE);
823static UINT rdpgfx_send_surface_frame_command(RdpgfxServerContext* context,
829 if (!checkCapsAreExchanged(context))
830 return CHANNEL_RC_NOT_INITIALIZED;
831 UINT error = CHANNEL_RC_OK;
832 UINT32 size = rdpgfx_pdu_length(rdpgfx_estimate_surface_command(cmd));
836 size += rdpgfx_pdu_length(RDPGFX_START_FRAME_PDU_SIZE);
841 size += rdpgfx_pdu_length(RDPGFX_END_FRAME_PDU_SIZE);
844 wStream* s = Stream_New(NULL, size);
848 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_New failed!");
849 return CHANNEL_RC_NO_MEMORY;
855 const size_t position = Stream_GetPosition(s);
856 error = rdpgfx_server_packet_init_header(s, RDPGFX_CMDID_STARTFRAME, 0);
858 if (error != CHANNEL_RC_OK)
860 WLog_Print(context->priv->log, WLOG_ERROR,
861 "Failed to init header with error %" PRIu32
"!", error);
865 if (!rdpgfx_write_start_frame_pdu(s, startFrame) ||
866 !rdpgfx_server_packet_complete_header(s, position))
872 const size_t pos = Stream_GetPosition(s);
873 error = rdpgfx_server_packet_init_header(s, rdpgfx_surface_command_cmdid(cmd),
876 if (error != CHANNEL_RC_OK)
878 WLog_Print(context->priv->log, WLOG_ERROR,
879 "Failed to init header with error %" PRIu32
"!", error);
883 error = rdpgfx_write_surface_command(context->priv->log, s, cmd);
885 if (error != CHANNEL_RC_OK)
887 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpgfx_write_surface_command failed!");
891 if (!rdpgfx_server_packet_complete_header(s, pos))
898 const size_t position = Stream_GetPosition(s);
899 error = rdpgfx_server_packet_init_header(s, RDPGFX_CMDID_ENDFRAME, 0);
901 if (error != CHANNEL_RC_OK)
903 WLog_Print(context->priv->log, WLOG_ERROR,
904 "Failed to init header with error %" PRIu32
"!", error);
908 if (!rdpgfx_write_end_frame_pdu(s, endFrame) ||
909 !rdpgfx_server_packet_complete_header(s, position))
913 return rdpgfx_server_packet_send(context, s);
915 Stream_Free(s, TRUE);
924static UINT rdpgfx_send_delete_encoding_context_pdu(RdpgfxServerContext* context,
927 if (!checkCapsAreExchanged(context))
928 return CHANNEL_RC_NOT_INITIALIZED;
930 rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_DELETEENCODINGCONTEXT, 6);
934 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpgfx_server_single_packet_new failed!");
935 return CHANNEL_RC_NO_MEMORY;
938 Stream_Write_UINT16(s, pdu->surfaceId);
939 Stream_Write_UINT32(s, pdu->codecContextId);
940 return rdpgfx_server_single_packet_send(context, s);
948static UINT rdpgfx_send_solid_fill_pdu(RdpgfxServerContext* context,
951 if (!checkCapsAreExchanged(context))
952 return CHANNEL_RC_NOT_INITIALIZED;
953 UINT error = CHANNEL_RC_OK;
955 wStream* s = rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_SOLIDFILL,
956 8 + 8 * pdu->fillRectCount);
960 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpgfx_server_single_packet_new failed!");
961 return CHANNEL_RC_NO_MEMORY;
964 Stream_Write_UINT16(s, pdu->surfaceId);
967 if ((error = rdpgfx_write_color32(s, &(pdu->fillPixel))))
969 WLog_Print(context->priv->log, WLOG_ERROR,
970 "rdpgfx_write_color32 failed with error %" PRIu32
"!", error);
974 Stream_Write_UINT16(s, pdu->fillRectCount);
976 for (UINT16 index = 0; index < pdu->fillRectCount; index++)
978 fillRect = &(pdu->fillRects[index]);
980 if ((error = rdpgfx_write_rect16(s, fillRect)))
982 WLog_Print(context->priv->log, WLOG_ERROR,
983 "rdpgfx_write_rect16 failed with error %" PRIu32
"!", error);
988 return rdpgfx_server_single_packet_send(context, s);
990 Stream_Free(s, TRUE);
999static UINT rdpgfx_send_surface_to_surface_pdu(RdpgfxServerContext* context,
1002 if (!checkCapsAreExchanged(context))
1003 return CHANNEL_RC_NOT_INITIALIZED;
1004 UINT error = CHANNEL_RC_OK;
1006 wStream* s = rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_SURFACETOSURFACE,
1007 14 + 4 * pdu->destPtsCount);
1011 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpgfx_server_single_packet_new failed!");
1012 return CHANNEL_RC_NO_MEMORY;
1015 Stream_Write_UINT16(s, pdu->surfaceIdSrc);
1016 Stream_Write_UINT16(s, pdu->surfaceIdDest);
1019 if ((error = rdpgfx_write_rect16(s, &(pdu->rectSrc))))
1021 WLog_Print(context->priv->log, WLOG_ERROR,
1022 "rdpgfx_write_rect16 failed with error %" PRIu32
"!", error);
1026 Stream_Write_UINT16(s, pdu->destPtsCount);
1028 for (UINT16 index = 0; index < pdu->destPtsCount; index++)
1030 destPt = &(pdu->destPts[index]);
1032 if ((error = rdpgfx_write_point16(s, destPt)))
1034 WLog_Print(context->priv->log, WLOG_ERROR,
1035 "rdpgfx_write_point16 failed with error %" PRIu32
"!", error);
1040 return rdpgfx_server_single_packet_send(context, s);
1042 Stream_Free(s, TRUE);
1051static UINT rdpgfx_send_surface_to_cache_pdu(RdpgfxServerContext* context,
1054 if (!checkCapsAreExchanged(context))
1055 return CHANNEL_RC_NOT_INITIALIZED;
1056 UINT error = CHANNEL_RC_OK;
1058 rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_SURFACETOCACHE, 20);
1062 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpgfx_server_single_packet_new failed!");
1063 return CHANNEL_RC_NO_MEMORY;
1066 Stream_Write_UINT16(s, pdu->surfaceId);
1067 Stream_Write_UINT64(s, pdu->cacheKey);
1068 Stream_Write_UINT16(s, pdu->cacheSlot);
1071 if ((error = rdpgfx_write_rect16(s, &(pdu->rectSrc))))
1073 WLog_Print(context->priv->log, WLOG_ERROR,
1074 "rdpgfx_write_rect16 failed with error %" PRIu32
"!", error);
1078 return rdpgfx_server_single_packet_send(context, s);
1080 Stream_Free(s, TRUE);
1089static UINT rdpgfx_send_cache_to_surface_pdu(RdpgfxServerContext* context,
1092 if (!checkCapsAreExchanged(context))
1093 return CHANNEL_RC_NOT_INITIALIZED;
1094 UINT error = CHANNEL_RC_OK;
1096 wStream* s = rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_CACHETOSURFACE,
1097 6 + 4 * pdu->destPtsCount);
1101 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpgfx_server_single_packet_new failed!");
1102 return CHANNEL_RC_NO_MEMORY;
1105 Stream_Write_UINT16(s, pdu->cacheSlot);
1106 Stream_Write_UINT16(s, pdu->surfaceId);
1107 Stream_Write_UINT16(s, pdu->destPtsCount);
1109 for (UINT16 index = 0; index < pdu->destPtsCount; index++)
1111 destPt = &(pdu->destPts[index]);
1113 if ((error = rdpgfx_write_point16(s, destPt)))
1115 WLog_Print(context->priv->log, WLOG_ERROR,
1116 "rdpgfx_write_point16 failed with error %" PRIu32
"", error);
1121 return rdpgfx_server_single_packet_send(context, s);
1123 Stream_Free(s, TRUE);
1132static UINT rdpgfx_send_map_surface_to_output_pdu(RdpgfxServerContext* context,
1135 if (!checkCapsAreExchanged(context))
1136 return CHANNEL_RC_NOT_INITIALIZED;
1138 rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_MAPSURFACETOOUTPUT, 12);
1142 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpgfx_server_single_packet_new failed!");
1143 return CHANNEL_RC_NO_MEMORY;
1146 Stream_Write_UINT16(s, pdu->surfaceId);
1147 Stream_Write_UINT16(s, 0);
1148 Stream_Write_UINT32(s, pdu->outputOriginX);
1149 Stream_Write_UINT32(s, pdu->outputOriginY);
1150 return rdpgfx_server_single_packet_send(context, s);
1158static UINT rdpgfx_send_map_surface_to_window_pdu(RdpgfxServerContext* context,
1161 if (!checkCapsAreExchanged(context))
1162 return CHANNEL_RC_NOT_INITIALIZED;
1164 rdpgfx_server_single_packet_new(context->priv->log, RDPGFX_CMDID_MAPSURFACETOWINDOW, 18);
1168 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpgfx_server_single_packet_new failed!");
1169 return CHANNEL_RC_NO_MEMORY;
1172 Stream_Write_UINT16(s, pdu->surfaceId);
1173 Stream_Write_UINT64(s, pdu->windowId);
1174 Stream_Write_UINT32(s, pdu->mappedWidth);
1175 Stream_Write_UINT32(s, pdu->mappedHeight);
1176 return rdpgfx_server_single_packet_send(context, s);
1180rdpgfx_send_map_surface_to_scaled_window_pdu(RdpgfxServerContext* context,
1183 if (!checkCapsAreExchanged(context))
1184 return CHANNEL_RC_NOT_INITIALIZED;
1185 wStream* s = rdpgfx_server_single_packet_new(context->priv->log,
1186 RDPGFX_CMDID_MAPSURFACETOSCALEDWINDOW, 26);
1190 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpgfx_server_single_packet_new failed!");
1191 return CHANNEL_RC_NO_MEMORY;
1194 Stream_Write_UINT16(s, pdu->surfaceId);
1195 Stream_Write_UINT64(s, pdu->windowId);
1196 Stream_Write_UINT32(s, pdu->mappedWidth);
1197 Stream_Write_UINT32(s, pdu->mappedHeight);
1198 Stream_Write_UINT32(s, pdu->targetWidth);
1199 Stream_Write_UINT32(s, pdu->targetHeight);
1200 return rdpgfx_server_single_packet_send(context, s);
1208static UINT rdpgfx_recv_frame_acknowledge_pdu(RdpgfxServerContext* context,
wStream* s)
1210 if (!checkCapsAreExchanged(context))
1211 return CHANNEL_RC_NOT_INITIALIZED;
1213 UINT error = CHANNEL_RC_OK;
1215 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
1216 return ERROR_INVALID_DATA;
1218 Stream_Read_UINT32(s, pdu.queueDepth);
1219 Stream_Read_UINT32(s, pdu.frameId);
1220 Stream_Read_UINT32(s, pdu.totalFramesDecoded);
1224 IFCALLRET(context->FrameAcknowledge, error, context, &pdu);
1227 WLog_Print(context->priv->log, WLOG_ERROR,
1228 "context->FrameAcknowledge failed with error %" PRIu32
"", error);
1239static UINT rdpgfx_recv_cache_import_offer_pdu(RdpgfxServerContext* context,
wStream* s)
1241 if (!checkCapsAreExchanged(context))
1242 return CHANNEL_RC_NOT_INITIALIZED;
1246 UINT error = CHANNEL_RC_OK;
1248 if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
1249 return ERROR_INVALID_DATA;
1252 Stream_Read_UINT16(s, pdu.cacheEntriesCount);
1255 if (pdu.cacheEntriesCount >= 5462)
1257 WLog_Print(context->priv->log, WLOG_ERROR,
"Invalid cacheEntriesCount: %" PRIu16
"",
1258 pdu.cacheEntriesCount);
1259 return ERROR_INVALID_DATA;
1262 if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, pdu.cacheEntriesCount, 12ull))
1263 return ERROR_INVALID_DATA;
1265 for (UINT16 index = 0; index < pdu.cacheEntriesCount; index++)
1267 cacheEntry = &(pdu.cacheEntries[index]);
1268 Stream_Read_UINT64(s, cacheEntry->cacheKey);
1269 Stream_Read_UINT32(s, cacheEntry->bitmapLength);
1274 IFCALLRET(context->CacheImportOffer, error, context, &pdu);
1277 WLog_Print(context->priv->log, WLOG_ERROR,
1278 "context->CacheImportOffer failed with error %" PRIu32
"", error);
1289static UINT rdpgfx_recv_caps_advertise_pdu(RdpgfxServerContext* context,
wStream* s)
1293 UINT error = ERROR_INVALID_DATA;
1296 return ERROR_BAD_ARGUMENTS;
1298 if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
1299 return ERROR_INVALID_DATA;
1301 Stream_Read_UINT16(s, pdu.capsSetCount);
1302 if (pdu.capsSetCount > 0)
1304 capsSets = calloc(pdu.capsSetCount, (RDPGFX_CAPSET_BASE_SIZE + 4));
1306 return ERROR_OUTOFMEMORY;
1309 pdu.capsSets = capsSets;
1311 for (UINT16 index = 0; index < pdu.capsSetCount; index++)
1315 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1318 Stream_Read_UINT32(s, capsSet->version);
1319 Stream_Read_UINT32(s, capsSet->length);
1321 if (capsSet->length >= 4)
1323 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1326 Stream_Peek_UINT32(s, capsSet->flags);
1329 if (!Stream_SafeSeek(s, capsSet->length))
1333 error = ERROR_BAD_CONFIGURATION;
1334 IFCALLRET(context->CapsAdvertise, error, context, &pdu);
1337 WLog_Print(context->priv->log, WLOG_ERROR,
1338 "context->CapsAdvertise failed with error %" PRIu32
"", error);
1350static UINT rdpgfx_recv_qoe_frame_acknowledge_pdu(RdpgfxServerContext* context,
wStream* s)
1352 if (!checkCapsAreExchanged(context))
1353 return CHANNEL_RC_NOT_INITIALIZED;
1355 UINT error = CHANNEL_RC_OK;
1357 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
1358 return ERROR_INVALID_DATA;
1360 Stream_Read_UINT32(s, pdu.frameId);
1361 Stream_Read_UINT32(s, pdu.timestamp);
1362 Stream_Read_UINT16(s, pdu.timeDiffSE);
1363 Stream_Read_UINT16(s, pdu.timeDiffEDR);
1367 IFCALLRET(context->QoeFrameAcknowledge, error, context, &pdu);
1370 WLog_Print(context->priv->log, WLOG_ERROR,
1371 "context->QoeFrameAcknowledge failed with error %" PRIu32
"", error);
1378rdpgfx_send_map_surface_to_scaled_output_pdu(RdpgfxServerContext* context,
1381 if (!checkCapsAreExchanged(context))
1382 return CHANNEL_RC_NOT_INITIALIZED;
1383 wStream* s = rdpgfx_server_single_packet_new(context->priv->log,
1384 RDPGFX_CMDID_MAPSURFACETOSCALEDOUTPUT, 20);
1388 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpgfx_server_single_packet_new failed!");
1389 return CHANNEL_RC_NO_MEMORY;
1392 Stream_Write_UINT16(s, pdu->surfaceId);
1393 Stream_Write_UINT16(s, 0);
1394 Stream_Write_UINT32(s, pdu->outputOriginX);
1395 Stream_Write_UINT32(s, pdu->outputOriginY);
1396 Stream_Write_UINT32(s, pdu->targetWidth);
1397 Stream_Write_UINT32(s, pdu->targetHeight);
1398 return rdpgfx_server_single_packet_send(context, s);
1406static UINT rdpgfx_server_receive_pdu(RdpgfxServerContext* context,
wStream* s)
1411 UINT error = CHANNEL_RC_OK;
1412 beg = Stream_GetPosition(s);
1414 if ((error = rdpgfx_read_header(s, &header)))
1416 WLog_Print(context->priv->log, WLOG_ERROR,
1417 "rdpgfx_read_header failed with error %" PRIu32
"!", error);
1421#ifdef WITH_DEBUG_RDPGFX
1422 WLog_DBG(TAG,
"cmdId: %s (0x%04" PRIX16
") flags: 0x%04" PRIX16
" pduLength: %" PRIu32
"",
1423 rdpgfx_get_cmd_id_string(header.cmdId), header.cmdId, header.flags, header.pduLength);
1426 switch (header.cmdId)
1428 case RDPGFX_CMDID_FRAMEACKNOWLEDGE:
1429 if ((error = rdpgfx_recv_frame_acknowledge_pdu(context, s)))
1430 WLog_Print(context->priv->log, WLOG_ERROR,
1431 "rdpgfx_recv_frame_acknowledge_pdu "
1432 "failed with error %" PRIu32
"!",
1437 case RDPGFX_CMDID_CACHEIMPORTOFFER:
1438 if ((error = rdpgfx_recv_cache_import_offer_pdu(context, s)))
1439 WLog_Print(context->priv->log, WLOG_ERROR,
1440 "rdpgfx_recv_cache_import_offer_pdu "
1441 "failed with error %" PRIu32
"!",
1446 case RDPGFX_CMDID_CAPSADVERTISE:
1447 if ((error = rdpgfx_recv_caps_advertise_pdu(context, s)))
1448 WLog_Print(context->priv->log, WLOG_ERROR,
1449 "rdpgfx_recv_caps_advertise_pdu "
1450 "failed with error %" PRIu32
"!",
1455 case RDPGFX_CMDID_QOEFRAMEACKNOWLEDGE:
1456 if ((error = rdpgfx_recv_qoe_frame_acknowledge_pdu(context, s)))
1457 WLog_Print(context->priv->log, WLOG_ERROR,
1458 "rdpgfx_recv_qoe_frame_acknowledge_pdu "
1459 "failed with error %" PRIu32
"!",
1465 error = CHANNEL_RC_BAD_PROC;
1471 WLog_Print(context->priv->log, WLOG_ERROR,
1472 "Error while parsing GFX cmdId: %s (0x%04" PRIX16
")",
1473 rdpgfx_get_cmd_id_string(header.cmdId), header.cmdId);
1477 end = Stream_GetPosition(s);
1479 if (end != (beg + header.pduLength))
1481 WLog_Print(context->priv->log, WLOG_ERROR,
1482 "Unexpected gfx pdu end: Actual: %" PRIuz
", Expected: %" PRIuz
"", end,
1483 (beg + header.pduLength));
1484 Stream_SetPosition(s, (beg + header.pduLength));
1490static BOOL rdpgfx_server_close(RdpgfxServerContext* context);
1492static DWORD WINAPI rdpgfx_server_thread_func(LPVOID arg)
1494 RdpgfxServerContext* context = (RdpgfxServerContext*)arg;
1495 WINPR_ASSERT(context);
1497 RdpgfxServerPrivate* priv = context->priv;
1500 HANDLE events[8] = { 0 };
1501 UINT error = CHANNEL_RC_OK;
1505 if (priv->ownThread)
1507 WINPR_ASSERT(priv->stopEvent);
1508 events[nCount++] = priv->stopEvent;
1511 WINPR_ASSERT(priv->channelEvent);
1512 events[nCount++] = priv->channelEvent;
1517 status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
1519 if (status == WAIT_FAILED)
1521 error = GetLastError();
1522 WLog_Print(context->priv->log, WLOG_ERROR,
1523 "WaitForMultipleObjects failed with error %" PRIu32
"", error);
1528 if (status == WAIT_OBJECT_0)
1531 if ((error = rdpgfx_server_handle_messages(context)))
1533 WLog_Print(context->priv->log, WLOG_ERROR,
1534 "rdpgfx_server_handle_messages failed with error %" PRIu32
"", error);
1539 if (error && context->rdpcontext)
1540 setChannelError(context->rdpcontext, error,
"rdpgfx_server_thread_func reported an error");
1546static BOOL rdpgfx_server_open(RdpgfxServerContext* context)
1548 WINPR_ASSERT(context);
1549 RdpgfxServerPrivate* priv = context->priv;
1550 void* buffer = NULL;
1554 if (!priv->isOpened)
1556 PULONG pSessionId = NULL;
1557 DWORD BytesReturned = 0;
1558 priv->SessionId = WTS_CURRENT_SESSION;
1559 UINT32 channelId = 0;
1562 if (WTSQuerySessionInformationA(context->vcm, WTS_CURRENT_SESSION, WTSSessionId,
1563 (LPSTR*)&pSessionId, &BytesReturned) == FALSE)
1565 WLog_Print(context->priv->log, WLOG_ERROR,
"WTSQuerySessionInformationA failed!");
1569 priv->SessionId = (DWORD)*pSessionId;
1570 WTSFreeMemory(pSessionId);
1571 priv->rdpgfx_channel = WTSVirtualChannelOpenEx(priv->SessionId, RDPGFX_DVC_CHANNEL_NAME,
1572 WTS_CHANNEL_OPTION_DYNAMIC);
1574 if (!priv->rdpgfx_channel)
1576 WLog_Print(context->priv->log, WLOG_ERROR,
"WTSVirtualChannelOpenEx failed!");
1580 channelId = WTSChannelGetIdByHandle(priv->rdpgfx_channel);
1582 IFCALLRET(context->ChannelIdAssigned, status, context, channelId);
1585 WLog_Print(context->priv->log, WLOG_ERROR,
"context->ChannelIdAssigned failed!");
1590 if (!WTSVirtualChannelQuery(priv->rdpgfx_channel, WTSVirtualEventHandle, &buffer,
1592 (BytesReturned !=
sizeof(HANDLE)))
1594 WLog_Print(context->priv->log, WLOG_ERROR,
1595 "WTSVirtualChannelQuery failed "
1596 "or invalid returned size(%" PRIu32
")",
1600 WTSFreeMemory(buffer);
1605 priv->channelEvent = *(HANDLE*)buffer;
1606 WTSFreeMemory(buffer);
1608 if (!(priv->zgfx = zgfx_context_new(TRUE)))
1610 WLog_Print(context->priv->log, WLOG_ERROR,
"Create zgfx context failed!");
1614 priv->isReady = FALSE;
1616 priv->activeCapSet = empty;
1617 if (priv->ownThread)
1619 if (!(priv->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
1621 WLog_Print(context->priv->log, WLOG_ERROR,
"CreateEvent failed!");
1625 if (!(priv->thread =
1626 CreateThread(NULL, 0, rdpgfx_server_thread_func, (
void*)context, 0, NULL)))
1628 WLog_Print(context->priv->log, WLOG_ERROR,
"CreateThread failed!");
1633 priv->isOpened = TRUE;
1637 WLog_Print(context->priv->log, WLOG_ERROR,
"RDPGFX channel is already opened!");
1640 rdpgfx_server_close(context);
1644BOOL rdpgfx_server_close(RdpgfxServerContext* context)
1646 WINPR_ASSERT(context);
1648 RdpgfxServerPrivate* priv = context->priv;
1651 if (priv->ownThread && priv->thread)
1653 (void)SetEvent(priv->stopEvent);
1655 if (WaitForSingleObject(priv->thread, INFINITE) == WAIT_FAILED)
1657 WLog_ERR(TAG,
"WaitForSingleObject failed with error %" PRIu32
"", GetLastError());
1661 (void)CloseHandle(priv->thread);
1662 (void)CloseHandle(priv->stopEvent);
1663 priv->thread = NULL;
1664 priv->stopEvent = NULL;
1667 zgfx_context_free(priv->zgfx);
1670 if (priv->rdpgfx_channel)
1672 (void)WTSVirtualChannelClose(priv->rdpgfx_channel);
1673 priv->rdpgfx_channel = NULL;
1676 priv->channelEvent = NULL;
1677 priv->isOpened = FALSE;
1678 priv->isReady = FALSE;
1680 priv->activeCapSet = empty;
1684static BOOL rdpgfx_server_initialize(RdpgfxServerContext* context, BOOL externalThread)
1686 WINPR_ASSERT(context);
1687 WINPR_ASSERT(context->priv);
1689 if (context->priv->isOpened)
1691 WLog_Print(context->priv->log, WLOG_WARN,
1692 "Application error: RDPEGFX channel already initialized, "
1693 "calling in this state is not possible!");
1697 context->priv->ownThread = !externalThread;
1701RdpgfxServerContext* rdpgfx_server_context_new(HANDLE vcm)
1703 RdpgfxServerContext* context = (RdpgfxServerContext*)calloc(1,
sizeof(RdpgfxServerContext));
1707 WLog_ERR(TAG,
"calloc failed!");
1712 context->Initialize = rdpgfx_server_initialize;
1713 context->Open = rdpgfx_server_open;
1714 context->Close = rdpgfx_server_close;
1715 context->ResetGraphics = rdpgfx_send_reset_graphics_pdu;
1716 context->StartFrame = rdpgfx_send_start_frame_pdu;
1717 context->EndFrame = rdpgfx_send_end_frame_pdu;
1718 context->SurfaceCommand = rdpgfx_send_surface_command;
1719 context->SurfaceFrameCommand = rdpgfx_send_surface_frame_command;
1720 context->DeleteEncodingContext = rdpgfx_send_delete_encoding_context_pdu;
1721 context->CreateSurface = rdpgfx_send_create_surface_pdu;
1722 context->DeleteSurface = rdpgfx_send_delete_surface_pdu;
1723 context->SolidFill = rdpgfx_send_solid_fill_pdu;
1724 context->SurfaceToSurface = rdpgfx_send_surface_to_surface_pdu;
1725 context->SurfaceToCache = rdpgfx_send_surface_to_cache_pdu;
1726 context->CacheToSurface = rdpgfx_send_cache_to_surface_pdu;
1727 context->CacheImportOffer = rdpgfx_process_cache_import_offer_pdu;
1728 context->CacheImportReply = rdpgfx_send_cache_import_reply_pdu;
1729 context->EvictCacheEntry = rdpgfx_send_evict_cache_entry_pdu;
1730 context->MapSurfaceToOutput = rdpgfx_send_map_surface_to_output_pdu;
1731 context->MapSurfaceToWindow = rdpgfx_send_map_surface_to_window_pdu;
1732 context->MapSurfaceToScaledOutput = rdpgfx_send_map_surface_to_scaled_output_pdu;
1733 context->MapSurfaceToScaledWindow = rdpgfx_send_map_surface_to_scaled_window_pdu;
1734 context->CapsAdvertise = NULL;
1735 context->CapsConfirm = rdpgfx_send_caps_confirm_pdu;
1736 context->FrameAcknowledge = NULL;
1737 context->QoeFrameAcknowledge = NULL;
1738 RdpgfxServerPrivate* priv = context->priv =
1739 (RdpgfxServerPrivate*)calloc(1,
sizeof(RdpgfxServerPrivate));
1743 WLog_ERR(TAG,
"calloc failed!");
1747 priv->log = WLog_Get(TAG);
1752 priv->input_stream = Stream_New(NULL, 4);
1754 if (!priv->input_stream)
1756 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_New failed!");
1760 priv->isOpened = FALSE;
1761 priv->isReady = FALSE;
1762 priv->ownThread = TRUE;
1766 priv->activeCapSet = empty;
1771 WINPR_PRAGMA_DIAG_PUSH
1772 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
1773 rdpgfx_server_context_free(context);
1774 WINPR_PRAGMA_DIAG_POP
1778void rdpgfx_server_context_free(RdpgfxServerContext* context)
1783 rdpgfx_server_close(context);
1786 Stream_Free(context->priv->input_stream, TRUE);
1788 free(context->priv);
1792HANDLE rdpgfx_server_get_event_handle(RdpgfxServerContext* context)
1798 return context->priv->channelEvent;
1810UINT rdpgfx_server_handle_messages(RdpgfxServerContext* context)
1812 DWORD BytesReturned = 0;
1813 void* buffer = NULL;
1814 UINT ret = CHANNEL_RC_OK;
1816 WINPR_ASSERT(context);
1817 WINPR_ASSERT(context->priv);
1819 RdpgfxServerPrivate* priv = context->priv;
1820 wStream* s = priv->input_stream;
1825 if (WTSVirtualChannelQuery(priv->rdpgfx_channel, WTSVirtualChannelReady, &buffer,
1826 &BytesReturned) == FALSE)
1828 if (GetLastError() == ERROR_NO_DATA)
1829 return ERROR_NO_DATA;
1831 WLog_Print(context->priv->log, WLOG_ERROR,
"WTSVirtualChannelQuery failed");
1832 return ERROR_INTERNAL_ERROR;
1835 priv->isReady = *((BOOL*)buffer);
1836 WTSFreeMemory(buffer);
1842 Stream_SetPosition(s, 0);
1844 if (!WTSVirtualChannelRead(priv->rdpgfx_channel, 0, NULL, 0, &BytesReturned))
1846 if (GetLastError() == ERROR_NO_DATA)
1847 return ERROR_NO_DATA;
1849 WLog_Print(context->priv->log, WLOG_ERROR,
"WTSVirtualChannelRead failed!");
1850 return ERROR_INTERNAL_ERROR;
1853 if (BytesReturned < 1)
1854 return CHANNEL_RC_OK;
1856 if (!Stream_EnsureRemainingCapacity(s, BytesReturned))
1858 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_EnsureRemainingCapacity failed!");
1859 return CHANNEL_RC_NO_MEMORY;
1862 const size_t len = Stream_Capacity(s);
1863 if (len > UINT32_MAX)
1864 return ERROR_INTERNAL_ERROR;
1865 if (WTSVirtualChannelRead(priv->rdpgfx_channel, 0, Stream_BufferAs(s,
char), (UINT32)len,
1866 &BytesReturned) == FALSE)
1868 WLog_Print(context->priv->log, WLOG_ERROR,
"WTSVirtualChannelRead failed!");
1869 return ERROR_INTERNAL_ERROR;
1872 Stream_SetLength(s, BytesReturned);
1873 Stream_SetPosition(s, 0);
1875 while (Stream_GetPosition(s) < Stream_Length(s))
1877 if ((ret = rdpgfx_server_receive_pdu(context, s)))
1879 WLog_Print(context->priv->log, WLOG_ERROR,
1880 "rdpgfx_server_receive_pdu "
1881 "failed with error %" PRIu32
"!",