diff --git a/client/X11/xf_gfx.c b/client/X11/xf_gfx.c index ca70df6e1..7a7fc6878 100644 --- a/client/X11/xf_gfx.c +++ b/client/X11/xf_gfx.c @@ -118,6 +118,13 @@ fail: return rc; } +static UINT xf_WindowUpdate(RdpgfxClientContext* context, xfGfxSurface* surface) +{ + WINPR_ASSERT(context); + WINPR_ASSERT(surface); + return IFCALLRESULT(CHANNEL_RC_OK, context->UpdateWindowFromSurface, context, &surface->gdi); +} + static UINT xf_UpdateSurfaces(RdpgfxClientContext* context) { UINT16 count; @@ -147,16 +154,16 @@ static UINT xf_UpdateSurfaces(RdpgfxClientContext* context) /* If UpdateSurfaceArea callback is available, the output has already been updated. */ if (context->UpdateSurfaceArea) { - if (surface->gdi.windowId != 0) + if (surface->gdi.handleInUpdateSurfaceArea) continue; } - status = ERROR_INTERNAL_ERROR; - if (surface->gdi.outputMapped) status = xf_OutputUpdate(xfc, surface); + else if (surface->gdi.windowMapped) + status = xf_WindowUpdate(context, surface); - if (status != 0) + if (status != CHANNEL_RC_OK) break; } @@ -170,10 +177,8 @@ UINT xf_OutputExpose(xfContext* xfc, UINT32 x, UINT32 y, UINT32 width, UINT32 he UINT16 count; UINT32 index; UINT status = ERROR_INTERNAL_ERROR; - xfGfxSurface* surface; - RECTANGLE_16 invalidRect; - RECTANGLE_16 surfaceRect; - RECTANGLE_16 intersection; + RECTANGLE_16 invalidRect = { 0 }; + RECTANGLE_16 intersection = { 0 }; UINT16* pSurfaceIds = NULL; RdpgfxClientContext* context; @@ -199,9 +204,10 @@ UINT xf_OutputExpose(xfContext* xfc, UINT32 x, UINT32 y, UINT32 width, UINT32 he } for (index = 0; index < count; index++) { - surface = (xfGfxSurface*)context->GetSurfaceData(context, pSurfaceIds[index]); + RECTANGLE_16 surfaceRect = { 0 }; + xfGfxSurface* surface = (xfGfxSurface*)context->GetSurfaceData(context, pSurfaceIds[index]); - if (!surface || !surface->gdi.outputMapped) + if (!surface || (!surface->gdi.outputMapped && !surface->gdi.windowMapped)) continue; surfaceRect.left = surface->gdi.outputOriginX; @@ -352,7 +358,7 @@ static UINT xf_CreateSurface(RdpgfxClientContext* context, surface->image->byte_order = LSBFirst; surface->image->bitmap_bit_order = LSBFirst; - surface->gdi.outputMapped = FALSE; + region16_init(&surface->gdi.invalidRegion); if (context->SetSurfaceData(context, surface->gdi.surfaceId, (void*)surface) != CHANNEL_RC_OK) @@ -390,7 +396,7 @@ static UINT xf_DeleteSurface(RdpgfxClientContext* context, if (surface) { - if (surface->gdi.windowId > 0) + if (surface->gdi.windowMapped) IFCALL(context->UnmapWindowForSurface, context, surface->gdi.windowId); #ifdef WITH_GFX_H264 @@ -414,6 +420,24 @@ static UINT xf_DeleteSurface(RdpgfxClientContext* context, return status; } +static UINT xf_UpdateWindowFromSurface(RdpgfxClientContext* context, gdiGfxSurface* surface) +{ + WINPR_ASSERT(context); + WINPR_ASSERT(surface); + + rdpGdi* gdi = (rdpGdi*)context->custom; + WINPR_ASSERT(gdi); + + xfContext* xfc = (xfContext*)gdi->context; + WINPR_ASSERT(gdi->context); + +// if (freerdp_settings_get_bool(gdi->context->settings, FreeRDP_RemoteApplicationMode)) +// return xf_AppUpdateWindowFromSurface(xfc, surface); + + WLog_WARN(TAG, "[%s] function not implemented", __func__); + return CHANNEL_RC_OK; +} + void xf_graphics_pipeline_init(xfContext* xfc, RdpgfxClientContext* gfx) { rdpGdi* gdi; @@ -434,6 +458,7 @@ void xf_graphics_pipeline_init(xfContext* xfc, RdpgfxClientContext* gfx) gfx->CreateSurface = xf_CreateSurface; gfx->DeleteSurface = xf_DeleteSurface; } + gfx->UpdateWindowFromSurface = xf_UpdateWindowFromSurface; } void xf_graphics_pipeline_uninit(xfContext* xfc, RdpgfxClientContext* gfx) diff --git a/include/freerdp/client/rdpgfx.h b/include/freerdp/client/rdpgfx.h index 95878b051..247c7708a 100644 --- a/include/freerdp/client/rdpgfx.h +++ b/include/freerdp/client/rdpgfx.h @@ -31,7 +31,7 @@ /** * Client Interface */ - +typedef struct gdi_gfx_surface gdiGfxSurface; typedef struct s_rdpgfx_client_context RdpgfxClientContext; typedef UINT (*pcRdpgfxResetGraphics)(RdpgfxClientContext* context, @@ -84,6 +84,9 @@ typedef void* (*pcRdpgfxGetCacheSlotData)(RdpgfxClientContext* context, UINT16 c typedef UINT (*pcRdpgfxUpdateSurfaces)(RdpgfxClientContext* context); +typedef UINT (*pcRdpgfxUpdateWindowFromSurface)(RdpgfxClientContext* context, + gdiGfxSurface* surface); + typedef UINT (*pcRdpgfxUpdateSurfaceArea)(RdpgfxClientContext* context, UINT16 surfaceId, UINT32 nrRects, const RECTANGLE_16* rects); @@ -147,6 +150,7 @@ struct s_rdpgfx_client_context /* No locking required */ pcRdpgfxUpdateSurfaces UpdateSurfaces; pcRdpgfxUpdateSurfaceArea UpdateSurfaceArea; + pcRdpgfxUpdateWindowFromSurface UpdateWindowFromSurface; /* These callbacks allow crating/destroying a window directly * mapped to a surface. diff --git a/include/freerdp/gdi/gfx.h b/include/freerdp/gdi/gfx.h index 85ee7cec2..f99c40c2b 100644 --- a/include/freerdp/gdi/gfx.h +++ b/include/freerdp/gdi/gfx.h @@ -42,6 +42,8 @@ struct gdi_gfx_surface UINT64 windowId; UINT32 outputTargetWidth; UINT32 outputTargetHeight; + BOOL windowMapped; + BOOL handleInUpdateSurfaceArea; }; typedef struct gdi_gfx_surface gdiGfxSurface; diff --git a/libfreerdp/gdi/gfx.c b/libfreerdp/gdi/gfx.c index 21daeb36d..b40508b83 100644 --- a/libfreerdp/gdi/gfx.c +++ b/libfreerdp/gdi/gfx.c @@ -23,6 +23,7 @@ #include "../core/update.h" +#include #include #include #include @@ -45,10 +46,10 @@ static BOOL is_within_surface(const gdiGfxSurface* surface, const RDPGFX_SURFACE RECTANGLE_16 rect; if (!surface || !cmd) return FALSE; - rect.left = cmd->left; - rect.top = cmd->top; - rect.right = cmd->right; - rect.bottom = cmd->bottom; + rect.left = (UINT16)MIN(UINT16_MAX, cmd->left); + rect.top = (UINT16)MIN(UINT16_MAX, cmd->top); + rect.right = (UINT16)MIN(UINT16_MAX, cmd->right); + rect.bottom = (UINT16)MIN(UINT16_MAX, cmd->bottom); if (!is_rect_valid(&rect, surface->width, surface->height)) { WLog_ERR(TAG, @@ -129,9 +130,6 @@ static UINT gdi_ResetGraphics(RdpgfxClientContext* context, continue; memset(surface->data, 0xFF, (size_t)surface->scanline * surface->height); - if (!surface->outputMapped) - continue; - region16_clear(&surface->invalidRegion); } @@ -139,15 +137,16 @@ static UINT gdi_ResetGraphics(RdpgfxClientContext* context, if (!freerdp_settings_get_bool(gdi->context->settings, FreeRDP_DeactivateClientDecoding)) { - if (!freerdp_client_codecs_reset(context->codecs, - freerdp_settings_get_codecs_flags(settings), gdi->width, - gdi->height)) + const UINT32 width = (UINT32)MIN(0, gdi->width); + const UINT32 height = (UINT32)MIN(0, gdi->height); + + if (!freerdp_client_codecs_reset( + context->codecs, freerdp_settings_get_codecs_flags(settings), width, height)) { goto fail; } - if (!freerdp_client_codecs_reset(gdi->context->codecs, - freerdp_settings_get_codecs_flags(settings), gdi->width, - gdi->height)) + if (!freerdp_client_codecs_reset( + gdi->context->codecs, freerdp_settings_get_codecs_flags(settings), width, height)) { goto fail; } @@ -183,8 +182,8 @@ static UINT gdi_OutputUpdate(rdpGdi* gdi, gdiGfxSurface* surface) surfaceY = surface->outputOriginY; surfaceRect.left = 0; surfaceRect.top = 0; - surfaceRect.right = surface->mappedWidth; - surfaceRect.bottom = surface->mappedHeight; + surfaceRect.right = (UINT16)MIN(UINT16_MAX, surface->mappedWidth); + surfaceRect.bottom = (UINT16)MIN(UINT16_MAX, surface->mappedHeight); region16_intersect_rect(&(surface->invalidRegion), &(surface->invalidRegion), &surfaceRect); sx = surface->outputTargetWidth / (double)surface->mappedWidth; sy = surface->outputTargetHeight / (double)surface->mappedHeight; @@ -228,6 +227,13 @@ fail: return rc; } +static UINT gdi_WindowUpdate(RdpgfxClientContext* context, gdiGfxSurface* surface) +{ + WINPR_ASSERT(context); + WINPR_ASSERT(surface); + return IFCALLRESULT(CHANNEL_RC_OK, context->UpdateWindowFromSurface, context, surface); +} + static UINT gdi_UpdateSurfaces(RdpgfxClientContext* context) { UINT16 count; @@ -256,14 +262,14 @@ static UINT gdi_UpdateSurfaces(RdpgfxClientContext* context) /* Already handled in UpdateSurfaceArea callbacks */ if (context->UpdateSurfaceArea) { - if (surface->windowId != 0) + if (surface->handleInUpdateSurfaceArea) continue; } - if (!surface->outputMapped) - continue; - - status = gdi_OutputUpdate(gdi, surface); + if (surface->outputMapped) + status = gdi_OutputUpdate(gdi, surface); + else if (surface->windowMapped) + status = gdi_WindowUpdate(context, surface); if (status != CHANNEL_RC_OK) break; @@ -329,7 +335,8 @@ static UINT gdi_SurfaceCommand_Uncompressed(rdpGdi* gdi, RdpgfxClientContext* co WINPR_ASSERT(gdi); WINPR_ASSERT(context); WINPR_ASSERT(cmd); - surface = (gdiGfxSurface*)context->GetSurfaceData(context, cmd->surfaceId); + surface = + (gdiGfxSurface*)context->GetSurfaceData(context, (UINT16)MIN(UINT16_MAX, cmd->surfaceId)); if (!surface) { @@ -355,10 +362,10 @@ static UINT gdi_SurfaceCommand_Uncompressed(rdpGdi* gdi, RdpgfxClientContext* co FREERDP_FLIP_NONE)) return ERROR_INTERNAL_ERROR; - invalidRect.left = cmd->left; - invalidRect.top = cmd->top; - invalidRect.right = cmd->right; - invalidRect.bottom = cmd->bottom; + invalidRect.left = (UINT16)MIN(UINT16_MAX, cmd->left); + invalidRect.top = (UINT16)MIN(UINT16_MAX, cmd->top); + invalidRect.right = (UINT16)MIN(UINT16_MAX, cmd->right); + invalidRect.bottom = (UINT16)MIN(UINT16_MAX, cmd->bottom); region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion), &invalidRect); status = IFCALLRESULT(CHANNEL_RC_OK, context->UpdateSurfaceArea, context, surface->surfaceId, 1, &invalidRect); @@ -392,7 +399,8 @@ static UINT gdi_SurfaceCommand_RemoteFX(rdpGdi* gdi, RdpgfxClientContext* contex WINPR_ASSERT(gdi); WINPR_ASSERT(context); WINPR_ASSERT(cmd); - surface = (gdiGfxSurface*)context->GetSurfaceData(context, cmd->surfaceId); + surface = + (gdiGfxSurface*)context->GetSurfaceData(context, (UINT16)MIN(UINT16_MAX, cmd->surfaceId)); if (!surface) { @@ -449,7 +457,8 @@ static UINT gdi_SurfaceCommand_ClearCodec(rdpGdi* gdi, RdpgfxClientContext* cont WINPR_ASSERT(gdi); WINPR_ASSERT(context); WINPR_ASSERT(cmd); - surface = (gdiGfxSurface*)context->GetSurfaceData(context, cmd->surfaceId); + surface = + (gdiGfxSurface*)context->GetSurfaceData(context, (UINT16)MIN(UINT16_MAX, cmd->surfaceId)); if (!surface) { @@ -469,10 +478,10 @@ static UINT gdi_SurfaceCommand_ClearCodec(rdpGdi* gdi, RdpgfxClientContext* cont return ERROR_INTERNAL_ERROR; } - invalidRect.left = cmd->left; - invalidRect.top = cmd->top; - invalidRect.right = cmd->right; - invalidRect.bottom = cmd->bottom; + invalidRect.left = (UINT16)MIN(UINT16_MAX, cmd->left); + invalidRect.top = (UINT16)MIN(UINT16_MAX, cmd->top); + invalidRect.right = (UINT16)MIN(UINT16_MAX, cmd->right); + invalidRect.bottom = (UINT16)MIN(UINT16_MAX, cmd->bottom); region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion), &invalidRect); status = IFCALLRESULT(CHANNEL_RC_OK, context->UpdateSurfaceArea, context, surface->surfaceId, 1, &invalidRect); @@ -505,7 +514,8 @@ static UINT gdi_SurfaceCommand_Planar(rdpGdi* gdi, RdpgfxClientContext* context, WINPR_ASSERT(gdi); WINPR_ASSERT(context); WINPR_ASSERT(cmd); - surface = (gdiGfxSurface*)context->GetSurfaceData(context, cmd->surfaceId); + surface = + (gdiGfxSurface*)context->GetSurfaceData(context, (UINT16)MIN(UINT16_MAX, cmd->surfaceId)); if (!surface) { @@ -524,10 +534,10 @@ static UINT gdi_SurfaceCommand_Planar(rdpGdi* gdi, RdpgfxClientContext* context, cmd->width, cmd->height, FALSE)) return ERROR_INTERNAL_ERROR; - invalidRect.left = cmd->left; - invalidRect.top = cmd->top; - invalidRect.right = cmd->right; - invalidRect.bottom = cmd->bottom; + invalidRect.left = (UINT16)MIN(UINT16_MAX, cmd->left); + invalidRect.top = (UINT16)MIN(UINT16_MAX, cmd->top); + invalidRect.right = (UINT16)MIN(UINT16_MAX, cmd->right); + invalidRect.bottom = (UINT16)MIN(UINT16_MAX, cmd->bottom); region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion), &invalidRect); status = IFCALLRESULT(CHANNEL_RC_OK, context->UpdateSurfaceArea, context, surface->surfaceId, 1, &invalidRect); @@ -564,7 +574,8 @@ static UINT gdi_SurfaceCommand_AVC420(rdpGdi* gdi, RdpgfxClientContext* context, WINPR_ASSERT(context); WINPR_ASSERT(cmd); - surface = (gdiGfxSurface*)context->GetSurfaceData(context, cmd->surfaceId); + surface = + (gdiGfxSurface*)context->GetSurfaceData(context, (UINT16)MIN(UINT16_MAX, cmd->surfaceId)); if (!surface) { @@ -643,16 +654,17 @@ static UINT gdi_SurfaceCommand_AVC444(rdpGdi* gdi, RdpgfxClientContext* context, INT32 rc; UINT status = CHANNEL_RC_OK; UINT32 i; - gdiGfxSurface* surface; - RDPGFX_AVC444_BITMAP_STREAM* bs; - RDPGFX_AVC420_BITMAP_STREAM* avc1; - RDPGFX_H264_METABLOCK* meta1; - RDPGFX_AVC420_BITMAP_STREAM* avc2; - RDPGFX_H264_METABLOCK* meta2; + gdiGfxSurface* surface = NULL; + RDPGFX_AVC444_BITMAP_STREAM* bs = NULL; + RDPGFX_AVC420_BITMAP_STREAM* avc1 = NULL; + RDPGFX_H264_METABLOCK* meta1 = NULL; + RDPGFX_AVC420_BITMAP_STREAM* avc2 = NULL; + RDPGFX_H264_METABLOCK* meta2 = NULL; WINPR_ASSERT(gdi); WINPR_ASSERT(context); WINPR_ASSERT(cmd); - surface = (gdiGfxSurface*)context->GetSurfaceData(context, cmd->surfaceId); + surface = + (gdiGfxSurface*)context->GetSurfaceData(context, (UINT16)MIN(UINT16_MAX, cmd->surfaceId)); if (!surface) { @@ -738,28 +750,24 @@ fail: static BOOL gdi_apply_alpha(BYTE* data, UINT32 format, UINT32 stride, RECTANGLE_16* rect, UINT32 startOffsetX, UINT32 count, BYTE a) { - UINT32 y; UINT32 written = 0; BOOL first = TRUE; const UINT32 bpp = FreeRDPGetBytesPerPixel(format); WINPR_ASSERT(rect); - for (y = rect->top; y < rect->bottom; y++) + for (UINT32 y = rect->top; y < rect->bottom; y++) { - UINT32 x; BYTE* line = &data[stride * y]; - for (x = first ? rect->left + startOffsetX : rect->left; x < rect->right; x++) + for (UINT32 x = first ? rect->left + startOffsetX : rect->left; x < rect->right; x++) { - UINT32 color; - BYTE r, g, b; - BYTE* src; + BYTE r = 0, g = 0, b = 0; if (written == count) return TRUE; - src = &line[x * bpp]; - color = FreeRDPReadColor(src, format); + BYTE* src = &line[x * bpp]; + UINT32 color = FreeRDPReadColor(src, format); FreeRDPSplitColor(color, format, &r, &g, &b, NULL, NULL); color = FreeRDPGetColor(format, r, g, b, a); FreeRDPWriteColor(src, format, color); @@ -794,7 +802,8 @@ static UINT gdi_SurfaceCommand_Alpha(rdpGdi* gdi, RdpgfxClientContext* context, if (!Stream_CheckAndLogRequiredLength(TAG, s, 4)) return ERROR_INVALID_DATA; - surface = (gdiGfxSurface*)context->GetSurfaceData(context, cmd->surfaceId); + surface = + (gdiGfxSurface*)context->GetSurfaceData(context, (UINT16)MIN(UINT16_MAX, cmd->surfaceId)); if (!surface) { @@ -814,16 +823,14 @@ static UINT gdi_SurfaceCommand_Alpha(rdpGdi* gdi, RdpgfxClientContext* context, if (compressed == 0) { - UINT32 x, y; - if (!Stream_CheckAndLogRequiredLength(TAG, s, cmd->height * cmd->width * 1ULL)) return ERROR_INVALID_DATA; - for (y = cmd->top; y < cmd->top + cmd->height; y++) + for (UINT32 y = cmd->top; y < cmd->top + cmd->height; y++) { BYTE* line = &surface->data[surface->scanline * y]; - for (x = cmd->left; x < cmd->left + cmd->width; x++) + for (UINT32 x = cmd->left; x < cmd->left + cmd->width; x++) { UINT32 color; BYTE r, g, b, a; @@ -839,11 +846,11 @@ static UINT gdi_SurfaceCommand_Alpha(rdpGdi* gdi, RdpgfxClientContext* context, else { UINT32 startOffsetX = 0; - RECTANGLE_16 rect; - rect.left = cmd->left; - rect.top = cmd->top; - rect.right = cmd->left + cmd->width; - rect.bottom = cmd->top + cmd->height; + RECTANGLE_16 rect = { 0 }; + rect.left = (UINT16)MIN(UINT16_MAX, cmd->left); + rect.top = (UINT16)MIN(UINT16_MAX, cmd->top); + rect.right = (UINT16)MIN(UINT16_MAX, cmd->left + cmd->width); + rect.bottom = (UINT16)MIN(UINT16_MAX, cmd->top + cmd->height); while (rect.top < rect.bottom) { @@ -886,10 +893,10 @@ static UINT gdi_SurfaceCommand_Alpha(rdpGdi* gdi, RdpgfxClientContext* context, } } - invalidRect.left = cmd->left; - invalidRect.top = cmd->top; - invalidRect.right = cmd->right; - invalidRect.bottom = cmd->bottom; + invalidRect.left = (UINT16)MIN(UINT16_MAX, cmd->left); + invalidRect.top = (UINT16)MIN(UINT16_MAX, cmd->top); + invalidRect.right = (UINT16)MIN(UINT16_MAX, cmd->right); + invalidRect.bottom = (UINT16)MIN(UINT16_MAX, cmd->bottom); region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion), &invalidRect); status = IFCALLRESULT(CHANNEL_RC_OK, context->UpdateSurfaceArea, context, surface->surfaceId, 1, &invalidRect); @@ -929,7 +936,8 @@ static UINT gdi_SurfaceCommand_Progressive(rdpGdi* gdi, RdpgfxClientContext* con WINPR_ASSERT(gdi); WINPR_ASSERT(context); WINPR_ASSERT(cmd); - surface = (gdiGfxSurface*)context->GetSurfaceData(context, cmd->surfaceId); + const UINT16 surfaceId = (UINT16)MIN(UINT16_MAX, cmd->surfaceId); + surface = (gdiGfxSurface*)context->GetSurfaceData(context, surfaceId); if (!surface) { @@ -942,8 +950,8 @@ static UINT gdi_SurfaceCommand_Progressive(rdpGdi* gdi, RdpgfxClientContext* con return ERROR_INVALID_DATA; WINPR_ASSERT(surface->codecs); - rc = progressive_create_surface_context(surface->codecs->progressive, cmd->surfaceId, - surface->width, surface->height); + rc = progressive_create_surface_context(surface->codecs->progressive, surfaceId, surface->width, + surface->height); if (rc < 0) { @@ -955,7 +963,7 @@ static UINT gdi_SurfaceCommand_Progressive(rdpGdi* gdi, RdpgfxClientContext* con rc = progressive_decompress(surface->codecs->progressive, cmd->data, cmd->length, surface->data, surface->format, surface->scanline, cmd->left, cmd->top, - &invalidRegion, cmd->surfaceId, gdi->frameId); + &invalidRegion, surfaceId, gdi->frameId); if (rc < 0) { @@ -1068,6 +1076,10 @@ static UINT gdi_DeleteEncodingContext(RdpgfxClientContext* context, const RDPGFX_DELETE_ENCODING_CONTEXT_PDU* deleteEncodingContext) { + WINPR_ASSERT(context); + WINPR_ASSERT(deleteEncodingContext); + WINPR_UNUSED(context); + WINPR_UNUSED(deleteEncodingContext); return CHANNEL_RC_OK; } @@ -1138,7 +1150,6 @@ static UINT gdi_CreateSurface(RdpgfxClientContext* context, } memset(surface->data, 0xFF, (size_t)surface->scanline * surface->height); - surface->outputMapped = FALSE; region16_init(&surface->invalidRegion); rc = context->SetSurfaceData(context, surface->surfaceId, (void*)surface); fail: @@ -1163,7 +1174,7 @@ static UINT gdi_DeleteSurface(RdpgfxClientContext* context, if (surface) { - if (surface->windowId != 0) + if (surface->windowMapped) rc = IFCALLRESULT(CHANNEL_RC_OK, context->UnmapWindowForSurface, context, surface->windowId); @@ -1295,7 +1306,9 @@ static UINT gdi_SurfaceToSurface(RdpgfxClientContext* context, for (index = 0; index < surfaceToSurface->destPtsCount; index++) { const RDPGFX_POINT16* destPt = &surfaceToSurface->destPts[index]; - const RECTANGLE_16 rect = { destPt->x, destPt->y, destPt->x + nWidth, destPt->y + nHeight }; + const RECTANGLE_16 rect = { destPt->x, destPt->y, + (UINT16)MIN(UINT16_MAX, destPt->x + nWidth), + (UINT16)MIN(UINT16_MAX, destPt->y + nHeight) }; if (!is_rect_valid(&rect, surfaceDst->width, surfaceDst->height)) goto fail; @@ -1408,8 +1421,9 @@ static UINT gdi_CacheToSurface(RdpgfxClientContext* context, for (index = 0; index < cacheToSurface->destPtsCount; index++) { const RDPGFX_POINT16* destPt = &cacheToSurface->destPts[index]; - const RECTANGLE_16 rect = { destPt->x, destPt->y, destPt->x + cacheEntry->width, - destPt->y + cacheEntry->height }; + const RECTANGLE_16 rect = { destPt->x, destPt->y, + (UINT16)MIN(UINT16_MAX, destPt->x + cacheEntry->width), + (UINT16)MIN(UINT16_MAX, destPt->y + cacheEntry->height) }; if (rectangle_is_empty(&rect)) continue; @@ -1551,8 +1565,8 @@ static UINT gdi_ExportCacheEntry(RdpgfxClientContext* context, UINT16 cacheSlot, if (cacheEntry) { exportCacheEntry->key64 = cacheEntry->cacheKey; - exportCacheEntry->width = cacheEntry->width; - exportCacheEntry->height = cacheEntry->height; + exportCacheEntry->width = (UINT16)MIN(UINT16_MAX, cacheEntry->width); + exportCacheEntry->height = (UINT16)MIN(UINT16_MAX, cacheEntry->height); exportCacheEntry->size = cacheEntry->width * cacheEntry->height * 4; exportCacheEntry->flags = 0; exportCacheEntry->data = cacheEntry->data; @@ -1595,13 +1609,16 @@ static UINT gdi_MapSurfaceToOutput(RdpgfxClientContext* context, const RDPGFX_MAP_SURFACE_TO_OUTPUT_PDU* surfaceToOutput) { UINT rc = ERROR_INTERNAL_ERROR; - gdiGfxSurface* surface; + gdiGfxSurface* surface = NULL; EnterCriticalSection(&context->mux); surface = (gdiGfxSurface*)context->GetSurfaceData(context, surfaceToOutput->surfaceId); if (!surface) goto fail; + if (surface->windowMapped) + goto fail; + surface->outputMapped = TRUE; surface->outputOriginX = surfaceToOutput->outputOriginX; surface->outputOriginY = surfaceToOutput->outputOriginY; @@ -1619,13 +1636,15 @@ gdi_MapSurfaceToScaledOutput(RdpgfxClientContext* context, const RDPGFX_MAP_SURFACE_TO_SCALED_OUTPUT_PDU* surfaceToOutput) { UINT rc = ERROR_INTERNAL_ERROR; - gdiGfxSurface* surface; + gdiGfxSurface* surface = NULL; EnterCriticalSection(&context->mux); surface = (gdiGfxSurface*)context->GetSurfaceData(context, surfaceToOutput->surfaceId); if (!surface) goto fail; + if (surface->windowMapped) + goto fail; surface->outputMapped = TRUE; surface->outputOriginX = surfaceToOutput->outputOriginX; surface->outputOriginY = surfaceToOutput->outputOriginY; @@ -1654,11 +1673,15 @@ static UINT gdi_MapSurfaceToWindow(RdpgfxClientContext* context, if (!surface) goto fail; - if (surface->windowId != 0) + if (surface->outputMapped) + goto fail; + + if (surface->windowMapped) { if (surface->windowId != surfaceToWindow->windowId) goto fail; } + surface->windowMapped = TRUE; surface->windowId = surfaceToWindow->windowId; surface->mappedWidth = surfaceToWindow->mappedWidth; @@ -1684,11 +1707,15 @@ gdi_MapSurfaceToScaledWindow(RdpgfxClientContext* context, if (!surface) goto fail; - if (surface->windowId != 0) + if (surface->outputMapped) + goto fail; + + if (surface->windowMapped) { if (surface->windowId != surfaceToWindow->windowId) goto fail; } + surface->windowMapped = TRUE; surface->windowId = surfaceToWindow->windowId; surface->mappedWidth = surfaceToWindow->mappedWidth;