diff --git a/include/freerdp/update.h b/include/freerdp/update.h index 1c8379094..e73654a60 100644 --- a/include/freerdp/update.h +++ b/include/freerdp/update.h @@ -177,6 +177,14 @@ typedef struct uint8* codeDeltaList; } MULTI_SCRBLT_ORDER; +typedef struct +{ + sint16 left; + sint16 top; + sint16 right; + sint16 bottom; +} DELTA_RECT; + typedef struct { sint16 nLeftRect; @@ -184,8 +192,8 @@ typedef struct sint16 nWidth; sint16 nHeight; uint32 color; - uint8 nDeltaEntries; - uint8* codeDeltaList; + uint8 numRectangles; + DELTA_RECT rectangles[45]; } MULTI_OPAQUE_RECT_ORDER; typedef struct diff --git a/libfreerdp-core/orders.c b/libfreerdp-core/orders.c index 08104db9c..e3df1d7a3 100644 --- a/libfreerdp-core/orders.c +++ b/libfreerdp-core/orders.c @@ -184,15 +184,15 @@ void update_read_2byte_unsigned(STREAM* s, uint16* value) stream_read_uint8(s, byte); - if (byte & 0x01) + if (byte & 0x80) { - *value = (byte & 0x7F) << 16; + *value = (byte & 0x7F) << 8; stream_read_uint8(s, byte); *value |= byte; } else { - *value = byte; + *value = (byte & 0x7F); } } @@ -203,17 +203,17 @@ void update_read_2byte_signed(STREAM* s, sint16* value) stream_read_uint8(s, byte); - negative = (byte & 0x02) ? True : False; + negative = (byte & 0x40) ? True : False; - if (byte & 0x01) + if (byte & 0x80) { - *value = (byte & 0x3F) << 16; + *value = (byte & 0x3F) << 8; stream_read_uint8(s, byte); *value |= byte; } else { - *value = byte; + *value = (byte & 0x3F); } if (negative) @@ -506,12 +506,47 @@ void update_read_multi_opaque_rect_order(STREAM* s, ORDER_INFO* orderInfo, MULTI } if (orderInfo->fieldFlags & ORDER_FIELD_08) - stream_read_uint8(s, multi_opaque_rect->nDeltaEntries); + stream_read_uint8(s, multi_opaque_rect->numRectangles); if (orderInfo->fieldFlags & ORDER_FIELD_09) { + int i; + uint8 flags; + uint8* zeroBits; + int zeroBitsSize; + DELTA_RECT* rectangles; + + rectangles = multi_opaque_rect->rectangles; + zeroBitsSize = ((multi_opaque_rect->numRectangles + 1) / 2); + stream_read_uint16(s, cbData); - stream_seek(s, cbData); + + stream_get_mark(s, zeroBits); + stream_seek(s, zeroBitsSize); + + memset(&rectangles[0], 0, sizeof(DELTA_RECT)); + + for (i = 0; i < multi_opaque_rect->numRectangles; i++) + { + flags = zeroBits[i / 2]; + + if (i % 2 == 0) + flags = (flags >> 4) & 0x0F; + else + flags = flags & 0x0F; + + if (~flags & 0x80) + update_read_2byte_signed(s, &rectangles[i].left); + + if (~flags & 0x40); + update_read_2byte_signed(s, &rectangles[i].top); + + if (~flags & 0x20); + update_read_2byte_signed(s, &rectangles[i].right); + + if (~flags & 0x10); + update_read_2byte_signed(s, &rectangles[i].bottom); + } } } diff --git a/libfreerdp-core/orders.h b/libfreerdp-core/orders.h index 90e3d71fb..1c15b5366 100644 --- a/libfreerdp-core/orders.h +++ b/libfreerdp-core/orders.h @@ -97,6 +97,8 @@ #define SO_CHAR_INC_EQUAL_BM_BASE 0x20 #define SO_MAXEXT_EQUAL_BM_SIDE 0x40 +#define SCREEN_BITMAP_SURFACE 0xFFFF + /* Order Classes */ #define ORDER_PRIMARY_CLASS 0x01 #define ORDER_SECONDARY_CLASS 0x03 diff --git a/libfreerdp-gdi/gdi.c b/libfreerdp-gdi/gdi.c index 5cee8f7ec..3e5972bf4 100644 --- a/libfreerdp-gdi/gdi.c +++ b/libfreerdp-gdi/gdi.c @@ -1187,7 +1187,29 @@ void gdi_opaque_rect(rdpUpdate* update, OPAQUE_RECT_ORDER* opaque_rect) void gdi_multi_opaque_rect(rdpUpdate* update, MULTI_OPAQUE_RECT_ORDER* multi_opaque_rect) { + int i; + GDI_RECT rect; + HGDI_BRUSH hBrush; + uint32 brush_color; + DELTA_RECT* rectangle; + GDI *gdi = GET_GDI(update); + for (i = 0; i < multi_opaque_rect->numRectangles; i++) + { + rectangle = &multi_opaque_rect->rectangles[i]; + + rect.left = rectangle->left; + rect.top = rectangle->top; + rect.right = rectangle->right; + rect.bottom = rectangle->bottom; + + brush_color = gdi_color_convert(multi_opaque_rect->color, gdi->srcBpp, 32, gdi->clrconv); + + hBrush = gdi_CreateSolidBrush(brush_color); + gdi_FillRect(gdi->drawing->hdc, &rect, hBrush); + } + + gdi_DeleteObject((HGDIOBJECT) hBrush); } void gdi_line_to(rdpUpdate* update, LINE_TO_ORDER* line_to)