diff --git a/client/Windows/wf_gdi.c b/client/Windows/wf_gdi.c index c036acf3c..4da886db7 100644 --- a/client/Windows/wf_gdi.c +++ b/client/Windows/wf_gdi.c @@ -670,17 +670,17 @@ void wf_gdi_surface_bits(wfContext* wfc, SURFACE_BITS_COMMAND* surface_bits_comm { int i, j; int tx, ty; - char* tile_bitmap; RFX_MESSAGE* message; BITMAPINFO bitmap_info; - tile_bitmap = (char*) malloc(32); - ZeroMemory(tile_bitmap, 32); - if (surface_bits_command->codecID == RDP_CODEC_ID_REMOTEFX) { freerdp_client_codecs_prepare(wfc->codecs, FREERDP_CODEC_REMOTEFX); - message = rfx_process_message(wfc->codecs->rfx, surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength); + if (!(message = rfx_process_message(wfc->codecs->rfx, surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength))) + { + WLog_ERR(TAG, "Failed to process RemoteFX message"); + return; + } /* blit each tile */ for (i = 0; i < message->numTiles; i++) @@ -750,9 +750,6 @@ void wf_gdi_surface_bits(wfContext* wfc, SURFACE_BITS_COMMAND* surface_bits_comm { WLog_ERR(TAG, "Unsupported codecID %d", surface_bits_command->codecID); } - - if (tile_bitmap != NULL) - free(tile_bitmap); } void wf_gdi_surface_frame_marker(wfContext* wfc, SURFACE_FRAME_MARKER* surface_frame_marker) diff --git a/client/X11/xf_gdi.c b/client/X11/xf_gdi.c index f3952cfa5..b3446a9a4 100644 --- a/client/X11/xf_gdi.c +++ b/client/X11/xf_gdi.c @@ -1178,7 +1178,11 @@ BOOL xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* cmd) { freerdp_client_codecs_prepare(xfc->codecs, FREERDP_CODEC_REMOTEFX); - message = rfx_process_message(xfc->codecs->rfx, cmd->bitmapData, cmd->bitmapDataLength); + if (!(message = rfx_process_message(xfc->codecs->rfx, cmd->bitmapData, cmd->bitmapDataLength))) + { + WLog_ERR(TAG, "Failed to process RemoteFX message"); + return FALSE; + } XSetFunction(xfc->display, xfc->gc, GXcopy); XSetFillStyle(xfc->display, xfc->gc, FillSolid); diff --git a/client/X11/xf_gfx.c b/client/X11/xf_gfx.c index 6a617aaa7..e457bcf7b 100644 --- a/client/X11/xf_gfx.c +++ b/client/X11/xf_gfx.c @@ -270,10 +270,11 @@ int xf_SurfaceCommand_RemoteFX(xfContext* xfc, RdpgfxClientContext* context, RDP if (!surface) return -1; - message = rfx_process_message(xfc->codecs->rfx, cmd->data, cmd->length); - - if (!message) + if (!(message = rfx_process_message(xfc->codecs->rfx, cmd->data, cmd->length))) + { + WLog_ERR(TAG, "Failed to process RemoteFX message"); return -1; + } region16_init(&clippingRects); diff --git a/include/freerdp/codec/rfx.h b/include/freerdp/codec/rfx.h index 3ad5dec6d..2bf0caa8d 100644 --- a/include/freerdp/codec/rfx.h +++ b/include/freerdp/codec/rfx.h @@ -164,17 +164,16 @@ FREERDP_API UINT16 rfx_message_get_rect_count(RFX_MESSAGE* message); FREERDP_API RFX_RECT* rfx_message_get_rect(RFX_MESSAGE* message, int index); FREERDP_API void rfx_message_free(RFX_CONTEXT* context, RFX_MESSAGE* message); -FREERDP_API void rfx_compose_message_header(RFX_CONTEXT* context, wStream* s); -FREERDP_API void rfx_compose_message(RFX_CONTEXT* context, wStream* s, +FREERDP_API BOOL rfx_compose_message(RFX_CONTEXT* context, wStream* s, const RFX_RECT* rects, int num_rects, BYTE* image_data, int width, int height, int rowstride); FREERDP_API RFX_MESSAGE* rfx_encode_message(RFX_CONTEXT* context, const RFX_RECT* rects, int numRects, BYTE* data, int width, int height, int scanline); FREERDP_API RFX_MESSAGE* rfx_encode_messages(RFX_CONTEXT* context, const RFX_RECT* rects, int numRects, BYTE* data, int width, int height, int scanline, int* numMessages, int maxDataSize); -FREERDP_API void rfx_write_message(RFX_CONTEXT* context, wStream* s, RFX_MESSAGE* message); +FREERDP_API BOOL rfx_write_message(RFX_CONTEXT* context, wStream* s, RFX_MESSAGE* message); -FREERDP_API int rfx_context_reset(RFX_CONTEXT* context); +FREERDP_API void rfx_context_reset(RFX_CONTEXT* context); FREERDP_API RFX_CONTEXT* rfx_context_new(BOOL encoder); FREERDP_API void rfx_context_free(RFX_CONTEXT* context); diff --git a/libfreerdp/codec/rfx.c b/libfreerdp/codec/rfx.c index b91e2ec2e..2ed91eb14 100644 --- a/libfreerdp/codec/rfx.c +++ b/libfreerdp/codec/rfx.c @@ -3,6 +3,7 @@ * RemoteFX Codec Library * * Copyright 2011 Vic Lee + * Copyright 2015 Norbert Federa * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -162,15 +163,11 @@ RFX_TILE* rfx_decoder_tile_new() { RFX_TILE* tile = NULL; - tile = (RFX_TILE*) malloc(sizeof(RFX_TILE)); + if (!(tile = (RFX_TILE*) calloc(1, sizeof(RFX_TILE)))) + return NULL; - if (tile) - { - ZeroMemory(tile, sizeof(RFX_TILE)); - - tile->data = (BYTE*) malloc(4096 * 4); /* 64x64 * 4 */ - tile->allocated = TRUE; - } + tile->data = (BYTE*) malloc(4096 * 4); /* 64x64 * 4 */ + tile->allocated = TRUE; return tile; } @@ -192,8 +189,7 @@ RFX_TILE* rfx_encoder_tile_new() void rfx_encoder_tile_free(RFX_TILE* tile) { - if (tile) - free(tile); + free(tile); } RFX_CONTEXT* rfx_context_new(BOOL encoder) @@ -359,8 +355,7 @@ void rfx_context_free(RFX_CONTEXT* context) assert(NULL != context->priv->BufferPool); priv = context->priv; - if (context->quants) - free(context->quants); + free(context->quants); ObjectPool_Free(priv->TilePool); @@ -372,10 +367,8 @@ void rfx_context_free(RFX_CONTEXT* context) CloseThreadpool(context->priv->ThreadPool); DestroyThreadpoolEnvironment(&context->priv->ThreadPoolEnv); - if (priv->workObjects) - free(priv->workObjects); - if (priv->tileWorkParams) - free(priv->tileWorkParams); + free(priv->workObjects); + free(priv->tileWorkParams); #ifdef WITH_PROFILER WLog_VRB(TAG, "WARNING: Profiling results probably unusable with multithreaded RemoteFX codec!"); @@ -418,17 +411,18 @@ void rfx_context_set_pixel_format(RFX_CONTEXT* context, RDP_PIXEL_FORMAT pixel_f } } -int rfx_context_reset(RFX_CONTEXT* context) +void rfx_context_reset(RFX_CONTEXT* context) { context->state = RFX_STATE_SEND_HEADERS; context->frameIdx = 0; - return 1; } static BOOL rfx_process_message_sync(RFX_CONTEXT* context, wStream* s) { UINT32 magic; + context->version = 0; + /* RFX_SYNC */ if (Stream_GetRemainingLength(s) < 6) { @@ -460,6 +454,9 @@ static BOOL rfx_process_message_codec_versions(RFX_CONTEXT* context, wStream* s) { BYTE numCodecs; + context->codec_id = 0; + context->codec_version = 0; + if (Stream_GetRemainingLength(s) < 1) { WLog_ERR(TAG, "RfxCodecVersion packet too small"); @@ -481,7 +478,7 @@ static BOOL rfx_process_message_codec_versions(RFX_CONTEXT* context, wStream* s) /* RFX_CODEC_VERSIONT */ Stream_Read_UINT8(s, context->codec_id); /* codecId (1 byte) */ - Stream_Read_UINT8(s, context->codec_version); /* version (2 bytes) */ + Stream_Read_UINT16(s, context->codec_version); /* version (2 bytes) */ WLog_Print(context->priv->log, WLOG_DEBUG, "id %d version 0x%X.", context->codec_id, context->codec_version); @@ -493,6 +490,9 @@ static BOOL rfx_process_message_channels(RFX_CONTEXT* context, wStream* s) BYTE channelId; BYTE numChannels; + context->width = 0; + context->height = 0; + if (Stream_GetRemainingLength(s) < 1) { WLog_ERR(TAG, "RfxMessageChannels packet too small"); @@ -506,8 +506,8 @@ static BOOL rfx_process_message_channels(RFX_CONTEXT* context, wStream* s) */ if (numChannels < 1) { - WLog_ERR(TAG, "numChannels:%d, expected:1", numChannels); - return TRUE; + WLog_ERR(TAG, "no channels announced"); + return FALSE; } if (Stream_GetRemainingLength(s) < (size_t) (numChannels * 5)) @@ -517,7 +517,13 @@ static BOOL rfx_process_message_channels(RFX_CONTEXT* context, wStream* s) } /* RFX_CHANNELT */ - Stream_Read_UINT8(s, channelId); /* channelId (1 byte) */ + Stream_Read_UINT8(s, channelId); /* channelId (1 byte), must be set to 0x00 */ + if (channelId != 0x00) + { + WLog_ERR(TAG, "channelId:0x%02X, expected:0x00", channelId); + return FALSE; + } + Stream_Read_UINT16(s, context->width); /* width (2 bytes) */ Stream_Read_UINT16(s, context->height); /* height (2 bytes) */ @@ -575,17 +581,24 @@ static BOOL rfx_process_message_context(RFX_CONTEXT* context, wStream* s) default: WLog_ERR(TAG, "unknown RLGR algorithm."); - break; + return FALSE; } return TRUE; } -static BOOL rfx_process_message_frame_begin(RFX_CONTEXT* context, RFX_MESSAGE* message, wStream* s) +static BOOL rfx_process_message_frame_begin(RFX_CONTEXT* context, RFX_MESSAGE* message, wStream* s, UINT16* pExpectedBlockType) { UINT32 frameIdx; UINT16 numRegions; + if (*pExpectedBlockType != WBT_FRAME_BEGIN) + { + WLog_ERR(TAG, "%s: message unexpeced", __FUNCTION__); + return FALSE; + } + *pExpectedBlockType = WBT_REGION; + if (Stream_GetRemainingLength(s) < 6) { WLog_ERR(TAG, "RfxMessageFrameBegin packet too small"); @@ -600,18 +613,35 @@ static BOOL rfx_process_message_frame_begin(RFX_CONTEXT* context, RFX_MESSAGE* m return TRUE; } -static void rfx_process_message_frame_end(RFX_CONTEXT* context, RFX_MESSAGE* message, wStream* s) +static BOOL rfx_process_message_frame_end(RFX_CONTEXT* context, RFX_MESSAGE* message, wStream* s, UINT16* pExpectedBlockType) { + if (*pExpectedBlockType != WBT_FRAME_END) + { + WLog_ERR(TAG, "%s: message unexpeced", __FUNCTION__); + return FALSE; + } + *pExpectedBlockType = WBT_FRAME_BEGIN; + WLog_Print(context->priv->log, WLOG_DEBUG, "RFX_FRAME_END"); + return TRUE; } -static BOOL rfx_process_message_region(RFX_CONTEXT* context, RFX_MESSAGE* message, wStream* s) +static BOOL rfx_process_message_region(RFX_CONTEXT* context, RFX_MESSAGE* message, wStream* s, UINT16* pExpectedBlockType) { int i; + UINT16 regionType; + UINT16 numTileSets; + + if (*pExpectedBlockType != WBT_REGION) + { + WLog_ERR(TAG, "%s: message unexpeced", __FUNCTION__); + return FALSE; + } + *pExpectedBlockType = WBT_EXTENSION; if (Stream_GetRemainingLength(s) < 3) { - WLog_ERR(TAG, "RfxMessageRegion packet too small"); + WLog_ERR(TAG, "%s: packet too small (regionFlags/numRects)", __FUNCTION__); return FALSE; } @@ -624,10 +654,11 @@ static BOOL rfx_process_message_region(RFX_CONTEXT* context, RFX_MESSAGE* messag It seems that server asks to clip whole session when numRects = 0. Issue: https://github.com/FreeRDP/FreeRDP/issues/1738 */ WLog_ERR(TAG, "no rects. Clip whole session."); - message->numRects = 1; - message->rects = (RFX_RECT*) realloc(message->rects, message->numRects * sizeof(RFX_RECT)); - if (!message->rects) + + if (!(message->rects = (RFX_RECT*) malloc(sizeof(RFX_RECT)))) return FALSE; + + message->numRects = 1; message->rects->x = 0; message->rects->y = 0; message->rects->width = context->width; @@ -638,12 +669,11 @@ static BOOL rfx_process_message_region(RFX_CONTEXT* context, RFX_MESSAGE* messag if (Stream_GetRemainingLength(s) < (size_t) (8 * message->numRects)) { - WLog_ERR(TAG, "RfxMessageRegion packet too small for num_rects=%d", message->numRects); + WLog_ERR(TAG, "%s: packet too small for num_rects=%d", __FUNCTION__, message->numRects); return FALSE; } - message->rects = (RFX_RECT*) realloc(message->rects, message->numRects * sizeof(RFX_RECT)); - if (!message->rects) + if (!(message->rects = (RFX_RECT*) calloc(message->numRects, sizeof(RFX_RECT)))) return FALSE; /* rects */ @@ -660,6 +690,27 @@ static BOOL rfx_process_message_region(RFX_CONTEXT* context, RFX_MESSAGE* messag message->rects[i].width, message->rects[i].height); } + if (Stream_GetRemainingLength(s) < 4) + { + WLog_ERR(TAG, "%s: packet too small (regionType/numTileSets)", __FUNCTION__); + return FALSE; + } + + Stream_Read_UINT16(s, regionType); /* regionType (2 bytes): MUST be set to CBT_REGION (0xCAC1) */ + Stream_Read_UINT16(s, numTileSets); /* numTilesets (2 bytes): MUST be set to 0x0001. */ + + if (regionType != CBT_REGION) + { + WLog_ERR(TAG, "%s: invalid region type 0x%04X", __FUNCTION__, CBT_REGION); + return FALSE; + } + + if (numTileSets != 0x0001) + { + WLog_ERR(TAG, "%s: invalid number of tilesets (%u)", __FUNCTION__, numTileSets); + return FALSE; + } + return TRUE; } @@ -676,7 +727,7 @@ void CALLBACK rfx_process_message_tile_work_callback(PTP_CALLBACK_INSTANCE insta rfx_decode_rgb(param->context, param->tile, param->tile->data, 64 * 4); } -static BOOL rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* message, wStream* s) +static BOOL rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* message, wStream* s, UINT16* pExpecedBlockType) { BOOL rc; int i, close_cnt; @@ -690,6 +741,14 @@ static BOOL rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* messa UINT32 tilesDataSize; PTP_WORK* work_objects = NULL; RFX_TILE_PROCESS_WORK_PARAM* params = NULL; + void *pmem; + + if (*pExpecedBlockType != WBT_EXTENSION) + { + WLog_ERR(TAG, "%s: message unexpeced", __FUNCTION__); + return FALSE; + } + *pExpecedBlockType = WBT_FRAME_END; if (Stream_GetRemainingLength(s) < 14) { @@ -714,7 +773,7 @@ static BOOL rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* messa if (context->numQuant < 1) { WLog_ERR(TAG, "no quantization value."); - return TRUE; + return FALSE; } Stream_Read_UINT16(s, message->numTiles); /* numTiles (2 bytes) */ @@ -722,16 +781,15 @@ static BOOL rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* messa if (message->numTiles < 1) { WLog_ERR(TAG, "no tiles."); - return TRUE; + return FALSE; } Stream_Read_UINT32(s, tilesDataSize); /* tilesDataSize (4 bytes) */ - context->quants = (UINT32 *)realloc((void*) context->quants, context->numQuant * 10 * sizeof(UINT32)); - if (!context->quants) + if (!(pmem = realloc((void*) context->quants, context->numQuant * 10 * sizeof(UINT32)))) return FALSE; - quants = context->quants; + quants = context->quants = (UINT32*) pmem; /* quantVals */ if (Stream_GetRemainingLength(s) < (size_t) (context->numQuant * 5)) @@ -767,31 +825,25 @@ static BOOL rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* messa context->quants[i * 10 + 8], context->quants[i * 10 + 9]); } - message->tiles = (RFX_TILE**) malloc(sizeof(RFX_TILE*) * message->numTiles); - ZeroMemory(message->tiles, sizeof(RFX_TILE*) * message->numTiles); + if (!(message->tiles = (RFX_TILE**) calloc(message->numTiles, sizeof(RFX_TILE*)))) + return FALSE; if (context->priv->UseThreads) { - work_objects = (PTP_WORK*) malloc(sizeof(PTP_WORK) * message->numTiles); - params = (RFX_TILE_PROCESS_WORK_PARAM*) - malloc(sizeof(RFX_TILE_PROCESS_WORK_PARAM) * message->numTiles); + work_objects = (PTP_WORK*) calloc(message->numTiles, sizeof(PTP_WORK)); + params = (RFX_TILE_PROCESS_WORK_PARAM*) calloc(message->numTiles, sizeof(RFX_TILE_PROCESS_WORK_PARAM)); if (!work_objects) { - if (params) - free(params); + free(params); return FALSE; } if (!params) { - if (work_objects) - free(work_objects); + free(work_objects); return FALSE; } - - ZeroMemory(work_objects, sizeof(PTP_WORK) * message->numTiles); - ZeroMemory(params, sizeof(RFX_TILE_PROCESS_WORK_PARAM) * message->numTiles); } /* tiles */ @@ -877,10 +929,8 @@ static BOOL rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* messa } } - if (work_objects) - free(work_objects); - if (params) - free(params); + free(work_objects); + free(params); for (i = 0; i < message->numTiles; i++) { @@ -895,19 +945,22 @@ static BOOL rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* messa RFX_MESSAGE* rfx_process_message(RFX_CONTEXT* context, BYTE* data, UINT32 length) { int pos; - wStream* s; UINT32 blockLen; UINT32 blockType; - RFX_MESSAGE* message; + RFX_MESSAGE* message = NULL; + wStream* s = NULL; + BOOL ok = TRUE; + UINT16 expectedDataBlockType = WBT_FRAME_BEGIN; - message = (RFX_MESSAGE*) malloc(sizeof(RFX_MESSAGE)); - ZeroMemory(message, sizeof(RFX_MESSAGE)); + if (!(s = Stream_New(data, length))) + goto fail; + + if (!(message = (RFX_MESSAGE*) calloc(1, sizeof(RFX_MESSAGE)))) + goto fail; message->freeRects = TRUE; - s = Stream_New(data, length); - - while (Stream_GetRemainingLength(s) > 6) + while (ok && Stream_GetRemainingLength(s) > 6) { /* RFX_BLOCKT */ Stream_Read_UINT16(s, blockType); /* blockType (2 bytes) */ @@ -918,75 +971,159 @@ RFX_MESSAGE* rfx_process_message(RFX_CONTEXT* context, BYTE* data, UINT32 length if (blockLen == 0) { WLog_ERR(TAG, "zero blockLen"); - break; + goto fail; } if (Stream_GetRemainingLength(s) < blockLen - 6) { - WLog_ERR(TAG, "rfx_process_message: packet too small for blocklen=%d", blockLen); - break; + WLog_ERR(TAG, "%s: packet too small for blocklen=%d", __FUNCTION__, blockLen); + goto fail; } - pos = Stream_GetPosition(s) - 6 + blockLen; + if (blockType != WBT_SYNC && context->version != WF_VERSION_1_0) + { + /* The TS_RFX_SYNC message MUST be the first message in any encoded stream. */ + WLog_ERR(TAG, "%s: TS_RFX_SYNC was not processed", __FUNCTION__); + goto fail; + } + + if (blockType > WBT_CONTEXT) + { + if (context->mode == 0) + { + /* Unknown rlgr mode. + * A valid TS_RFX_CONTEXT message should have been processed by now + */ + WLog_ERR(TAG, "%s: TS_RFX_CONTEXT was not processed", __FUNCTION__); + goto fail; + } + + if (context->codec_version != WF_VERSION_1_0) + { + /* Unknown codec version. + * A valid TS_RFX_CODEC_VERSIONS message should have been processed by now + */ + WLog_ERR(TAG, "%s: TS_RFX_CODEC_VERSIONS was not processed", __FUNCTION__); + goto fail; + } + + if (!context->width || !context->height) + { + /* Empty plane. + * A valid TS_RFX_CODEC_CHANNELS message should have been processed by now + * which would have resulted in a non-zero width and height in the context + */ + WLog_ERR(TAG, "%s: TS_RFX_CODEC_CHANNELS was not processed", __FUNCTION__); + goto fail; + } + } + if (blockType >= WBT_CONTEXT && blockType <= WBT_EXTENSION) { /* RFX_CODEC_CHANNELT */ - /* codecId (1 byte) must be set to 0x01 */ - /* channelId (1 byte) must be set to 0x00 */ - if (!Stream_SafeSeek(s, 2)) + UINT8 codecId; + UINT8 channelId; + + if (Stream_GetRemainingLength(s) < 2) + goto fail; + + Stream_Read_UINT8(s, codecId); /* codecId (1 byte) must be set to 0x01 */ + Stream_Read_UINT8(s, channelId); /* channelId (1 byte) 0xFF or 0x00, see below */ + + if (codecId != 0x01) { - WLog_ERR(TAG, "rfx_process_message: unable to skip RFX_CODEC_CHANNELT"); - break; + WLog_ERR(TAG, "%s: invalid codecId 0x%02X", __FUNCTION__, codecId); + goto fail; + } + + if (blockType == WBT_CONTEXT) + { + /* If the blockType is set to WBT_CONTEXT, then channelId MUST be set to 0xFF.*/ + if (channelId != 0xFF) + { + WLog_ERR(TAG, "%s: invalid channelId 0x%02X for blockType 0x%04X", __FUNCTION__, channelId, blockType); + goto fail; + } + } + else + { + /* For all other values of blockType, channelId MUST be set to 0x00. */ + if (channelId != 0x00) + { + WLog_ERR(TAG, "%s: invalid channelId 0x%02X for blockType WBT_CONTEXT", __FUNCTION__, channelId); + goto fail; + } } } + switch (blockType) { + /* Header messages: + * The stream MUST start with the header messages and any of these headers can appear + * in the stream at a later stage. The header messages can be repeated. + */ + case WBT_SYNC: - rfx_process_message_sync(context, s); - break; - - case WBT_CODEC_VERSIONS: - rfx_process_message_codec_versions(context, s); - break; - - case WBT_CHANNELS: - rfx_process_message_channels(context, s); + ok = rfx_process_message_sync(context, s); break; case WBT_CONTEXT: - rfx_process_message_context(context, s); + ok = rfx_process_message_context(context, s); break; + case WBT_CODEC_VERSIONS: + ok = rfx_process_message_codec_versions(context, s); + break; + + case WBT_CHANNELS: + ok = rfx_process_message_channels(context, s); + break; + + /* Data messages: + * The data associated with each encoded frame or image is always bracketed by the + * TS_RFX_FRAME_BEGIN (section 2.2.2.3.1) and TS_RFX_FRAME_END (section 2.2.2.3.2) messages. + * There MUST only be one TS_RFX_REGION (section 2.2.2.3.3) message per frame and one TS_RFX_TILESET + * (section 2.2.2.3.4) message per TS_RFX_REGION. + */ + case WBT_FRAME_BEGIN: - rfx_process_message_frame_begin(context, message, s); - break; - - case WBT_FRAME_END: - rfx_process_message_frame_end(context, message, s); + ok = rfx_process_message_frame_begin(context, message, s, &expectedDataBlockType); break; case WBT_REGION: - rfx_process_message_region(context, message, s); + ok = rfx_process_message_region(context, message, s, &expectedDataBlockType); break; case WBT_EXTENSION: - rfx_process_message_tileset(context, message, s); + ok = rfx_process_message_tileset(context, message, s, &expectedDataBlockType); + break; + + case WBT_FRAME_END: + ok = rfx_process_message_frame_end(context, message, s, &expectedDataBlockType); break; default: - WLog_ERR(TAG, "unknown blockType 0x%X", blockType); - break; + WLog_ERR(TAG, "%s: unknown blockType 0x%X", __FUNCTION__, blockType); + goto fail; } Stream_SetPosition(s, pos); } - Stream_Free(s, FALSE); + if (ok) + { + Stream_Free(s, FALSE); + return message; + } - return message; +fail: + Stream_Free(s, FALSE); + rfx_message_free(context, message); + + return NULL; } UINT16 rfx_message_get_tile_count(RFX_MESSAGE* message) @@ -1093,7 +1230,7 @@ static void rfx_write_message_context(RFX_CONTEXT* context, wStream* s) Stream_Write_UINT16(s, WBT_CONTEXT); /* CodecChannelT.blockType (2 bytes) */ Stream_Write_UINT32(s, 13); /* CodecChannelT.blockLen (4 bytes) */ Stream_Write_UINT8(s, 1); /* CodecChannelT.codecId (1 byte) */ - Stream_Write_UINT8(s, 0); /* CodecChannelT.channelId (1 byte) */ + Stream_Write_UINT8(s, 0xFF); /* CodecChannelT.channelId (1 byte) */ Stream_Write_UINT8(s, 0); /* ctxId (1 byte) */ Stream_Write_UINT16(s, CT_TILE_64x64); /* tileSize (2 bytes) */ @@ -1108,15 +1245,17 @@ static void rfx_write_message_context(RFX_CONTEXT* context, wStream* s) rfx_update_context_properties(context); } -void rfx_compose_message_header(RFX_CONTEXT* context, wStream* s) +static BOOL rfx_compose_message_header(RFX_CONTEXT* context, wStream* s) { if (!Stream_EnsureRemainingCapacity(s, 12 + 10 + 12 + 13)) - return; + return FALSE; rfx_write_message_sync(context, s); rfx_write_message_context(context, s); rfx_write_message_codec_versions(context, s); rfx_write_message_channels(context, s); + + return TRUE; } static int rfx_tile_length(RFX_TILE* tile) @@ -1124,13 +1263,13 @@ static int rfx_tile_length(RFX_TILE* tile) return 19 + tile->YLen + tile->CbLen + tile->CrLen; } -static void rfx_write_tile(RFX_CONTEXT* context, wStream* s, RFX_TILE* tile) +static BOOL rfx_write_tile(RFX_CONTEXT* context, wStream* s, RFX_TILE* tile) { UINT32 blockLen; blockLen = rfx_tile_length(tile); if (!Stream_EnsureRemainingCapacity(s, blockLen)) - return; + return FALSE; Stream_Write_UINT16(s, CBT_TILE); /* BlockT.blockType (2 bytes) */ Stream_Write_UINT32(s, blockLen); /* BlockT.blockLen (4 bytes) */ @@ -1145,6 +1284,8 @@ static void rfx_write_tile(RFX_CONTEXT* context, wStream* s, RFX_TILE* tile) Stream_Write(s, tile->YData, tile->YLen); /* YData */ Stream_Write(s, tile->CbData, tile->CbLen); /* CbData */ Stream_Write(s, tile->CrData, tile->CrLen); /* CrData */ + + return TRUE; } struct _RFX_TILE_COMPOSE_WORK_PARAM @@ -1186,21 +1327,21 @@ static BOOL computeRegion(const RFX_RECT* rects, int numRects, REGION16 *region, BOOL setupWorkers(RFX_CONTEXT *context, int nbTiles) { RFX_CONTEXT_PRIV *priv = context->priv; + void* pmem; if (!context->priv->UseThreads) return TRUE; - priv->workObjects = (PTP_WORK*) realloc(priv->workObjects, sizeof(PTP_WORK) * nbTiles); - - if (!priv->workObjects) + if (!(pmem = realloc((void*) priv->workObjects, sizeof(PTP_WORK) * nbTiles))) return FALSE; - priv->tileWorkParams = (RFX_TILE_COMPOSE_WORK_PARAM*) - realloc(priv->tileWorkParams, sizeof(RFX_TILE_COMPOSE_WORK_PARAM) * nbTiles); + priv->workObjects = (PTP_WORK*) pmem; - if (!priv->tileWorkParams) + if (!(pmem = realloc((void*) priv->tileWorkParams, sizeof(RFX_TILE_COMPOSE_WORK_PARAM) * nbTiles))) return FALSE; + priv->tileWorkParams = (RFX_TILE_COMPOSE_WORK_PARAM*) pmem; + return TRUE; } @@ -1215,6 +1356,7 @@ RFX_MESSAGE* rfx_encode_message(RFX_CONTEXT* context, const RFX_RECT* rects, int RFX_MESSAGE* message = NULL; PTP_WORK* workObject = NULL; RFX_TILE_COMPOSE_WORK_PARAM *workParam = NULL; + BOOL success = FALSE; REGION16 rectsRegion, tilesRegion; RECTANGLE_16 currentTileRect; @@ -1228,11 +1370,12 @@ RFX_MESSAGE* rfx_encode_message(RFX_CONTEXT* context, const RFX_RECT* rects, int assert(height > 0); assert(scanline > 0); - message = (RFX_MESSAGE*)calloc(1, sizeof(RFX_MESSAGE)); - - if (!message) + if (!(message = (RFX_MESSAGE*)calloc(1, sizeof(RFX_MESSAGE)))) return NULL; + region16_init(&tilesRegion); + region16_init(&rectsRegion); + if (context->state == RFX_STATE_SEND_HEADERS) rfx_update_context_properties(context); @@ -1240,9 +1383,11 @@ RFX_MESSAGE* rfx_encode_message(RFX_CONTEXT* context, const RFX_RECT* rects, int if (!context->numQuant) { - context->numQuant = 1; - context->quants = (UINT32*) malloc(sizeof(rfx_default_quantization_values)); + if (!(context->quants = (UINT32*) malloc(sizeof(rfx_default_quantization_values)))) + goto skip_encoding_loop; + CopyMemory(context->quants, &rfx_default_quantization_values, sizeof(rfx_default_quantization_values)); + context->numQuant = 1; context->quantIdxY = 0; context->quantIdxCb = 0; context->quantIdxCr = 0; @@ -1253,10 +1398,8 @@ RFX_MESSAGE* rfx_encode_message(RFX_CONTEXT* context, const RFX_RECT* rects, int bytesPerPixel = (context->bits_per_pixel / 8); - region16_init(&rectsRegion); - if (!computeRegion(rects, numRects, &rectsRegion, width, height)) - goto out_free_message; + goto skip_encoding_loop; extents = region16_extents(&rectsRegion); assert(extents->right - extents->left > 0); @@ -1266,13 +1409,11 @@ RFX_MESSAGE* rfx_encode_message(RFX_CONTEXT* context, const RFX_RECT* rects, int maxTilesY = 1 + TILE_NO(extents->bottom - 1) - TILE_NO(extents->top); maxNbTiles = maxTilesX * maxTilesY; - message->tiles = calloc(maxNbTiles, sizeof(RFX_TILE*)); - - if (!message->tiles) - goto out_free_message; + if (!(message->tiles = calloc(maxNbTiles, sizeof(RFX_TILE*)))) + goto skip_encoding_loop; if (!setupWorkers(context, maxNbTiles)) - goto out_clean_tiles; + goto skip_encoding_loop; if (context->priv->UseThreads) { @@ -1281,16 +1422,13 @@ RFX_MESSAGE* rfx_encode_message(RFX_CONTEXT* context, const RFX_RECT* rects, int } regionRect = region16_rects(&rectsRegion, ®ionNbRects); - message->rects = rfxRect = calloc(regionNbRects, sizeof(RFX_RECT)); - if (!message->rects) - goto out_clean_tiles; + if (!(message->rects = calloc(regionNbRects, sizeof(RFX_RECT)))) + goto skip_encoding_loop; message->numRects = regionNbRects; - region16_init(&tilesRegion); - - for (i = 0; i < regionNbRects; i++, regionRect++, rfxRect++) + for (i = 0, rfxRect = message->rects; i < regionNbRects; i++, regionRect++, rfxRect++) { int startTileX = regionRect->left / 64; int endTileX = (regionRect->right - 1) / 64; @@ -1328,10 +1466,8 @@ RFX_MESSAGE* rfx_encode_message(RFX_CONTEXT* context, const RFX_RECT* rects, int if (region16_intersects_rect(&tilesRegion, ¤tTileRect)) continue; - tile = (RFX_TILE*) ObjectPool_Take(context->priv->TilePool); - - if (!tile) - goto out_clean_rects;; + if (!(tile = (RFX_TILE*) ObjectPool_Take(context->priv->TilePool))) + goto skip_encoding_loop; tile->xIdx = xIdx; tile->yIdx = yIdx; @@ -1357,24 +1493,28 @@ RFX_MESSAGE* rfx_encode_message(RFX_CONTEXT* context, const RFX_RECT* rects, int tile->YLen = tile->CbLen = tile->CrLen = 0; - tile->YCbCrData = (BYTE *)BufferPool_Take(context->priv->BufferPool, -1); - if (!tile->YCbCrData) - goto out_clean_rects; + if (!(tile->YCbCrData = (BYTE *)BufferPool_Take(context->priv->BufferPool, -1))) + goto skip_encoding_loop; tile->YData = (BYTE*) &(tile->YCbCrData[((8192 + 32) * 0) + 16]); tile->CbData = (BYTE*) &(tile->YCbCrData[((8192 + 32) * 1) + 16]); tile->CrData = (BYTE*) &(tile->YCbCrData[((8192 + 32) * 2) + 16]); + message->tiles[message->numTiles] = tile; + message->numTiles++; + if (context->priv->UseThreads) { workParam->context = context; workParam->tile = tile; - *workObject = CreateThreadpoolWork( + if (!(*workObject = CreateThreadpoolWork( (PTP_WORK_CALLBACK)rfx_compose_message_tile_work_callback, (void*) workParam, - &context->priv->ThreadPoolEnv - ); + &context->priv->ThreadPoolEnv))) + { + goto skip_encoding_loop; + } SubmitThreadpoolWork(*workObject); @@ -1386,25 +1526,26 @@ RFX_MESSAGE* rfx_encode_message(RFX_CONTEXT* context, const RFX_RECT* rects, int rfx_encode_rgb(context, tile); } - message->tiles[message->numTiles] = tile; - message->numTiles++; - if (!region16_union_rect(&tilesRegion, &tilesRegion, ¤tTileRect)) - goto out_clean_rects; + goto skip_encoding_loop; } /* xIdx */ } /* yIdx */ } /* rects */ - if (message->numTiles != maxNbTiles) + success = TRUE; + +skip_encoding_loop: + + if (success && message->numTiles != maxNbTiles) { - message->tiles = realloc(message->tiles, sizeof(RFX_TILE*) * message->numTiles); + void* pmem = realloc((void*) message->tiles, sizeof(RFX_TILE*) * message->numTiles); - if (!message->tiles) - goto out_clean_rects; + if (pmem) + message->tiles = (RFX_TILE**) pmem; + else + success = FALSE; } - region16_uninit(&tilesRegion); - /* when using threads ensure all computations are done */ message->tilesDataSize = 0; workObject = context->priv->workObjects; @@ -1414,30 +1555,29 @@ RFX_MESSAGE* rfx_encode_message(RFX_CONTEXT* context, const RFX_RECT* rects, int tile = message->tiles[i]; if (context->priv->UseThreads) { - WaitForThreadpoolWorkCallbacks(*workObject, FALSE); - CloseThreadpoolWork(*workObject); + if (*workObject) + { + WaitForThreadpoolWorkCallbacks(*workObject, FALSE); + CloseThreadpoolWork(*workObject); + } workObject++; } message->tilesDataSize += rfx_tile_length(tile); } - - region16_uninit(&rectsRegion); - return message; - -out_clean_rects: - free(message->rects); -out_clean_tiles: - free(message->tiles); region16_uninit(&tilesRegion); -out_free_message: - WLog_ERR(TAG, "remoteFx error"); region16_uninit(&rectsRegion); - free(message); - return 0; -} + if (success) + return message; + + WLog_ERR(TAG, "%s: failed", __FUNCTION__); + + message->freeRects = TRUE; + rfx_message_free(context, message); + return NULL; +} RFX_MESSAGE* rfx_split_message(RFX_CONTEXT* context, RFX_MESSAGE* message, int* numMessages, int maxDataSize) { @@ -1449,9 +1589,7 @@ RFX_MESSAGE* rfx_split_message(RFX_CONTEXT* context, RFX_MESSAGE* message, int* *numMessages = ((message->tilesDataSize + maxDataSize) / maxDataSize) * 4; - messages = (RFX_MESSAGE*) calloc((*numMessages), sizeof(RFX_MESSAGE)); - - if (!messages) + if (!(messages = (RFX_MESSAGE*) calloc((*numMessages), sizeof(RFX_MESSAGE)))) return NULL; j = 0; @@ -1470,9 +1608,10 @@ RFX_MESSAGE* rfx_split_message(RFX_CONTEXT* context, RFX_MESSAGE* message, int* messages[j].quantVals = message->quantVals; messages[j].numRects = message->numRects; messages[j].rects = message->rects; - messages[j].tiles = (RFX_TILE**) malloc(sizeof(RFX_TILE*) * message->numTiles); messages[j].freeRects = FALSE; messages[j].freeArray = TRUE; + if (!(messages[j].tiles = (RFX_TILE**) calloc(message->numTiles, sizeof(RFX_TILE*)))) + goto free_messages; } messages[j].tilesDataSize += tileDataSize; @@ -1484,31 +1623,38 @@ RFX_MESSAGE* rfx_split_message(RFX_CONTEXT* context, RFX_MESSAGE* message, int* context->frameIdx += j; message->numTiles = 0; - for (i = 0; i < *numMessages; i++) - { - for (j = 0; j < messages[i].numTiles; j++) - { - - } - } - return messages; + +free_messages: + for (i = 0; i < j; i++) + free(messages[i].tiles); + + free(messages); + + return NULL; } RFX_MESSAGE* rfx_encode_messages(RFX_CONTEXT* context, const RFX_RECT* rects, int numRects, BYTE* data, int width, int height, int scanline, int* numMessages, int maxDataSize) { RFX_MESSAGE* message; - RFX_MESSAGE* messages; + RFX_MESSAGE* messageList; + + if (!(message = rfx_encode_message(context, rects, numRects, data, width, height, scanline))) + return NULL; + + if (!(messageList = rfx_split_message(context, message, numMessages, maxDataSize))) + { + message->freeRects = TRUE; + rfx_message_free(context, message); + return NULL; + } - message = rfx_encode_message(context, rects, numRects, data, width, height, scanline); - messages = rfx_split_message(context, message, numMessages, maxDataSize); rfx_message_free(context, message); - - return messages; + return messageList; } -static void rfx_write_message_tileset(RFX_CONTEXT* context, wStream* s, RFX_MESSAGE* message) +static BOOL rfx_write_message_tileset(RFX_CONTEXT* context, wStream* s, RFX_MESSAGE* message) { int i; RFX_TILE* tile; @@ -1517,7 +1663,7 @@ static void rfx_write_message_tileset(RFX_CONTEXT* context, wStream* s, RFX_MESS blockLen = 22 + (message->numQuant * 5) + message->tilesDataSize; if (!Stream_EnsureRemainingCapacity(s, blockLen)) - return; + return FALSE; Stream_Write_UINT16(s, WBT_EXTENSION); /* CodecChannelT.blockType (2 bytes) */ Stream_Write_UINT32(s, blockLen); /* set CodecChannelT.blockLen (4 bytes) */ @@ -1542,17 +1688,22 @@ static void rfx_write_message_tileset(RFX_CONTEXT* context, wStream* s, RFX_MESS for (i = 0; i < message->numTiles; i++) { tile = message->tiles[i]; - rfx_write_tile(context, s, tile); + if (!rfx_write_tile(context, s, tile)) + return FALSE; } +#ifdef WITH_DEBUG_RFX WLog_Print(context->priv->log, WLOG_DEBUG, "numQuant: %d numTiles: %d tilesDataSize: %d", message->numQuant, message->numTiles, message->tilesDataSize); +#endif + + return TRUE; } -void rfx_write_message_frame_begin(RFX_CONTEXT* context, wStream* s, RFX_MESSAGE* message) +BOOL rfx_write_message_frame_begin(RFX_CONTEXT* context, wStream* s, RFX_MESSAGE* message) { if (!Stream_EnsureRemainingCapacity(s, 14)) - return; + return FALSE; Stream_Write_UINT16(s, WBT_FRAME_BEGIN); /* CodecChannelT.blockType */ Stream_Write_UINT32(s, 14); /* CodecChannelT.blockLen */ @@ -1560,16 +1711,18 @@ void rfx_write_message_frame_begin(RFX_CONTEXT* context, wStream* s, RFX_MESSAGE Stream_Write_UINT8(s, 0); /* CodecChannelT.channelId */ Stream_Write_UINT32(s, message->frameIdx); /* frameIdx */ Stream_Write_UINT16(s, 1); /* numRegions */ + + return TRUE; } -void rfx_write_message_region(RFX_CONTEXT* context, wStream* s, RFX_MESSAGE* message) +BOOL rfx_write_message_region(RFX_CONTEXT* context, wStream* s, RFX_MESSAGE* message) { int i; UINT32 blockLen; blockLen = 15 + (message->numRects * 8); if (!Stream_EnsureRemainingCapacity(s, blockLen)) - return; + return FALSE; Stream_Write_UINT16(s, WBT_REGION); /* CodecChannelT.blockType (2 bytes) */ Stream_Write_UINT32(s, blockLen); /* set CodecChannelT.blockLen (4 bytes) */ @@ -1590,41 +1743,56 @@ void rfx_write_message_region(RFX_CONTEXT* context, wStream* s, RFX_MESSAGE* mes Stream_Write_UINT16(s, CBT_REGION); /* regionType (2 bytes) */ Stream_Write_UINT16(s, 1); /* numTilesets (2 bytes) */ + + return TRUE; } -void rfx_write_message_frame_end(RFX_CONTEXT* context, wStream* s, RFX_MESSAGE* message) +BOOL rfx_write_message_frame_end(RFX_CONTEXT* context, wStream* s, RFX_MESSAGE* message) { if (!Stream_EnsureRemainingCapacity(s, 8)) - return; + return FALSE; Stream_Write_UINT16(s, WBT_FRAME_END); /* CodecChannelT.blockType */ Stream_Write_UINT32(s, 8); /* CodecChannelT.blockLen */ Stream_Write_UINT8(s, 1); /* CodecChannelT.codecId */ Stream_Write_UINT8(s, 0); /* CodecChannelT.channelId */ + + return TRUE; } -void rfx_write_message(RFX_CONTEXT* context, wStream* s, RFX_MESSAGE* message) +BOOL rfx_write_message(RFX_CONTEXT* context, wStream* s, RFX_MESSAGE* message) { if (context->state == RFX_STATE_SEND_HEADERS) { - rfx_compose_message_header(context, s); + if (!rfx_compose_message_header(context, s)) + return FALSE; context->state = RFX_STATE_SEND_FRAME_DATA; } - rfx_write_message_frame_begin(context, s, message); - rfx_write_message_region(context, s, message); - rfx_write_message_tileset(context, s, message); - rfx_write_message_frame_end(context, s, message); + if (!rfx_write_message_frame_begin(context, s, message) || + !rfx_write_message_region(context, s, message) || + !rfx_write_message_tileset(context, s, message) || + !rfx_write_message_frame_end(context, s, message)) + { + return FALSE; + } + + return TRUE; } -void rfx_compose_message(RFX_CONTEXT* context, wStream* s, +BOOL rfx_compose_message(RFX_CONTEXT* context, wStream* s, const RFX_RECT* rects, int numRects, BYTE* data, int width, int height, int scanline) { RFX_MESSAGE* message; + BOOL ret = TRUE; - message = rfx_encode_message(context, rects, numRects, data, width, height, scanline); + if (!(message = rfx_encode_message(context, rects, numRects, data, width, height, scanline))) + return FALSE; - rfx_write_message(context, s, message); + ret = rfx_write_message(context, s, message); + message->freeRects = TRUE; rfx_message_free(context, message); + + return ret; } diff --git a/libfreerdp/gdi/gdi.c b/libfreerdp/gdi/gdi.c index 972e0f2d9..573c2f84d 100644 --- a/libfreerdp/gdi/gdi.c +++ b/libfreerdp/gdi/gdi.c @@ -1029,7 +1029,11 @@ static BOOL gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* cmd) { freerdp_client_codecs_prepare(gdi->codecs, FREERDP_CODEC_REMOTEFX); - message = rfx_process_message(gdi->codecs->rfx, cmd->bitmapData, cmd->bitmapDataLength); + if (!(message = rfx_process_message(gdi->codecs->rfx, cmd->bitmapData, cmd->bitmapDataLength))) + { + WLog_ERR(TAG, "Failed to process RemoteFX message"); + return FALSE; + } /* blit each tile */ for (i = 0; i < message->numTiles; i++) diff --git a/libfreerdp/gdi/gfx.c b/libfreerdp/gdi/gfx.c index fd35d6c28..b38e44e16 100644 --- a/libfreerdp/gdi/gfx.c +++ b/libfreerdp/gdi/gfx.c @@ -199,10 +199,11 @@ int gdi_SurfaceCommand_RemoteFX(rdpGdi* gdi, RdpgfxClientContext* context, RDPGF if (!surface) return -1; - message = rfx_process_message(gdi->codecs->rfx, cmd->data, cmd->length); - - if (!message) + if (!(message = rfx_process_message(gdi->codecs->rfx, cmd->data, cmd->length))) + { + WLog_ERR(TAG, "Failed to process RemoteFX message"); return -1; + } region16_init(&clippingRects); diff --git a/server/Mac/mf_peer.c b/server/Mac/mf_peer.c index 239aafd6d..d9d8b90f7 100644 --- a/server/Mac/mf_peer.c +++ b/server/Mac/mf_peer.c @@ -147,8 +147,11 @@ void mf_peer_rfx_update(freerdp_peer* client) mfp->rfx_context->width = mfi->servscreen_width; mfp->rfx_context->height = mfi->servscreen_height; - rfx_compose_message(mfp->rfx_context, s, &rect, 1, - (BYTE*) dataBits, rect.width, rect.height, pitch); + if (!(rfx_compose_message(mfp->rfx_context, s, &rect, 1, + (BYTE*) dataBits, rect.width, rect.height, pitch))) + { + return; + } cmd->destLeft = x; cmd->destTop = y; diff --git a/server/Sample/sfreerdp.c b/server/Sample/sfreerdp.c index 55d05a769..95b99f549 100644 --- a/server/Sample/sfreerdp.c +++ b/server/Sample/sfreerdp.c @@ -157,8 +157,6 @@ static void test_peer_draw_background(freerdp_peer* client) if (!client->settings->RemoteFxCodec && !client->settings->NSCodec) return; - test_peer_begin_frame(client); - s = test_peer_stream_init(context); rect.x = 0; @@ -167,13 +165,18 @@ static void test_peer_draw_background(freerdp_peer* client) rect.height = client->settings->DesktopHeight; size = rect.width * rect.height * 3; - rgb_data = malloc(size); + if (!(rgb_data = malloc(size))) + return; + memset(rgb_data, 0xA0, size); if (client->settings->RemoteFxCodec) { - rfx_compose_message(context->rfx_context, s, - &rect, 1, rgb_data, rect.width, rect.height, rect.width * 3); + if (!rfx_compose_message(context->rfx_context, s, + &rect, 1, rgb_data, rect.width, rect.height, rect.width * 3)) + { + goto out; + } cmd->codecID = client->settings->RemoteFxCodecId; } else @@ -192,11 +195,13 @@ static void test_peer_draw_background(freerdp_peer* client) cmd->height = rect.height; cmd->bitmapDataLength = Stream_GetPosition(s); cmd->bitmapData = Stream_Buffer(s); + + test_peer_begin_frame(client); update->SurfaceBits(update->context, cmd); - - free(rgb_data); - test_peer_end_frame(client); + +out: + free(rgb_data); } static void test_peer_load_icon(freerdp_peer* client) diff --git a/server/Windows/wf_update.c b/server/Windows/wf_update.c index 0c7991773..76c60aec5 100644 --- a/server/Windows/wf_update.c +++ b/server/Windows/wf_update.c @@ -129,8 +129,11 @@ void wf_update_encode(wfInfo* wfi) //WLog_DBG(TAG, "x:%d y:%d w:%d h:%d", wfi->invalid.left, wfi->invalid.top, width, height); Stream_Clear(wfi->s); - rfx_compose_message(wfi->rfx_context, wfi->s, &rect, 1, - pDataBits, width, height, stride); + if (!(rfx_compose_message(wfi->rfx_context, wfi->s, &rect, 1, + pDataBits, width, height, stride))) + { + return; + } wfi->frame_idx = wfi->rfx_context->frameIdx; diff --git a/server/shadow/shadow_client.c b/server/shadow/shadow_client.c index 30ab90e11..757317034 100644 --- a/server/shadow/shadow_client.c +++ b/server/shadow/shadow_client.c @@ -384,6 +384,7 @@ int shadow_client_send_surface_bits(rdpShadowClient* client, rdpShadowSurface* s { RFX_RECT rect; RFX_MESSAGE* messages; + RFX_RECT *messageRects = NULL; shadow_encoder_prepare(encoder, FREERDP_CODEC_REMOTEFX); @@ -394,9 +395,12 @@ int shadow_client_send_surface_bits(rdpShadowClient* client, rdpShadowSurface* s rect.width = nWidth; rect.height = nHeight; - messages = rfx_encode_messages(encoder->rfx, &rect, 1, pSrcData, + if (!(messages = rfx_encode_messages(encoder->rfx, &rect, 1, pSrcData, surface->width, surface->height, nSrcStep, &numMessages, - settings->MultifragMaxRequestSize); + settings->MultifragMaxRequestSize))) + { + return 0; + } cmd.codecID = settings->RemoteFxCodecId; @@ -409,10 +413,20 @@ int shadow_client_send_surface_bits(rdpShadowClient* client, rdpShadowSurface* s cmd.width = surface->width; cmd.height = surface->height; + if (numMessages > 0) + messageRects = messages[0].rects; + for (i = 0; i < numMessages; i++) { Stream_SetPosition(s, 0); - rfx_write_message(encoder->rfx, s, &messages[i]); + if (!rfx_write_message(encoder->rfx, s, &messages[i])) + { + while (i < numMessages) + { + rfx_message_free(encoder->rfx, &messages[i++]); + } + break; + } rfx_message_free(encoder->rfx, &messages[i]); cmd.bitmapDataLength = Stream_GetPosition(s); @@ -427,6 +441,7 @@ int shadow_client_send_surface_bits(rdpShadowClient* client, rdpShadowSurface* s IFCALL(update->SurfaceFrameBits, update->context, &cmd, first, last, frameId); } + free(messageRects); free(messages); } else if (settings->NSCodec)