diff --git a/channels/rdpsnd/client/rdpsnd_main.c b/channels/rdpsnd/client/rdpsnd_main.c index 33ac176ea..2afd56430 100644 --- a/channels/rdpsnd/client/rdpsnd_main.c +++ b/channels/rdpsnd/client/rdpsnd_main.c @@ -1197,7 +1197,7 @@ static void rdpsnd_virtual_channel_event_terminated(rdpsndPlugin* rdpsnd) { if (rdpsnd) { - audio_format_free(rdpsnd->fixed_format); + audio_formats_free(rdpsnd->fixed_format, 1); free(rdpsnd->subsystem); free(rdpsnd->device_name); CloseHandle(rdpsnd->stopEvent); diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c index a27adb425..4cf405fc4 100644 --- a/client/X11/xf_client.c +++ b/client/X11/xf_client.c @@ -1108,9 +1108,9 @@ static BOOL xf_pre_connect(freerdp* instance) settings->OrderSupport[NEG_MEMBLT_V2_INDEX] = settings->BitmapCacheEnabled; settings->OrderSupport[NEG_MEM3BLT_V2_INDEX] = settings->BitmapCacheEnabled; settings->OrderSupport[NEG_SAVEBITMAP_INDEX] = FALSE; - settings->OrderSupport[NEG_GLYPH_INDEX_INDEX] = TRUE; - settings->OrderSupport[NEG_FAST_INDEX_INDEX] = TRUE; - settings->OrderSupport[NEG_FAST_GLYPH_INDEX] = TRUE; + settings->OrderSupport[NEG_GLYPH_INDEX_INDEX] = settings->GlyphSupportLevel != GLYPH_SUPPORT_NONE; + settings->OrderSupport[NEG_FAST_INDEX_INDEX] = settings->GlyphSupportLevel != GLYPH_SUPPORT_NONE; + settings->OrderSupport[NEG_FAST_GLYPH_INDEX] = settings->GlyphSupportLevel != GLYPH_SUPPORT_NONE; settings->OrderSupport[NEG_POLYGON_SC_INDEX] = FALSE; settings->OrderSupport[NEG_POLYGON_CB_INDEX] = FALSE; settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE; diff --git a/client/common/cmdline.c b/client/common/cmdline.c index 932860697..c3c0bc17f 100644 --- a/client/common/cmdline.c +++ b/client/common/cmdline.c @@ -1756,6 +1756,10 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, { settings->ConsoleSession = enable; } + CommandLineSwitchCase(arg, "relax-order-checks") + { + settings->AllowUnanouncedOrdersFromServer = arg->Value; + } CommandLineSwitchCase(arg, "restricted-admin") { settings->ConsoleSession = enable; diff --git a/client/common/cmdline.h b/client/common/cmdline.h index 6072d5051..e2f700c77 100644 --- a/client/common/cmdline.h +++ b/client/common/cmdline.h @@ -142,6 +142,7 @@ static COMMAND_LINE_ARGUMENT_A args[] = { "pwidth", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Physical width of display (in millimeters)" }, { "reconnect-cookie", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Pass base64 reconnect cookie to the connection" }, { "redirect-prefer", COMMAND_LINE_VALUE_REQUIRED, "[,[,]]", NULL, NULL, -1, NULL, "Override the preferred redirection order" }, + { "relax-order-checks", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, "relax-order-checks", "Do not check if a RDP order was announced during capability exchange, only use when connecting to a buggy server" }, { "restricted-admin", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, "restrictedAdmin", "Restricted admin mode" }, { "rfx", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "RemoteFX" }, { "rfx-mode", COMMAND_LINE_VALUE_REQUIRED, "image|video", NULL, NULL, -1, NULL, "RemoteFX mode" }, diff --git a/include/freerdp/primary.h b/include/freerdp/primary.h index 3ed07a776..a1f810fdb 100644 --- a/include/freerdp/primary.h +++ b/include/freerdp/primary.h @@ -212,7 +212,7 @@ struct _MULTI_DRAW_NINE_GRID_ORDER UINT32 bitmapId; UINT32 nDeltaEntries; UINT32 cbData; - BYTE* codeDeltaList; + DELTA_RECT rectangles[45]; }; typedef struct _MULTI_DRAW_NINE_GRID_ORDER MULTI_DRAW_NINE_GRID_ORDER; diff --git a/include/freerdp/settings.h b/include/freerdp/settings.h index 41aa7ec3e..058b43209 100644 --- a/include/freerdp/settings.h +++ b/include/freerdp/settings.h @@ -165,15 +165,15 @@ #define NEG_MEMBLT_INDEX 0x03 #define NEG_MEM3BLT_INDEX 0x04 #define NEG_ATEXTOUT_INDEX 0x05 -#define NEG_AEXTTEXTOUT_INDEX 0x06 -#define NEG_DRAWNINEGRID_INDEX 0x07 +#define NEG_AEXTTEXTOUT_INDEX 0x06 /* Must be ignored */ +#define NEG_DRAWNINEGRID_INDEX 0x07 /* Must be ignored */ #define NEG_LINETO_INDEX 0x08 #define NEG_MULTI_DRAWNINEGRID_INDEX 0x09 -#define NEG_OPAQUE_RECT_INDEX 0x0A +#define NEG_OPAQUE_RECT_INDEX 0x0A /* Must be ignored */ #define NEG_SAVEBITMAP_INDEX 0x0B -#define NEG_WTEXTOUT_INDEX 0x0C -#define NEG_MEMBLT_V2_INDEX 0x0D -#define NEG_MEM3BLT_V2_INDEX 0x0E +#define NEG_WTEXTOUT_INDEX 0x0C /* Must be ignored */ +#define NEG_MEMBLT_V2_INDEX 0x0D /* Must be ignored */ +#define NEG_MEM3BLT_V2_INDEX 0x0E /* Must be ignored */ #define NEG_MULTIDSTBLT_INDEX 0x0F #define NEG_MULTIPATBLT_INDEX 0x10 #define NEG_MULTISCRBLT_INDEX 0x11 @@ -182,15 +182,15 @@ #define NEG_POLYGON_SC_INDEX 0x14 #define NEG_POLYGON_CB_INDEX 0x15 #define NEG_POLYLINE_INDEX 0x16 -#define NEG_UNUSED23_INDEX 0x17 +#define NEG_UNUSED23_INDEX 0x17 /* Must be ignored */ #define NEG_FAST_GLYPH_INDEX 0x18 #define NEG_ELLIPSE_SC_INDEX 0x19 #define NEG_ELLIPSE_CB_INDEX 0x1A #define NEG_GLYPH_INDEX_INDEX 0x1B -#define NEG_GLYPH_WEXTTEXTOUT_INDEX 0x1C -#define NEG_GLYPH_WLONGTEXTOUT_INDEX 0x1D -#define NEG_GLYPH_WLONGEXTTEXTOUT_INDEX 0x1E -#define NEG_UNUSED31_INDEX 0x1F +#define NEG_GLYPH_WEXTTEXTOUT_INDEX 0x1C /* Must be ignored */ +#define NEG_GLYPH_WLONGTEXTOUT_INDEX 0x1D /* Must be ignored */ +#define NEG_GLYPH_WLONGEXTTEXTOUT_INDEX 0x1E /* Must be ignored */ +#define NEG_UNUSED31_INDEX 0x1F /* Must be ignored */ /* Glyph Support Level */ #define GLYPH_SUPPORT_NONE 0x0000 @@ -1265,7 +1265,8 @@ struct rdp_settings ALIGN64 BYTE* OrderSupport; /* 2432 */ ALIGN64 BOOL BitmapCacheV3Enabled; /* 2433 */ ALIGN64 BOOL AltSecFrameMarkerSupport; /* 2434 */ - UINT64 padding2497[2497 - 2435]; /* 2435 */ + ALIGN64 BOOL AllowUnanouncedOrdersFromServer; /* 2435 */ + UINT64 padding2497[2497 - 2436]; /* 2436 */ /* Bitmap Cache Capabilities */ ALIGN64 BOOL BitmapCacheEnabled; /* 2497 */ diff --git a/libfreerdp/codec/color.c b/libfreerdp/codec/color.c index 15d8d2ff8..ed006464c 100644 --- a/libfreerdp/codec/color.c +++ b/libfreerdp/codec/color.c @@ -87,6 +87,9 @@ BOOL freerdp_image_copy_from_monochrome(BYTE* pDstData, UINT32 DstFormat, UINT32 monoStep; const UINT32 dstBytesPerPixel = GetBytesPerPixel(DstFormat); + if (!pDstData || !pSrcData || !palette) + return FALSE; + if (nDstStep == 0) nDstStep = dstBytesPerPixel * nWidth; @@ -203,7 +206,7 @@ BOOL freerdp_image_copy_from_pointer_data( const BYTE* andBits; const BYTE* xorBits; BYTE* pDstPixel = &pDstData[((nYDst + y) * nDstStep) + - (nXDst * GetBytesPerPixel(DstFormat))]; + (nXDst * GetBytesPerPixel(DstFormat))]; xorBit = andBit = 0x80; if (!vFlip) @@ -281,7 +284,7 @@ BOOL freerdp_image_copy_from_pointer_data( const BYTE* xorBits; const BYTE* andBits = NULL; BYTE* pDstPixel = &pDstData[((nYDst + y) * nDstStep) + - (nXDst * GetBytesPerPixel(DstFormat))]; + (nXDst * GetBytesPerPixel(DstFormat))]; andBit = 0x80; if (!vFlip) @@ -326,9 +329,9 @@ BOOL freerdp_image_copy_from_pointer_data( } xorPixel = FreeRDPConvertColor(xorPixel, - pixelFormat, - PIXEL_FORMAT_ARGB32, - palette); + pixelFormat, + PIXEL_FORMAT_ARGB32, + palette); xorBits += xorBytesPerPixel; andPixel = 0; @@ -352,7 +355,7 @@ BOOL freerdp_image_copy_from_pointer_data( } color = FreeRDPConvertColor(xorPixel, PIXEL_FORMAT_ARGB32, - DstFormat, palette); + DstFormat, palette); WriteColor(pDstPixel, DstFormat, color); pDstPixel += GetBytesPerPixel(DstFormat); } @@ -435,11 +438,11 @@ BOOL freerdp_image_copy(BYTE* pDstData, DWORD DstFormat, for (y = 0; y < nHeight; y++) { const BYTE* srcLine = &pSrcData[(y + nYSrc) * - nSrcStep * srcVMultiplier + - srcVOffset]; + nSrcStep * srcVMultiplier + + srcVOffset]; BYTE* dstLine = &pDstData[(y + nYDst) * - nDstStep * dstVMultiplier + - dstVOffset]; + nDstStep * dstVMultiplier + + dstVOffset]; memcpy(&dstLine[xDstOffset], &srcLine[xSrcOffset], copyDstWidth); } @@ -450,11 +453,11 @@ BOOL freerdp_image_copy(BYTE* pDstData, DWORD DstFormat, for (y = nHeight - 1; y >= 0; y--) { const BYTE* srcLine = &pSrcData[(y + nYSrc) * - nSrcStep * srcVMultiplier + - srcVOffset]; + nSrcStep * srcVMultiplier + + srcVOffset]; BYTE* dstLine = &pDstData[(y + nYDst) * - nDstStep * dstVMultiplier + - dstVOffset]; + nDstStep * dstVMultiplier + + dstVOffset]; memcpy(&dstLine[xDstOffset], &srcLine[xSrcOffset], copyDstWidth); } @@ -465,11 +468,11 @@ BOOL freerdp_image_copy(BYTE* pDstData, DWORD DstFormat, for (y = 0; y < nHeight; y++) { const BYTE* srcLine = &pSrcData[(y + nYSrc) * - nSrcStep * srcVMultiplier + - srcVOffset]; + nSrcStep * srcVMultiplier + + srcVOffset]; BYTE* dstLine = &pDstData[(y + nYDst) * - nDstStep * dstVMultiplier + - dstVOffset]; + nDstStep * dstVMultiplier + + dstVOffset]; memmove(&dstLine[xDstOffset], &srcLine[xSrcOffset], copyDstWidth); } @@ -480,11 +483,11 @@ BOOL freerdp_image_copy(BYTE* pDstData, DWORD DstFormat, for (y = nHeight - 1; y >= 0; y--) { const BYTE* srcLine = &pSrcData[(y + nYSrc) * - nSrcStep * srcVMultiplier + - srcVOffset]; + nSrcStep * srcVMultiplier + + srcVOffset]; BYTE* dstLine = &pDstData[(y + nYDst) * - nDstStep * dstVMultiplier + - dstVOffset]; + nDstStep * dstVMultiplier + + dstVOffset]; memmove(&dstLine[xDstOffset], &srcLine[xSrcOffset], copyDstWidth); } @@ -499,11 +502,11 @@ BOOL freerdp_image_copy(BYTE* pDstData, DWORD DstFormat, for (y = 0; y < nHeight; y++) { const BYTE* srcLine = &pSrcData[(y + nYSrc) * - nSrcStep * srcVMultiplier + - srcVOffset]; + nSrcStep * srcVMultiplier + + srcVOffset]; BYTE* dstLine = &pDstData[(y + nYDst) * - nDstStep * dstVMultiplier + - dstVOffset]; + nDstStep * dstVMultiplier + + dstVOffset]; memcpy(&dstLine[xDstOffset], &srcLine[xSrcOffset], copyDstWidth); } @@ -516,10 +519,10 @@ BOOL freerdp_image_copy(BYTE* pDstData, DWORD DstFormat, for (y = 0; y < nHeight; y++) { const BYTE* srcLine = &pSrcData[(y + nYSrc) * - nSrcStep * srcVMultiplier + - srcVOffset]; + nSrcStep * srcVMultiplier + + srcVOffset]; BYTE* dstLine = &pDstData[(y + nYDst) * - nDstStep * dstVMultiplier + dstVOffset]; + nDstStep * dstVMultiplier + dstVOffset]; for (x = 0; x < nWidth; x++) { diff --git a/libfreerdp/codec/include/bitmap.c b/libfreerdp/codec/include/bitmap.c index d9a50b113..a594a1bd4 100644 --- a/libfreerdp/codec/include/bitmap.c +++ b/libfreerdp/codec/include/bitmap.c @@ -292,7 +292,7 @@ static INLINE BYTE* WRITEFIRSTLINEFGBGIMAGE(BYTE* pbDest, BYTE bitmask, /** * Decompress an RLE compressed bitmap. */ -static INLINE void RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, +static INLINE BOOL RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, BYTE* pbDestBuffer, UINT32 rowDelta, UINT32 width, UINT32 height) { @@ -310,6 +310,9 @@ static INLINE void RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, UINT32 advance; RLEEXTRA + if (!pbSrcBuffer || !pbDestBuffer) + return FALSE; + while (pbSrc < pbEnd) { /* Watch out for the end of the first scanline. */ @@ -628,6 +631,11 @@ static INLINE void RLEDECOMPRESS(const BYTE* pbSrcBuffer, UINT32 cbSrcBuffer, DESTWRITEPIXEL(pbDest, BLACK_PIXEL); DESTNEXTPIXEL(pbDest); break; + + default: + return FALSE; } } + + return TRUE; } diff --git a/libfreerdp/codec/interleaved.c b/libfreerdp/codec/interleaved.c index 943ca007b..44bdde794 100644 --- a/libfreerdp/codec/interleaved.c +++ b/libfreerdp/codec/interleaved.c @@ -276,7 +276,7 @@ BOOL interleaved_decompress(BITMAP_INTERLEAVED_CONTEXT* interleaved, UINT32 SrcFormat; UINT32 BufferSize; - if (!interleaved) + if (!interleaved || !pSrcData || !pDstData) return FALSE; switch (bpp) @@ -322,19 +322,25 @@ BOOL interleaved_decompress(BITMAP_INTERLEAVED_CONTEXT* interleaved, switch (bpp) { case 24: - RleDecompress24to24(pSrcData, SrcSize, interleaved->TempBuffer, - scanline, nSrcWidth, nSrcHeight); + if (!RleDecompress24to24(pSrcData, SrcSize, interleaved->TempBuffer, + scanline, nSrcWidth, nSrcHeight)) + return FALSE; + break; case 16: case 15: - RleDecompress16to16(pSrcData, SrcSize, interleaved->TempBuffer, - scanline, nSrcWidth, nSrcHeight); + if (!RleDecompress16to16(pSrcData, SrcSize, interleaved->TempBuffer, + scanline, nSrcWidth, nSrcHeight)) + return FALSE; + break; case 8: - RleDecompress8to8(pSrcData, SrcSize, interleaved->TempBuffer, - scanline, nSrcWidth, nSrcHeight); + if (!RleDecompress8to8(pSrcData, SrcSize, interleaved->TempBuffer, + scanline, nSrcWidth, nSrcHeight)) + return FALSE; + break; default: diff --git a/libfreerdp/core/capabilities.c b/libfreerdp/core/capabilities.c index 32e04cc7b..36b8a4753 100644 --- a/libfreerdp/core/capabilities.c +++ b/libfreerdp/core/capabilities.c @@ -1453,7 +1453,7 @@ static BOOL rdp_write_brush_capability_set(wStream* s, rdpSettings* settings) return FALSE; header = rdp_capability_set_start(s); - Stream_Write_UINT32(s, BRUSH_COLOR_FULL); /* brushSupportLevel (4 bytes) */ + Stream_Write_UINT32(s, settings->BrushSupportLevel); /* brushSupportLevel (4 bytes) */ rdp_capability_set_finish(s, header, CAPSET_TYPE_BRUSH); return TRUE; } diff --git a/libfreerdp/core/fastpath.c b/libfreerdp/core/fastpath.c index c3506063c..b09a18fea 100644 --- a/libfreerdp/core/fastpath.c +++ b/libfreerdp/core/fastpath.c @@ -265,15 +265,24 @@ static BOOL fastpath_recv_orders(rdpFastPath* fastpath, wStream* s) UINT16 numberOrders; if (!fastpath || !fastpath->rdp || !s) + { + WLog_ERR(TAG, "Invalid arguments"); return FALSE; + } update = fastpath->rdp->update; if (!update) + { + WLog_ERR(TAG, "Invalid configuration"); return FALSE; + } if (Stream_GetRemainingLength(s) < 2) + { + WLog_ERR(TAG, "Stream short"); return FALSE; + } Stream_Read_UINT16(s, numberOrders); /* numberOrders (2 bytes) */ diff --git a/libfreerdp/core/orders.c b/libfreerdp/core/orders.c index 5d75b6463..ad9b331f5 100644 --- a/libfreerdp/core/orders.c +++ b/libfreerdp/core/orders.c @@ -25,6 +25,7 @@ #include "window.h" +#include #include #include @@ -42,70 +43,6 @@ #define TAG FREERDP_TAG("core.orders") -static const char* const PRIMARY_DRAWING_ORDER_STRINGS[] = -{ - "DstBlt", - "PatBlt", - "ScrBlt", - "", "", "", "", - "DrawNineGrid", - "MultiDrawNineGrid", - "LineTo", - "OpaqueRect", - "SaveBitmap", - "", - "MemBlt", - "Mem3Blt", - "MultiDstBlt", - "MultiPatBlt", - "MultiScrBlt", - "MultiOpaqueRect", - "FastIndex", - "PolygonSC", - "PolygonCB", - "Polyline", - "", - "FastGlyph", - "EllipseSC", - "EllipseCB", - "GlyphIndex" -}; - -static const char* const SECONDARY_DRAWING_ORDER_STRINGS[] = -{ - "Cache Bitmap", - "Cache Color Table", - "Cache Bitmap (Compressed)", - "Cache Glyph", - "Cache Bitmap V2", - "Cache Bitmap V2 (Compressed)", - "", - "Cache Brush", - "Cache Bitmap V3" -}; - -#define SECONDARY_DRAWING_ORDER_COUNT (ARRAYSIZE(SECONDARY_DRAWING_ORDER_STRINGS)) - -static const char* const ALTSEC_DRAWING_ORDER_STRINGS[] = -{ - "Switch Surface", - "Create Offscreen Bitmap", - "Stream Bitmap First", - "Stream Bitmap Next", - "Create NineGrid Bitmap", - "Draw GDI+ First", - "Draw GDI+ Next", - "Draw GDI+ End", - "Draw GDI+ Cache First", - "Draw GDI+ Cache Next", - "Draw GDI+ Cache End", - "Windowing", - "Desktop Composition", - "Frame Marker" -}; - -#define ALTSEC_DRAWING_ORDER_COUNT (ARRAYSIZE(ALTSEC_DRAWING_ORDER_STRINGS)) - const BYTE PRIMARY_DRAWING_ORDER_FIELD_BYTES[] = { DSTBLT_ORDER_FIELD_BYTES, @@ -179,14 +116,560 @@ static const BYTE BPP_BMF[] = 6, 0, 0, 0, 0, 0, 0, 0 }; -static const char* update_secondary_order_to_string(BYTE order) +static BOOL check_order_activated(wLog* log, rdpSettings* settings, const char* orderName, + BOOL condition) { - if (order >= ARRAYSIZE(SECONDARY_DRAWING_ORDER_STRINGS)) - return "UNKNOWN"; + if (!condition) + { + if (settings->AllowUnanouncedOrdersFromServer) + { + WLog_Print(log, WLOG_WARN, + "%s - SERVER BUG: The support for this feature was not announced!", orderName); + return TRUE; + } + else + { + WLog_Print(log, WLOG_ERROR, + "%s - SERVER BUG: The support for this feature was not announced! Use /relax-order-checks to ignore", + orderName); + return FALSE; + } + } - return SECONDARY_DRAWING_ORDER_STRINGS[order]; + return TRUE; } +static BOOL check_alt_order_supported(wLog* log, rdpSettings* settings, BYTE orderType, + const char* orderName) +{ + BOOL condition = FALSE; + + switch (orderType) + { + case ORDER_TYPE_CREATE_OFFSCREEN_BITMAP: + case ORDER_TYPE_SWITCH_SURFACE: + condition = settings->OffscreenSupportLevel != 0; + break; + + case ORDER_TYPE_CREATE_NINE_GRID_BITMAP: + condition = settings->DrawNineGridEnabled; + break; + + case ORDER_TYPE_FRAME_MARKER: + condition = settings->FrameMarkerCommandEnabled; + break; + + case ORDER_TYPE_GDIPLUS_FIRST: + case ORDER_TYPE_GDIPLUS_NEXT: + case ORDER_TYPE_GDIPLUS_END: + case ORDER_TYPE_GDIPLUS_CACHE_FIRST: + case ORDER_TYPE_GDIPLUS_CACHE_NEXT: + case ORDER_TYPE_GDIPLUS_CACHE_END: + condition = settings->DrawGdiPlusCacheEnabled; + break; + + case ORDER_TYPE_STREAM_BITMAP_FIRST: + case ORDER_TYPE_STREAM_BITMAP_NEXT: + case ORDER_TYPE_WINDOW: + case ORDER_TYPE_COMPDESK_FIRST: + condition = TRUE; + break; + + default: + WLog_Print(log, WLOG_WARN, + "%s - Alternate Secondary Drawing Order UNKNOWN", orderName); + condition = FALSE; + break; + } + + return check_order_activated(log, settings, orderName, condition); +} + +static BOOL check_secondary_order_supported(wLog* log, rdpSettings* settings, BYTE orderType, + const char* orderName) +{ + BOOL condition = FALSE; + + switch (orderType) + { + case ORDER_TYPE_BITMAP_UNCOMPRESSED: + case ORDER_TYPE_CACHE_BITMAP_COMPRESSED: + condition = settings->BitmapCacheEnabled; + break; + + case ORDER_TYPE_BITMAP_UNCOMPRESSED_V2: + case ORDER_TYPE_BITMAP_COMPRESSED_V2: + condition = settings->BitmapCacheEnabled; + break; + + case ORDER_TYPE_BITMAP_COMPRESSED_V3: + condition = settings->BitmapCacheV3Enabled; + break; + + case ORDER_TYPE_CACHE_COLOR_TABLE: + condition = (settings->OrderSupport[NEG_MEMBLT_INDEX] || settings->OrderSupport[NEG_MEM3BLT_INDEX]); + break; + + case ORDER_TYPE_CACHE_GLYPH: + { + switch (settings->GlyphSupportLevel) + { + case GLYPH_SUPPORT_PARTIAL: + case GLYPH_SUPPORT_FULL: + case GLYPH_SUPPORT_ENCODE: + condition = TRUE; + break; + + case GLYPH_SUPPORT_NONE: + default: + condition = FALSE; + break; + } + } + break; + + case ORDER_TYPE_CACHE_BRUSH: + condition = TRUE; + break; + + default: + WLog_Print(log, WLOG_WARN, "SECONDARY ORDER %s not supported", orderName); + break; + } + + return check_order_activated(log, settings, orderName, condition); +} + +static BOOL check_primary_order_supported(wLog* log, rdpSettings* settings, UINT32 orderType, + const char* orderName) +{ + BOOL condition = FALSE; + + switch (orderType) + { + case ORDER_TYPE_DSTBLT: + condition = settings->OrderSupport[NEG_DSTBLT_INDEX]; + break; + + case ORDER_TYPE_SCRBLT: + condition = settings->OrderSupport[NEG_SCRBLT_INDEX]; + break; + + case ORDER_TYPE_DRAW_NINE_GRID: + condition = settings->OrderSupport[NEG_DRAWNINEGRID_INDEX]; + break; + + case ORDER_TYPE_MULTI_DRAW_NINE_GRID: + condition = settings->OrderSupport[NEG_MULTI_DRAWNINEGRID_INDEX]; + break; + + case ORDER_TYPE_LINE_TO: + condition = settings->OrderSupport[NEG_LINETO_INDEX]; + break; + + /* [MS-RDPEGDI] 2.2.2.2.1.1.2.5 OpaqueRect (OPAQUERECT_ORDER) + * suggests that PatBlt and OpaqueRect imply each other. */ + case ORDER_TYPE_PATBLT: + case ORDER_TYPE_OPAQUE_RECT: + condition = settings->OrderSupport[NEG_OPAQUE_RECT_INDEX] || + settings->OrderSupport[NEG_PATBLT_INDEX]; + break; + + case ORDER_TYPE_SAVE_BITMAP: + condition = settings->OrderSupport[NEG_SAVEBITMAP_INDEX]; + break; + + case ORDER_TYPE_MEMBLT: + condition = settings->OrderSupport[NEG_MEMBLT_INDEX]; + break; + + case ORDER_TYPE_MEM3BLT: + condition = settings->OrderSupport[NEG_MEM3BLT_INDEX]; + break; + + case ORDER_TYPE_MULTI_DSTBLT: + condition = settings->OrderSupport[NEG_MULTIDSTBLT_INDEX]; + break; + + case ORDER_TYPE_MULTI_PATBLT: + condition = settings->OrderSupport[NEG_MULTIPATBLT_INDEX]; + break; + + case ORDER_TYPE_MULTI_SCRBLT: + condition = settings->OrderSupport[NEG_MULTIDSTBLT_INDEX]; + break; + + case ORDER_TYPE_MULTI_OPAQUE_RECT: + condition = settings->OrderSupport[NEG_MULTIOPAQUERECT_INDEX]; + break; + + case ORDER_TYPE_FAST_INDEX: + condition = settings->OrderSupport[NEG_FAST_INDEX_INDEX]; + break; + + case ORDER_TYPE_POLYGON_SC: + condition = settings->OrderSupport[NEG_POLYGON_SC_INDEX]; + break; + + case ORDER_TYPE_POLYGON_CB: + condition = settings->OrderSupport[NEG_POLYGON_CB_INDEX]; + break; + + case ORDER_TYPE_POLYLINE: + condition = settings->OrderSupport[NEG_POLYLINE_INDEX]; + break; + + case ORDER_TYPE_FAST_GLYPH: + condition = settings->OrderSupport[NEG_FAST_GLYPH_INDEX]; + break; + + case ORDER_TYPE_ELLIPSE_SC: + condition = settings->OrderSupport[NEG_ELLIPSE_SC_INDEX]; + break; + + case ORDER_TYPE_ELLIPSE_CB: + condition = settings->OrderSupport[NEG_ELLIPSE_CB_INDEX]; + break; + + case ORDER_TYPE_GLYPH_INDEX: + condition = settings->OrderSupport[NEG_GLYPH_INDEX_INDEX]; + break; + + default: + WLog_Print(log, WLOG_WARN, "%s Primary Drawing Order not supported", orderName); + break; + } + + return check_order_activated(log, settings, orderName, condition); +} + +static const char* primary_order_string(UINT32 orderType) +{ + const char* orders[] = + { + "[0x%02"PRIu8"] DstBlt", + "[0x%02"PRIu8"] PatBlt", + "[0x%02"PRIu8"] ScrBlt", + "[0x%02"PRIu8"] UNUSED", + "[0x%02"PRIu8"] UNUSED", + "[0x%02"PRIu8"] UNUSED", + "[0x%02"PRIu8"] UNUSED", + "[0x%02"PRIu8"] DrawNineGrid", + "[0x%02"PRIu8"] MultiDrawNineGrid", + "[0x%02"PRIu8"] LineTo", + "[0x%02"PRIu8"] OpaqueRect", + "[0x%02"PRIu8"] SaveBitmap", + "[0x%02"PRIu8"] UNUSED", + "[0x%02"PRIu8"] MemBlt", + "[0x%02"PRIu8"] Mem3Blt", + "[0x%02"PRIu8"] MultiDstBlt", + "[0x%02"PRIu8"] MultiPatBlt", + "[0x%02"PRIu8"] MultiScrBlt", + "[0x%02"PRIu8"] MultiOpaqueRect", + "[0x%02"PRIu8"] FastIndex", + "[0x%02"PRIu8"] PolygonSC", + "[0x%02"PRIu8"] PolygonCB", + "[0x%02"PRIu8"] Polyline", + "[0x%02"PRIu8"] UNUSED", + "[0x%02"PRIu8"] FastGlyph", + "[0x%02"PRIu8"] EllipseSC", + "[0x%02"PRIu8"] EllipseCB", + "[0x%02"PRIu8"] GlyphIndex" + }; + const char* fmt = "[0x%02"PRIu8"] UNKNOWN"; + static char buffer[64] = {0}; + + if (orderType < ARRAYSIZE(orders)) + fmt = orders[orderType]; + + sprintf_s(buffer, ARRAYSIZE(buffer), fmt, orderType); + return buffer; +} +static const char* secondary_order_string(UINT32 orderType) +{ + const char* orders[] = + { + "[0x%02"PRIu8"] Cache Bitmap", + "[0x%02"PRIu8"] Cache Color Table", + "[0x%02"PRIu8"] Cache Bitmap (Compressed)", + "[0x%02"PRIu8"] Cache Glyph", + "[0x%02"PRIu8"] Cache Bitmap V2", + "[0x%02"PRIu8"] Cache Bitmap V2 (Compressed)", + "[0x%02"PRIu8"] UNUSED", + "[0x%02"PRIu8"] Cache Brush", + "[0x%02"PRIu8"] Cache Bitmap V3" + }; + const char* fmt = "[0x%02"PRIu8"] UNKNOWN"; + static char buffer[64] = {0}; + + if (orderType < ARRAYSIZE(orders)) + fmt = orders[orderType]; + + sprintf_s(buffer, ARRAYSIZE(buffer), fmt, orderType); + return buffer; +} +static const char* altsec_order_string(BYTE orderType) +{ + const char* orders[] = + { + "[0x%02"PRIu8"] Switch Surface", + "[0x%02"PRIu8"] Create Offscreen Bitmap", + "[0x%02"PRIu8"] Stream Bitmap First", + "[0x%02"PRIu8"] Stream Bitmap Next", + "[0x%02"PRIu8"] Create NineGrid Bitmap", + "[0x%02"PRIu8"] Draw GDI+ First", + "[0x%02"PRIu8"] Draw GDI+ Next", + "[0x%02"PRIu8"] Draw GDI+ End", + "[0x%02"PRIu8"] Draw GDI+ Cache First", + "[0x%02"PRIu8"] Draw GDI+ Cache Next", + "[0x%02"PRIu8"] Draw GDI+ Cache End", + "[0x%02"PRIu8"] Windowing", + "[0x%02"PRIu8"] Desktop Composition", + "[0x%02"PRIu8"] Frame Marker" + }; + const char* fmt = "[0x%02"PRIu8"] UNKNOWN"; + static char buffer[64] = {0}; + + if (orderType < ARRAYSIZE(orders)) + fmt = orders[orderType]; + + sprintf_s(buffer, ARRAYSIZE(buffer), fmt, orderType); + return buffer; +} +static BOOL freerdp_primary_adjust_bound(wLog* log, const char* order, rdpContext* context, + INT32* pLeft, INT32* pTop, + INT32* pRight, + INT32* pBottom) +{ + UINT32 dw, dh; + INT32 left = *pLeft; + INT32 top = *pTop; + INT32 right = *pRight; + INT32 bottom = *pBottom; + + if (!context || !context->settings) + return FALSE; + + dw = context->settings->DesktopWidth; + dh = context->settings->DesktopHeight; + + if (left < 0) + left = 0; + + if (top < 0) + top = 0; + + if (right < 0) + right = 0; + + if (bottom < 0) + bottom = 0; + + if (right > dw) + right = dw; + + if (left > right) + left = right; + + if (top > dh) + top = dh; + + if (bottom > dh) + bottom = dh; + + if (top > bottom) + top = bottom; + + if (*pLeft != left) + WLog_Print(log, WLOG_WARN, "[%s] Adjusted left from %"PRId32" to %"PRId32, order, *pLeft, left); + + if (*pTop != top) + WLog_Print(log, WLOG_WARN, "[%s] Adjusted top from %"PRId32" to %"PRId32, order, *pTop, top); + + if (*pRight != right) + WLog_Print(log, WLOG_WARN, "[%s] Adjusted right from %"PRId32" to %"PRId32, order, *pRight, right); + + if (*pBottom != bottom) + WLog_Print(log, WLOG_WARN, "[%s] Adjusted bottom from %"PRId32" to %"PRId32, order, *pBottom, + bottom); + + *pLeft = left; + *pTop = top; + *pRight = right; + *pBottom = bottom; + return TRUE; +} +static BOOL freerdp_primary_adjust_bounds(wLog* log, const char* order, rdpContext* context, + rdpBounds* bounds) +{ + if (!context || !context->settings || !bounds) + return FALSE; + + return freerdp_primary_adjust_bound(log, order, context, &bounds->left, &bounds->top, + &bounds->right, + &bounds->bottom); +} +static BOOL freerdp_primary_adjust_rect(wLog* log, const char* order, rdpContext* context, + INT32* pLeft, INT32* pTop, + INT32* pWidth, + INT32* pHeight) +{ + UINT32 dw, dh; + INT32 left = *pLeft; + INT32 top = *pTop; + INT32 width = *pWidth; + INT32 height = *pHeight; + + if (!context || !context->settings) + return FALSE; + + dw = context->settings->DesktopWidth; + dh = context->settings->DesktopHeight; + + if (left < 0) + left = 0; + + if (top < 0) + top = 0; + + if (width < 0) + width = 0; + + if (height < 0) + height = 0; + + if (left > dw) + left = dw; + + if (left + width > dw) + width = dw - left; + + if (top > dh) + top = dh; + + if (top + height > dh) + height = dh - top; + + if (*pLeft != left) + WLog_Print(log, WLOG_WARN, "[%s] Adjusted left from %"PRId32" to %"PRId32, order, *pLeft, left); + + if (*pTop != top) + WLog_Print(log, WLOG_WARN, "[%s] Adjusted top from %"PRId32" to %"PRId32, order, *pTop, top); + + if (*pWidth != width) + WLog_Print(log, WLOG_WARN, "[%s] Adjusted width from %"PRId32" to %"PRId32, order, *pWidth, width); + + if (*pHeight != height) + WLog_Print(log, WLOG_WARN, "[%s] Adjusted height from %"PRId32" to %"PRId32, order, *pHeight, + height); + + *pLeft = left; + *pTop = top; + *pWidth = width; + *pHeight = height; + return TRUE; +} +static BOOL freerdp_adjust_point(wLog* log, const char* order, rdpContext* context, INT32* pX, + INT32* pY) +{ + UINT32 dw, dh; + INT32 x = *pX; + INT32 y = *pY; + + if (!context || !context->settings) + return FALSE; + + dw = context->settings->DesktopWidth; + dh = context->settings->DesktopHeight; + + if (x < 0) + x = 0; + + if (y < 0) + y = 0; + + if (x > dw) + x = dw; + + if (y > dh) + y = dh; + + if (x != *pX) + WLog_Print(log, WLOG_WARN, "[%s] adjusted x from %"PRId32" to %"PRId32, order, *pX, x); + + if (y != *pY) + WLog_Print(log, WLOG_WARN, "[%s] adjusted y from %"PRId32" to %"PRId32, order, *pY, y); + + *pX = x; + *pY = y; + return TRUE; +} +static BOOL adjust_point(rdpContext* context, INT32* px, INT32* py) +{ + INT32 x, y; + UINT32 dw, dh; + + if (!context || !context->settings || !px || !py) + return FALSE; + + x = *px; + y = *py; + dw = context->settings->DesktopWidth; + dh = context->settings->DesktopHeight; + + if (x < 0) + x = 0; + + if (y < 0) + y = 0; + + if (x > dw) + x = dw; + + if (y > dh) + y = dh; + + *px = x; + *py = y; + return TRUE;; +} +static BOOL freerdp_adjust_delta_rect(wLog* log, const char* order, rdpContext* context, + UINT32 count, DELTA_RECT* data) +{ + UINT32 i; + + if (!context || !data) + goto fail; + + if (count > 45) + goto fail; + + for (i = 0; i < count; i++) + { + DELTA_RECT* delta = &data[i]; + + if (!freerdp_primary_adjust_rect(log, order, context, &delta->left, &delta->top, &delta->width, + &delta->height)) + goto fail; + } + + return TRUE; +fail: + WLog_ERR(TAG, "invalid delta rectangles"); + return FALSE; +} +static BOOL freerdp_check_glyph_op_bound(wLog* log, const char* order, rdpContext* context, + INT32 left, INT32 top, INT32 right, + INT32 bottom) +{ + if (right == -32768) + right = left; + + if (bottom == -32768) + bottom = top; + + return freerdp_primary_adjust_bound(log, order, context, &left, &top, &right, &bottom); +} static INLINE BOOL update_read_coord(wStream* s, INT32* coord, BOOL delta) { INT8 lsi8; @@ -211,13 +694,11 @@ static INLINE BOOL update_read_coord(wStream* s, INT32* coord, BOOL delta) return TRUE; } - static INLINE BOOL update_write_coord(wStream* s, INT32 coord) { Stream_Write_UINT16(s, coord); return TRUE; } - static INLINE BOOL update_read_color(wStream* s, UINT32* color) { BYTE byte; @@ -234,7 +715,6 @@ static INLINE BOOL update_read_color(wStream* s, UINT32* color) *color |= ((UINT32) byte << 16) & 0xFF0000; return TRUE; } - static INLINE BOOL update_write_color(wStream* s, UINT32 color) { BYTE byte; @@ -246,7 +726,6 @@ static INLINE BOOL update_write_color(wStream* s, UINT32 color) Stream_Write_UINT8(s, byte); return TRUE; } - static INLINE BOOL update_read_colorref(wStream* s, UINT32* color) { BYTE byte; @@ -264,12 +743,10 @@ static INLINE BOOL update_read_colorref(wStream* s, UINT32* color) Stream_Seek_UINT8(s); return TRUE; } - static INLINE BOOL update_read_color_quad(wStream* s, UINT32* color) { return update_read_colorref(s, color); } - static INLINE void update_write_color_quad(wStream* s, UINT32 color) { BYTE byte; @@ -280,7 +757,6 @@ static INLINE void update_write_color_quad(wStream* s, UINT32 color) byte = color & 0xFF; Stream_Write_UINT8(s, byte); } - static INLINE BOOL update_read_2byte_unsigned(wStream* s, UINT32* value) { BYTE byte; @@ -306,7 +782,6 @@ static INLINE BOOL update_read_2byte_unsigned(wStream* s, UINT32* value) return TRUE; } - static INLINE BOOL update_write_2byte_unsigned(wStream* s, UINT32 value) { BYTE byte; @@ -329,7 +804,6 @@ static INLINE BOOL update_write_2byte_unsigned(wStream* s, UINT32 value) return TRUE; } - static INLINE BOOL update_read_2byte_signed(wStream* s, INT32* value) { BYTE byte; @@ -356,7 +830,6 @@ static INLINE BOOL update_read_2byte_signed(wStream* s, INT32* value) return TRUE; } - static INLINE BOOL update_write_2byte_signed(wStream* s, INT32 value) { BYTE byte; @@ -394,7 +867,6 @@ static INLINE BOOL update_write_2byte_signed(wStream* s, INT32 value) return TRUE; } - static INLINE BOOL update_read_4byte_unsigned(wStream* s, UINT32* value) { BYTE byte; @@ -445,7 +917,6 @@ static INLINE BOOL update_read_4byte_unsigned(wStream* s, UINT32* value) return TRUE; } - static INLINE BOOL update_write_4byte_unsigned(wStream* s, UINT32 value) { BYTE byte; @@ -486,7 +957,6 @@ static INLINE BOOL update_write_4byte_unsigned(wStream* s, UINT32 value) return TRUE; } - static INLINE BOOL update_read_delta(wStream* s, INT32* value) { BYTE byte; @@ -518,7 +988,6 @@ static INLINE BOOL update_read_delta(wStream* s, INT32* value) return TRUE; } - #if 0 static INLINE void update_read_glyph_delta(wStream* s, UINT16* value) { @@ -530,7 +999,6 @@ static INLINE void update_read_glyph_delta(wStream* s, UINT16* value) else *value = (byte & 0x3F); } - static INLINE void update_seek_glyph_delta(wStream* s) { BYTE byte; @@ -540,7 +1008,6 @@ static INLINE void update_seek_glyph_delta(wStream* s) Stream_Seek_UINT8(s); } #endif - static INLINE BOOL update_read_brush(wStream* s, rdpBrush* brush, BYTE fieldFlags) { @@ -603,7 +1070,6 @@ static INLINE BOOL update_read_brush(wStream* s, rdpBrush* brush, return TRUE; } - static INLINE BOOL update_write_brush(wStream* s, rdpBrush* brush, BYTE fieldFlags) { @@ -651,7 +1117,6 @@ static INLINE BOOL update_write_brush(wStream* s, rdpBrush* brush, return TRUE; } - static INLINE BOOL update_read_delta_rects(wStream* s, DELTA_RECT* rectangles, UINT32 number) { @@ -714,7 +1179,6 @@ static INLINE BOOL update_read_delta_rects(wStream* s, DELTA_RECT* rectangles, return TRUE; } - static INLINE BOOL update_read_delta_points(wStream* s, DELTA_POINT* points, int number, INT16 x, INT16 y) { @@ -756,8 +1220,6 @@ static INLINE BOOL update_read_delta_points(wStream* s, DELTA_POINT* points, return TRUE; } - - #define ORDER_FIELD_BYTE(NO, TARGET) \ do {\ if (orderInfo->fieldFlags & (1 << (NO-1))) \ @@ -769,7 +1231,6 @@ static INLINE BOOL update_read_delta_points(wStream* s, DELTA_POINT* points, Stream_Read_UINT8(s, TARGET); \ } \ } while(0) - #define ORDER_FIELD_2BYTE(NO, TARGET1, TARGET2) \ do {\ if (orderInfo->fieldFlags & (1 << (NO-1))) \ @@ -782,7 +1243,6 @@ static INLINE BOOL update_read_delta_points(wStream* s, DELTA_POINT* points, Stream_Read_UINT8(s, TARGET2); \ } \ } while(0) - #define ORDER_FIELD_UINT16(NO, TARGET) \ do {\ if (orderInfo->fieldFlags & (1 << (NO-1))) \ @@ -805,7 +1265,6 @@ static INLINE BOOL update_read_delta_points(wStream* s, DELTA_POINT* points, Stream_Read_UINT32(s, TARGET); \ } \ } while(0) - #define ORDER_FIELD_COORD(NO, TARGET) \ do { \ if ((orderInfo->fieldFlags & (1 << (NO-1))) && !update_read_coord(s, &TARGET, orderInfo->deltaCoordinates)) { \ @@ -813,7 +1272,6 @@ static INLINE BOOL update_read_delta_points(wStream* s, DELTA_POINT* points, return FALSE; \ } \ } while(0) - static INLINE BOOL ORDER_FIELD_COLOR(const ORDER_INFO* orderInfo, wStream* s, UINT32 NO, UINT32* TARGET) { @@ -825,7 +1283,6 @@ static INLINE BOOL ORDER_FIELD_COLOR(const ORDER_INFO* orderInfo, wStream* s, return TRUE; } - static INLINE BOOL FIELD_SKIP_BUFFER16(wStream* s, UINT32 TARGET_LEN) { if (Stream_GetRemainingLength(s) < 2) @@ -841,9 +1298,8 @@ static INLINE BOOL FIELD_SKIP_BUFFER16(wStream* s, UINT32 TARGET_LEN) return TRUE; } - /* Primary Drawing Orders */ -static BOOL update_read_dstblt_order(wStream* s, ORDER_INFO* orderInfo, +static BOOL update_read_dstblt_order(wStream* s, const ORDER_INFO* orderInfo, DSTBLT_ORDER* dstblt) { ORDER_FIELD_COORD(1, dstblt->nLeftRect); @@ -878,7 +1334,7 @@ BOOL update_write_dstblt_order(wStream* s, ORDER_INFO* orderInfo, Stream_Write_UINT8(s, dstblt->bRop); return TRUE; } -static BOOL update_read_patblt_order(wStream* s, ORDER_INFO* orderInfo, +static BOOL update_read_patblt_order(wStream* s, const ORDER_INFO* orderInfo, PATBLT_ORDER* patblt) { ORDER_FIELD_COORD(1, patblt->nLeftRect); @@ -925,7 +1381,7 @@ BOOL update_write_patblt_order(wStream* s, ORDER_INFO* orderInfo, update_write_brush(s, &patblt->brush, orderInfo->fieldFlags >> 7); return TRUE; } -static BOOL update_read_scrblt_order(wStream* s, ORDER_INFO* orderInfo, +static BOOL update_read_scrblt_order(wStream* s, const ORDER_INFO* orderInfo, SCRBLT_ORDER* scrblt) { ORDER_FIELD_COORD(1, scrblt->nLeftRect); @@ -966,7 +1422,7 @@ BOOL update_write_scrblt_order(wStream* s, ORDER_INFO* orderInfo, update_write_coord(s, scrblt->nYSrc); return TRUE; } -static BOOL update_read_opaque_rect_order(wStream* s, ORDER_INFO* orderInfo, +static BOOL update_read_opaque_rect_order(wStream* s, const ORDER_INFO* orderInfo, OPAQUE_RECT_ORDER* opaque_rect) { BYTE byte; @@ -1040,7 +1496,7 @@ BOOL update_write_opaque_rect_order(wStream* s, ORDER_INFO* orderInfo, return TRUE; } static BOOL update_read_draw_nine_grid_order(wStream* s, - ORDER_INFO* orderInfo, + const ORDER_INFO* orderInfo, DRAW_NINE_GRID_ORDER* draw_nine_grid) { ORDER_FIELD_COORD(1, draw_nine_grid->srcLeft); @@ -1050,7 +1506,7 @@ static BOOL update_read_draw_nine_grid_order(wStream* s, ORDER_FIELD_UINT16(5, draw_nine_grid->bitmapId); return TRUE; } -static BOOL update_read_multi_dstblt_order(wStream* s, ORDER_INFO* orderInfo, +static BOOL update_read_multi_dstblt_order(wStream* s, const ORDER_INFO* orderInfo, MULTI_DSTBLT_ORDER* multi_dstblt) { ORDER_FIELD_COORD(1, multi_dstblt->nLeftRect); @@ -1072,7 +1528,7 @@ static BOOL update_read_multi_dstblt_order(wStream* s, ORDER_INFO* orderInfo, return TRUE; } -static BOOL update_read_multi_patblt_order(wStream* s, ORDER_INFO* orderInfo, +static BOOL update_read_multi_patblt_order(wStream* s, const ORDER_INFO* orderInfo, MULTI_PATBLT_ORDER* multi_patblt) { ORDER_FIELD_COORD(1, multi_patblt->nLeftRect); @@ -1102,7 +1558,7 @@ static BOOL update_read_multi_patblt_order(wStream* s, ORDER_INFO* orderInfo, return TRUE; } -static BOOL update_read_multi_scrblt_order(wStream* s, ORDER_INFO* orderInfo, +static BOOL update_read_multi_scrblt_order(wStream* s, const ORDER_INFO* orderInfo, MULTI_SCRBLT_ORDER* multi_scrblt) { ORDER_FIELD_COORD(1, multi_scrblt->nLeftRect); @@ -1127,7 +1583,7 @@ static BOOL update_read_multi_scrblt_order(wStream* s, ORDER_INFO* orderInfo, return TRUE; } static BOOL update_read_multi_opaque_rect_order(wStream* s, - ORDER_INFO* orderInfo, + const ORDER_INFO* orderInfo, MULTI_OPAQUE_RECT_ORDER* multi_opaque_rect) { BYTE byte; @@ -1181,7 +1637,7 @@ static BOOL update_read_multi_opaque_rect_order(wStream* s, return TRUE; } static BOOL update_read_multi_draw_nine_grid_order(wStream* s, - ORDER_INFO* orderInfo, + const ORDER_INFO* orderInfo, MULTI_DRAW_NINE_GRID_ORDER* multi_draw_nine_grid) { ORDER_FIELD_COORD(1, multi_draw_nine_grid->srcLeft); @@ -1193,12 +1649,17 @@ static BOOL update_read_multi_draw_nine_grid_order(wStream* s, if (orderInfo->fieldFlags & ORDER_FIELD_07) { - FIELD_SKIP_BUFFER16(s, multi_draw_nine_grid->cbData); + if (Stream_GetRemainingLength(s) < 2) + return FALSE; + + Stream_Read_UINT16(s, multi_draw_nine_grid->cbData); + return update_read_delta_rects(s, multi_draw_nine_grid->rectangles, + multi_draw_nine_grid->nDeltaEntries); } return TRUE; } -static BOOL update_read_line_to_order(wStream* s, ORDER_INFO* orderInfo, +static BOOL update_read_line_to_order(wStream* s, const ORDER_INFO* orderInfo, LINE_TO_ORDER* line_to) { ORDER_FIELD_UINT16(1, line_to->backMode); @@ -1248,7 +1709,7 @@ BOOL update_write_line_to_order(wStream* s, ORDER_INFO* orderInfo, update_write_color(s, line_to->penColor); return TRUE; } -static BOOL update_read_polyline_order(wStream* s, ORDER_INFO* orderInfo, +static BOOL update_read_polyline_order(wStream* s, const ORDER_INFO* orderInfo, POLYLINE_ORDER* polyline) { UINT16 word; @@ -1288,7 +1749,7 @@ static BOOL update_read_polyline_order(wStream* s, ORDER_INFO* orderInfo, return TRUE; } -static BOOL update_read_memblt_order(wStream* s, ORDER_INFO* orderInfo, +static BOOL update_read_memblt_order(wStream* s, const ORDER_INFO* orderInfo, MEMBLT_ORDER* memblt) { if (!s || !orderInfo || !memblt) @@ -1343,7 +1804,7 @@ BOOL update_write_memblt_order(wStream* s, ORDER_INFO* orderInfo, Stream_Write_UINT16(s, memblt->cacheIndex); return TRUE; } -static BOOL update_read_mem3blt_order(wStream* s, ORDER_INFO* orderInfo, +static BOOL update_read_mem3blt_order(wStream* s, const ORDER_INFO* orderInfo, MEM3BLT_ORDER* mem3blt) { ORDER_FIELD_UINT16(1, mem3blt->cacheId); @@ -1366,7 +1827,7 @@ static BOOL update_read_mem3blt_order(wStream* s, ORDER_INFO* orderInfo, mem3blt->bitmap = NULL; return TRUE; } -static BOOL update_read_save_bitmap_order(wStream* s, ORDER_INFO* orderInfo, +static BOOL update_read_save_bitmap_order(wStream* s, const ORDER_INFO* orderInfo, SAVE_BITMAP_ORDER* save_bitmap) { ORDER_FIELD_UINT32(1, save_bitmap->savedBitmapPosition); @@ -1377,7 +1838,7 @@ static BOOL update_read_save_bitmap_order(wStream* s, ORDER_INFO* orderInfo, ORDER_FIELD_BYTE(6, save_bitmap->operation); return TRUE; } -static BOOL update_read_glyph_index_order(wStream* s, ORDER_INFO* orderInfo, +static BOOL update_read_glyph_index_order(wStream* s, const ORDER_INFO* orderInfo, GLYPH_INDEX_ORDER* glyph_index) { ORDER_FIELD_BYTE(1, glyph_index->cacheId); @@ -1474,7 +1935,7 @@ BOOL update_write_glyph_index_order(wStream* s, ORDER_INFO* orderInfo, Stream_Write(s, glyph_index->data, glyph_index->cbData); return TRUE; } -static BOOL update_read_fast_index_order(wStream* s, ORDER_INFO* orderInfo, +static BOOL update_read_fast_index_order(wStream* s, const ORDER_INFO* orderInfo, FAST_INDEX_ORDER* fast_index) { ORDER_FIELD_BYTE(1, fast_index->cacheId); @@ -1508,7 +1969,7 @@ static BOOL update_read_fast_index_order(wStream* s, ORDER_INFO* orderInfo, return TRUE; } -static BOOL update_read_fast_glyph_order(wStream* s, ORDER_INFO* orderInfo, +static BOOL update_read_fast_glyph_order(wStream* s, const ORDER_INFO* orderInfo, FAST_GLYPH_ORDER* fastGlyph) { BYTE* phold; @@ -1583,7 +2044,7 @@ static BOOL update_read_fast_glyph_order(wStream* s, ORDER_INFO* orderInfo, return TRUE; } -static BOOL update_read_polygon_sc_order(wStream* s, ORDER_INFO* orderInfo, +static BOOL update_read_polygon_sc_order(wStream* s, const ORDER_INFO* orderInfo, POLYGON_SC_ORDER* polygon_sc) { UINT32 num = polygon_sc->numPoints; @@ -1616,7 +2077,7 @@ static BOOL update_read_polygon_sc_order(wStream* s, ORDER_INFO* orderInfo, return TRUE; } -static BOOL update_read_polygon_cb_order(wStream* s, ORDER_INFO* orderInfo, +static BOOL update_read_polygon_cb_order(wStream* s, const ORDER_INFO* orderInfo, POLYGON_CB_ORDER* polygon_cb) { UINT32 num = polygon_cb->numPoints; @@ -1659,7 +2120,7 @@ static BOOL update_read_polygon_cb_order(wStream* s, ORDER_INFO* orderInfo, polygon_cb->bRop2 = (polygon_cb->bRop2 & 0x1F); return TRUE; } -static BOOL update_read_ellipse_sc_order(wStream* s, ORDER_INFO* orderInfo, +static BOOL update_read_ellipse_sc_order(wStream* s, const ORDER_INFO* orderInfo, ELLIPSE_SC_ORDER* ellipse_sc) { ORDER_FIELD_COORD(1, ellipse_sc->leftRect); @@ -1671,7 +2132,7 @@ static BOOL update_read_ellipse_sc_order(wStream* s, ORDER_INFO* orderInfo, ORDER_FIELD_COLOR(orderInfo, s, 7, &ellipse_sc->color); return TRUE; } -static BOOL update_read_ellipse_cb_order(wStream* s, ORDER_INFO* orderInfo, +static BOOL update_read_ellipse_cb_order(wStream* s, const ORDER_INFO* orderInfo, ELLIPSE_CB_ORDER* ellipse_cb) { ORDER_FIELD_COORD(1, ellipse_cb->leftRect); @@ -1709,7 +2170,7 @@ static CACHE_BITMAP_ORDER* update_read_cache_bitmap_order(rdpUpdate* update, wSt if ((cache_bitmap->bitmapBpp < 1) || (cache_bitmap->bitmapBpp > 32)) { - WLog_ERR(TAG, "invalid bitmap bpp %"PRIu32"", cache_bitmap->bitmapBpp); + WLog_Print(update->log, WLOG_ERROR, "invalid bitmap bpp %"PRIu32"", cache_bitmap->bitmapBpp); goto fail; } @@ -1992,7 +2453,7 @@ static CACHE_BITMAP_V3_ORDER* update_read_cache_bitmap_v3_order(rdpUpdate* updat if ((bitmapData->bpp < 1) || (bitmapData->bpp > 32)) { - WLog_ERR(TAG, "invalid bpp value %"PRIu32"", bitmapData->bpp); + WLog_Print(update->log, WLOG_ERROR, "invalid bpp value %"PRIu32"", bitmapData->bpp); goto fail; } @@ -2019,7 +2480,6 @@ fail: free_cache_bitmap_v3_order(update->context, cache_bitmap_v3); return NULL; } - int update_approximate_cache_bitmap_v3_order(CACHE_BITMAP_V3_ORDER* cache_bitmap_v3, UINT16* flags) { @@ -2090,7 +2550,6 @@ fail: free_cache_color_table_order(update->context, cache_color_table); return NULL; } - int update_approximate_cache_color_table_order( const CACHE_COLOR_TABLE_ORDER* cache_color_table, UINT16* flags) { @@ -2123,7 +2582,8 @@ BOOL update_write_cache_color_table_order(wStream* s, return TRUE; } -static CACHE_GLYPH_ORDER* update_read_cache_glyph_order(rdpUpdate* update, wStream* s, UINT16 flags) +static CACHE_GLYPH_ORDER* update_read_cache_glyph_order(rdpUpdate* update, wStream* s, + UINT16 flags) { UINT32 i; CACHE_GLYPH_ORDER* cache_glyph_order = calloc(1, sizeof(CACHE_GLYPH_ORDER)); @@ -2181,7 +2641,6 @@ fail: free_cache_glyph_order(update->context, cache_glyph_order); return NULL; } - int update_approximate_cache_glyph_order( const CACHE_GLYPH_ORDER* cache_glyph, UINT16* flags) { @@ -2287,13 +2746,11 @@ fail: free_cache_glyph_v2_order(update->context, cache_glyph_v2); return NULL; } - int update_approximate_cache_glyph_v2_order( const CACHE_GLYPH_V2_ORDER* cache_glyph_v2, UINT16* flags) { return 8 + cache_glyph_v2->cGlyphs * 32; } - BOOL update_write_cache_glyph_v2_order(wStream* s, const CACHE_GLYPH_V2_ORDER* cache_glyph_v2, UINT16* flags) @@ -2370,7 +2827,8 @@ static BOOL update_compress_brush(wStream* s, const BYTE* input, BYTE bpp) { return FALSE; } -static CACHE_BRUSH_ORDER* update_read_cache_brush_order(rdpUpdate* update, wStream* s, UINT16 flags) +static CACHE_BRUSH_ORDER* update_read_cache_brush_order(rdpUpdate* update, wStream* s, + UINT16 flags) { int i; BYTE iBitmapFormat; @@ -2385,6 +2843,10 @@ static CACHE_BRUSH_ORDER* update_read_cache_brush_order(rdpUpdate* update, wStre Stream_Read_UINT8(s, cache_brush->index); /* cacheEntry (1 byte) */ Stream_Read_UINT8(s, iBitmapFormat); /* iBitmapFormat (1 byte) */ + + if (iBitmapFormat > ARRAYSIZE(BMF_BPP)) + goto fail; + cache_brush->bpp = BMF_BPP[iBitmapFormat]; Stream_Read_UINT8(s, cache_brush->cx); /* cx (1 byte) */ Stream_Read_UINT8(s, cache_brush->cy); /* cy (1 byte) */ @@ -2397,7 +2859,8 @@ static CACHE_BRUSH_ORDER* update_read_cache_brush_order(rdpUpdate* update, wStre { if (cache_brush->length != 8) { - WLog_ERR(TAG, "incompatible 1bpp brush of length:%"PRIu32"", cache_brush->length); + WLog_Print(update->log, WLOG_ERROR, "incompatible 1bpp brush of length:%"PRIu32"", + cache_brush->length); goto fail; } @@ -2536,7 +2999,7 @@ static BOOL update_read_create_offscreen_bitmap_order(wStream* s, if (deleteListPresent) { - int i; + UINT32 i; if (Stream_GetRemainingLength(s) < 2) return FALSE; @@ -2558,7 +3021,7 @@ static BOOL update_read_create_offscreen_bitmap_order(wStream* s, if (Stream_GetRemainingLength(s) < 2 * deleteList->cIndices) return FALSE; - for (i = 0; i < (int) deleteList->cIndices; i++) + for (i = 0; i < deleteList->cIndices; i++) { Stream_Read_UINT16(s, deleteList->indices[i]); } @@ -2991,26 +3454,151 @@ BOOL update_write_bounds(wStream* s, ORDER_INFO* orderInfo) return TRUE; } -static BOOL update_recv_primary_order(rdpUpdate* update, wStream* s, BYTE flags) + +static BOOL read_primary_order(wLog* log, const char* orderName, wStream* s, + const ORDER_INFO* orderInfo, rdpPrimaryUpdate* primary) { - ORDER_INFO* orderInfo; - rdpContext* context = update->context; - rdpPrimaryUpdate* primary = update->primary; - orderInfo = &(primary->order_info); + BOOL rc = FALSE; - if (flags & ORDER_TYPE_CHANGE) - Stream_Read_UINT8(s, orderInfo->orderType); /* orderType (1 byte) */ + if (!s || !orderInfo || !primary || !orderName) + return FALSE; - if (orderInfo->orderType >= PRIMARY_DRAWING_ORDER_COUNT) + switch (orderInfo->orderType) { - WLog_ERR(TAG, "Invalid Primary Drawing Order (0x%08"PRIX32")", orderInfo->orderType); + case ORDER_TYPE_DSTBLT: + rc = update_read_dstblt_order(s, orderInfo, &(primary->dstblt)); + break; + + case ORDER_TYPE_PATBLT: + rc = update_read_patblt_order(s, orderInfo, &(primary->patblt)); + break; + + case ORDER_TYPE_SCRBLT: + rc = update_read_scrblt_order(s, orderInfo, &(primary->scrblt)); + break; + + case ORDER_TYPE_OPAQUE_RECT: + rc = update_read_opaque_rect_order(s, orderInfo, &(primary->opaque_rect)); + break; + + case ORDER_TYPE_DRAW_NINE_GRID: + rc = update_read_draw_nine_grid_order(s, orderInfo, &(primary->draw_nine_grid)); + break; + + case ORDER_TYPE_MULTI_DSTBLT: + rc = update_read_multi_dstblt_order(s, orderInfo, &(primary->multi_dstblt)); + break; + + case ORDER_TYPE_MULTI_PATBLT: + rc = update_read_multi_patblt_order(s, orderInfo, &(primary->multi_patblt)); + break; + + case ORDER_TYPE_MULTI_SCRBLT: + rc = update_read_multi_scrblt_order(s, orderInfo, &(primary->multi_scrblt)); + break; + + case ORDER_TYPE_MULTI_OPAQUE_RECT: + rc = update_read_multi_opaque_rect_order(s, orderInfo, + &(primary->multi_opaque_rect)); + break; + + case ORDER_TYPE_MULTI_DRAW_NINE_GRID: + rc = update_read_multi_draw_nine_grid_order(s, orderInfo, + &(primary->multi_draw_nine_grid)); + break; + + case ORDER_TYPE_LINE_TO: + rc = update_read_line_to_order(s, orderInfo, &(primary->line_to)); + break; + + case ORDER_TYPE_POLYLINE: + rc = update_read_polyline_order(s, orderInfo, &(primary->polyline)); + break; + + case ORDER_TYPE_MEMBLT: + rc = update_read_memblt_order(s, orderInfo, &(primary->memblt)); + break; + + case ORDER_TYPE_MEM3BLT: + rc = update_read_mem3blt_order(s, orderInfo, &(primary->mem3blt)); + break; + + case ORDER_TYPE_SAVE_BITMAP: + rc = update_read_save_bitmap_order(s, orderInfo, &(primary->save_bitmap)); + break; + + case ORDER_TYPE_GLYPH_INDEX: + rc = update_read_glyph_index_order(s, orderInfo, &(primary->glyph_index)); + break; + + case ORDER_TYPE_FAST_INDEX: + rc = update_read_fast_index_order(s, orderInfo, &(primary->fast_index)); + break; + + case ORDER_TYPE_FAST_GLYPH: + rc = update_read_fast_glyph_order(s, orderInfo, &(primary->fast_glyph)); + break; + + case ORDER_TYPE_POLYGON_SC: + rc = update_read_polygon_sc_order(s, orderInfo, &(primary->polygon_sc)); + break; + + case ORDER_TYPE_POLYGON_CB: + rc = update_read_polygon_cb_order(s, orderInfo, &(primary->polygon_cb)); + break; + + case ORDER_TYPE_ELLIPSE_SC: + rc = update_read_ellipse_sc_order(s, orderInfo, &(primary->ellipse_sc)); + break; + + case ORDER_TYPE_ELLIPSE_CB: + rc = update_read_ellipse_cb_order(s, orderInfo, &(primary->ellipse_cb)); + break; + + default: + WLog_Print(log, WLOG_WARN, "Primary Drawing Order %s not supported, ignoring", orderName); + rc = TRUE; + break; + } + + if (!rc) + { + WLog_Print(log, WLOG_ERROR, "%s - update_read_dstblt_order() failed", orderName); return FALSE; } + return TRUE; +} + +static BOOL update_recv_primary_order(rdpUpdate* update, wStream* s, BYTE flags) +{ + BOOL rc = FALSE; + rdpContext* context = update->context; + rdpPrimaryUpdate* primary = update->primary; + ORDER_INFO* orderInfo = &(primary->order_info); + rdpSettings* settings = context->settings; + const char* orderName; + + if (flags & ORDER_TYPE_CHANGE) + { + if (Stream_GetRemainingLength(s) < 1) + { + WLog_Print(update->log, WLOG_ERROR, "Stream_GetRemainingLength(s) < 1"); + return FALSE; + } + + Stream_Read_UINT8(s, orderInfo->orderType); /* orderType (1 byte) */ + } + + orderName = primary_order_string(orderInfo->orderType); + + if (!check_primary_order_supported(update->log, settings, orderInfo->orderType, orderName)) + return FALSE; + if (!update_read_field_flags(s, &(orderInfo->fieldFlags), flags, PRIMARY_DRAWING_ORDER_FIELD_BYTES[orderInfo->orderType])) { - WLog_ERR(TAG, "update_read_field_flags() failed"); + WLog_Print(update->log, WLOG_ERROR, "update_read_field_flags() failed"); return FALSE; } @@ -3020,320 +3608,404 @@ static BOOL update_recv_primary_order(rdpUpdate* update, wStream* s, BYTE flags) { if (!update_read_bounds(s, &orderInfo->bounds)) { - WLog_ERR(TAG, "update_read_bounds() failed"); + WLog_Print(update->log, WLOG_ERROR, "update_read_bounds() failed"); return FALSE; } } - IFCALL(update->SetBounds, context, &orderInfo->bounds); + if (!freerdp_primary_adjust_bounds(update->log, orderName, context, &orderInfo->bounds)) + return FALSE; + + rc = IFCALLRESULT(FALSE, update->SetBounds, context, &orderInfo->bounds); + + if (!rc) + return FALSE; } orderInfo->deltaCoordinates = (flags & ORDER_DELTA_COORDINATES) ? TRUE : FALSE; + if (!read_primary_order(update->log, orderName, s, orderInfo, primary)) + return FALSE; + switch (orderInfo->orderType) { case ORDER_TYPE_DSTBLT: - if (!update_read_dstblt_order(s, orderInfo, &(primary->dstblt))) { - WLog_ERR(TAG, "ORDER_TYPE_DSTBLT - update_read_dstblt_order() failed"); - return FALSE; - } + WLog_Print(update->log, WLOG_DEBUG, + "Primary Drawing Order %s rop=%s [0x%08"PRIx32"]", + orderName, + gdi_rop3_code_string(primary->dstblt.bRop), gdi_rop3_code(primary->dstblt.bRop)); - WLog_Print(update->log, WLOG_DEBUG, - "%s Primary Drawing Order (0x%08"PRIX32") rop=%s [0x%08"PRIx32"]", - PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType, - gdi_rop3_code_string(primary->dstblt.bRop), gdi_rop3_code(primary->dstblt.bRop)); - IFCALL(primary->DstBlt, context, &primary->dstblt); + if (!freerdp_primary_adjust_rect(update->log, orderName, context, + &primary->dstblt.nLeftRect, + &primary->dstblt.nTopRect, + &primary->dstblt.nWidth, + &primary->dstblt.nHeight)) + return FALSE; + + rc = IFCALLRESULT(FALSE, primary->DstBlt, context, &primary->dstblt); + } break; case ORDER_TYPE_PATBLT: - if (!update_read_patblt_order(s, orderInfo, &(primary->patblt))) { - WLog_ERR(TAG, "ORDER_TYPE_PATBLT - update_read_patblt_order() failed"); - return FALSE; - } + WLog_Print(update->log, WLOG_DEBUG, + "Primary Drawing Order %s rop=%s [0x%08"PRIx32"]", orderName, + gdi_rop3_code_string(primary->patblt.bRop), gdi_rop3_code(primary->patblt.bRop)); - WLog_Print(update->log, WLOG_DEBUG, - "%s Primary Drawing Order (0x%08"PRIX32") rop=%s [0x%08"PRIx32"]", - PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType, - gdi_rop3_code_string(primary->patblt.bRop), gdi_rop3_code(primary->patblt.bRop)); - IFCALL(primary->PatBlt, context, &primary->patblt); + if (!freerdp_primary_adjust_rect(update->log, orderName, context, + &primary->patblt.nLeftRect, + &primary->patblt.nTopRect, + &primary->patblt.nWidth, + &primary->patblt.nHeight)) + return FALSE; + + rc = IFCALLRESULT(FALSE, primary->PatBlt, context, &primary->patblt); + } break; case ORDER_TYPE_SCRBLT: - if (!update_read_scrblt_order(s, orderInfo, &(primary->scrblt))) { - WLog_ERR(TAG, "ORDER_TYPE_SCRBLT - update_read_scrblt_order() failed"); - return FALSE; - } + WLog_Print(update->log, WLOG_DEBUG, + "Primary Drawing Order %s rop=%s [0x%08"PRIx32"]", orderName, + gdi_rop3_code_string(primary->scrblt.bRop), gdi_rop3_code(primary->scrblt.bRop)); - WLog_Print(update->log, WLOG_DEBUG, - "%s Primary Drawing Order (0x%08"PRIX32") rop=%s [0x%08"PRIx32"]", - PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType, - gdi_rop3_code_string(primary->scrblt.bRop), gdi_rop3_code(primary->scrblt.bRop)); - IFCALL(primary->ScrBlt, context, &primary->scrblt); + if (!freerdp_primary_adjust_rect(update->log, orderName, context, + &primary->scrblt.nLeftRect, + &primary->scrblt.nTopRect, + &primary->scrblt.nWidth, + &primary->scrblt.nHeight)) + return FALSE; + + rc = IFCALLRESULT(FALSE, primary->ScrBlt, context, &primary->scrblt); + } break; case ORDER_TYPE_OPAQUE_RECT: - if (!update_read_opaque_rect_order(s, orderInfo, &(primary->opaque_rect))) { - WLog_ERR(TAG, - "ORDER_TYPE_OPAQUE_RECT - update_read_opaque_rect_order() failed"); - return FALSE; - } + WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName); - WLog_Print(update->log, WLOG_DEBUG, "%s Primary Drawing Order (0x%08"PRIX32")", - PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType); - IFCALL(primary->OpaqueRect, context, &primary->opaque_rect); + if (!freerdp_primary_adjust_rect(update->log, orderName, context, &primary->opaque_rect.nLeftRect, + &primary->opaque_rect.nTopRect, + &primary->opaque_rect.nWidth, + &primary->opaque_rect.nHeight)) + return FALSE; + + rc = IFCALLRESULT(FALSE, primary->OpaqueRect, context, &primary->opaque_rect); + } break; case ORDER_TYPE_DRAW_NINE_GRID: - if (!update_read_draw_nine_grid_order(s, orderInfo, &(primary->draw_nine_grid))) { - WLog_ERR(TAG, - "ORDER_TYPE_DRAW_NINE_GRID - update_read_draw_nine_grid_order() failed"); - return FALSE; - } + WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName); - WLog_Print(update->log, WLOG_DEBUG, "%s Primary Drawing Order (0x%08"PRIX32")", - PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType); - IFCALL(primary->DrawNineGrid, context, &primary->draw_nine_grid); + if (!freerdp_primary_adjust_bound(update->log, orderName, context, &primary->draw_nine_grid.srcLeft, + &primary->draw_nine_grid.srcTop, &primary->draw_nine_grid.srcRight, + &primary->draw_nine_grid.srcBottom)) + return FALSE; + + rc = IFCALLRESULT(FALSE, primary->DrawNineGrid, context, &primary->draw_nine_grid); + } break; case ORDER_TYPE_MULTI_DSTBLT: - if (!update_read_multi_dstblt_order(s, orderInfo, &(primary->multi_dstblt))) { - WLog_ERR(TAG, - "ORDER_TYPE_MULTI_DSTBLT - update_read_multi_dstblt_order() failed"); - return FALSE; - } + WLog_Print(update->log, WLOG_DEBUG, + "Primary Drawing Order %s rop=%s [0x%08"PRIx32"]", orderName, + gdi_rop3_code_string(primary->multi_dstblt.bRop), gdi_rop3_code(primary->multi_dstblt.bRop)); - WLog_Print(update->log, WLOG_DEBUG, - "%s Primary Drawing Order (0x%08"PRIX32") rop=%s [0x%08"PRIx32"]", - PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType, - gdi_rop3_code_string(primary->multi_dstblt.bRop), gdi_rop3_code(primary->multi_dstblt.bRop)); - IFCALL(primary->MultiDstBlt, context, &primary->multi_dstblt); + if (!freerdp_primary_adjust_rect(update->log, orderName, context, + &primary->multi_dstblt.nLeftRect, + &primary->multi_dstblt.nTopRect, + &primary->multi_dstblt.nWidth, + &primary->multi_dstblt.nHeight)) + return FALSE; + + if (!freerdp_adjust_delta_rect(update->log, orderName, context, primary->multi_dstblt.numRectangles, + primary->multi_dstblt.rectangles)) + return FALSE; + + rc = IFCALLRESULT(FALSE, primary->MultiDstBlt, context, &primary->multi_dstblt); + } break; case ORDER_TYPE_MULTI_PATBLT: - if (!update_read_multi_patblt_order(s, orderInfo, &(primary->multi_patblt))) { - WLog_ERR(TAG, - "ORDER_TYPE_MULTI_PATBLT - update_read_multi_patblt_order() failed"); - return FALSE; - } + WLog_Print(update->log, WLOG_DEBUG, + "Primary Drawing Order %s rop=%s [0x%08"PRIx32"]", orderName, + gdi_rop3_code_string(primary->multi_patblt.bRop), gdi_rop3_code(primary->multi_patblt.bRop)); - WLog_Print(update->log, WLOG_DEBUG, - "%s Primary Drawing Order (0x%08"PRIX32") rop=%s [0x%08"PRIx32"]", - PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType, - gdi_rop3_code_string(primary->multi_patblt.bRop), gdi_rop3_code(primary->multi_patblt.bRop)); - IFCALL(primary->MultiPatBlt, context, &primary->multi_patblt); + if (!freerdp_primary_adjust_rect(update->log, orderName, context, + &primary->multi_patblt.nLeftRect, + &primary->multi_patblt.nTopRect, + &primary->multi_patblt.nWidth, + &primary->multi_patblt.nHeight)) + return FALSE; + + if (!freerdp_adjust_delta_rect(update->log, orderName, context, primary->multi_patblt.numRectangles, + primary->multi_patblt.rectangles)) + return FALSE; + + rc = IFCALLRESULT(FALSE, primary->MultiPatBlt, context, &primary->multi_patblt); + } break; case ORDER_TYPE_MULTI_SCRBLT: - if (!update_read_multi_scrblt_order(s, orderInfo, &(primary->multi_scrblt))) { - WLog_ERR(TAG, - "ORDER_TYPE_MULTI_SCRBLT - update_read_multi_scrblt_order() failed"); - return FALSE; - } + WLog_Print(update->log, WLOG_DEBUG, + "Primary Drawing Order %s rop=%s [0x%08"PRIx32"]", orderName, + gdi_rop3_code_string(primary->multi_scrblt.bRop), gdi_rop3_code(primary->multi_scrblt.bRop)); - WLog_Print(update->log, WLOG_DEBUG, - "%s Primary Drawing Order (0x%08"PRIX32") rop=%s [0x%08"PRIx32"]", - PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType, - gdi_rop3_code_string(primary->multi_scrblt.bRop), gdi_rop3_code(primary->multi_scrblt.bRop)); - IFCALL(primary->MultiScrBlt, context, &primary->multi_scrblt); + if (!freerdp_primary_adjust_rect(update->log, orderName, context, + &primary->multi_scrblt.nLeftRect, + &primary->multi_scrblt.nTopRect, + &primary->multi_scrblt.nWidth, + &primary->multi_scrblt.nHeight)) + return FALSE; + + if (!freerdp_adjust_delta_rect(update->log, orderName, context, primary->multi_scrblt.numRectangles, + primary->multi_scrblt.rectangles)) + return FALSE; + + rc = IFCALLRESULT(FALSE, primary->MultiScrBlt, context, &primary->multi_scrblt); + } break; case ORDER_TYPE_MULTI_OPAQUE_RECT: - if (!update_read_multi_opaque_rect_order(s, orderInfo, - &(primary->multi_opaque_rect))) { - WLog_ERR(TAG, - "ORDER_TYPE_MULTI_OPAQUE_RECT - update_read_multi_opaque_rect_order() failed"); - return FALSE; - } + WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName); - WLog_Print(update->log, WLOG_DEBUG, "%s Primary Drawing Order (0x%08"PRIX32")", - PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType); - IFCALL(primary->MultiOpaqueRect, context, &primary->multi_opaque_rect); + if (!freerdp_primary_adjust_rect(update->log, orderName, context, + &primary->multi_opaque_rect.nLeftRect, + &primary->multi_opaque_rect.nTopRect, + &primary->multi_opaque_rect.nWidth, + &primary->multi_opaque_rect.nHeight)) + return FALSE; + + if (!freerdp_adjust_delta_rect(update->log, orderName, context, + primary->multi_opaque_rect.numRectangles, + primary->multi_opaque_rect.rectangles)) + return FALSE; + + rc = IFCALLRESULT(FALSE, primary->MultiOpaqueRect, context, &primary->multi_opaque_rect); + } break; case ORDER_TYPE_MULTI_DRAW_NINE_GRID: - if (!update_read_multi_draw_nine_grid_order(s, orderInfo, - &(primary->multi_draw_nine_grid))) { - WLog_ERR(TAG, - "ORDER_TYPE_MULTI_DRAW_NINE_GRID - update_read_multi_draw_nine_grid_order() failed"); - return FALSE; - } + WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName); - WLog_Print(update->log, WLOG_DEBUG, "%s Primary Drawing Order (0x%08"PRIX32")", - PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType); - IFCALL(primary->MultiDrawNineGrid, context, &primary->multi_draw_nine_grid); + if (!freerdp_primary_adjust_bound(update->log, orderName, context, + &primary->multi_draw_nine_grid.srcLeft, + &primary->multi_draw_nine_grid.srcTop, + &primary->multi_draw_nine_grid.srcRight, + &primary->multi_draw_nine_grid.srcBottom)) + return FALSE; + + if (!freerdp_adjust_delta_rect(update->log, orderName, context, + primary->multi_draw_nine_grid.nDeltaEntries, + primary->multi_draw_nine_grid.rectangles)) + return FALSE; + + rc = IFCALLRESULT(FALSE, primary->MultiDrawNineGrid, context, &primary->multi_draw_nine_grid); + } break; case ORDER_TYPE_LINE_TO: - if (!update_read_line_to_order(s, orderInfo, &(primary->line_to))) { - WLog_ERR(TAG, "ORDER_TYPE_LINE_TO - update_read_line_to_order() failed"); - return FALSE; + WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName); + rc = IFCALLRESULT(FALSE, primary->LineTo, context, &primary->line_to); } - - WLog_Print(update->log, WLOG_DEBUG, "%s Primary Drawing Order (0x%08"PRIX32")", - PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType); - IFCALL(primary->LineTo, context, &primary->line_to); break; case ORDER_TYPE_POLYLINE: - if (!update_read_polyline_order(s, orderInfo, &(primary->polyline))) { - WLog_ERR(TAG, "ORDER_TYPE_POLYLINE - update_read_polyline_order() failed"); - return FALSE; + WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName); + rc = IFCALLRESULT(FALSE, primary->Polyline, context, &primary->polyline); } - - WLog_Print(update->log, WLOG_DEBUG, "%s Primary Drawing Order (0x%08"PRIX32")", - PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType); - IFCALL(primary->Polyline, context, &primary->polyline); break; case ORDER_TYPE_MEMBLT: - if (!update_read_memblt_order(s, orderInfo, &(primary->memblt))) { - WLog_ERR(TAG, "ORDER_TYPE_MEMBLT - update_read_memblt_order() failed"); - return FALSE; - } + WLog_Print(update->log, WLOG_DEBUG, + "Primary Drawing Order %s rop=%s [0x%08"PRIx32"]", orderName, + gdi_rop3_code_string(primary->memblt.bRop), gdi_rop3_code(primary->memblt.bRop)); - WLog_Print(update->log, WLOG_DEBUG, - "%s Primary Drawing Order (0x%08"PRIX32") rop=%s [0x%08"PRIx32"]", - PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType, - gdi_rop3_code_string(primary->memblt.bRop), gdi_rop3_code(primary->memblt.bRop)); - IFCALL(primary->MemBlt, context, &primary->memblt); + if (!freerdp_primary_adjust_rect(update->log, orderName, context, + &primary->memblt.nLeftRect, + &primary->memblt.nTopRect, + &primary->memblt.nWidth, + &primary->memblt.nHeight)) + return FALSE; + + if (!freerdp_adjust_point(update->log, orderName, context, &primary->memblt.nXSrc, + &primary->memblt.nYSrc)) + return FALSE; + + rc = IFCALLRESULT(FALSE, primary->MemBlt, context, &primary->memblt); + } break; case ORDER_TYPE_MEM3BLT: - if (!update_read_mem3blt_order(s, orderInfo, &(primary->mem3blt))) { - WLog_ERR(TAG, "ORDER_TYPE_MEM3BLT - update_read_mem3blt_order() failed"); - return FALSE; - } + WLog_Print(update->log, WLOG_DEBUG, + "Primary Drawing Order %s rop=%s [0x%08"PRIx32"]", orderName, + gdi_rop3_code_string(primary->mem3blt.bRop), gdi_rop3_code(primary->mem3blt.bRop)); - WLog_Print(update->log, WLOG_DEBUG, - "%s Primary Drawing Order (0x%08"PRIX32") rop=%s [0x%08"PRIx32"]", - PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType, - gdi_rop3_code_string(primary->mem3blt.bRop), gdi_rop3_code(primary->mem3blt.bRop)); - IFCALL(primary->Mem3Blt, context, &primary->mem3blt); + if (!freerdp_primary_adjust_rect(update->log, orderName, context, + &primary->mem3blt.nLeftRect, + &primary->mem3blt.nTopRect, + &primary->mem3blt.nWidth, + &primary->mem3blt.nHeight)) + return FALSE; + + if (!freerdp_adjust_point(update->log, orderName, context, &primary->mem3blt.nXSrc, + &primary->mem3blt.nYSrc)) + return FALSE; + + rc = IFCALLRESULT(FALSE, primary->Mem3Blt, context, &primary->mem3blt); + } break; case ORDER_TYPE_SAVE_BITMAP: - if (!update_read_save_bitmap_order(s, orderInfo, &(primary->save_bitmap))) { - WLog_ERR(TAG, - "ORDER_TYPE_SAVE_BITMAP - update_read_save_bitmap_order() failed"); - return FALSE; - } + WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName); - WLog_Print(update->log, WLOG_DEBUG, "%s Primary Drawing Order (0x%08"PRIX32")", - PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType); - IFCALL(primary->SaveBitmap, context, &primary->save_bitmap); + if (!freerdp_primary_adjust_bound(update->log, orderName, context, &primary->save_bitmap.nLeftRect, + &primary->save_bitmap.nTopRect, &primary->save_bitmap.nRightRect, + &primary->save_bitmap.nBottomRect)) + return FALSE; + + rc = IFCALLRESULT(FALSE, primary->SaveBitmap, context, &primary->save_bitmap); + } break; case ORDER_TYPE_GLYPH_INDEX: - if (!update_read_glyph_index_order(s, orderInfo, &(primary->glyph_index))) { - WLog_ERR(TAG, - "ORDER_TYPE_GLYPH_INDEX - update_read_glyph_index_order() failed"); - return FALSE; - } + WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName); - WLog_Print(update->log, WLOG_DEBUG, "%s Primary Drawing Order (0x%08"PRIX32")", - PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType); - IFCALL(primary->GlyphIndex, context, &primary->glyph_index); + if (!freerdp_primary_adjust_bound(update->log, orderName, context, &primary->glyph_index.bkLeft, + &primary->glyph_index.bkTop, + &primary->glyph_index.bkRight, &primary->fast_index.bkBottom)) + return FALSE; + + if (!freerdp_primary_adjust_bound(update->log, orderName, context, &primary->glyph_index.opLeft, + &primary->glyph_index.opTop, + &primary->glyph_index.opRight, &primary->fast_index.opBottom)) + return FALSE; + + if (!freerdp_adjust_point(update->log, orderName, context, &primary->glyph_index.x, + &primary->glyph_index.y)) + return FALSE; + + rc = IFCALLRESULT(FALSE, primary->GlyphIndex, context, &primary->glyph_index); + } break; case ORDER_TYPE_FAST_INDEX: - if (!update_read_fast_index_order(s, orderInfo, &(primary->fast_index))) { - WLog_ERR(TAG, "ORDER_TYPE_FAST_INDEX - update_read_fast_index_order() failed"); - return FALSE; - } + WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName); - WLog_Print(update->log, WLOG_DEBUG, "%s Primary Drawing Order (0x%08"PRIX32")", - PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType); - IFCALL(primary->FastIndex, context, &primary->fast_index); + if (!freerdp_primary_adjust_bound(update->log, orderName, context, + &primary->fast_index.bkLeft, + &primary->fast_index.bkTop, + &primary->fast_index.bkRight, &primary->fast_index.bkBottom)) + return FALSE; + + if (!freerdp_check_glyph_op_bound(update->log, orderName, context, primary->fast_index.opLeft, + primary->fast_index.opTop, + primary->fast_index.opRight, primary->fast_index.opBottom)) + return FALSE; + + if (!freerdp_adjust_point(update->log, orderName, context, &primary->fast_index.x, + &primary->fast_index.y)) + return FALSE; + + rc = IFCALLRESULT(FALSE, primary->FastIndex, context, &primary->fast_index); + } break; case ORDER_TYPE_FAST_GLYPH: - if (!update_read_fast_glyph_order(s, orderInfo, &(primary->fast_glyph))) { - WLog_ERR(TAG, "ORDER_TYPE_FAST_GLYPH - update_read_fast_glyph_order() failed"); - return FALSE; - } + WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName); - WLog_Print(update->log, WLOG_DEBUG, "%s Primary Drawing Order (0x%08"PRIX32")", - PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType); - IFCALL(primary->FastGlyph, context, &primary->fast_glyph); + if (!freerdp_primary_adjust_bound(update->log, orderName, context, &primary->fast_glyph.bkLeft, + &primary->fast_glyph.bkTop, + &primary->fast_glyph.bkRight, &primary->fast_index.bkBottom)) + return FALSE; + + if (!freerdp_check_glyph_op_bound(update->log, orderName, context, primary->fast_glyph.opLeft, + primary->fast_glyph.opTop, + primary->fast_glyph.opRight, primary->fast_index.opBottom)) + return FALSE; + + if (!adjust_point(context, &primary->fast_glyph.x, &primary->fast_glyph.y)) + return FALSE; + + rc = IFCALLRESULT(FALSE, primary->FastGlyph, context, &primary->fast_glyph); + } break; case ORDER_TYPE_POLYGON_SC: - if (!update_read_polygon_sc_order(s, orderInfo, &(primary->polygon_sc))) { - WLog_ERR(TAG, "ORDER_TYPE_POLYGON_SC - update_read_polygon_sc_order() failed"); - return FALSE; + WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName); + rc = IFCALLRESULT(FALSE, primary->PolygonSC, context, &primary->polygon_sc); } - - WLog_Print(update->log, WLOG_DEBUG, "%s Primary Drawing Order (0x%08"PRIX32")", - PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType); - IFCALL(primary->PolygonSC, context, &primary->polygon_sc); break; case ORDER_TYPE_POLYGON_CB: - if (!update_read_polygon_cb_order(s, orderInfo, &(primary->polygon_cb))) { - WLog_ERR(TAG, "ORDER_TYPE_POLYGON_CB - update_read_polygon_cb_order() failed"); - return FALSE; + WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName); + rc = IFCALLRESULT(FALSE, primary->PolygonCB, context, &primary->polygon_cb); } - - WLog_Print(update->log, WLOG_DEBUG, "%s Primary Drawing Order (0x%08"PRIX32")", - PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType); - IFCALL(primary->PolygonCB, context, &primary->polygon_cb); break; case ORDER_TYPE_ELLIPSE_SC: - if (!update_read_ellipse_sc_order(s, orderInfo, &(primary->ellipse_sc))) { - WLog_ERR(TAG, "ORDER_TYPE_ELLIPSE_SC - update_read_ellipse_sc_order() failed"); - return FALSE; - } + WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName); - WLog_Print(update->log, WLOG_DEBUG, "%s Primary Drawing Order (0x%08"PRIX32")", - PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType); - IFCALL(primary->EllipseSC, context, &primary->ellipse_sc); + if (!freerdp_primary_adjust_bound(update->log, orderName, context, &primary->ellipse_sc.leftRect, + &primary->ellipse_sc.topRect, + &primary->ellipse_sc.rightRect, &primary->ellipse_sc.bottomRect)) + return FALSE; + + rc = IFCALLRESULT(FALSE, primary->EllipseSC, context, &primary->ellipse_sc); + } break; case ORDER_TYPE_ELLIPSE_CB: - if (!update_read_ellipse_cb_order(s, orderInfo, &(primary->ellipse_cb))) { - WLog_ERR(TAG, "ORDER_TYPE_ELLIPSE_CB - update_read_ellipse_cb_order() failed"); - return FALSE; - } + WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName); - WLog_Print(update->log, WLOG_DEBUG, "%s Primary Drawing Order (0x%08"PRIX32")", - PRIMARY_DRAWING_ORDER_STRINGS[orderInfo->orderType], orderInfo->orderType); - IFCALL(primary->EllipseCB, context, &primary->ellipse_cb); + if (!freerdp_primary_adjust_bound(update->log, orderName, context, &primary->ellipse_cb.leftRect, + &primary->ellipse_cb.topRect, + &primary->ellipse_cb.rightRect, &primary->ellipse_cb.bottomRect)) + return FALSE; + + rc = IFCALLRESULT(FALSE, primary->EllipseCB, context, &primary->ellipse_cb); + } break; default: + WLog_Print(update->log, WLOG_WARN, "Primary Drawing Order %s not supported", orderName); break; } + if (!rc) + { + WLog_Print(update->log, WLOG_WARN, + "Primary Drawing Order %s failed", orderName); + return FALSE; + } + if (flags & ORDER_BOUNDS) { - IFCALL(update->SetBounds, context, NULL); + rc = IFCALLRESULT(FALSE, update->SetBounds, context, NULL); } - return TRUE; + return rc; } + static BOOL update_recv_secondary_order(rdpUpdate* update, wStream* s, BYTE flags) { @@ -3343,11 +4015,13 @@ static BOOL update_recv_secondary_order(rdpUpdate* update, wStream* s, UINT16 extraFlags; UINT16 orderLength; rdpContext* context = update->context; + rdpSettings* settings = context->settings; rdpSecondaryUpdate* secondary = update->secondary; + const char* name; if (Stream_GetRemainingLength(s) < 5) { - WLog_ERR(TAG, "Stream_GetRemainingLength(s) < 5"); + WLog_Print(update->log, WLOG_ERROR, "Stream_GetRemainingLength(s) < 5"); return FALSE; } @@ -3355,8 +4029,11 @@ static BOOL update_recv_secondary_order(rdpUpdate* update, wStream* s, Stream_Read_UINT16(s, extraFlags); /* extraFlags (2 bytes) */ Stream_Read_UINT8(s, orderType); /* orderType (1 byte) */ next = Stream_Pointer(s) + ((INT16) orderLength) + 7; - WLog_Print(update->log, WLOG_DEBUG, "%s Secondary Drawing Order (0x%02"PRIX8")", - update_secondary_order_to_string(orderType), orderType); + name = secondary_order_string(orderType); + WLog_Print(update->log, WLOG_DEBUG, "Secondary Drawing Order %s", name); + + if (!check_secondary_order_supported(update->log, settings, orderType, name)) + return FALSE; switch (orderType) { @@ -3413,30 +4090,43 @@ static BOOL update_recv_secondary_order(rdpUpdate* update, wStream* s, break; case ORDER_TYPE_CACHE_GLYPH: - if (secondary->glyph_v2) { - CACHE_GLYPH_V2_ORDER* order = update_read_cache_glyph_v2_order(update, s, extraFlags); - - if (order) + switch (settings->GlyphSupportLevel) { - rc = IFCALLRESULT(FALSE, secondary->CacheGlyphV2, context, order); - free_cache_glyph_v2_order(context, order); + case GLYPH_SUPPORT_PARTIAL: + case GLYPH_SUPPORT_FULL: + { + CACHE_GLYPH_ORDER* order = update_read_cache_glyph_order(update, s, extraFlags); + + if (order) + { + rc = IFCALLRESULT(FALSE, secondary->CacheGlyph, context, order); + free_cache_glyph_order(context, order); + } + } + break; + + case GLYPH_SUPPORT_ENCODE: + { + CACHE_GLYPH_V2_ORDER* order = update_read_cache_glyph_v2_order(update, s, extraFlags); + + if (order) + { + rc = IFCALLRESULT(FALSE, secondary->CacheGlyphV2, context, order); + free_cache_glyph_v2_order(context, order); + } + } + break; + + case GLYPH_SUPPORT_NONE: + default: + break; } } - else - { - CACHE_GLYPH_ORDER* order = update_read_cache_glyph_order(update, s, extraFlags); - - if (order) - { - rc = IFCALLRESULT(FALSE, secondary->CacheGlyph, context, order); - free_cache_glyph_order(context, order); - } - } - break; case ORDER_TYPE_CACHE_BRUSH: + /* [MS-RDPEGDI] 2.2.2.2.1.2.7 Cache Brush (CACHE_BRUSH_ORDER) */ { CACHE_BRUSH_ORDER* order = update_read_cache_brush_order(update, s, extraFlags); @@ -3449,207 +4139,207 @@ static BOOL update_recv_secondary_order(rdpUpdate* update, wStream* s, break; default: + WLog_Print(update->log, WLOG_WARN, "SECONDARY ORDER %s not supported", name); break; } if (!rc) { - WLog_ERR(TAG, "SECONDARY ORDER %s [%"PRIx16"] failed", update_secondary_order_to_string(orderType), - orderType); + WLog_Print(update->log, WLOG_ERROR, "SECONDARY ORDER %s failed", name); } Stream_SetPointer(s, next); return rc; } -static BOOL update_recv_altsec_order(rdpUpdate* update, wStream* s, - BYTE flags) -{ - BYTE orderType; - rdpContext* context = update->context; - rdpAltSecUpdate* altsec = update->altsec; - orderType = flags >>= 2; /* orderType is in higher 6 bits of flags field */ - if (orderType < ALTSEC_DRAWING_ORDER_COUNT) - WLog_Print(update->log, WLOG_DEBUG, - "%s Alternate Secondary Drawing Order (0x%02"PRIX8")", - ALTSEC_DRAWING_ORDER_STRINGS[orderType], orderType); - else - WLog_Print(update->log, WLOG_DEBUG, - "Unknown Alternate Secondary Drawing Order: 0x%02"PRIX8"", orderType); +static BOOL read_altsec_order(wStream* s, BYTE orderType, rdpAltSecUpdate* altsec) +{ + BOOL rc = FALSE; switch (orderType) { case ORDER_TYPE_CREATE_OFFSCREEN_BITMAP: - if (!update_read_create_offscreen_bitmap_order(s, - &(altsec->create_offscreen_bitmap))) - { - WLog_ERR(TAG, - "ORDER_TYPE_CREATE_OFFSCREEN_BITMAP - update_read_create_offscreen_bitmap_order() failed"); - return FALSE; - } - - IFCALL(altsec->CreateOffscreenBitmap, context, - &(altsec->create_offscreen_bitmap)); + rc = update_read_create_offscreen_bitmap_order(s, + &(altsec->create_offscreen_bitmap)); break; case ORDER_TYPE_SWITCH_SURFACE: - if (!update_read_switch_surface_order(s, &(altsec->switch_surface))) - { - WLog_ERR(TAG, - "ORDER_TYPE_SWITCH_SURFACE - update_read_switch_surface_order() failed"); - return FALSE; - } - - IFCALL(altsec->SwitchSurface, context, &(altsec->switch_surface)); + rc = update_read_switch_surface_order(s, &(altsec->switch_surface)); break; case ORDER_TYPE_CREATE_NINE_GRID_BITMAP: - if (!update_read_create_nine_grid_bitmap_order(s, - &(altsec->create_nine_grid_bitmap))) - { - WLog_ERR(TAG, - "ORDER_TYPE_CREATE_NINE_GRID_BITMAP - update_read_create_nine_grid_bitmap_order() failed"); - return FALSE; - } - - IFCALL(altsec->CreateNineGridBitmap, context, - &(altsec->create_nine_grid_bitmap)); + rc = update_read_create_nine_grid_bitmap_order(s, + &(altsec->create_nine_grid_bitmap)); break; case ORDER_TYPE_FRAME_MARKER: - if (!update_read_frame_marker_order(s, &(altsec->frame_marker))) - { - WLog_ERR(TAG, - "ORDER_TYPE_FRAME_MARKER - update_read_frame_marker_order() failed"); - return FALSE; - } - - IFCALL(altsec->FrameMarker, context, &(altsec->frame_marker)); + rc = update_read_frame_marker_order(s, &(altsec->frame_marker)); break; case ORDER_TYPE_STREAM_BITMAP_FIRST: - if (!update_read_stream_bitmap_first_order(s, &(altsec->stream_bitmap_first))) - { - WLog_ERR(TAG, - "ORDER_TYPE_STREAM_BITMAP_FIRST - update_read_stream_bitmap_first_order() failed"); - return FALSE; - } - - IFCALL(altsec->StreamBitmapFirst, context, &(altsec->stream_bitmap_first)); + rc = update_read_stream_bitmap_first_order(s, &(altsec->stream_bitmap_first)); break; case ORDER_TYPE_STREAM_BITMAP_NEXT: - if (!update_read_stream_bitmap_next_order(s, &(altsec->stream_bitmap_next))) - { - WLog_ERR(TAG, - "ORDER_TYPE_STREAM_BITMAP_NEXT - update_read_stream_bitmap_next_order() failed"); - return FALSE; - } - - IFCALL(altsec->StreamBitmapNext, context, &(altsec->stream_bitmap_next)); + rc = update_read_stream_bitmap_next_order(s, &(altsec->stream_bitmap_next)); break; case ORDER_TYPE_GDIPLUS_FIRST: - if (!update_read_draw_gdiplus_first_order(s, &(altsec->draw_gdiplus_first))) - { - WLog_ERR(TAG, - "ORDER_TYPE_GDIPLUS_FIRST - update_read_draw_gdiplus_first_order() failed"); - return FALSE; - } - - IFCALL(altsec->DrawGdiPlusFirst, context, &(altsec->draw_gdiplus_first)); + rc = update_read_draw_gdiplus_first_order(s, &(altsec->draw_gdiplus_first)); break; case ORDER_TYPE_GDIPLUS_NEXT: - if (!update_read_draw_gdiplus_next_order(s, &(altsec->draw_gdiplus_next))) - { - WLog_ERR(TAG, - "ORDER_TYPE_GDIPLUS_NEXT - update_read_draw_gdiplus_next_order() failed"); - return FALSE; - } - - IFCALL(altsec->DrawGdiPlusNext, context, &(altsec->draw_gdiplus_next)); + rc = update_read_draw_gdiplus_next_order(s, &(altsec->draw_gdiplus_next)); break; case ORDER_TYPE_GDIPLUS_END: - if (!update_read_draw_gdiplus_end_order(s, &(altsec->draw_gdiplus_end))) - { - WLog_ERR(TAG, - "ORDER_TYPE_GDIPLUS_END - update_read_draw_gdiplus_end_order() failed"); - return FALSE; - } - - IFCALL(altsec->DrawGdiPlusEnd, context, &(altsec->draw_gdiplus_end)); + rc = update_read_draw_gdiplus_end_order(s, &(altsec->draw_gdiplus_end)); break; case ORDER_TYPE_GDIPLUS_CACHE_FIRST: - if (!update_read_draw_gdiplus_cache_first_order(s, - &(altsec->draw_gdiplus_cache_first))) - { - WLog_ERR(TAG, - "ORDER_TYPE_GDIPLUS_CACHE_FIRST - update_read_draw_gdiplus_cache_first_order() failed"); - return FALSE; - } - - IFCALL(altsec->DrawGdiPlusCacheFirst, context, - &(altsec->draw_gdiplus_cache_first)); + rc = update_read_draw_gdiplus_cache_first_order(s, + &(altsec->draw_gdiplus_cache_first)); break; case ORDER_TYPE_GDIPLUS_CACHE_NEXT: - if (!update_read_draw_gdiplus_cache_next_order(s, - &(altsec->draw_gdiplus_cache_next))) - { - WLog_ERR(TAG, - "ORDER_TYPE_GDIPLUS_CACHE_NEXT - update_read_draw_gdiplus_cache_next_order() failed"); - return FALSE; - } - - IFCALL(altsec->DrawGdiPlusCacheNext, context, - &(altsec->draw_gdiplus_cache_next)); + rc = update_read_draw_gdiplus_cache_next_order(s, + &(altsec->draw_gdiplus_cache_next)); break; case ORDER_TYPE_GDIPLUS_CACHE_END: - if (!update_read_draw_gdiplus_cache_end_order(s, - &(altsec->draw_gdiplus_cache_end))) - { - WLog_ERR(TAG, - "ORDER_TYPE_GDIPLUS_CACHE_END - update_read_draw_gdiplus_cache_end_order() failed"); - return FALSE; - } - - IFCALL(altsec->DrawGdiPlusCacheEnd, context, &(altsec->draw_gdiplus_cache_end)); + rc = update_read_draw_gdiplus_cache_end_order(s, + &(altsec->draw_gdiplus_cache_end)); break; case ORDER_TYPE_WINDOW: - return update_recv_altsec_window_order(update, s); + /* This order is handled elsewhere. */ + break; case ORDER_TYPE_COMPDESK_FIRST: + rc = TRUE; break; default: break; } - return TRUE; + return rc; +} + +static BOOL update_recv_altsec_order(rdpUpdate* update, wStream* s, + BYTE flags) +{ + BYTE orderType = flags >>= 2; /* orderType is in higher 6 bits of flags field */ + BOOL rc = FALSE; + rdpContext* context = update->context; + rdpSettings* settings = context->settings; + rdpAltSecUpdate* altsec = update->altsec; + const char* orderName = altsec_order_string(orderType); + WLog_Print(update->log, WLOG_DEBUG, + "Alternate Secondary Drawing Order %s", orderName); + + if (!check_alt_order_supported(update->log, settings, orderType, orderName)) + return FALSE; + + if (!read_altsec_order(s, orderType, altsec)) + return FALSE; + + switch (orderType) + { + case ORDER_TYPE_CREATE_OFFSCREEN_BITMAP: + IFCALLRET(altsec->CreateOffscreenBitmap, rc, context, + &(altsec->create_offscreen_bitmap)); + break; + + case ORDER_TYPE_SWITCH_SURFACE: + IFCALLRET(altsec->SwitchSurface, rc, context, &(altsec->switch_surface)); + break; + + case ORDER_TYPE_CREATE_NINE_GRID_BITMAP: + IFCALLRET(altsec->CreateNineGridBitmap, rc, context, + &(altsec->create_nine_grid_bitmap)); + break; + + case ORDER_TYPE_FRAME_MARKER: + IFCALLRET(altsec->FrameMarker, rc, context, &(altsec->frame_marker)); + break; + + case ORDER_TYPE_STREAM_BITMAP_FIRST: + IFCALLRET(altsec->StreamBitmapFirst, rc, context, &(altsec->stream_bitmap_first)); + break; + + case ORDER_TYPE_STREAM_BITMAP_NEXT: + IFCALLRET(altsec->StreamBitmapNext, rc, context, &(altsec->stream_bitmap_next)); + break; + + case ORDER_TYPE_GDIPLUS_FIRST: + IFCALLRET(altsec->DrawGdiPlusFirst, rc, context, &(altsec->draw_gdiplus_first)); + break; + + case ORDER_TYPE_GDIPLUS_NEXT: + IFCALLRET(altsec->DrawGdiPlusNext, rc, context, &(altsec->draw_gdiplus_next)); + break; + + case ORDER_TYPE_GDIPLUS_END: + IFCALLRET(altsec->DrawGdiPlusEnd, rc, context, &(altsec->draw_gdiplus_end)); + break; + + case ORDER_TYPE_GDIPLUS_CACHE_FIRST: + IFCALLRET(altsec->DrawGdiPlusCacheFirst, rc, context, + &(altsec->draw_gdiplus_cache_first)); + break; + + case ORDER_TYPE_GDIPLUS_CACHE_NEXT: + IFCALLRET(altsec->DrawGdiPlusCacheNext, rc, context, + &(altsec->draw_gdiplus_cache_next)); + break; + + case ORDER_TYPE_GDIPLUS_CACHE_END: + IFCALLRET(altsec->DrawGdiPlusCacheEnd, rc, context, &(altsec->draw_gdiplus_cache_end)); + break; + + case ORDER_TYPE_WINDOW: + rc = update_recv_altsec_window_order(update, s); + break; + + case ORDER_TYPE_COMPDESK_FIRST: + rc = TRUE; + break; + + default: + break; + } + + if (!rc) + { + WLog_Print(update->log, WLOG_WARN, + "Alternate Secondary Drawing Order %s failed", orderName); + } + + return rc; } BOOL update_recv_order(rdpUpdate* update, wStream* s) { + BOOL rc; BYTE controlFlags; if (Stream_GetRemainingLength(s) < 1) { - WLog_ERR(TAG, "Stream_GetRemainingLength(s) < 1"); + WLog_Print(update->log, WLOG_ERROR, "Stream_GetRemainingLength(s) < 1"); return FALSE; } Stream_Read_UINT8(s, controlFlags); /* controlFlags (1 byte) */ if (!(controlFlags & ORDER_STANDARD)) - return update_recv_altsec_order(update, s, controlFlags); + rc = update_recv_altsec_order(update, s, controlFlags); else if (controlFlags & ORDER_SECONDARY) - return update_recv_secondary_order(update, s, controlFlags); + rc = update_recv_secondary_order(update, s, controlFlags); else - return update_recv_primary_order(update, s, controlFlags); + rc = update_recv_primary_order(update, s, controlFlags); - return TRUE; + if (!rc) + WLog_Print(update->log, WLOG_ERROR, "order flags %02"PRIx8" failed", controlFlags); + + return rc; } diff --git a/libfreerdp/core/settings.c b/libfreerdp/core/settings.c index a49d0c60a..3d18bbccf 100644 --- a/libfreerdp/core/settings.c +++ b/libfreerdp/core/settings.c @@ -337,6 +337,7 @@ rdpSettings* freerdp_settings_new(DWORD flags) settings->FIPSMode = FALSE; settings->CompressionEnabled = TRUE; settings->LogonNotify = TRUE; + settings->BrushSupportLevel = BRUSH_COLOR_FULL; if (settings->ServerMode) settings->CompressionLevel = PACKET_COMPR_TYPE_RDP61; @@ -390,23 +391,23 @@ rdpSettings* freerdp_settings_new(DWORD flags) settings->OrderSupport[NEG_SCRBLT_INDEX] = TRUE; settings->OrderSupport[NEG_OPAQUE_RECT_INDEX] = TRUE; settings->OrderSupport[NEG_DRAWNINEGRID_INDEX] = TRUE; - settings->OrderSupport[NEG_MULTIDSTBLT_INDEX] = TRUE; - settings->OrderSupport[NEG_MULTIPATBLT_INDEX] = TRUE; - settings->OrderSupport[NEG_MULTISCRBLT_INDEX] = TRUE; + settings->OrderSupport[NEG_MULTIDSTBLT_INDEX] = FALSE; + settings->OrderSupport[NEG_MULTIPATBLT_INDEX] = FALSE; + settings->OrderSupport[NEG_MULTISCRBLT_INDEX] = FALSE; settings->OrderSupport[NEG_MULTIOPAQUERECT_INDEX] = TRUE; - settings->OrderSupport[NEG_MULTI_DRAWNINEGRID_INDEX] = TRUE; + settings->OrderSupport[NEG_MULTI_DRAWNINEGRID_INDEX] = FALSE; settings->OrderSupport[NEG_LINETO_INDEX] = TRUE; settings->OrderSupport[NEG_POLYLINE_INDEX] = TRUE; settings->OrderSupport[NEG_MEMBLT_INDEX] = TRUE; settings->OrderSupport[NEG_MEM3BLT_INDEX] = TRUE; - settings->OrderSupport[NEG_SAVEBITMAP_INDEX] = TRUE; - settings->OrderSupport[NEG_GLYPH_INDEX_INDEX] = TRUE; - settings->OrderSupport[NEG_FAST_INDEX_INDEX] = TRUE; - settings->OrderSupport[NEG_FAST_GLYPH_INDEX] = TRUE; - settings->OrderSupport[NEG_POLYGON_SC_INDEX] = TRUE; - settings->OrderSupport[NEG_POLYGON_CB_INDEX] = TRUE; - settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = TRUE; - settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = TRUE; + settings->OrderSupport[NEG_SAVEBITMAP_INDEX] = FALSE; + settings->OrderSupport[NEG_GLYPH_INDEX_INDEX] = FALSE; + settings->OrderSupport[NEG_FAST_INDEX_INDEX] = FALSE; + settings->OrderSupport[NEG_FAST_GLYPH_INDEX] = FALSE; + settings->OrderSupport[NEG_POLYGON_SC_INDEX] = FALSE; + settings->OrderSupport[NEG_POLYGON_CB_INDEX] = FALSE; + settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE; + settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE; settings->ClientProductId = calloc(1, 32); if (!settings->ClientProductId) diff --git a/libfreerdp/core/window.c b/libfreerdp/core/window.c index 4e84c4113..a9b3c00b8 100644 --- a/libfreerdp/core/window.c +++ b/libfreerdp/core/window.c @@ -33,7 +33,7 @@ BOOL rail_read_unicode_string(wStream* s, RAIL_UNICODE_STRING* unicode_string) { UINT16 new_len; - BYTE *new_str; + BYTE* new_str; if (Stream_GetRemainingLength(s) < 2) return FALSE; @@ -52,9 +52,10 @@ BOOL rail_read_unicode_string(wStream* s, RAIL_UNICODE_STRING* unicode_string) } new_str = (BYTE*) realloc(unicode_string->string, new_len); + if (!new_str) { - free (unicode_string->string); + free(unicode_string->string); unicode_string->string = NULL; return FALSE; } @@ -62,7 +63,6 @@ BOOL rail_read_unicode_string(wStream* s, RAIL_UNICODE_STRING* unicode_string) unicode_string->string = new_str; unicode_string->length = new_len; Stream_Read(s, unicode_string->string, unicode_string->length); - return TRUE; } @@ -110,14 +110,15 @@ BOOL update_read_icon_info(wStream* s, ICON_INFO* iconInfo) /* bitsMask */ newBitMask = (BYTE*) realloc(iconInfo->bitsMask, iconInfo->cbBitsMask); + if (!newBitMask) { - free (iconInfo->bitsMask); + free(iconInfo->bitsMask); iconInfo->bitsMask = NULL; return FALSE; } - iconInfo->bitsMask = newBitMask; + iconInfo->bitsMask = newBitMask; Stream_Read(s, iconInfo->bitsMask, iconInfo->cbBitsMask); /* colorTable */ @@ -126,21 +127,23 @@ BOOL update_read_icon_info(wStream* s, ICON_INFO* iconInfo) if (iconInfo->cbColorTable) { iconInfo->colorTable = (BYTE*) malloc(iconInfo->cbColorTable); + if (!iconInfo->colorTable) return FALSE; } } else if (iconInfo->cbColorTable) { - BYTE *new_tab; - + BYTE* new_tab; new_tab = (BYTE*) realloc(iconInfo->colorTable, iconInfo->cbColorTable); + if (!new_tab) { - free (iconInfo->colorTable); + free(iconInfo->colorTable); iconInfo->colorTable = NULL; return FALSE; } + iconInfo->colorTable = new_tab; } else @@ -153,17 +156,17 @@ BOOL update_read_icon_info(wStream* s, ICON_INFO* iconInfo) Stream_Read(s, iconInfo->colorTable, iconInfo->cbColorTable); /* bitsColor */ - newBitMask = (BYTE *)realloc(iconInfo->bitsColor, iconInfo->cbBitsColor); + newBitMask = (BYTE*)realloc(iconInfo->bitsColor, iconInfo->cbBitsColor); + if (!newBitMask) { - free (iconInfo->bitsColor); + free(iconInfo->bitsColor); iconInfo->bitsColor = NULL; return FALSE; } + iconInfo->bitsColor = newBitMask; - Stream_Read(s, iconInfo->bitsColor, iconInfo->cbBitsColor); - return TRUE; } @@ -174,7 +177,6 @@ BOOL update_read_cached_icon_info(wStream* s, CACHED_ICON_INFO* cachedIconInfo) Stream_Read_UINT16(s, cachedIconInfo->cacheEntry); /* cacheEntry (2 bytes) */ Stream_Read_UINT8(s, cachedIconInfo->cacheId); /* cacheId (1 byte) */ - return TRUE; } @@ -185,12 +187,12 @@ BOOL update_read_notify_icon_infotip(wStream* s, NOTIFY_ICON_INFOTIP* notifyIcon Stream_Read_UINT32(s, notifyIconInfoTip->timeout); /* timeout (4 bytes) */ Stream_Read_UINT32(s, notifyIconInfoTip->flags); /* infoFlags (4 bytes) */ - return rail_read_unicode_string(s, ¬ifyIconInfoTip->text) && /* infoTipText */ - rail_read_unicode_string(s, ¬ifyIconInfoTip->title); /* title */ + rail_read_unicode_string(s, ¬ifyIconInfoTip->title); /* title */ } -BOOL update_read_window_state_order(wStream* s, WINDOW_ORDER_INFO* orderInfo, WINDOW_STATE_ORDER* windowState) +BOOL update_read_window_state_order(wStream* s, WINDOW_ORDER_INFO* orderInfo, + WINDOW_STATE_ORDER* windowState) { int i; int size; @@ -295,18 +297,21 @@ BOOL update_read_window_state_order(wStream* s, WINDOW_ORDER_INFO* orderInfo, WI Stream_Read_UINT16(s, windowState->numWindowRects); /* numWindowRects (2 bytes) */ - if (windowState->numWindowRects == 0) { + if (windowState->numWindowRects == 0) + { return TRUE; } size = sizeof(RECTANGLE_16) * windowState->numWindowRects; newRect = (RECTANGLE_16*)realloc(windowState->windowRects, size); + if (!newRect) { free(windowState->windowRects); windowState->windowRects = NULL; return FALSE; } + windowState->windowRects = newRect; if (Stream_GetRemainingLength(s) < 8 * windowState->numWindowRects) @@ -338,17 +343,21 @@ BOOL update_read_window_state_order(wStream* s, WINDOW_ORDER_INFO* orderInfo, WI Stream_Read_UINT16(s, windowState->numVisibilityRects); /* numVisibilityRects (2 bytes) */ - if (windowState->numVisibilityRects == 0) { + if (windowState->numVisibilityRects == 0) + { return TRUE; } + size = sizeof(RECTANGLE_16) * windowState->numVisibilityRects; newRect = (RECTANGLE_16*)realloc(windowState->visibilityRects, size); + if (!newRect) { free(windowState->visibilityRects); windowState->visibilityRects = NULL; return FALSE; } + windowState->visibilityRects = newRect; if (Stream_GetRemainingLength(s) < windowState->numVisibilityRects * 8) @@ -363,22 +372,27 @@ BOOL update_read_window_state_order(wStream* s, WINDOW_ORDER_INFO* orderInfo, WI Stream_Read_UINT16(s, windowState->visibilityRects[i].bottom); /* bottom (2 bytes) */ } } + return TRUE; } -BOOL update_read_window_icon_order(wStream* s, WINDOW_ORDER_INFO* orderInfo, WINDOW_ICON_ORDER* window_icon) +BOOL update_read_window_icon_order(wStream* s, WINDOW_ORDER_INFO* orderInfo, + WINDOW_ICON_ORDER* window_icon) { update_free_window_icon_info(window_icon->iconInfo); window_icon->iconInfo = (ICON_INFO*) calloc(1, sizeof(ICON_INFO)); + if (!window_icon->iconInfo) return FALSE; return update_read_icon_info(s, window_icon->iconInfo); /* iconInfo (ICON_INFO) */ } -BOOL update_read_window_cached_icon_order(wStream* s, WINDOW_ORDER_INFO* orderInfo, WINDOW_CACHED_ICON_ORDER* window_cached_icon) +BOOL update_read_window_cached_icon_order(wStream* s, WINDOW_ORDER_INFO* orderInfo, + WINDOW_CACHED_ICON_ORDER* window_cached_icon) { - return update_read_cached_icon_info(s, &window_cached_icon->cachedIcon); /* cachedIcon (CACHED_ICON_INFO) */ + return update_read_cached_icon_info(s, + &window_cached_icon->cachedIcon); /* cachedIcon (CACHED_ICON_INFO) */ } void update_read_window_delete_order(wStream* s, WINDOW_ORDER_INFO* orderInfo) @@ -401,6 +415,7 @@ BOOL update_recv_window_info_order(rdpUpdate* update, wStream* s, WINDOW_ORDER_I { if (!update_read_window_icon_order(s, orderInfo, &window->window_icon)) return FALSE; + WLog_Print(update->log, WLOG_DEBUG, "WindowIcon"); IFCALLRET(window->WindowIcon, result, context, orderInfo, &window->window_icon); } @@ -408,6 +423,7 @@ BOOL update_recv_window_info_order(rdpUpdate* update, wStream* s, WINDOW_ORDER_I { if (!update_read_window_cached_icon_order(s, orderInfo, &window->window_cached_icon)) return FALSE; + WLog_Print(update->log, WLOG_DEBUG, "WindowCachedIcon"); IFCALLRET(window->WindowCachedIcon, result, context, orderInfo, &window->window_cached_icon); } @@ -437,12 +453,14 @@ BOOL update_recv_window_info_order(rdpUpdate* update, wStream* s, WINDOW_ORDER_I return result; } -BOOL update_read_notification_icon_state_order(wStream* s, WINDOW_ORDER_INFO* orderInfo, NOTIFY_ICON_STATE_ORDER* notify_icon_state) +BOOL update_read_notification_icon_state_order(wStream* s, WINDOW_ORDER_INFO* orderInfo, + NOTIFY_ICON_STATE_ORDER* notify_icon_state) { if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_VERSION) { if (Stream_GetRemainingLength(s) < 4) return FALSE; + Stream_Read_UINT32(s, notify_icon_state->version); /* version (4 bytes) */ } @@ -454,7 +472,8 @@ BOOL update_read_notification_icon_state_order(wStream* s, WINDOW_ORDER_INFO* or if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_INFO_TIP) { - if (!update_read_notify_icon_infotip(s, ¬ify_icon_state->infoTip)) /* infoTip (NOTIFY_ICON_INFOTIP) */ + if (!update_read_notify_icon_infotip(s, + ¬ify_icon_state->infoTip)) /* infoTip (NOTIFY_ICON_INFOTIP) */ return FALSE; } @@ -474,7 +493,8 @@ BOOL update_read_notification_icon_state_order(wStream* s, WINDOW_ORDER_INFO* or if (orderInfo->fieldFlags & WINDOW_ORDER_CACHED_ICON) { - if (!update_read_cached_icon_info(s, ¬ify_icon_state->cachedIcon)) /* cachedIcon (CACHED_ICON_INFO) */ + if (!update_read_cached_icon_info(s, + ¬ify_icon_state->cachedIcon)) /* cachedIcon (CACHED_ICON_INFO) */ return FALSE; } @@ -486,7 +506,8 @@ void update_read_notification_icon_delete_order(wStream* s, WINDOW_ORDER_INFO* o /* notification icon deletion event */ } -BOOL update_recv_notification_icon_info_order(rdpUpdate* update, wStream* s, WINDOW_ORDER_INFO* orderInfo) +BOOL update_recv_notification_icon_info_order(rdpUpdate* update, wStream* s, + WINDOW_ORDER_INFO* orderInfo) { rdpContext* context = update->context; rdpWindowUpdate* window = update->window; @@ -524,7 +545,8 @@ BOOL update_recv_notification_icon_info_order(rdpUpdate* update, wStream* s, WIN return result; } -BOOL update_read_desktop_actively_monitored_order(wStream* s, WINDOW_ORDER_INFO* orderInfo, MONITORED_DESKTOP_ORDER* monitored_desktop) +BOOL update_read_desktop_actively_monitored_order(wStream* s, WINDOW_ORDER_INFO* orderInfo, + MONITORED_DESKTOP_ORDER* monitored_desktop) { int i; int size; @@ -539,7 +561,7 @@ BOOL update_read_desktop_actively_monitored_order(wStream* s, WINDOW_ORDER_INFO* if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_DESKTOP_ZORDER) { - UINT32 *newid; + UINT32* newid; if (Stream_GetRemainingLength(s) < 1) return FALSE; @@ -549,16 +571,18 @@ BOOL update_read_desktop_actively_monitored_order(wStream* s, WINDOW_ORDER_INFO* if (Stream_GetRemainingLength(s) < 4 * monitored_desktop->numWindowIds) return FALSE; - if (monitored_desktop->numWindowIds > 0) { + if (monitored_desktop->numWindowIds > 0) + { size = sizeof(UINT32) * monitored_desktop->numWindowIds; - newid = (UINT32*)realloc(monitored_desktop->windowIds, size); + if (!newid) { free(monitored_desktop->windowIds); monitored_desktop->windowIds = NULL; return FALSE; } + monitored_desktop->windowIds = newid; /* windowIds */ @@ -593,6 +617,7 @@ BOOL update_recv_desktop_info_order(rdpUpdate* update, wStream* s, WINDOW_ORDER_ { if (!update_read_desktop_actively_monitored_order(s, orderInfo, &window->monitored_desktop)) return FALSE; + WLog_Print(update->log, WLOG_DEBUG, "ActivelyMonitoredDesktop"); IFCALLRET(window->MonitoredDesktop, result, context, orderInfo, &window->monitored_desktop); } @@ -602,39 +627,44 @@ BOOL update_recv_desktop_info_order(rdpUpdate* update, wStream* s, WINDOW_ORDER_ void update_free_window_icon_info(ICON_INFO* iconInfo) { - if (!iconInfo) - return; - - free(iconInfo->bitsColor); - iconInfo->bitsColor = NULL; - - free(iconInfo->bitsMask); - iconInfo->bitsMask = NULL; - - free(iconInfo->colorTable); - iconInfo->colorTable = NULL; + if (!iconInfo) + return; + free(iconInfo->bitsColor); + iconInfo->bitsColor = NULL; + free(iconInfo->bitsMask); + iconInfo->bitsMask = NULL; + free(iconInfo->colorTable); + iconInfo->colorTable = NULL; free(iconInfo); } BOOL update_recv_altsec_window_order(rdpUpdate* update, wStream* s) { + BOOL rc = TRUE; UINT16 orderSize; rdpWindowUpdate* window = update->window; if (Stream_GetRemainingLength(s) < 6) + { + WLog_Print(update->log, WLOG_ERROR, "Stream short"); return FALSE; + } Stream_Read_UINT16(s, orderSize); /* orderSize (2 bytes) */ Stream_Read_UINT32(s, window->orderInfo.fieldFlags); /* FieldsPresentFlags (4 bytes) */ if (window->orderInfo.fieldFlags & WINDOW_ORDER_TYPE_WINDOW) - return update_recv_window_info_order(update, s, &window->orderInfo); + rc = update_recv_window_info_order(update, s, &window->orderInfo); else if (window->orderInfo.fieldFlags & WINDOW_ORDER_TYPE_NOTIFY) - return update_recv_notification_icon_info_order(update, s, &window->orderInfo); + rc = update_recv_notification_icon_info_order(update, s, &window->orderInfo); else if (window->orderInfo.fieldFlags & WINDOW_ORDER_TYPE_DESKTOP) - return update_recv_desktop_info_order(update, s, &window->orderInfo); + rc = update_recv_desktop_info_order(update, s, &window->orderInfo); - return TRUE; + if (!rc) + WLog_Print(update->log, WLOG_ERROR, "windoworder flags %08"PRIx32" failed", + window->orderInfo.fieldFlags); + + return rc; } diff --git a/libfreerdp/gdi/bitmap.c b/libfreerdp/gdi/bitmap.c index 0c8775362..946111cbf 100644 --- a/libfreerdp/gdi/bitmap.c +++ b/libfreerdp/gdi/bitmap.c @@ -56,7 +56,7 @@ INLINE UINT32 gdi_GetPixel(HGDI_DC hdc, UINT32 nXPos, UINT32 nYPos) { HGDI_BITMAP hBmp = (HGDI_BITMAP) hdc->selectedObject; BYTE* data = &(hBmp->data[(nYPos * hBmp->scanline) + nXPos * GetBytesPerPixel( - hBmp->format)]); + hBmp->format)]); return ReadColor(data, hBmp->format); } @@ -80,7 +80,7 @@ static INLINE UINT32 gdi_SetPixelBmp(HGDI_BITMAP hBmp, UINT32 X, UINT32 Y, UINT32 crColor) { BYTE* p = &hBmp->data[(Y * hBmp->scanline) + X * GetBytesPerPixel( - hBmp->format)]; + hBmp->format)]; WriteColor(p, hBmp->format, crColor); return crColor; } @@ -480,9 +480,15 @@ BOOL gdi_BitBlt(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest, switch (rop) { case GDI_SRCCOPY: + if (!hdcSrc) + return FALSE; + hSrcBmp = (HGDI_BITMAP) hdcSrc->selectedObject; hDstBmp = (HGDI_BITMAP) hdcDest->selectedObject; + if (!hSrcBmp || !hDstBmp) + return FALSE; + if (!freerdp_image_copy(hDstBmp->data, hDstBmp->format, hDstBmp->scanline, nXDest, nYDest, nWidth, nHeight, hSrcBmp->data, hSrcBmp->format, hSrcBmp->scanline, nXSrc, nYSrc, palette, FREERDP_FLIP_NONE)) @@ -494,6 +500,9 @@ BOOL gdi_BitBlt(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest, hSrcBmp = (HGDI_BITMAP) hdcDest->selectedObject; hDstBmp = (HGDI_BITMAP) hdcDest->selectedObject; + if (!hSrcBmp || !hDstBmp) + return FALSE; + if (!freerdp_image_copy(hDstBmp->data, hDstBmp->format, hDstBmp->scanline, nXDest, nYDest, nWidth, nHeight, hSrcBmp->data, hSrcBmp->format, hSrcBmp->scanline, nXSrc, nYSrc, palette, FREERDP_FLIP_NONE)) diff --git a/libfreerdp/gdi/gdi.c b/libfreerdp/gdi/gdi.c index 111518583..02c9f9123 100644 --- a/libfreerdp/gdi/gdi.c +++ b/libfreerdp/gdi/gdi.c @@ -574,7 +574,7 @@ static BOOL gdi_dstblt(rdpContext* context, const DSTBLT_ORDER* dstblt) gdi_rop3_code(dstblt->bRop), &gdi->palette); } -static BOOL gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt) +static BOOL gdi_patblt(rdpContext* context, const PATBLT_ORDER* patblt) { const rdpBrush* brush = &patblt->brush; UINT32 foreColor; @@ -663,9 +663,7 @@ static BOOL gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt) break; } - if (!hbrush) - gdi_DeleteObject((HGDIOBJECT) hBmp); - else + if (hbrush) { hbrush->nXOrg = brush->x; hbrush->nYOrg = brush->y; @@ -676,6 +674,7 @@ static BOOL gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt) } out_error: + gdi_DeleteObject((HGDIOBJECT) hBmp); gdi_DeleteObject((HGDIOBJECT) hbrush); gdi->drawing->hdc->brush = originalBrush; gdi_SetTextColor(gdi->drawing->hdc, originalColor); @@ -933,6 +932,7 @@ static BOOL gdi_mem3blt(rdpContext* context, MEM3BLT_ORDER* mem3blt) mem3blt->nXSrc, mem3blt->nYSrc, gdi_rop3_code(mem3blt->bRop), &gdi->palette); gdi_DeleteObject((HGDIOBJECT) gdi->drawing->hdc->brush); + gdi_DeleteObject((HGDIOBJECT) hBmp); gdi->drawing->hdc->brush = originalBrush; } break; diff --git a/libfreerdp/gdi/graphics.c b/libfreerdp/gdi/graphics.c index fbb3f029c..3ba73fe6b 100644 --- a/libfreerdp/gdi/graphics.c +++ b/libfreerdp/gdi/graphics.c @@ -112,10 +112,11 @@ static void gdi_Bitmap_Free(rdpContext* context, rdpBitmap* bitmap) if (gdi_bitmap) { - gdi_SelectObject(gdi_bitmap->hdc, (HGDIOBJECT) gdi_bitmap->org_bitmap); + if (gdi_bitmap->hdc) + gdi_SelectObject(gdi_bitmap->hdc, (HGDIOBJECT) gdi_bitmap->org_bitmap); + gdi_DeleteObject((HGDIOBJECT) gdi_bitmap->bitmap); gdi_DeleteDC(gdi_bitmap->hdc); - _aligned_free(bitmap->data); } @@ -139,7 +140,6 @@ static BOOL gdi_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap, UINT32 codecId) { UINT32 SrcSize = length; - UINT32 SrcFormat; rdpGdi* gdi = context->gdi; bitmap->compressed = FALSE; bitmap->format = gdi->dstFormat; @@ -173,7 +173,19 @@ static BOOL gdi_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap, } else { - SrcFormat = gdi_get_pixel_format(bpp); + const UINT32 SrcFormat = gdi_get_pixel_format(bpp); + const size_t sbpp = GetBytesPerPixel(SrcFormat); + const size_t dbpp = GetBytesPerPixel(bitmap->format); + + if ((sbpp == 0) || (dbpp == 0)) + return FALSE; + else + { + const size_t dstSize = SrcSize * dbpp / sbpp; + + if (dstSize < bitmap->length) + return FALSE; + } if (!freerdp_image_copy(bitmap->data, bitmap->format, 0, 0, 0, DstWidth, DstHeight, pSrcData, SrcFormat, @@ -193,6 +205,7 @@ static BOOL gdi_Bitmap_SetSurface(rdpContext* context, rdpBitmap* bitmap, return FALSE; gdi = context->gdi; + if (!gdi) return FALSE;