2 * FreeRDP: A Remote Desktop Protocol Implementation
5 * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
24 #include <winpr/crt.h>
25 #include <winpr/print.h>
26 #include <winpr/synch.h>
27 #include <winpr/thread.h>
28 #include <winpr/collections.h>
34 #include <freerdp/log.h>
35 #include <freerdp/peer.h>
36 #include <freerdp/codec/bitmap.h>
38 #define TAG FREERDP_TAG("core.update")
40 const char* const UPDATE_TYPE_STRINGS[] =
48 extern const BYTE PRIMARY_DRAWING_ORDER_FIELD_BYTES[];
50 BOOL update_recv_orders(rdpUpdate* update, wStream* s)
54 if (Stream_GetRemainingLength(s) < 6)
57 Stream_Seek_UINT16(s); /* pad2OctetsA (2 bytes) */
58 Stream_Read_UINT16(s, numberOrders); /* numberOrders (2 bytes) */
59 Stream_Seek_UINT16(s); /* pad2OctetsB (2 bytes) */
61 while (numberOrders > 0)
63 if (!update_recv_order(update, s))
72 BOOL update_read_bitmap_data(rdpUpdate* update, wStream* s, BITMAP_DATA* bitmapData)
74 if (Stream_GetRemainingLength(s) < 18)
77 Stream_Read_UINT16(s, bitmapData->destLeft);
78 Stream_Read_UINT16(s, bitmapData->destTop);
79 Stream_Read_UINT16(s, bitmapData->destRight);
80 Stream_Read_UINT16(s, bitmapData->destBottom);
81 Stream_Read_UINT16(s, bitmapData->width);
82 Stream_Read_UINT16(s, bitmapData->height);
83 Stream_Read_UINT16(s, bitmapData->bitsPerPixel);
84 Stream_Read_UINT16(s, bitmapData->flags);
85 Stream_Read_UINT16(s, bitmapData->bitmapLength);
87 if (bitmapData->flags & BITMAP_COMPRESSION)
89 if (!(bitmapData->flags & NO_BITMAP_COMPRESSION_HDR))
91 Stream_Read_UINT16(s, bitmapData->cbCompFirstRowSize); /* cbCompFirstRowSize (2 bytes) */
92 Stream_Read_UINT16(s, bitmapData->cbCompMainBodySize); /* cbCompMainBodySize (2 bytes) */
93 Stream_Read_UINT16(s, bitmapData->cbScanWidth); /* cbScanWidth (2 bytes) */
94 Stream_Read_UINT16(s, bitmapData->cbUncompressedSize); /* cbUncompressedSize (2 bytes) */
95 bitmapData->bitmapLength = bitmapData->cbCompMainBodySize;
98 bitmapData->compressed = TRUE;
99 Stream_GetPointer(s, bitmapData->bitmapDataStream);
100 Stream_Seek(s, bitmapData->bitmapLength);
104 if (Stream_GetRemainingLength(s) < bitmapData->bitmapLength)
107 bitmapData->compressed = FALSE;
108 Stream_GetPointer(s, bitmapData->bitmapDataStream);
109 Stream_Seek(s, bitmapData->bitmapLength);
115 BOOL update_write_bitmap_data(rdpUpdate* update, wStream* s, BITMAP_DATA* bitmapData)
117 Stream_EnsureRemainingCapacity(s, 64 + bitmapData->bitmapLength);
119 bitmapData->flags = 0;
120 bitmapData->cbCompFirstRowSize = 0;
122 if (bitmapData->compressed)
123 bitmapData->flags |= BITMAP_COMPRESSION;
125 if (update->context->settings->NoBitmapCompressionHeader)
127 bitmapData->flags |= NO_BITMAP_COMPRESSION_HDR;
128 bitmapData->cbCompMainBodySize = bitmapData->bitmapLength;
131 Stream_Write_UINT16(s, bitmapData->destLeft);
132 Stream_Write_UINT16(s, bitmapData->destTop);
133 Stream_Write_UINT16(s, bitmapData->destRight);
134 Stream_Write_UINT16(s, bitmapData->destBottom);
135 Stream_Write_UINT16(s, bitmapData->width);
136 Stream_Write_UINT16(s, bitmapData->height);
137 Stream_Write_UINT16(s, bitmapData->bitsPerPixel);
138 Stream_Write_UINT16(s, bitmapData->flags);
139 Stream_Write_UINT16(s, bitmapData->bitmapLength);
141 if (bitmapData->flags & BITMAP_COMPRESSION)
143 if (!(bitmapData->flags & NO_BITMAP_COMPRESSION_HDR))
145 Stream_Write_UINT16(s, bitmapData->cbCompFirstRowSize); /* cbCompFirstRowSize (2 bytes) */
146 Stream_Write_UINT16(s, bitmapData->cbCompMainBodySize); /* cbCompMainBodySize (2 bytes) */
147 Stream_Write_UINT16(s, bitmapData->cbScanWidth); /* cbScanWidth (2 bytes) */
148 Stream_Write_UINT16(s, bitmapData->cbUncompressedSize); /* cbUncompressedSize (2 bytes) */
151 Stream_Write(s, bitmapData->bitmapDataStream, bitmapData->bitmapLength);
155 Stream_Write(s, bitmapData->bitmapDataStream, bitmapData->bitmapLength);
161 BOOL update_read_bitmap_update(rdpUpdate* update, wStream* s, BITMAP_UPDATE* bitmapUpdate)
165 if (Stream_GetRemainingLength(s) < 2)
168 Stream_Read_UINT16(s, bitmapUpdate->number); /* numberRectangles (2 bytes) */
170 WLog_Print(update->log, WLOG_DEBUG, "BitmapUpdate: %d", bitmapUpdate->number);
172 if (bitmapUpdate->number > bitmapUpdate->count)
176 count = bitmapUpdate->number * 2;
178 bitmapUpdate->rectangles = (BITMAP_DATA*) realloc(bitmapUpdate->rectangles,
179 sizeof(BITMAP_DATA) * count);
181 ZeroMemory(&bitmapUpdate->rectangles[bitmapUpdate->count],
182 sizeof(BITMAP_DATA) * (count - bitmapUpdate->count));
184 bitmapUpdate->count = count;
188 for (i = 0; i < (int) bitmapUpdate->number; i++)
190 if (!update_read_bitmap_data(update, s, &bitmapUpdate->rectangles[i]))
196 BOOL update_write_bitmap_update(rdpUpdate* update, wStream* s, BITMAP_UPDATE* bitmapUpdate)
200 Stream_EnsureRemainingCapacity(s, 32);
202 Stream_Write_UINT16(s, UPDATE_TYPE_BITMAP); /* updateType */
204 Stream_Write_UINT16(s, bitmapUpdate->number); /* numberRectangles (2 bytes) */
207 for (i = 0; i < (int) bitmapUpdate->number; i++)
209 if (!update_write_bitmap_data(update, s, &bitmapUpdate->rectangles[i]))
216 BOOL update_read_palette(rdpUpdate* update, wStream* s, PALETTE_UPDATE* palette_update)
219 PALETTE_ENTRY* entry;
221 if (Stream_GetRemainingLength(s) < 6)
224 Stream_Seek_UINT16(s); /* pad2Octets (2 bytes) */
225 Stream_Read_UINT32(s, palette_update->number); /* numberColors (4 bytes), must be set to 256 */
227 if (palette_update->number > 256)
228 palette_update->number = 256;
230 if (Stream_GetRemainingLength(s) < palette_update->number * 3)
234 for (i = 0; i < (int) palette_update->number; i++)
236 entry = &palette_update->entries[i];
238 Stream_Read_UINT8(s, entry->red);
239 Stream_Read_UINT8(s, entry->green);
240 Stream_Read_UINT8(s, entry->blue);
245 void update_read_synchronize(rdpUpdate* update, wStream* s)
247 Stream_Seek_UINT16(s); /* pad2Octets (2 bytes) */
250 * The Synchronize Update is an artifact from the
251 * T.128 protocol and should be ignored.
255 BOOL update_read_play_sound(wStream* s, PLAY_SOUND_UPDATE* play_sound)
257 if (Stream_GetRemainingLength(s) < 8)
260 Stream_Read_UINT32(s, play_sound->duration); /* duration (4 bytes) */
261 Stream_Read_UINT32(s, play_sound->frequency); /* frequency (4 bytes) */
266 BOOL update_recv_play_sound(rdpUpdate* update, wStream* s)
268 if (!update_read_play_sound(s, &update->play_sound))
271 IFCALL(update->PlaySound, update->context, &update->play_sound);
275 BOOL update_read_pointer_position(wStream* s, POINTER_POSITION_UPDATE* pointer_position)
277 if (Stream_GetRemainingLength(s) < 4)
280 Stream_Read_UINT16(s, pointer_position->xPos); /* xPos (2 bytes) */
281 Stream_Read_UINT16(s, pointer_position->yPos); /* yPos (2 bytes) */
285 BOOL update_read_pointer_system(wStream* s, POINTER_SYSTEM_UPDATE* pointer_system)
287 if (Stream_GetRemainingLength(s) < 4)
290 Stream_Read_UINT32(s, pointer_system->type); /* systemPointerType (4 bytes) */
294 BOOL update_read_pointer_color(wStream* s, POINTER_COLOR_UPDATE* pointer_color, int xorBpp)
299 if (Stream_GetRemainingLength(s) < 14)
302 Stream_Read_UINT16(s, pointer_color->cacheIndex); /* cacheIndex (2 bytes) */
303 Stream_Read_UINT16(s, pointer_color->xPos); /* xPos (2 bytes) */
304 Stream_Read_UINT16(s, pointer_color->yPos); /* yPos (2 bytes) */
307 * As stated in 2.2.9.1.1.4.4 Color Pointer Update:
308 * The maximum allowed pointer width/height is 96 pixels if the client indicated support
309 * for large pointers by setting the LARGE_POINTER_FLAG (0x00000001) in the Large
310 * Pointer Capability Set (section 2.2.7.2.7). If the LARGE_POINTER_FLAG was not
311 * set, the maximum allowed pointer width/height is 32 pixels.
313 * So we check for a maximum of 96 for CVE-2014-0250.
315 Stream_Read_UINT16(s, pointer_color->width); /* width (2 bytes) */
316 Stream_Read_UINT16(s, pointer_color->height); /* height (2 bytes) */
317 if ((pointer_color->width > 96) || (pointer_color->height > 96))
320 Stream_Read_UINT16(s, pointer_color->lengthAndMask); /* lengthAndMask (2 bytes) */
321 Stream_Read_UINT16(s, pointer_color->lengthXorMask); /* lengthXorMask (2 bytes) */
324 * There does not seem to be any documentation on why
325 * xPos / yPos can be larger than width / height
326 * so it is missing in documentation or a bug in implementation
327 * 2.2.9.1.1.4.4 Color Pointer Update (TS_COLORPOINTERATTRIBUTE)
329 if (pointer_color->xPos >= pointer_color->width)
330 pointer_color->xPos = 0;
331 if (pointer_color->yPos >= pointer_color->height)
332 pointer_color->yPos = 0;
334 if (pointer_color->lengthXorMask > 0)
339 * xorMaskData (variable): A variable-length array of bytes. Contains the 24-bpp, bottom-up
340 * XOR mask scan-line data. The XOR mask is padded to a 2-byte boundary for each encoded
341 * scan-line. For example, if a 3x3 pixel cursor is being sent, then each scan-line will consume 10
342 * bytes (3 pixels per scan-line multiplied by 3 bytes per pixel, rounded up to the next even
345 * In fact instead of 24-bpp, the bpp parameter is given by the containing packet.
347 if (Stream_GetRemainingLength(s) < pointer_color->lengthXorMask)
350 scanlineSize = (7 + xorBpp * pointer_color->width) / 8;
351 scanlineSize = ((scanlineSize + 1) / 2) * 2;
352 if (scanlineSize * pointer_color->height != pointer_color->lengthXorMask)
354 WLog_ERR(TAG, "invalid lengthXorMask: width=%d height=%d, %d instead of %d",
355 pointer_color->width, pointer_color->height,
356 pointer_color->lengthXorMask, scanlineSize * pointer_color->height);
360 newMask = realloc(pointer_color->xorMaskData, pointer_color->lengthXorMask);
364 pointer_color->xorMaskData = newMask;
366 Stream_Read(s, pointer_color->xorMaskData, pointer_color->lengthXorMask);
369 if (pointer_color->lengthAndMask > 0)
372 * andMaskData (variable): A variable-length array of bytes. Contains the 1-bpp, bottom-up
373 * AND mask scan-line data. The AND mask is padded to a 2-byte boundary for each encoded
374 * scan-line. For example, if a 7x7 pixel cursor is being sent, then each scan-line will consume 2
375 * bytes (7 pixels per scan-line multiplied by 1 bpp, rounded up to the next even number of
378 if (Stream_GetRemainingLength(s) < pointer_color->lengthAndMask)
381 scanlineSize = ((7 + pointer_color->width) / 8);
382 scanlineSize = ((1 + scanlineSize) / 2) * 2;
383 if (scanlineSize * pointer_color->height != pointer_color->lengthAndMask)
385 WLog_ERR(TAG, "invalid lengthAndMask: %d instead of %d",
386 pointer_color->lengthAndMask, scanlineSize * pointer_color->height);
390 newMask = realloc(pointer_color->andMaskData, pointer_color->lengthAndMask);
394 pointer_color->andMaskData = newMask;
396 Stream_Read(s, pointer_color->andMaskData, pointer_color->lengthAndMask);
399 if (Stream_GetRemainingLength(s) > 0)
400 Stream_Seek_UINT8(s); /* pad (1 byte) */
405 BOOL update_read_pointer_new(wStream* s, POINTER_NEW_UPDATE* pointer_new)
407 if (Stream_GetRemainingLength(s) < 2)
410 Stream_Read_UINT16(s, pointer_new->xorBpp); /* xorBpp (2 bytes) */
411 if ((pointer_new->xorBpp < 1) || (pointer_new->xorBpp > 32))
413 WLog_ERR(TAG, "invalid xorBpp %d", pointer_new->xorBpp);
416 return update_read_pointer_color(s, &pointer_new->colorPtrAttr, pointer_new->xorBpp); /* colorPtrAttr */
419 BOOL update_read_pointer_cached(wStream* s, POINTER_CACHED_UPDATE* pointer_cached)
421 if (Stream_GetRemainingLength(s) < 2)
424 Stream_Read_UINT16(s, pointer_cached->cacheIndex); /* cacheIndex (2 bytes) */
428 BOOL update_recv_pointer(rdpUpdate* update, wStream* s)
431 rdpContext* context = update->context;
432 rdpPointerUpdate* pointer = update->pointer;
434 if (Stream_GetRemainingLength(s) < 2 + 2)
437 Stream_Read_UINT16(s, messageType); /* messageType (2 bytes) */
438 Stream_Seek_UINT16(s); /* pad2Octets (2 bytes) */
442 case PTR_MSG_TYPE_POSITION:
443 if (!update_read_pointer_position(s, &pointer->pointer_position))
445 IFCALL(pointer->PointerPosition, context, &pointer->pointer_position);
448 case PTR_MSG_TYPE_SYSTEM:
449 if (!update_read_pointer_system(s, &pointer->pointer_system))
451 IFCALL(pointer->PointerSystem, context, &pointer->pointer_system);
454 case PTR_MSG_TYPE_COLOR:
455 if (!update_read_pointer_color(s, &pointer->pointer_color, 24))
457 IFCALL(pointer->PointerColor, context, &pointer->pointer_color);
460 case PTR_MSG_TYPE_POINTER:
461 if (!update_read_pointer_new(s, &pointer->pointer_new))
463 IFCALL(pointer->PointerNew, context, &pointer->pointer_new);
466 case PTR_MSG_TYPE_CACHED:
467 if (!update_read_pointer_cached(s, &pointer->pointer_cached))
469 IFCALL(pointer->PointerCached, context, &pointer->pointer_cached);
478 BOOL update_recv(rdpUpdate* update, wStream* s)
481 rdpContext* context = update->context;
483 if (Stream_GetRemainingLength(s) < 2)
486 Stream_Read_UINT16(s, updateType); /* updateType (2 bytes) */
487 //WLog_DBG(TAG, "%s Update Data PDU", UPDATE_TYPE_STRINGS[updateType]);
489 IFCALL(update->BeginPaint, context);
493 case UPDATE_TYPE_ORDERS:
494 if (!update_recv_orders(update, s))
496 /* XXX: Do we have to call EndPaint? */
501 case UPDATE_TYPE_BITMAP:
502 if (!update_read_bitmap_update(update, s, &update->bitmap_update))
504 IFCALL(update->BitmapUpdate, context, &update->bitmap_update);
507 case UPDATE_TYPE_PALETTE:
508 if (!update_read_palette(update, s, &update->palette_update))
510 IFCALL(update->Palette, context, &update->palette_update);
513 case UPDATE_TYPE_SYNCHRONIZE:
514 update_read_synchronize(update, s);
515 IFCALL(update->Synchronize, context);
519 IFCALL(update->EndPaint, context);
524 void update_reset_state(rdpUpdate* update)
526 rdpPrimaryUpdate* primary = update->primary;
527 rdpAltSecUpdate* altsec = update->altsec;
529 ZeroMemory(&primary->order_info, sizeof(ORDER_INFO));
530 ZeroMemory(&primary->dstblt, sizeof(DSTBLT_ORDER));
531 ZeroMemory(&primary->patblt, sizeof(PATBLT_ORDER));
532 ZeroMemory(&primary->scrblt, sizeof(SCRBLT_ORDER));
533 ZeroMemory(&primary->opaque_rect, sizeof(OPAQUE_RECT_ORDER));
534 ZeroMemory(&primary->draw_nine_grid, sizeof(DRAW_NINE_GRID_ORDER));
535 ZeroMemory(&primary->multi_dstblt, sizeof(MULTI_DSTBLT_ORDER));
536 ZeroMemory(&primary->multi_patblt, sizeof(MULTI_PATBLT_ORDER));
537 ZeroMemory(&primary->multi_scrblt, sizeof(MULTI_SCRBLT_ORDER));
538 ZeroMemory(&primary->multi_opaque_rect, sizeof(MULTI_OPAQUE_RECT_ORDER));
539 ZeroMemory(&primary->multi_draw_nine_grid, sizeof(MULTI_DRAW_NINE_GRID_ORDER));
540 ZeroMemory(&primary->line_to, sizeof(LINE_TO_ORDER));
541 ZeroMemory(&primary->polyline, sizeof(POLYLINE_ORDER));
542 ZeroMemory(&primary->memblt, sizeof(MEMBLT_ORDER));
543 ZeroMemory(&primary->mem3blt, sizeof(MEM3BLT_ORDER));
544 ZeroMemory(&primary->save_bitmap, sizeof(SAVE_BITMAP_ORDER));
545 ZeroMemory(&primary->glyph_index, sizeof(GLYPH_INDEX_ORDER));
546 ZeroMemory(&primary->fast_index, sizeof(FAST_INDEX_ORDER));
547 ZeroMemory(&primary->fast_glyph, sizeof(FAST_GLYPH_ORDER));
548 ZeroMemory(&primary->polygon_sc, sizeof(POLYGON_SC_ORDER));
549 ZeroMemory(&primary->polygon_cb, sizeof(POLYGON_CB_ORDER));
550 ZeroMemory(&primary->ellipse_sc, sizeof(ELLIPSE_SC_ORDER));
551 ZeroMemory(&primary->ellipse_cb, sizeof(ELLIPSE_CB_ORDER));
553 primary->order_info.orderType = ORDER_TYPE_PATBLT;
555 if (!update->initialState)
557 altsec->switch_surface.bitmapId = SCREEN_BITMAP_SURFACE;
558 IFCALL(altsec->SwitchSurface, update->context, &(altsec->switch_surface));
562 void update_post_connect(rdpUpdate* update)
564 update->asynchronous = update->context->settings->AsyncUpdate;
566 if (update->asynchronous)
567 update->proxy = update_message_proxy_new(update);
569 update->altsec->switch_surface.bitmapId = SCREEN_BITMAP_SURFACE;
570 IFCALL(update->altsec->SwitchSurface, update->context, &(update->altsec->switch_surface));
572 update->initialState = FALSE;
575 void update_post_disconnect(rdpUpdate* update)
577 update->asynchronous = update->context->settings->AsyncUpdate;
579 if (update->asynchronous)
580 update_message_proxy_free(update->proxy);
583 static void update_begin_paint(rdpContext* context)
586 rdpUpdate* update = context->update;
589 update->EndPaint(context);
591 s = fastpath_update_pdu_init_new(context->rdp->fastpath);
592 Stream_SealLength(s);
593 Stream_Seek(s, 2); /* numberOrders (2 bytes) */
595 update->combineUpdates = TRUE;
596 update->numberOrders = 0;
600 static void update_end_paint(rdpContext* context)
604 rdpUpdate* update = context->update;
610 headerLength = Stream_Length(s);
611 Stream_SealLength(s);
613 Stream_SetPosition(s, headerLength);
614 Stream_Write_UINT16(s, update->numberOrders); /* numberOrders (2 bytes) */
615 Stream_SetPosition(s, Stream_Length(s));
617 if (update->numberOrders > 0)
619 WLog_ERR(TAG, "sending %d orders", update->numberOrders);
620 fastpath_send_update_pdu(context->rdp->fastpath, FASTPATH_UPDATETYPE_ORDERS, s);
623 update->combineUpdates = FALSE;
624 update->numberOrders = 0;
627 Stream_Free(s, TRUE);
630 static void update_flush(rdpContext* context)
632 rdpUpdate* update = context->update;
634 if (update->numberOrders > 0)
636 update->EndPaint(context);
637 update->BeginPaint(context);
641 static void update_force_flush(rdpContext* context)
643 rdpUpdate* update = context->update;
645 if (update->numberOrders > 0)
647 update->EndPaint(context);
648 update->BeginPaint(context);
652 static BOOL update_check_flush(rdpContext* context, int size)
655 rdpUpdate* update = context->update;
661 update->BeginPaint(context);
665 if (Stream_GetPosition(s) + size + 64 >= 0x3FFF)
667 update_flush(context);
674 static void update_set_bounds(rdpContext* context, rdpBounds* bounds)
676 rdpUpdate* update = context->update;
678 CopyMemory(&update->previousBounds, &update->currentBounds, sizeof(rdpBounds));
681 ZeroMemory(&update->currentBounds, sizeof(rdpBounds));
683 CopyMemory(&update->currentBounds, bounds, sizeof(rdpBounds));
686 BOOL update_bounds_is_null(rdpBounds* bounds)
688 if ((bounds->left == 0) && (bounds->top == 0) &&
689 (bounds->right == 0) && (bounds->bottom == 0))
695 BOOL update_bounds_equals(rdpBounds* bounds1, rdpBounds* bounds2)
697 if ((bounds1->left == bounds2->left) && (bounds1->top == bounds2->top) &&
698 (bounds1->right == bounds2->right) && (bounds1->bottom == bounds2->bottom))
704 int update_prepare_bounds(rdpContext* context, ORDER_INFO* orderInfo)
707 rdpUpdate* update = context->update;
709 orderInfo->boundsFlags = 0;
711 if (update_bounds_is_null(&update->currentBounds))
714 orderInfo->controlFlags |= ORDER_BOUNDS;
716 if (update_bounds_equals(&update->previousBounds, &update->currentBounds))
718 orderInfo->controlFlags |= ORDER_ZERO_BOUNDS_DELTAS;
725 if (update->previousBounds.left != update->currentBounds.left)
727 orderInfo->bounds.left = update->currentBounds.left;
728 orderInfo->boundsFlags |= BOUND_LEFT;
732 if (update->previousBounds.top != update->currentBounds.top)
734 orderInfo->bounds.top = update->currentBounds.top;
735 orderInfo->boundsFlags |= BOUND_TOP;
739 if (update->previousBounds.right != update->currentBounds.right)
741 orderInfo->bounds.right = update->currentBounds.right;
742 orderInfo->boundsFlags |= BOUND_RIGHT;
746 if (update->previousBounds.bottom != update->currentBounds.bottom)
748 orderInfo->bounds.bottom = update->currentBounds.bottom;
749 orderInfo->boundsFlags |= BOUND_BOTTOM;
757 int update_prepare_order_info(rdpContext* context, ORDER_INFO* orderInfo, UINT32 orderType)
761 orderInfo->fieldFlags = 0;
762 orderInfo->orderType = orderType;
764 orderInfo->controlFlags = ORDER_STANDARD;
766 orderInfo->controlFlags |= ORDER_TYPE_CHANGE;
769 length += PRIMARY_DRAWING_ORDER_FIELD_BYTES[orderInfo->orderType];
771 length += update_prepare_bounds(context, orderInfo);
776 int update_write_order_info(rdpContext* context, wStream* s, ORDER_INFO* orderInfo, int offset)
780 position = Stream_GetPosition(s);
781 Stream_SetPosition(s, offset);
783 Stream_Write_UINT8(s, orderInfo->controlFlags); /* controlFlags (1 byte) */
785 if (orderInfo->controlFlags & ORDER_TYPE_CHANGE)
786 Stream_Write_UINT8(s, orderInfo->orderType); /* orderType (1 byte) */
788 update_write_field_flags(s, orderInfo->fieldFlags, orderInfo->controlFlags,
789 PRIMARY_DRAWING_ORDER_FIELD_BYTES[orderInfo->orderType]);
791 update_write_bounds(s, orderInfo);
793 Stream_SetPosition(s, position);
798 static void update_write_refresh_rect(wStream* s, BYTE count, RECTANGLE_16* areas)
802 Stream_Write_UINT8(s, count); /* numberOfAreas (1 byte) */
803 Stream_Seek(s, 3); /* pad3Octets (3 bytes) */
805 for (i = 0; i < count; i++)
807 Stream_Write_UINT16(s, areas[i].left); /* left (2 bytes) */
808 Stream_Write_UINT16(s, areas[i].top); /* top (2 bytes) */
809 Stream_Write_UINT16(s, areas[i].right); /* right (2 bytes) */
810 Stream_Write_UINT16(s, areas[i].bottom); /* bottom (2 bytes) */
814 static void update_send_refresh_rect(rdpContext* context, BYTE count, RECTANGLE_16* areas)
817 rdpRdp* rdp = context->rdp;
819 if (rdp->settings->RefreshRect)
821 s = rdp_data_pdu_init(rdp);
822 update_write_refresh_rect(s, count, areas);
824 rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_REFRESH_RECT, rdp->mcs->userId);
829 static void update_write_suppress_output(wStream* s, BYTE allow, RECTANGLE_16* area)
831 Stream_Write_UINT8(s, allow); /* allowDisplayUpdates (1 byte) */
832 Stream_Seek(s, 3); /* pad3Octets (3 bytes) */
836 Stream_Write_UINT16(s, area->left); /* left (2 bytes) */
837 Stream_Write_UINT16(s, area->top); /* top (2 bytes) */
838 Stream_Write_UINT16(s, area->right); /* right (2 bytes) */
839 Stream_Write_UINT16(s, area->bottom); /* bottom (2 bytes) */
843 static void update_send_suppress_output(rdpContext* context, BYTE allow, RECTANGLE_16* area)
846 rdpRdp* rdp = context->rdp;
848 if (rdp->settings->SuppressOutput)
850 s = rdp_data_pdu_init(rdp);
851 update_write_suppress_output(s, allow, area);
853 rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SUPPRESS_OUTPUT, rdp->mcs->userId);
858 static void update_send_surface_command(rdpContext* context, wStream* s)
861 rdpRdp* rdp = context->rdp;
863 update = fastpath_update_pdu_init(rdp->fastpath);
864 Stream_EnsureRemainingCapacity(update, Stream_GetPosition(s));
865 Stream_Write(update, Stream_Buffer(s), Stream_GetPosition(s));
866 fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, update);
867 Stream_Release(update);
870 static void update_send_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surfaceBitsCommand)
873 rdpRdp* rdp = context->rdp;
875 update_force_flush(context);
877 s = fastpath_update_pdu_init(rdp->fastpath);
878 Stream_EnsureRemainingCapacity(s, SURFCMD_SURFACE_BITS_HEADER_LENGTH + (int) surfaceBitsCommand->bitmapDataLength);
879 update_write_surfcmd_surface_bits_header(s, surfaceBitsCommand);
880 Stream_Write(s, surfaceBitsCommand->bitmapData, surfaceBitsCommand->bitmapDataLength);
881 fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, s);
883 update_force_flush(context);
888 static void update_send_surface_frame_marker(rdpContext* context, SURFACE_FRAME_MARKER* surfaceFrameMarker)
891 rdpRdp* rdp = context->rdp;
893 update_force_flush(context);
895 s = fastpath_update_pdu_init(rdp->fastpath);
896 update_write_surfcmd_frame_marker(s, surfaceFrameMarker->frameAction, surfaceFrameMarker->frameId);
897 fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, s);
899 update_force_flush(context);
904 static void update_send_surface_frame_bits(rdpContext* context, SURFACE_BITS_COMMAND* cmd, BOOL first, BOOL last, UINT32 frameId)
907 rdpRdp* rdp = context->rdp;
909 update_force_flush(context);
911 s = fastpath_update_pdu_init(rdp->fastpath);
912 Stream_EnsureRemainingCapacity(s, SURFCMD_SURFACE_BITS_HEADER_LENGTH + (int) cmd->bitmapDataLength + 16);
915 update_write_surfcmd_frame_marker(s, SURFACECMD_FRAMEACTION_BEGIN, frameId);
917 update_write_surfcmd_surface_bits_header(s, cmd);
918 Stream_Write(s, cmd->bitmapData, cmd->bitmapDataLength);
922 update_write_surfcmd_frame_marker(s, SURFACECMD_FRAMEACTION_END, frameId);
924 fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, s);
926 update_force_flush(context);
931 static void update_send_frame_acknowledge(rdpContext* context, UINT32 frameId)
934 rdpRdp* rdp = context->rdp;
936 if (rdp->settings->ReceivedCapabilities[CAPSET_TYPE_FRAME_ACKNOWLEDGE])
938 s = rdp_data_pdu_init(rdp);
939 Stream_Write_UINT32(s, frameId);
940 rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_FRAME_ACKNOWLEDGE, rdp->mcs->userId);
945 static void update_send_synchronize(rdpContext* context)
948 rdpRdp* rdp = context->rdp;
950 s = fastpath_update_pdu_init(rdp->fastpath);
951 Stream_Zero(s, 2); /* pad2Octets (2 bytes) */
952 fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SYNCHRONIZE, s);
956 static void update_send_desktop_resize(rdpContext* context)
958 rdp_server_reactivate(context->rdp);
961 static void update_send_bitmap_update(rdpContext* context, BITMAP_UPDATE* bitmapUpdate)
964 rdpRdp* rdp = context->rdp;
965 rdpUpdate* update = context->update;
967 update_force_flush(context);
969 s = fastpath_update_pdu_init(rdp->fastpath);
970 update_write_bitmap_update(update, s, bitmapUpdate);
971 fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_BITMAP, s);
973 update_force_flush(context);
978 static void update_send_play_sound(rdpContext* context, PLAY_SOUND_UPDATE* play_sound)
981 rdpRdp* rdp = context->rdp;
983 if (!rdp->settings->ReceivedCapabilities[CAPSET_TYPE_SOUND]) {
986 s = rdp_data_pdu_init(rdp);
987 Stream_Write_UINT32(s, play_sound->duration);
988 Stream_Write_UINT32(s, play_sound->frequency);
989 rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_PLAY_SOUND, rdp->mcs->userId);
993 * Primary Drawing Orders
996 static void update_send_dstblt(rdpContext* context, DSTBLT_ORDER* dstblt)
1001 ORDER_INFO orderInfo;
1002 rdpUpdate* update = context->update;
1004 headerLength = update_prepare_order_info(context, &orderInfo, ORDER_TYPE_DSTBLT);
1006 update_check_flush(context, headerLength + update_approximate_dstblt_order(&orderInfo, dstblt));
1009 offset = Stream_GetPosition(s);
1011 Stream_EnsureRemainingCapacity(s, headerLength);
1012 Stream_Seek(s, headerLength);
1014 update_write_dstblt_order(s, &orderInfo, dstblt);
1015 update_write_order_info(context, s, &orderInfo, offset);
1017 update->numberOrders++;
1020 static void update_send_patblt(rdpContext* context, PATBLT_ORDER* patblt)
1025 ORDER_INFO orderInfo;
1026 rdpUpdate* update = context->update;
1028 headerLength = update_prepare_order_info(context, &orderInfo, ORDER_TYPE_PATBLT);
1030 update_check_flush(context, headerLength + update_approximate_patblt_order(&orderInfo, patblt));
1033 offset = Stream_GetPosition(s);
1035 Stream_EnsureRemainingCapacity(s, headerLength);
1036 Stream_Seek(s, headerLength);
1038 update_write_patblt_order(s, &orderInfo, patblt);
1039 update_write_order_info(context, s, &orderInfo, offset);
1041 update->numberOrders++;
1044 static void update_send_scrblt(rdpContext* context, SCRBLT_ORDER* scrblt)
1049 ORDER_INFO orderInfo;
1050 rdpUpdate* update = context->update;
1052 headerLength = update_prepare_order_info(context, &orderInfo, ORDER_TYPE_SCRBLT);
1054 update_check_flush(context, headerLength + update_approximate_scrblt_order(&orderInfo, scrblt));
1057 offset = Stream_GetPosition(s);
1059 Stream_EnsureRemainingCapacity(s, headerLength);
1060 Stream_Seek(s, headerLength);
1062 update_write_scrblt_order(s, &orderInfo, scrblt);
1063 update_write_order_info(context, s, &orderInfo, offset);
1065 update->numberOrders++;
1068 static void update_send_opaque_rect(rdpContext* context, OPAQUE_RECT_ORDER* opaque_rect)
1073 ORDER_INFO orderInfo;
1074 rdpUpdate* update = context->update;
1076 headerLength = update_prepare_order_info(context, &orderInfo, ORDER_TYPE_OPAQUE_RECT);
1078 update_check_flush(context, headerLength + update_approximate_opaque_rect_order(&orderInfo, opaque_rect));
1081 offset = Stream_GetPosition(s);
1083 Stream_EnsureRemainingCapacity(s, headerLength);
1084 Stream_Seek(s, headerLength);
1086 update_write_opaque_rect_order(s, &orderInfo, opaque_rect);
1087 update_write_order_info(context, s, &orderInfo, offset);
1089 update->numberOrders++;
1092 static void update_send_line_to(rdpContext* context, LINE_TO_ORDER* line_to)
1097 ORDER_INFO orderInfo;
1098 rdpUpdate* update = context->update;
1100 headerLength = update_prepare_order_info(context, &orderInfo, ORDER_TYPE_LINE_TO);
1102 update_check_flush(context, headerLength + update_approximate_line_to_order(&orderInfo, line_to));
1105 offset = Stream_GetPosition(s);
1107 Stream_EnsureRemainingCapacity(s, headerLength);
1108 Stream_Seek(s, headerLength);
1110 update_write_line_to_order(s, &orderInfo, line_to);
1111 update_write_order_info(context, s, &orderInfo, offset);
1113 update->numberOrders++;
1116 static void update_send_memblt(rdpContext* context, MEMBLT_ORDER* memblt)
1121 ORDER_INFO orderInfo;
1122 rdpUpdate* update = context->update;
1124 headerLength = update_prepare_order_info(context, &orderInfo, ORDER_TYPE_MEMBLT);
1126 update_check_flush(context, headerLength + update_approximate_memblt_order(&orderInfo, memblt));
1129 offset = Stream_GetPosition(s);
1131 Stream_EnsureRemainingCapacity(s, headerLength);
1132 Stream_Seek(s, headerLength);
1134 update_write_memblt_order(s, &orderInfo, memblt);
1135 update_write_order_info(context, s, &orderInfo, offset);
1137 update->numberOrders++;
1140 static void update_send_glyph_index(rdpContext* context, GLYPH_INDEX_ORDER* glyph_index)
1145 ORDER_INFO orderInfo;
1146 rdpUpdate* update = context->update;
1148 headerLength = update_prepare_order_info(context, &orderInfo, ORDER_TYPE_GLYPH_INDEX);
1150 update_check_flush(context, headerLength + update_approximate_glyph_index_order(&orderInfo, glyph_index));
1153 offset = Stream_GetPosition(s);
1155 Stream_EnsureRemainingCapacity(s, headerLength);
1156 Stream_Seek(s, headerLength);
1158 update_write_glyph_index_order(s, &orderInfo, glyph_index);
1159 update_write_order_info(context, s, &orderInfo, offset);
1161 update->numberOrders++;
1165 * Secondary Drawing Orders
1168 static void update_send_cache_bitmap(rdpContext* context, CACHE_BITMAP_ORDER* cache_bitmap)
1176 rdpUpdate* update = context->update;
1181 orderType = cache_bitmap->compressed ?
1182 ORDER_TYPE_CACHE_BITMAP_COMPRESSED : ORDER_TYPE_BITMAP_UNCOMPRESSED;
1184 update_check_flush(context, headerLength + update_approximate_cache_bitmap_order(cache_bitmap, cache_bitmap->compressed, &extraFlags));
1187 bm = Stream_GetPosition(s);
1189 Stream_EnsureRemainingCapacity(s, headerLength);
1190 Stream_Seek(s, headerLength);
1192 update_write_cache_bitmap_order(s, cache_bitmap, cache_bitmap->compressed, &extraFlags);
1193 em = Stream_GetPosition(s);
1195 orderLength = (em - bm) - 13;
1197 Stream_SetPosition(s, bm);
1198 Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY); /* controlFlags (1 byte) */
1199 Stream_Write_UINT16(s, orderLength); /* orderLength (2 bytes) */
1200 Stream_Write_UINT16(s, extraFlags); /* extraFlags (2 bytes) */
1201 Stream_Write_UINT8(s, orderType); /* orderType (1 byte) */
1202 Stream_SetPosition(s, em);
1204 update->numberOrders++;
1207 static void update_send_cache_bitmap_v2(rdpContext* context, CACHE_BITMAP_V2_ORDER* cache_bitmap_v2)
1215 rdpUpdate* update = context->update;
1220 orderType = cache_bitmap_v2->compressed ?
1221 ORDER_TYPE_BITMAP_COMPRESSED_V2 : ORDER_TYPE_BITMAP_UNCOMPRESSED_V2;
1223 if (context->settings->NoBitmapCompressionHeader)
1224 cache_bitmap_v2->flags |= CBR2_NO_BITMAP_COMPRESSION_HDR;
1226 update_check_flush(context, headerLength + update_approximate_cache_bitmap_v2_order(cache_bitmap_v2, cache_bitmap_v2->compressed, &extraFlags));
1229 bm = Stream_GetPosition(s);
1231 Stream_EnsureRemainingCapacity(s, headerLength);
1232 Stream_Seek(s, headerLength);
1234 update_write_cache_bitmap_v2_order(s, cache_bitmap_v2, cache_bitmap_v2->compressed, &extraFlags);
1235 em = Stream_GetPosition(s);
1237 orderLength = (em - bm) - 13;
1239 Stream_SetPosition(s, bm);
1240 Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY); /* controlFlags (1 byte) */
1241 Stream_Write_UINT16(s, orderLength); /* orderLength (2 bytes) */
1242 Stream_Write_UINT16(s, extraFlags); /* extraFlags (2 bytes) */
1243 Stream_Write_UINT8(s, orderType); /* orderType (1 byte) */
1244 Stream_SetPosition(s, em);
1246 update->numberOrders++;
1249 static void update_send_cache_bitmap_v3(rdpContext* context, CACHE_BITMAP_V3_ORDER* cache_bitmap_v3)
1257 rdpUpdate* update = context->update;
1261 orderType = ORDER_TYPE_BITMAP_COMPRESSED_V3;
1263 update_check_flush(context, headerLength + update_approximate_cache_bitmap_v3_order(cache_bitmap_v3, &extraFlags));
1266 bm = Stream_GetPosition(s);
1268 Stream_EnsureRemainingCapacity(s, headerLength);
1269 Stream_Seek(s, headerLength);
1271 update_write_cache_bitmap_v3_order(s, cache_bitmap_v3, &extraFlags);
1272 em = Stream_GetPosition(s);
1274 orderLength = (em - bm) - 13;
1276 Stream_SetPosition(s, bm);
1277 Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY); /* controlFlags (1 byte) */
1278 Stream_Write_UINT16(s, orderLength); /* orderLength (2 bytes) */
1279 Stream_Write_UINT16(s, extraFlags); /* extraFlags (2 bytes) */
1280 Stream_Write_UINT8(s, orderType); /* orderType (1 byte) */
1281 Stream_SetPosition(s, em);
1283 update->numberOrders++;
1286 static void update_send_cache_color_table(rdpContext* context, CACHE_COLOR_TABLE_ORDER* cache_color_table)
1293 rdpUpdate* update = context->update;
1298 update_check_flush(context, headerLength + update_approximate_cache_color_table_order(cache_color_table, &flags));
1301 bm = Stream_GetPosition(s);
1303 Stream_EnsureRemainingCapacity(s, headerLength);
1304 Stream_Seek(s, headerLength);
1306 update_write_cache_color_table_order(s, cache_color_table, &flags);
1307 em = Stream_GetPosition(s);
1309 orderLength = (em - bm) - 13;
1311 Stream_SetPosition(s, bm);
1312 Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY); /* controlFlags (1 byte) */
1313 Stream_Write_UINT16(s, orderLength); /* orderLength (2 bytes) */
1314 Stream_Write_UINT16(s, flags); /* extraFlags (2 bytes) */
1315 Stream_Write_UINT8(s, ORDER_TYPE_CACHE_COLOR_TABLE); /* orderType (1 byte) */
1316 Stream_SetPosition(s, em);
1318 update->numberOrders++;
1321 static void update_send_cache_glyph(rdpContext* context, CACHE_GLYPH_ORDER* cache_glyph)
1328 rdpUpdate* update = context->update;
1333 update_check_flush(context, headerLength + update_approximate_cache_glyph_order(cache_glyph, &flags));
1336 bm = Stream_GetPosition(s);
1338 Stream_EnsureRemainingCapacity(s, headerLength);
1339 Stream_Seek(s, headerLength);
1341 update_write_cache_glyph_order(s, cache_glyph, &flags);
1342 em = Stream_GetPosition(s);
1344 orderLength = (em - bm) - 13;
1346 Stream_SetPosition(s, bm);
1347 Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY); /* controlFlags (1 byte) */
1348 Stream_Write_UINT16(s, orderLength); /* orderLength (2 bytes) */
1349 Stream_Write_UINT16(s, flags); /* extraFlags (2 bytes) */
1350 Stream_Write_UINT8(s, ORDER_TYPE_CACHE_GLYPH); /* orderType (1 byte) */
1351 Stream_SetPosition(s, em);
1353 update->numberOrders++;
1356 static void update_send_cache_glyph_v2(rdpContext* context, CACHE_GLYPH_V2_ORDER* cache_glyph_v2)
1363 rdpUpdate* update = context->update;
1368 update_check_flush(context, headerLength + update_approximate_cache_glyph_v2_order(cache_glyph_v2, &flags));
1371 bm = Stream_GetPosition(s);
1373 Stream_EnsureRemainingCapacity(s, headerLength);
1374 Stream_Seek(s, headerLength);
1376 update_write_cache_glyph_v2_order(s, cache_glyph_v2, &flags);
1377 em = Stream_GetPosition(s);
1379 orderLength = (em - bm) - 13;
1381 Stream_SetPosition(s, bm);
1382 Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY); /* controlFlags (1 byte) */
1383 Stream_Write_UINT16(s, orderLength); /* orderLength (2 bytes) */
1384 Stream_Write_UINT16(s, flags); /* extraFlags (2 bytes) */
1385 Stream_Write_UINT8(s, ORDER_TYPE_CACHE_GLYPH); /* orderType (1 byte) */
1386 Stream_SetPosition(s, em);
1388 update->numberOrders++;
1391 static void update_send_cache_brush(rdpContext* context, CACHE_BRUSH_ORDER* cache_brush)
1398 rdpUpdate* update = context->update;
1403 update_check_flush(context, headerLength + update_approximate_cache_brush_order(cache_brush, &flags));
1406 bm = Stream_GetPosition(s);
1408 Stream_EnsureRemainingCapacity(s, headerLength);
1409 Stream_Seek(s, headerLength);
1411 update_write_cache_brush_order(s, cache_brush, &flags);
1412 em = Stream_GetPosition(s);
1414 orderLength = (em - bm) - 13;
1416 Stream_SetPosition(s, bm);
1417 Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY); /* controlFlags (1 byte) */
1418 Stream_Write_UINT16(s, orderLength); /* orderLength (2 bytes) */
1419 Stream_Write_UINT16(s, flags); /* extraFlags (2 bytes) */
1420 Stream_Write_UINT8(s, ORDER_TYPE_CACHE_BRUSH); /* orderType (1 byte) */
1421 Stream_SetPosition(s, em);
1423 update->numberOrders++;
1427 * Alternate Secondary Drawing Orders
1430 static void update_send_create_offscreen_bitmap_order(rdpContext* context, CREATE_OFFSCREEN_BITMAP_ORDER* create_offscreen_bitmap)
1437 rdpUpdate* update = context->update;
1440 orderType = ORDER_TYPE_CREATE_OFFSCREEN_BITMAP;
1441 controlFlags = ORDER_SECONDARY | (orderType << 2);
1443 update_check_flush(context, headerLength + update_approximate_create_offscreen_bitmap_order(create_offscreen_bitmap));
1446 bm = Stream_GetPosition(s);
1448 Stream_EnsureRemainingCapacity(s, headerLength);
1449 Stream_Seek(s, headerLength);
1451 update_write_create_offscreen_bitmap_order(s, create_offscreen_bitmap);
1452 em = Stream_GetPosition(s);
1454 Stream_SetPosition(s, bm);
1455 Stream_Write_UINT8(s, controlFlags); /* controlFlags (1 byte) */
1456 Stream_SetPosition(s, em);
1458 update->numberOrders++;
1461 static void update_send_switch_surface_order(rdpContext* context, SWITCH_SURFACE_ORDER* switch_surface)
1468 rdpUpdate* update = context->update;
1471 orderType = ORDER_TYPE_SWITCH_SURFACE;
1472 controlFlags = ORDER_SECONDARY | (orderType << 2);
1474 update_check_flush(context, headerLength + update_approximate_switch_surface_order(switch_surface));
1477 bm = Stream_GetPosition(s);
1479 Stream_EnsureRemainingCapacity(s, headerLength);
1480 Stream_Seek(s, headerLength);
1482 update_write_switch_surface_order(s, switch_surface);
1483 em = Stream_GetPosition(s);
1485 Stream_SetPosition(s, bm);
1486 Stream_Write_UINT8(s, controlFlags); /* controlFlags (1 byte) */
1487 Stream_SetPosition(s, em);
1489 update->numberOrders++;
1492 static void update_send_pointer_system(rdpContext* context, POINTER_SYSTEM_UPDATE* pointer_system)
1496 rdpRdp* rdp = context->rdp;
1498 s = fastpath_update_pdu_init(rdp->fastpath);
1500 if (pointer_system->type == SYSPTR_NULL)
1501 updateCode = FASTPATH_UPDATETYPE_PTR_NULL;
1503 updateCode = FASTPATH_UPDATETYPE_PTR_DEFAULT;
1505 fastpath_send_update_pdu(rdp->fastpath, updateCode, s);
1509 static void update_write_pointer_color(wStream* s, POINTER_COLOR_UPDATE* pointer_color)
1511 Stream_EnsureRemainingCapacity(s, 15 + (int) pointer_color->lengthAndMask + (int) pointer_color->lengthXorMask);
1513 Stream_Write_UINT16(s, pointer_color->cacheIndex);
1514 Stream_Write_UINT16(s, pointer_color->xPos);
1515 Stream_Write_UINT16(s, pointer_color->yPos);
1516 Stream_Write_UINT16(s, pointer_color->width);
1517 Stream_Write_UINT16(s, pointer_color->height);
1518 Stream_Write_UINT16(s, pointer_color->lengthAndMask);
1519 Stream_Write_UINT16(s, pointer_color->lengthXorMask);
1521 if (pointer_color->lengthXorMask > 0)
1522 Stream_Write(s, pointer_color->xorMaskData, pointer_color->lengthXorMask);
1524 if (pointer_color->lengthAndMask > 0)
1525 Stream_Write(s, pointer_color->andMaskData, pointer_color->lengthAndMask);
1527 Stream_Write_UINT8(s, 0); /* pad (1 byte) */
1530 static void update_send_pointer_color(rdpContext* context, POINTER_COLOR_UPDATE* pointer_color)
1533 rdpRdp* rdp = context->rdp;
1535 s = fastpath_update_pdu_init(rdp->fastpath);
1536 update_write_pointer_color(s, pointer_color);
1537 fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_COLOR, s);
1541 static void update_send_pointer_new(rdpContext* context, POINTER_NEW_UPDATE* pointer_new)
1544 rdpRdp* rdp = context->rdp;
1546 s = fastpath_update_pdu_init(rdp->fastpath);
1547 Stream_Write_UINT16(s, pointer_new->xorBpp); /* xorBpp (2 bytes) */
1548 update_write_pointer_color(s, &pointer_new->colorPtrAttr);
1549 fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_POINTER, s);
1553 static void update_send_pointer_cached(rdpContext* context, POINTER_CACHED_UPDATE* pointer_cached)
1556 rdpRdp* rdp = context->rdp;
1558 s = fastpath_update_pdu_init(rdp->fastpath);
1559 Stream_Write_UINT16(s, pointer_cached->cacheIndex); /* cacheIndex (2 bytes) */
1560 fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_CACHED, s);
1564 BOOL update_read_refresh_rect(rdpUpdate* update, wStream* s)
1568 RECTANGLE_16* areas;
1570 if (Stream_GetRemainingLength(s) < 4)
1573 Stream_Read_UINT8(s, numberOfAreas);
1574 Stream_Seek(s, 3); /* pad3Octects */
1576 if (Stream_GetRemainingLength(s) < ((size_t) numberOfAreas * 4 * 2))
1579 areas = (RECTANGLE_16*) malloc(sizeof(RECTANGLE_16) * numberOfAreas);
1581 for (index = 0; index < numberOfAreas; index++)
1583 Stream_Read_UINT16(s, areas[index].left);
1584 Stream_Read_UINT16(s, areas[index].top);
1585 Stream_Read_UINT16(s, areas[index].right);
1586 Stream_Read_UINT16(s, areas[index].bottom);
1589 IFCALL(update->RefreshRect, update->context, numberOfAreas, areas);
1596 BOOL update_read_suppress_output(rdpUpdate* update, wStream* s)
1598 BYTE allowDisplayUpdates;
1600 if (Stream_GetRemainingLength(s) < 4)
1603 Stream_Read_UINT8(s, allowDisplayUpdates);
1604 Stream_Seek(s, 3); /* pad3Octects */
1606 if (allowDisplayUpdates > 0 && Stream_GetRemainingLength(s) < 8)
1609 IFCALL(update->SuppressOutput, update->context, allowDisplayUpdates,
1610 allowDisplayUpdates > 0 ? (RECTANGLE_16*) Stream_Pointer(s) : NULL);
1615 void update_register_server_callbacks(rdpUpdate* update)
1617 update->BeginPaint = update_begin_paint;
1618 update->EndPaint = update_end_paint;
1619 update->SetBounds = update_set_bounds;
1620 update->Synchronize = update_send_synchronize;
1621 update->DesktopResize = update_send_desktop_resize;
1622 update->BitmapUpdate = update_send_bitmap_update;
1623 update->SurfaceBits = update_send_surface_bits;
1624 update->SurfaceFrameMarker = update_send_surface_frame_marker;
1625 update->SurfaceCommand = update_send_surface_command;
1626 update->SurfaceFrameBits = update_send_surface_frame_bits;
1627 update->PlaySound = update_send_play_sound;
1628 update->primary->DstBlt = update_send_dstblt;
1629 update->primary->PatBlt = update_send_patblt;
1630 update->primary->ScrBlt = update_send_scrblt;
1631 update->primary->OpaqueRect = update_send_opaque_rect;
1632 update->primary->LineTo = update_send_line_to;
1633 update->primary->MemBlt = update_send_memblt;
1634 update->primary->GlyphIndex = update_send_glyph_index;
1635 update->secondary->CacheBitmap = update_send_cache_bitmap;
1636 update->secondary->CacheBitmapV2 = update_send_cache_bitmap_v2;
1637 update->secondary->CacheBitmapV3 = update_send_cache_bitmap_v3;
1638 update->secondary->CacheColorTable = update_send_cache_color_table;
1639 update->secondary->CacheGlyph = update_send_cache_glyph;
1640 update->secondary->CacheGlyphV2 = update_send_cache_glyph_v2;
1641 update->secondary->CacheBrush = update_send_cache_brush;
1642 update->altsec->CreateOffscreenBitmap = update_send_create_offscreen_bitmap_order;
1643 update->altsec->SwitchSurface = update_send_switch_surface_order;
1644 update->pointer->PointerSystem = update_send_pointer_system;
1645 update->pointer->PointerColor = update_send_pointer_color;
1646 update->pointer->PointerNew = update_send_pointer_new;
1647 update->pointer->PointerCached = update_send_pointer_cached;
1650 void update_register_client_callbacks(rdpUpdate* update)
1652 update->RefreshRect = update_send_refresh_rect;
1653 update->SuppressOutput = update_send_suppress_output;
1654 update->SurfaceFrameAcknowledge = update_send_frame_acknowledge;
1657 int update_process_messages(rdpUpdate* update)
1659 return update_message_queue_process_pending_messages(update);
1662 static void update_free_queued_message(void *obj)
1664 wMessage *msg = (wMessage*)obj;
1666 update_message_queue_free_message(msg);
1669 rdpUpdate* update_new(rdpRdp* rdp)
1671 const wObject cb = { NULL, NULL, NULL, update_free_queued_message, NULL };
1674 update = (rdpUpdate*) malloc(sizeof(rdpUpdate));
1678 OFFSCREEN_DELETE_LIST* deleteList;
1680 ZeroMemory(update, sizeof(rdpUpdate));
1683 update->log = WLog_Get("com.freerdp.core.update");
1685 update->bitmap_update.count = 64;
1686 update->bitmap_update.rectangles = (BITMAP_DATA*) malloc(sizeof(BITMAP_DATA) * update->bitmap_update.count);
1687 ZeroMemory(update->bitmap_update.rectangles, sizeof(BITMAP_DATA) * update->bitmap_update.count);
1689 update->pointer = (rdpPointerUpdate*) malloc(sizeof(rdpPointerUpdate));
1690 ZeroMemory(update->pointer, sizeof(rdpPointerUpdate));
1692 update->primary = (rdpPrimaryUpdate*) malloc(sizeof(rdpPrimaryUpdate));
1693 ZeroMemory(update->primary, sizeof(rdpPrimaryUpdate));
1695 update->secondary = (rdpSecondaryUpdate*) malloc(sizeof(rdpSecondaryUpdate));
1696 ZeroMemory(update->secondary, sizeof(rdpSecondaryUpdate));
1698 update->altsec = (rdpAltSecUpdate*) malloc(sizeof(rdpAltSecUpdate));
1699 ZeroMemory(update->altsec, sizeof(rdpAltSecUpdate));
1701 update->window = (rdpWindowUpdate*) malloc(sizeof(rdpWindowUpdate));
1702 ZeroMemory(update->window, sizeof(rdpWindowUpdate));
1704 deleteList = &(update->altsec->create_offscreen_bitmap.deleteList);
1705 deleteList->sIndices = 64;
1706 deleteList->indices = malloc(deleteList->sIndices * 2);
1707 deleteList->cIndices = 0;
1709 update->SuppressOutput = update_send_suppress_output;
1711 update->initialState = TRUE;
1713 update->queue = MessageQueue_New(&cb);
1719 void update_free(rdpUpdate* update)
1723 OFFSCREEN_DELETE_LIST* deleteList;
1725 deleteList = &(update->altsec->create_offscreen_bitmap.deleteList);
1726 free(deleteList->indices);
1728 free(update->bitmap_update.rectangles);
1730 free(update->pointer->pointer_color.andMaskData);
1731 free(update->pointer->pointer_color.xorMaskData);
1732 free(update->pointer->pointer_new.colorPtrAttr.andMaskData);
1733 free(update->pointer->pointer_new.colorPtrAttr.xorMaskData);
1734 free(update->pointer);
1736 free(update->primary->polyline.points);
1737 free(update->primary->polygon_sc.points);
1738 if (update->primary->fast_glyph.glyphData.aj)
1739 free(update->primary->fast_glyph.glyphData.aj);
1740 free(update->primary);
1742 free(update->secondary);
1743 free(update->altsec);
1744 free(update->window);
1746 MessageQueue_Free(update->queue);