diff --git a/libfreerdp/core/orders.c b/libfreerdp/core/orders.c index 7e3e152ed..15f5b8e3e 100644 --- a/libfreerdp/core/orders.c +++ b/libfreerdp/core/orders.c @@ -271,13 +271,14 @@ static INLINE BOOL update_write_2byte_unsigned(wStream* s, UINT32 value) if (value >= 0x7F) { byte = ((value & 0x7F00) >> 8); - stream_write_BYTE(s, byte); + stream_write_BYTE(s, byte | 0x80); byte = (value & 0xFF); stream_write_BYTE(s, byte); } else { - stream_write_BYTE(s, value); + byte = (value & 0x7F); + stream_write_BYTE(s, byte); } return TRUE; @@ -301,12 +302,52 @@ static INLINE BOOL update_read_2byte_signed(wStream* s, INT32* value) { if (Stream_GetRemainingLength(s) < 1) return FALSE; + stream_read_BYTE(s, byte); *value = (*value << 8) | byte; } if (negative) *value *= -1; + + return TRUE; +} + +static INLINE BOOL update_write_2byte_signed(wStream* s, INT32 value) +{ + BYTE byte; + BOOL negative = FALSE; + + if (value < 0) + { + negative = TRUE; + value *= -1; + } + + if (value > 0x3FFF) + return FALSE; + + if (value >= 0x3F) + { + byte = ((value & 0x3F00) >> 8); + + if (negative) + byte |= 0x40; + + stream_write_BYTE(s, byte | 0x80); + byte = (value & 0xFF); + stream_write_BYTE(s, byte); + } + else + { + byte = (value & 0x3F); + + if (negative) + byte |= 0x40; + + stream_write_BYTE(s, byte); + } + return TRUE; } @@ -968,6 +1009,43 @@ BOOL update_read_memblt_order(wStream* s, ORDER_INFO* orderInfo, MEMBLT_ORDER* m memblt->colorIndex = (memblt->cacheId >> 8); memblt->cacheId = (memblt->cacheId & 0xFF); + + return TRUE; +} + +BOOL update_write_memblt_order(wStream* s, ORDER_INFO* orderInfo, MEMBLT_ORDER* memblt) +{ + UINT16 cacheId; + + cacheId = (memblt->cacheId & 0xFF) | ((memblt->colorIndex & 0xFF) << 8); + + orderInfo->fieldFlags |= ORDER_FIELD_01; + stream_write_UINT16(s, memblt->cacheId); + + orderInfo->fieldFlags |= ORDER_FIELD_02; + update_write_coord(s, memblt->nLeftRect); + + orderInfo->fieldFlags |= ORDER_FIELD_03; + update_write_coord(s, memblt->nTopRect); + + orderInfo->fieldFlags |= ORDER_FIELD_04; + update_write_coord(s, memblt->nWidth); + + orderInfo->fieldFlags |= ORDER_FIELD_05; + update_write_coord(s, memblt->nHeight); + + orderInfo->fieldFlags |= ORDER_FIELD_06; + stream_write_BYTE(s, memblt->bRop); + + orderInfo->fieldFlags |= ORDER_FIELD_07; + update_write_coord(s, memblt->nXSrc); + + orderInfo->fieldFlags |= ORDER_FIELD_08; + update_write_coord(s, memblt->nYSrc); + + orderInfo->fieldFlags |= ORDER_FIELD_09; + stream_write_UINT16(s, memblt->cacheIndex); + return TRUE; } @@ -1506,18 +1584,18 @@ BOOL update_read_cache_glyph_order(wStream* s, CACHE_GLYPH_ORDER* cache_glyph_or return TRUE; } -BOOL update_read_cache_glyph_v2_order(wStream* s, CACHE_GLYPH_V2_ORDER* cache_glyph_v2_order, UINT16 flags) +BOOL update_read_cache_glyph_v2_order(wStream* s, CACHE_GLYPH_V2_ORDER* cache_glyph_v2, UINT16 flags) { int i; GLYPH_DATA_V2* glyph; - cache_glyph_v2_order->cacheId = (flags & 0x000F); - cache_glyph_v2_order->flags = (flags & 0x00F0) >> 4; - cache_glyph_v2_order->cGlyphs = (flags & 0xFF00) >> 8; + cache_glyph_v2->cacheId = (flags & 0x000F); + cache_glyph_v2->flags = (flags & 0x00F0) >> 4; + cache_glyph_v2->cGlyphs = (flags & 0xFF00) >> 8; - for (i = 0; i < (int) cache_glyph_v2_order->cGlyphs; i++) + for (i = 0; i < (int) cache_glyph_v2->cGlyphs; i++) { - glyph = &cache_glyph_v2_order->glyphData[i]; + glyph = &cache_glyph_v2->glyphData[i]; if (Stream_GetRemainingLength(s) < 1) return FALSE; @@ -1544,7 +1622,43 @@ BOOL update_read_cache_glyph_v2_order(wStream* s, CACHE_GLYPH_V2_ORDER* cache_gl if (flags & CG_GLYPH_UNICODE_PRESENT) { - return stream_skip(s, cache_glyph_v2_order->cGlyphs * 2); + return stream_skip(s, cache_glyph_v2->cGlyphs * 2); + } + + return TRUE; +} + +BOOL update_write_cache_glyph_v2_order(wStream* s, CACHE_GLYPH_V2_ORDER* cache_glyph_v2, UINT16* flags) +{ + int i; + GLYPH_DATA_V2* glyph; + + *flags = (cache_glyph_v2->cacheId & 0x000F) | + ((cache_glyph_v2->flags & 0x000F) << 4) | + ((cache_glyph_v2->cGlyphs & 0x00FF) << 8); + + for (i = 0; i < (int) cache_glyph_v2->cGlyphs; i++) + { + glyph = &cache_glyph_v2->glyphData[i]; + + stream_write_BYTE(s, glyph->cacheIndex); + + if (!update_write_2byte_signed(s, glyph->x) || + !update_write_2byte_signed(s, glyph->y) || + !update_write_2byte_unsigned(s, glyph->cx) || + !update_write_2byte_unsigned(s, glyph->cy)) + { + return FALSE; + } + + glyph->cb = ((glyph->cx + 7) / 8) * glyph->cy; + glyph->cb += ((glyph->cb % 4) > 0) ? 4 - (glyph->cb % 4) : 0; + stream_write(s, glyph->aj, glyph->cb); + } + + if (*flags & CG_GLYPH_UNICODE_PRESENT) + { + Stream_Zero(s, cache_glyph_v2->cGlyphs * 2); } return TRUE; diff --git a/libfreerdp/core/orders.h b/libfreerdp/core/orders.h index 3b95c2915..598333c85 100644 --- a/libfreerdp/core/orders.h +++ b/libfreerdp/core/orders.h @@ -202,6 +202,7 @@ BOOL update_read_multi_draw_nine_grid_order(wStream* s, ORDER_INFO* orderInfo, M BOOL update_read_line_to_order(wStream* s, ORDER_INFO* orderInfo, LINE_TO_ORDER* line_to); BOOL update_read_polyline_order(wStream* s, ORDER_INFO* orderInfo, POLYLINE_ORDER* polyline); BOOL update_read_memblt_order(wStream* s, ORDER_INFO* orderInfo, MEMBLT_ORDER* memblt); +BOOL update_write_memblt_order(wStream* s, ORDER_INFO* orderInfo, MEMBLT_ORDER* memblt); BOOL update_read_mem3blt_order(wStream* s, ORDER_INFO* orderInfo, MEM3BLT_ORDER* mem3blt); BOOL update_read_save_bitmap_order(wStream* s, ORDER_INFO* orderInfo, SAVE_BITMAP_ORDER* save_bitmap); BOOL update_read_glyph_index_order(wStream* s, ORDER_INFO* orderInfo, GLYPH_INDEX_ORDER* glyph_index); @@ -219,6 +220,7 @@ BOOL update_read_cache_bitmap_v3_order(wStream* s, CACHE_BITMAP_V3_ORDER* cache_ BOOL update_read_cache_color_table_order(wStream* s, CACHE_COLOR_TABLE_ORDER* cache_color_table_order, UINT16 flags); BOOL update_read_cache_glyph_order(wStream* s, CACHE_GLYPH_ORDER* cache_glyph_order, UINT16 flags); BOOL update_read_cache_glyph_v2_order(wStream* s, CACHE_GLYPH_V2_ORDER* cache_glyph_v2_order, UINT16 flags); +BOOL update_write_cache_glyph_v2_order(wStream* s, CACHE_GLYPH_V2_ORDER* cache_glyph_v2, UINT16* flags); BOOL update_read_cache_brush_order(wStream* s, CACHE_BRUSH_ORDER* cache_brush_order, UINT16 flags); BOOL update_read_create_offscreen_bitmap_order(wStream* s, CREATE_OFFSCREEN_BITMAP_ORDER* create_offscreen_bitmap); diff --git a/libfreerdp/core/update.c b/libfreerdp/core/update.c index 5ecfc455a..56882c077 100644 --- a/libfreerdp/core/update.c +++ b/libfreerdp/core/update.c @@ -619,6 +619,31 @@ static void update_send_opaque_rect(rdpContext* context, OPAQUE_RECT_ORDER* opaq fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_ORDERS, s); } +static void update_send_memblt(rdpContext* context, MEMBLT_ORDER* memblt) +{ + wStream* s; + BYTE *bm, *em; + ORDER_INFO orderInfo; + rdpRdp* rdp = context->rdp; + + orderInfo.fieldFlags = 0; + s = fastpath_update_pdu_init(rdp->fastpath); + bm = Stream_Pointer(s); + + Stream_Seek(s, 5); + update_write_memblt_order(s, &orderInfo, memblt); + em = Stream_Pointer(s); + + Stream_Pointer(s) = bm; + stream_write_UINT16(s, 1); /* numberOrders (2 bytes) */ + stream_write_BYTE(s, ORDER_STANDARD | ORDER_TYPE_CHANGE); /* controlFlags (1 byte) */ + stream_write_BYTE(s, ORDER_TYPE_MEMBLT); /* orderType (1 byte) */ + stream_write_BYTE(s, orderInfo.fieldFlags); /* fieldFlags (variable) */ + Stream_Pointer(s) = em; + + fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_ORDERS, s); +} + static void update_send_cache_bitmap_v2(rdpContext* context, CACHE_BITMAP_V2_ORDER* cache_bitmap_v2) { wStream* s; @@ -637,14 +662,40 @@ static void update_send_cache_bitmap_v2(rdpContext* context, CACHE_BITMAP_V2_ORD Stream_Pointer(s) = bm; stream_write_UINT16(s, 1); /* numberOrders (2 bytes) */ stream_write_BYTE(s, ORDER_STANDARD | ORDER_SECONDARY | ORDER_TYPE_CHANGE); /* controlFlags (1 byte) */ - stream_write_UINT16(s, 0); /* orderLength (2 bytes) */ - stream_write_UINT16(s, 0); /* extraFlags (2 bytes) */ + stream_write_UINT16(s, (em - bm) - 13); /* orderLength (2 bytes) */ + stream_write_UINT16(s, flags); /* extraFlags (2 bytes) */ stream_write_BYTE(s, ORDER_TYPE_BITMAP_UNCOMPRESSED_V2); /* orderType (1 byte) */ Stream_Pointer(s) = em; fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_ORDERS, s); } +static void update_send_cache_glyph_v2(rdpContext* context, CACHE_GLYPH_V2_ORDER* cache_glyph_v2) +{ + wStream* s; + UINT16 flags; + BYTE *bm, *em; + rdpRdp* rdp = context->rdp; + + flags = 0; + s = fastpath_update_pdu_init(rdp->fastpath); + bm = Stream_Pointer(s); + + Stream_Seek(s, 8); + update_write_cache_glyph_v2_order(s, cache_glyph_v2, &flags); + em = Stream_Pointer(s); + + Stream_Pointer(s) = bm; + stream_write_UINT16(s, 1); /* numberOrders (2 bytes) */ + stream_write_BYTE(s, ORDER_STANDARD | ORDER_SECONDARY | ORDER_TYPE_CHANGE); /* controlFlags (1 byte) */ + stream_write_UINT16(s, (em - bm) - 13); /* orderLength (2 bytes) */ + stream_write_UINT16(s, flags); /* extraFlags (2 bytes) */ + stream_write_BYTE(s, ORDER_TYPE_CACHE_GLYPH); /* orderType (1 byte) */ + Stream_Pointer(s) = em; + + fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_ORDERS, s); +} + static void update_send_pointer_system(rdpContext* context, POINTER_SYSTEM_UPDATE* pointer_system) { wStream* s; @@ -775,7 +826,9 @@ void update_register_server_callbacks(rdpUpdate* update) update->SurfaceCommand = update_send_surface_command; update->primary->ScrBlt = update_send_scrblt; update->primary->OpaqueRect = update_send_opaque_rect; + update->primary->MemBlt = update_send_memblt; update->secondary->CacheBitmapV2 = update_send_cache_bitmap_v2; + update->secondary->CacheGlyphV2 = update_send_cache_glyph_v2; update->pointer->PointerSystem = update_send_pointer_system; update->pointer->PointerColor = update_send_pointer_color; update->pointer->PointerNew = update_send_pointer_new;