libfreerdp-core: add SurfaceFrameBits function to combine frame marker with surface...
[platform/upstream/freerdp.git] / libfreerdp / core / update.c
1 /**
2  * FreeRDP: A Remote Desktop Protocol Implementation
3  * Update Data PDUs
4  *
5  * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6  *
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
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
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.
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
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>
29
30 #include "update.h"
31 #include "surface.h"
32 #include "message.h"
33
34 #include <freerdp/log.h>
35 #include <freerdp/peer.h>
36 #include <freerdp/codec/bitmap.h>
37
38 #define TAG FREERDP_TAG("core.update")
39
40 const char* const UPDATE_TYPE_STRINGS[] =
41 {
42         "Orders",
43         "Bitmap",
44         "Palette",
45         "Synchronize"
46 };
47
48 extern const BYTE PRIMARY_DRAWING_ORDER_FIELD_BYTES[];
49
50 BOOL update_recv_orders(rdpUpdate* update, wStream* s)
51 {
52         UINT16 numberOrders;
53
54         if (Stream_GetRemainingLength(s) < 6)
55                 return FALSE;
56
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) */
60
61         while (numberOrders > 0)
62         {
63                 if (!update_recv_order(update, s))
64                         return FALSE;
65
66                 numberOrders--;
67         }
68
69         return TRUE;
70 }
71
72 BOOL update_read_bitmap_data(rdpUpdate* update, wStream* s, BITMAP_DATA* bitmapData)
73 {
74         if (Stream_GetRemainingLength(s) < 18)
75                 return FALSE;
76
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);
86
87         if (bitmapData->flags & BITMAP_COMPRESSION)
88         {
89                 if (!(bitmapData->flags & NO_BITMAP_COMPRESSION_HDR))
90                 {
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;
96                 }
97
98                 bitmapData->compressed = TRUE;
99                 Stream_GetPointer(s, bitmapData->bitmapDataStream);
100                 Stream_Seek(s, bitmapData->bitmapLength);
101         }
102         else
103         {
104                 if (Stream_GetRemainingLength(s) < bitmapData->bitmapLength)
105                         return FALSE;
106
107                 bitmapData->compressed = FALSE;
108                 Stream_GetPointer(s, bitmapData->bitmapDataStream);
109                 Stream_Seek(s, bitmapData->bitmapLength);
110         }
111
112         return TRUE;
113 }
114
115 BOOL update_write_bitmap_data(rdpUpdate* update, wStream* s, BITMAP_DATA* bitmapData)
116 {
117         Stream_EnsureRemainingCapacity(s, 64 + bitmapData->bitmapLength);
118
119         bitmapData->flags = 0;
120         bitmapData->cbCompFirstRowSize = 0;
121
122         if (bitmapData->compressed)
123                 bitmapData->flags |= BITMAP_COMPRESSION;
124
125         if (update->context->settings->NoBitmapCompressionHeader)
126         {
127                 bitmapData->flags |= NO_BITMAP_COMPRESSION_HDR;
128                 bitmapData->cbCompMainBodySize = bitmapData->bitmapLength;
129         }
130
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);
140
141         if (bitmapData->flags & BITMAP_COMPRESSION)
142         {
143                 if (!(bitmapData->flags & NO_BITMAP_COMPRESSION_HDR))
144                 {
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) */
149                 }
150
151                 Stream_Write(s, bitmapData->bitmapDataStream, bitmapData->bitmapLength);
152         }
153         else
154         {
155                 Stream_Write(s, bitmapData->bitmapDataStream, bitmapData->bitmapLength);
156         }
157
158         return TRUE;
159 }
160
161 BOOL update_read_bitmap_update(rdpUpdate* update, wStream* s, BITMAP_UPDATE* bitmapUpdate)
162 {
163         int i;
164
165         if (Stream_GetRemainingLength(s) < 2)
166                 return FALSE;
167
168         Stream_Read_UINT16(s, bitmapUpdate->number); /* numberRectangles (2 bytes) */
169
170         WLog_Print(update->log, WLOG_DEBUG, "BitmapUpdate: %d", bitmapUpdate->number);
171
172         if (bitmapUpdate->number > bitmapUpdate->count)
173         {
174                 UINT16 count;
175
176                 count = bitmapUpdate->number * 2;
177
178                 bitmapUpdate->rectangles = (BITMAP_DATA*) realloc(bitmapUpdate->rectangles,
179                                 sizeof(BITMAP_DATA) * count);
180
181                 ZeroMemory(&bitmapUpdate->rectangles[bitmapUpdate->count],
182                                 sizeof(BITMAP_DATA) * (count - bitmapUpdate->count));
183
184                 bitmapUpdate->count = count;
185         }
186
187         /* rectangles */
188         for (i = 0; i < (int) bitmapUpdate->number; i++)
189         {
190                 if (!update_read_bitmap_data(update, s, &bitmapUpdate->rectangles[i]))
191                         return FALSE;
192         }
193         return TRUE;
194 }
195
196 BOOL update_write_bitmap_update(rdpUpdate* update, wStream* s, BITMAP_UPDATE* bitmapUpdate)
197 {
198         int i;
199
200         Stream_EnsureRemainingCapacity(s, 32);
201
202         Stream_Write_UINT16(s, UPDATE_TYPE_BITMAP); /* updateType */
203
204         Stream_Write_UINT16(s, bitmapUpdate->number); /* numberRectangles (2 bytes) */
205
206         /* rectangles */
207         for (i = 0; i < (int) bitmapUpdate->number; i++)
208         {
209                 if (!update_write_bitmap_data(update, s, &bitmapUpdate->rectangles[i]))
210                         return FALSE;
211         }
212
213         return TRUE;
214 }
215
216 BOOL update_read_palette(rdpUpdate* update, wStream* s, PALETTE_UPDATE* palette_update)
217 {
218         int i;
219         PALETTE_ENTRY* entry;
220
221         if (Stream_GetRemainingLength(s) < 6)
222                 return FALSE;
223
224         Stream_Seek_UINT16(s); /* pad2Octets (2 bytes) */
225         Stream_Read_UINT32(s, palette_update->number); /* numberColors (4 bytes), must be set to 256 */
226
227         if (palette_update->number > 256)
228                 palette_update->number = 256;
229
230         if (Stream_GetRemainingLength(s) < palette_update->number * 3)
231                 return FALSE;
232
233         /* paletteEntries */
234         for (i = 0; i < (int) palette_update->number; i++)
235         {
236                 entry = &palette_update->entries[i];
237
238                 Stream_Read_UINT8(s, entry->red);
239                 Stream_Read_UINT8(s, entry->green);
240                 Stream_Read_UINT8(s, entry->blue);
241         }
242         return TRUE;
243 }
244
245 void update_read_synchronize(rdpUpdate* update, wStream* s)
246 {
247         Stream_Seek_UINT16(s); /* pad2Octets (2 bytes) */
248
249         /**
250          * The Synchronize Update is an artifact from the
251          * T.128 protocol and should be ignored.
252          */
253 }
254
255 BOOL update_read_play_sound(wStream* s, PLAY_SOUND_UPDATE* play_sound)
256 {
257         if (Stream_GetRemainingLength(s) < 8)
258                 return FALSE;
259
260         Stream_Read_UINT32(s, play_sound->duration); /* duration (4 bytes) */
261         Stream_Read_UINT32(s, play_sound->frequency); /* frequency (4 bytes) */
262
263         return TRUE;
264 }
265
266 BOOL update_recv_play_sound(rdpUpdate* update, wStream* s)
267 {
268         if (!update_read_play_sound(s, &update->play_sound))
269                 return FALSE;
270
271         IFCALL(update->PlaySound, update->context, &update->play_sound);
272         return TRUE;
273 }
274
275 BOOL update_read_pointer_position(wStream* s, POINTER_POSITION_UPDATE* pointer_position)
276 {
277         if (Stream_GetRemainingLength(s) < 4)
278                 return FALSE;
279
280         Stream_Read_UINT16(s, pointer_position->xPos); /* xPos (2 bytes) */
281         Stream_Read_UINT16(s, pointer_position->yPos); /* yPos (2 bytes) */
282         return TRUE;
283 }
284
285 BOOL update_read_pointer_system(wStream* s, POINTER_SYSTEM_UPDATE* pointer_system)
286 {
287         if (Stream_GetRemainingLength(s) < 4)
288                 return FALSE;
289
290         Stream_Read_UINT32(s, pointer_system->type); /* systemPointerType (4 bytes) */
291         return TRUE;
292 }
293
294 BOOL update_read_pointer_color(wStream* s, POINTER_COLOR_UPDATE* pointer_color, int xorBpp)
295 {
296         BYTE *newMask;
297         int scanlineSize;
298
299         if (Stream_GetRemainingLength(s) < 14)
300                 return FALSE;
301
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) */
305
306         /**
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.
312          *
313          *  So we check for a maximum of 96 for CVE-2014-0250.
314          */
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))
318                 return FALSE;
319
320         Stream_Read_UINT16(s, pointer_color->lengthAndMask); /* lengthAndMask (2 bytes) */
321         Stream_Read_UINT16(s, pointer_color->lengthXorMask); /* lengthXorMask (2 bytes) */
322
323         /**
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)
328          */
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;
333
334         if (pointer_color->lengthXorMask > 0)
335         {
336                 /**
337                  * Spec states that:
338                  *
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
343                  * number of bytes).
344                  *
345                  * In fact instead of 24-bpp, the bpp parameter is given by the containing packet.
346                  */
347                 if (Stream_GetRemainingLength(s) < pointer_color->lengthXorMask)
348                         return FALSE;
349
350                 scanlineSize = (7 + xorBpp * pointer_color->width) / 8;
351                 scanlineSize = ((scanlineSize + 1) / 2) * 2;
352                 if (scanlineSize * pointer_color->height != pointer_color->lengthXorMask)
353                 {
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);
357                         return FALSE;
358                 }
359
360                 newMask = realloc(pointer_color->xorMaskData, pointer_color->lengthXorMask);
361                 if (!newMask)
362                         return FALSE;
363
364                 pointer_color->xorMaskData = newMask;
365
366                 Stream_Read(s, pointer_color->xorMaskData, pointer_color->lengthXorMask);
367         }
368
369         if (pointer_color->lengthAndMask > 0)
370         {
371                 /**
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
376                  * bytes).
377                  */
378                 if (Stream_GetRemainingLength(s) < pointer_color->lengthAndMask)
379                         return FALSE;
380
381                 scanlineSize = ((7 + pointer_color->width) / 8);
382                 scanlineSize = ((1 + scanlineSize) / 2) * 2;
383                 if (scanlineSize * pointer_color->height != pointer_color->lengthAndMask)
384                 {
385                         WLog_ERR(TAG,  "invalid lengthAndMask: %d instead of %d",
386                                          pointer_color->lengthAndMask, scanlineSize * pointer_color->height);
387                         return FALSE;
388                 }
389
390                 newMask = realloc(pointer_color->andMaskData, pointer_color->lengthAndMask);
391                 if (!newMask)
392                         return FALSE;
393
394                 pointer_color->andMaskData = newMask;
395
396                 Stream_Read(s, pointer_color->andMaskData, pointer_color->lengthAndMask);
397         }
398
399         if (Stream_GetRemainingLength(s) > 0)
400                 Stream_Seek_UINT8(s); /* pad (1 byte) */
401
402         return TRUE;
403 }
404
405 BOOL update_read_pointer_new(wStream* s, POINTER_NEW_UPDATE* pointer_new)
406 {
407         if (Stream_GetRemainingLength(s) < 2)
408                 return FALSE;
409
410         Stream_Read_UINT16(s, pointer_new->xorBpp); /* xorBpp (2 bytes) */
411         if ((pointer_new->xorBpp < 1) || (pointer_new->xorBpp > 32))
412         {
413                 WLog_ERR(TAG,  "invalid xorBpp %d", pointer_new->xorBpp);
414                 return FALSE;
415         }
416         return update_read_pointer_color(s, &pointer_new->colorPtrAttr, pointer_new->xorBpp); /* colorPtrAttr */
417 }
418
419 BOOL update_read_pointer_cached(wStream* s, POINTER_CACHED_UPDATE* pointer_cached)
420 {
421         if (Stream_GetRemainingLength(s) < 2)
422                 return FALSE;
423
424         Stream_Read_UINT16(s, pointer_cached->cacheIndex); /* cacheIndex (2 bytes) */
425         return TRUE;
426 }
427
428 BOOL update_recv_pointer(rdpUpdate* update, wStream* s)
429 {
430         UINT16 messageType;
431         rdpContext* context = update->context;
432         rdpPointerUpdate* pointer = update->pointer;
433
434         if (Stream_GetRemainingLength(s) < 2 + 2)
435                 return FALSE;
436
437         Stream_Read_UINT16(s, messageType); /* messageType (2 bytes) */
438         Stream_Seek_UINT16(s); /* pad2Octets (2 bytes) */
439
440         switch (messageType)
441         {
442                 case PTR_MSG_TYPE_POSITION:
443                         if (!update_read_pointer_position(s, &pointer->pointer_position))
444                                 return FALSE;
445                         IFCALL(pointer->PointerPosition, context, &pointer->pointer_position);
446                         break;
447
448                 case PTR_MSG_TYPE_SYSTEM:
449                         if (!update_read_pointer_system(s, &pointer->pointer_system))
450                                 return FALSE;
451                         IFCALL(pointer->PointerSystem, context, &pointer->pointer_system);
452                         break;
453
454                 case PTR_MSG_TYPE_COLOR:
455                         if (!update_read_pointer_color(s, &pointer->pointer_color, 24))
456                                 return FALSE;
457                         IFCALL(pointer->PointerColor, context, &pointer->pointer_color);
458                         break;
459
460                 case PTR_MSG_TYPE_POINTER:
461                         if (!update_read_pointer_new(s, &pointer->pointer_new))
462                                 return FALSE;
463                         IFCALL(pointer->PointerNew, context, &pointer->pointer_new);
464                         break;
465
466                 case PTR_MSG_TYPE_CACHED:
467                         if (!update_read_pointer_cached(s, &pointer->pointer_cached))
468                                 return FALSE;
469                         IFCALL(pointer->PointerCached, context, &pointer->pointer_cached);
470                         break;
471
472                 default:
473                         break;
474         }
475         return TRUE;
476 }
477
478 BOOL update_recv(rdpUpdate* update, wStream* s)
479 {
480         UINT16 updateType;
481         rdpContext* context = update->context;
482
483         if (Stream_GetRemainingLength(s) < 2)
484                 return FALSE;
485
486         Stream_Read_UINT16(s, updateType); /* updateType (2 bytes) */
487         //WLog_DBG(TAG, "%s Update Data PDU", UPDATE_TYPE_STRINGS[updateType]);
488
489         IFCALL(update->BeginPaint, context);
490
491         switch (updateType)
492         {
493                 case UPDATE_TYPE_ORDERS:
494                         if (!update_recv_orders(update, s))
495                         {
496                                 /* XXX: Do we have to call EndPaint? */
497                                 return FALSE;
498                         }
499                         break;
500
501                 case UPDATE_TYPE_BITMAP:
502                         if (!update_read_bitmap_update(update, s, &update->bitmap_update))
503                                 return FALSE;
504                         IFCALL(update->BitmapUpdate, context, &update->bitmap_update);
505                         break;
506
507                 case UPDATE_TYPE_PALETTE:
508                         if (!update_read_palette(update, s, &update->palette_update))
509                                 return FALSE;
510                         IFCALL(update->Palette, context, &update->palette_update);
511                         break;
512
513                 case UPDATE_TYPE_SYNCHRONIZE:
514                         update_read_synchronize(update, s);
515                         IFCALL(update->Synchronize, context);
516                         break;
517         }
518
519         IFCALL(update->EndPaint, context);
520
521         return TRUE;
522 }
523
524 void update_reset_state(rdpUpdate* update)
525 {
526         rdpPrimaryUpdate* primary = update->primary;
527         rdpAltSecUpdate* altsec = update->altsec;
528
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));
552
553         primary->order_info.orderType = ORDER_TYPE_PATBLT;
554
555         if (!update->initialState)
556         {
557                 altsec->switch_surface.bitmapId = SCREEN_BITMAP_SURFACE;
558                 IFCALL(altsec->SwitchSurface, update->context, &(altsec->switch_surface));
559         }
560 }
561
562 void update_post_connect(rdpUpdate* update)
563 {
564         update->asynchronous = update->context->settings->AsyncUpdate;
565
566         if (update->asynchronous)
567                 update->proxy = update_message_proxy_new(update);
568
569         update->altsec->switch_surface.bitmapId = SCREEN_BITMAP_SURFACE;
570         IFCALL(update->altsec->SwitchSurface, update->context, &(update->altsec->switch_surface));
571
572         update->initialState = FALSE;
573 }
574
575 void update_post_disconnect(rdpUpdate* update)
576 {
577         update->asynchronous = update->context->settings->AsyncUpdate;
578
579         if (update->asynchronous)
580                 update_message_proxy_free(update->proxy);
581 }
582
583 static void update_begin_paint(rdpContext* context)
584 {
585         wStream* s;
586         rdpUpdate* update = context->update;
587
588         if (update->us)
589                 update->EndPaint(context);
590
591         s = fastpath_update_pdu_init_new(context->rdp->fastpath);
592         Stream_SealLength(s);
593         Stream_Seek(s, 2); /* numberOrders (2 bytes) */
594
595         update->combineUpdates = TRUE;
596         update->numberOrders = 0;
597         update->us = s;
598 }
599
600 static void update_end_paint(rdpContext* context)
601 {
602         wStream* s;
603         int headerLength;
604         rdpUpdate* update = context->update;
605
606         if (!update->us)
607                 return;
608
609         s = update->us;
610         headerLength = Stream_Length(s);
611         Stream_SealLength(s);
612
613         Stream_SetPosition(s, headerLength);
614         Stream_Write_UINT16(s, update->numberOrders); /* numberOrders (2 bytes) */
615         Stream_SetPosition(s, Stream_Length(s));
616
617         if (update->numberOrders > 0)
618         {
619                 WLog_ERR(TAG,  "sending %d orders", update->numberOrders);
620                 fastpath_send_update_pdu(context->rdp->fastpath, FASTPATH_UPDATETYPE_ORDERS, s);
621         }
622
623         update->combineUpdates = FALSE;
624         update->numberOrders = 0;
625         update->us = NULL;
626
627         Stream_Free(s, TRUE);
628 }
629
630 static void update_flush(rdpContext* context)
631 {
632         rdpUpdate* update = context->update;
633
634         if (update->numberOrders > 0)
635         {
636                 update->EndPaint(context);
637                 update->BeginPaint(context);
638         }
639 }
640
641 static void update_force_flush(rdpContext* context)
642 {
643         rdpUpdate* update = context->update;
644
645         if (update->numberOrders > 0)
646         {
647                 update->EndPaint(context);
648                 update->BeginPaint(context);
649         }
650 }
651
652 static BOOL update_check_flush(rdpContext* context, int size)
653 {
654         wStream* s;
655         rdpUpdate* update = context->update;
656
657         s = update->us;
658
659         if (!update->us)
660         {
661                 update->BeginPaint(context);
662                 return FALSE;
663         }
664
665         if (Stream_GetPosition(s) + size + 64 >= 0x3FFF)
666         {
667                 update_flush(context);
668                 return TRUE;
669         }
670
671         return FALSE;
672 }
673
674 static void update_set_bounds(rdpContext* context, rdpBounds* bounds)
675 {
676         rdpUpdate* update = context->update;
677
678         CopyMemory(&update->previousBounds, &update->currentBounds, sizeof(rdpBounds));
679
680         if (!bounds)
681                 ZeroMemory(&update->currentBounds, sizeof(rdpBounds));
682         else
683                 CopyMemory(&update->currentBounds, bounds, sizeof(rdpBounds));
684 }
685
686 BOOL update_bounds_is_null(rdpBounds* bounds)
687 {
688         if ((bounds->left == 0) && (bounds->top == 0) &&
689                         (bounds->right == 0) && (bounds->bottom == 0))
690                 return TRUE;
691
692         return FALSE;
693 }
694
695 BOOL update_bounds_equals(rdpBounds* bounds1, rdpBounds* bounds2)
696 {
697         if ((bounds1->left == bounds2->left) && (bounds1->top == bounds2->top) &&
698                 (bounds1->right == bounds2->right) && (bounds1->bottom == bounds2->bottom))
699                 return TRUE;
700
701         return FALSE;
702 }
703
704 int update_prepare_bounds(rdpContext* context, ORDER_INFO* orderInfo)
705 {
706         int length = 0;
707         rdpUpdate* update = context->update;
708
709         orderInfo->boundsFlags = 0;
710
711         if (update_bounds_is_null(&update->currentBounds))
712                 return 0;
713
714         orderInfo->controlFlags |= ORDER_BOUNDS;
715
716         if (update_bounds_equals(&update->previousBounds, &update->currentBounds))
717         {
718                 orderInfo->controlFlags |= ORDER_ZERO_BOUNDS_DELTAS;
719                 return 0;
720         }
721         else
722         {
723                 length += 1;
724
725                 if (update->previousBounds.left != update->currentBounds.left)
726                 {
727                         orderInfo->bounds.left = update->currentBounds.left;
728                         orderInfo->boundsFlags |= BOUND_LEFT;
729                         length += 2;
730                 }
731
732                 if (update->previousBounds.top != update->currentBounds.top)
733                 {
734                         orderInfo->bounds.top = update->currentBounds.top;
735                         orderInfo->boundsFlags |= BOUND_TOP;
736                         length += 2;
737                 }
738
739                 if (update->previousBounds.right != update->currentBounds.right)
740                 {
741                         orderInfo->bounds.right = update->currentBounds.right;
742                         orderInfo->boundsFlags |= BOUND_RIGHT;
743                         length += 2;
744                 }
745
746                 if (update->previousBounds.bottom != update->currentBounds.bottom)
747                 {
748                         orderInfo->bounds.bottom = update->currentBounds.bottom;
749                         orderInfo->boundsFlags |= BOUND_BOTTOM;
750                         length += 2;
751                 }
752         }
753
754         return length;
755 }
756
757 int update_prepare_order_info(rdpContext* context, ORDER_INFO* orderInfo, UINT32 orderType)
758 {
759         int length = 1;
760
761         orderInfo->fieldFlags = 0;
762         orderInfo->orderType = orderType;
763
764         orderInfo->controlFlags = ORDER_STANDARD;
765
766         orderInfo->controlFlags |= ORDER_TYPE_CHANGE;
767         length += 1;
768
769         length += PRIMARY_DRAWING_ORDER_FIELD_BYTES[orderInfo->orderType];
770
771         length += update_prepare_bounds(context, orderInfo);
772
773         return length;
774 }
775
776 int update_write_order_info(rdpContext* context, wStream* s, ORDER_INFO* orderInfo, int offset)
777 {
778         int position;
779
780         position = Stream_GetPosition(s);
781         Stream_SetPosition(s, offset);
782
783         Stream_Write_UINT8(s, orderInfo->controlFlags); /* controlFlags (1 byte) */
784
785         if (orderInfo->controlFlags & ORDER_TYPE_CHANGE)
786                 Stream_Write_UINT8(s, orderInfo->orderType); /* orderType (1 byte) */
787
788         update_write_field_flags(s, orderInfo->fieldFlags, orderInfo->controlFlags,
789                         PRIMARY_DRAWING_ORDER_FIELD_BYTES[orderInfo->orderType]);
790
791         update_write_bounds(s, orderInfo);
792
793         Stream_SetPosition(s, position);
794
795         return 0;
796 }
797
798 static void update_write_refresh_rect(wStream* s, BYTE count, RECTANGLE_16* areas)
799 {
800         int i;
801
802         Stream_Write_UINT8(s, count); /* numberOfAreas (1 byte) */
803         Stream_Seek(s, 3); /* pad3Octets (3 bytes) */
804
805         for (i = 0; i < count; i++)
806         {
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) */
811         }
812 }
813
814 static void update_send_refresh_rect(rdpContext* context, BYTE count, RECTANGLE_16* areas)
815 {
816         wStream* s;
817         rdpRdp* rdp = context->rdp;
818
819         if (rdp->settings->RefreshRect)
820         {
821                 s = rdp_data_pdu_init(rdp);
822                 update_write_refresh_rect(s, count, areas);
823
824                 rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_REFRESH_RECT, rdp->mcs->userId);
825                 Stream_Release(s);
826         }
827 }
828
829 static void update_write_suppress_output(wStream* s, BYTE allow, RECTANGLE_16* area)
830 {
831         Stream_Write_UINT8(s, allow); /* allowDisplayUpdates (1 byte) */
832         Stream_Seek(s, 3); /* pad3Octets (3 bytes) */
833
834         if (allow > 0)
835         {
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) */
840         }
841 }
842
843 static void update_send_suppress_output(rdpContext* context, BYTE allow, RECTANGLE_16* area)
844 {
845         wStream* s;
846         rdpRdp* rdp = context->rdp;
847
848         if (rdp->settings->SuppressOutput)
849         {
850                 s = rdp_data_pdu_init(rdp);
851                 update_write_suppress_output(s, allow, area);
852
853                 rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SUPPRESS_OUTPUT, rdp->mcs->userId);
854                 Stream_Release(s);
855         }
856 }
857
858 static void update_send_surface_command(rdpContext* context, wStream* s)
859 {
860         wStream* update;
861         rdpRdp* rdp = context->rdp;
862
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);
868 }
869
870 static void update_send_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surfaceBitsCommand)
871 {
872         wStream* s;
873         rdpRdp* rdp = context->rdp;
874
875         update_force_flush(context);
876
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);
882
883         update_force_flush(context);
884
885         Stream_Release(s);
886 }
887
888 static void update_send_surface_frame_marker(rdpContext* context, SURFACE_FRAME_MARKER* surfaceFrameMarker)
889 {
890         wStream* s;
891         rdpRdp* rdp = context->rdp;
892
893         update_force_flush(context);
894
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);
898
899         update_force_flush(context);
900
901         Stream_Release(s);
902 }
903
904 static void update_send_surface_frame_bits(rdpContext* context, SURFACE_BITS_COMMAND* cmd, BOOL first, BOOL last, UINT32 frameId)
905 {
906         wStream* s;
907         rdpRdp* rdp = context->rdp;
908
909         update_force_flush(context);
910
911         s = fastpath_update_pdu_init(rdp->fastpath);
912         Stream_EnsureRemainingCapacity(s, SURFCMD_SURFACE_BITS_HEADER_LENGTH + (int) cmd->bitmapDataLength + 16);
913
914         if (first)
915                 update_write_surfcmd_frame_marker(s, SURFACECMD_FRAMEACTION_BEGIN, frameId);
916
917         update_write_surfcmd_surface_bits_header(s, cmd);
918         Stream_Write(s, cmd->bitmapData, cmd->bitmapDataLength);
919
920
921         if (last)
922                 update_write_surfcmd_frame_marker(s, SURFACECMD_FRAMEACTION_END, frameId);
923
924         fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, s);
925
926         update_force_flush(context);
927
928         Stream_Release(s);
929 }
930
931 static void update_send_frame_acknowledge(rdpContext* context, UINT32 frameId)
932 {
933         wStream* s;
934         rdpRdp* rdp = context->rdp;
935
936         if (rdp->settings->ReceivedCapabilities[CAPSET_TYPE_FRAME_ACKNOWLEDGE])
937         {
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);
941                 Stream_Release(s);
942         }
943 }
944
945 static void update_send_synchronize(rdpContext* context)
946 {
947         wStream* s;
948         rdpRdp* rdp = context->rdp;
949
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);
953         Stream_Release(s);
954 }
955
956 static void update_send_desktop_resize(rdpContext* context)
957 {
958         rdp_server_reactivate(context->rdp);
959 }
960
961 static void update_send_bitmap_update(rdpContext* context, BITMAP_UPDATE* bitmapUpdate)
962 {
963         wStream* s;
964         rdpRdp* rdp = context->rdp;
965         rdpUpdate* update = context->update;
966
967         update_force_flush(context);
968
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);
972
973         update_force_flush(context);
974
975         Stream_Release(s);
976 }
977
978 static void update_send_play_sound(rdpContext* context, PLAY_SOUND_UPDATE* play_sound)
979 {
980         wStream* s;
981         rdpRdp* rdp = context->rdp;
982
983         if (!rdp->settings->ReceivedCapabilities[CAPSET_TYPE_SOUND]) {
984                 return;
985         }
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);
990         Stream_Release(s);
991 }
992 /**
993  * Primary Drawing Orders
994  */
995
996 static void update_send_dstblt(rdpContext* context, DSTBLT_ORDER* dstblt)
997 {
998         wStream* s;
999         int offset;
1000         int headerLength;
1001         ORDER_INFO orderInfo;
1002         rdpUpdate* update = context->update;
1003
1004         headerLength = update_prepare_order_info(context, &orderInfo, ORDER_TYPE_DSTBLT);
1005
1006         update_check_flush(context, headerLength + update_approximate_dstblt_order(&orderInfo, dstblt));
1007
1008         s = update->us;
1009         offset = Stream_GetPosition(s);
1010
1011         Stream_EnsureRemainingCapacity(s, headerLength);
1012         Stream_Seek(s, headerLength);
1013
1014         update_write_dstblt_order(s, &orderInfo, dstblt);
1015         update_write_order_info(context, s, &orderInfo, offset);
1016
1017         update->numberOrders++;
1018 }
1019
1020 static void update_send_patblt(rdpContext* context, PATBLT_ORDER* patblt)
1021 {
1022         wStream* s;
1023         int offset;
1024         int headerLength;
1025         ORDER_INFO orderInfo;
1026         rdpUpdate* update = context->update;
1027
1028         headerLength = update_prepare_order_info(context, &orderInfo, ORDER_TYPE_PATBLT);
1029
1030         update_check_flush(context, headerLength + update_approximate_patblt_order(&orderInfo, patblt));
1031
1032         s = update->us;
1033         offset = Stream_GetPosition(s);
1034
1035         Stream_EnsureRemainingCapacity(s, headerLength);
1036         Stream_Seek(s, headerLength);
1037
1038         update_write_patblt_order(s, &orderInfo, patblt);
1039         update_write_order_info(context, s, &orderInfo, offset);
1040
1041         update->numberOrders++;
1042 }
1043
1044 static void update_send_scrblt(rdpContext* context, SCRBLT_ORDER* scrblt)
1045 {
1046         wStream* s;
1047         int offset;
1048         int headerLength;
1049         ORDER_INFO orderInfo;
1050         rdpUpdate* update = context->update;
1051
1052         headerLength = update_prepare_order_info(context, &orderInfo, ORDER_TYPE_SCRBLT);
1053
1054         update_check_flush(context, headerLength + update_approximate_scrblt_order(&orderInfo, scrblt));
1055
1056         s = update->us;
1057         offset = Stream_GetPosition(s);
1058
1059         Stream_EnsureRemainingCapacity(s, headerLength);
1060         Stream_Seek(s, headerLength);
1061
1062         update_write_scrblt_order(s, &orderInfo, scrblt);
1063         update_write_order_info(context, s, &orderInfo, offset);
1064
1065         update->numberOrders++;
1066 }
1067
1068 static void update_send_opaque_rect(rdpContext* context, OPAQUE_RECT_ORDER* opaque_rect)
1069 {
1070         wStream* s;
1071         int offset;
1072         int headerLength;
1073         ORDER_INFO orderInfo;
1074         rdpUpdate* update = context->update;
1075
1076         headerLength = update_prepare_order_info(context, &orderInfo, ORDER_TYPE_OPAQUE_RECT);
1077
1078         update_check_flush(context, headerLength + update_approximate_opaque_rect_order(&orderInfo, opaque_rect));
1079
1080         s = update->us;
1081         offset = Stream_GetPosition(s);
1082
1083         Stream_EnsureRemainingCapacity(s, headerLength);
1084         Stream_Seek(s, headerLength);
1085
1086         update_write_opaque_rect_order(s, &orderInfo, opaque_rect);
1087         update_write_order_info(context, s, &orderInfo, offset);
1088
1089         update->numberOrders++;
1090 }
1091
1092 static void update_send_line_to(rdpContext* context, LINE_TO_ORDER* line_to)
1093 {
1094         wStream* s;
1095         int offset;
1096         int headerLength;
1097         ORDER_INFO orderInfo;
1098         rdpUpdate* update = context->update;
1099
1100         headerLength = update_prepare_order_info(context, &orderInfo, ORDER_TYPE_LINE_TO);
1101
1102         update_check_flush(context, headerLength + update_approximate_line_to_order(&orderInfo, line_to));
1103
1104         s = update->us;
1105         offset = Stream_GetPosition(s);
1106
1107         Stream_EnsureRemainingCapacity(s, headerLength);
1108         Stream_Seek(s, headerLength);
1109
1110         update_write_line_to_order(s, &orderInfo, line_to);
1111         update_write_order_info(context, s, &orderInfo, offset);
1112
1113         update->numberOrders++;
1114 }
1115
1116 static void update_send_memblt(rdpContext* context, MEMBLT_ORDER* memblt)
1117 {
1118         wStream* s;
1119         int offset;
1120         int headerLength;
1121         ORDER_INFO orderInfo;
1122         rdpUpdate* update = context->update;
1123
1124         headerLength = update_prepare_order_info(context, &orderInfo, ORDER_TYPE_MEMBLT);
1125
1126         update_check_flush(context, headerLength + update_approximate_memblt_order(&orderInfo, memblt));
1127
1128         s = update->us;
1129         offset = Stream_GetPosition(s);
1130
1131         Stream_EnsureRemainingCapacity(s, headerLength);
1132         Stream_Seek(s, headerLength);
1133
1134         update_write_memblt_order(s, &orderInfo, memblt);
1135         update_write_order_info(context, s, &orderInfo, offset);
1136
1137         update->numberOrders++;
1138 }
1139
1140 static void update_send_glyph_index(rdpContext* context, GLYPH_INDEX_ORDER* glyph_index)
1141 {
1142         wStream* s;
1143         int offset;
1144         int headerLength;
1145         ORDER_INFO orderInfo;
1146         rdpUpdate* update = context->update;
1147
1148         headerLength = update_prepare_order_info(context, &orderInfo, ORDER_TYPE_GLYPH_INDEX);
1149
1150         update_check_flush(context, headerLength + update_approximate_glyph_index_order(&orderInfo, glyph_index));
1151
1152         s = update->us;
1153         offset = Stream_GetPosition(s);
1154
1155         Stream_EnsureRemainingCapacity(s, headerLength);
1156         Stream_Seek(s, headerLength);
1157
1158         update_write_glyph_index_order(s, &orderInfo, glyph_index);
1159         update_write_order_info(context, s, &orderInfo, offset);
1160
1161         update->numberOrders++;
1162 }
1163
1164 /*
1165  * Secondary Drawing Orders
1166  */
1167
1168 static void update_send_cache_bitmap(rdpContext* context, CACHE_BITMAP_ORDER* cache_bitmap)
1169 {
1170         wStream* s;
1171         int bm, em;
1172         BYTE orderType;
1173         int headerLength;
1174         UINT16 extraFlags;
1175         INT16 orderLength;
1176         rdpUpdate* update = context->update;
1177
1178         extraFlags = 0;
1179         headerLength = 6;
1180
1181         orderType = cache_bitmap->compressed ?
1182                         ORDER_TYPE_CACHE_BITMAP_COMPRESSED : ORDER_TYPE_BITMAP_UNCOMPRESSED;
1183
1184         update_check_flush(context, headerLength + update_approximate_cache_bitmap_order(cache_bitmap, cache_bitmap->compressed, &extraFlags));
1185
1186         s = update->us;
1187         bm = Stream_GetPosition(s);
1188
1189         Stream_EnsureRemainingCapacity(s, headerLength);
1190         Stream_Seek(s, headerLength);
1191
1192         update_write_cache_bitmap_order(s, cache_bitmap, cache_bitmap->compressed, &extraFlags);
1193         em = Stream_GetPosition(s);
1194
1195         orderLength = (em - bm) - 13;
1196
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);
1203
1204         update->numberOrders++;
1205 }
1206
1207 static void update_send_cache_bitmap_v2(rdpContext* context, CACHE_BITMAP_V2_ORDER* cache_bitmap_v2)
1208 {
1209         wStream* s;
1210         int bm, em;
1211         BYTE orderType;
1212         int headerLength;
1213         UINT16 extraFlags;
1214         INT16 orderLength;
1215         rdpUpdate* update = context->update;
1216
1217         extraFlags = 0;
1218         headerLength = 6;
1219
1220         orderType = cache_bitmap_v2->compressed ?
1221                         ORDER_TYPE_BITMAP_COMPRESSED_V2 : ORDER_TYPE_BITMAP_UNCOMPRESSED_V2;
1222
1223         if (context->settings->NoBitmapCompressionHeader)
1224                 cache_bitmap_v2->flags |= CBR2_NO_BITMAP_COMPRESSION_HDR;
1225
1226         update_check_flush(context, headerLength + update_approximate_cache_bitmap_v2_order(cache_bitmap_v2, cache_bitmap_v2->compressed, &extraFlags));
1227
1228         s = update->us;
1229         bm = Stream_GetPosition(s);
1230
1231         Stream_EnsureRemainingCapacity(s, headerLength);
1232         Stream_Seek(s, headerLength);
1233
1234         update_write_cache_bitmap_v2_order(s, cache_bitmap_v2, cache_bitmap_v2->compressed, &extraFlags);
1235         em = Stream_GetPosition(s);
1236
1237         orderLength = (em - bm) - 13;
1238
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);
1245
1246         update->numberOrders++;
1247 }
1248
1249 static void update_send_cache_bitmap_v3(rdpContext* context, CACHE_BITMAP_V3_ORDER* cache_bitmap_v3)
1250 {
1251         wStream* s;
1252         int bm, em;
1253         BYTE orderType;
1254         int headerLength;
1255         UINT16 extraFlags;
1256         INT16 orderLength;
1257         rdpUpdate* update = context->update;
1258
1259         extraFlags = 0;
1260         headerLength = 6;
1261         orderType = ORDER_TYPE_BITMAP_COMPRESSED_V3;
1262
1263         update_check_flush(context, headerLength + update_approximate_cache_bitmap_v3_order(cache_bitmap_v3, &extraFlags));
1264
1265         s = update->us;
1266         bm = Stream_GetPosition(s);
1267
1268         Stream_EnsureRemainingCapacity(s, headerLength);
1269         Stream_Seek(s, headerLength);
1270
1271         update_write_cache_bitmap_v3_order(s, cache_bitmap_v3, &extraFlags);
1272         em = Stream_GetPosition(s);
1273
1274         orderLength = (em - bm) - 13;
1275
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);
1282
1283         update->numberOrders++;
1284 }
1285
1286 static void update_send_cache_color_table(rdpContext* context, CACHE_COLOR_TABLE_ORDER* cache_color_table)
1287 {
1288         wStream* s;
1289         UINT16 flags;
1290         int bm, em;
1291         int headerLength;
1292         INT16 orderLength;
1293         rdpUpdate* update = context->update;
1294
1295         flags = 0;
1296         headerLength = 6;
1297
1298         update_check_flush(context, headerLength + update_approximate_cache_color_table_order(cache_color_table, &flags));
1299
1300         s = update->us;
1301         bm = Stream_GetPosition(s);
1302
1303         Stream_EnsureRemainingCapacity(s, headerLength);
1304         Stream_Seek(s, headerLength);
1305
1306         update_write_cache_color_table_order(s, cache_color_table, &flags);
1307         em = Stream_GetPosition(s);
1308
1309         orderLength = (em - bm) - 13;
1310
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);
1317
1318         update->numberOrders++;
1319 }
1320
1321 static void update_send_cache_glyph(rdpContext* context, CACHE_GLYPH_ORDER* cache_glyph)
1322 {
1323         wStream* s;
1324         UINT16 flags;
1325         int bm, em;
1326         int headerLength;
1327         INT16 orderLength;
1328         rdpUpdate* update = context->update;
1329
1330         flags = 0;
1331         headerLength = 6;
1332
1333         update_check_flush(context, headerLength + update_approximate_cache_glyph_order(cache_glyph, &flags));
1334
1335         s = update->us;
1336         bm = Stream_GetPosition(s);
1337
1338         Stream_EnsureRemainingCapacity(s, headerLength);
1339         Stream_Seek(s, headerLength);
1340
1341         update_write_cache_glyph_order(s, cache_glyph, &flags);
1342         em = Stream_GetPosition(s);
1343
1344         orderLength = (em - bm) - 13;
1345
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);
1352
1353         update->numberOrders++;
1354 }
1355
1356 static void update_send_cache_glyph_v2(rdpContext* context, CACHE_GLYPH_V2_ORDER* cache_glyph_v2)
1357 {
1358         wStream* s;
1359         UINT16 flags;
1360         int bm, em;
1361         int headerLength;
1362         INT16 orderLength;
1363         rdpUpdate* update = context->update;
1364
1365         flags = 0;
1366         headerLength = 6;
1367
1368         update_check_flush(context, headerLength + update_approximate_cache_glyph_v2_order(cache_glyph_v2, &flags));
1369
1370         s = update->us;
1371         bm = Stream_GetPosition(s);
1372
1373         Stream_EnsureRemainingCapacity(s, headerLength);
1374         Stream_Seek(s, headerLength);
1375
1376         update_write_cache_glyph_v2_order(s, cache_glyph_v2, &flags);
1377         em = Stream_GetPosition(s);
1378
1379         orderLength = (em - bm) - 13;
1380
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);
1387
1388         update->numberOrders++;
1389 }
1390
1391 static void update_send_cache_brush(rdpContext* context, CACHE_BRUSH_ORDER* cache_brush)
1392 {
1393         wStream* s;
1394         UINT16 flags;
1395         int bm, em;
1396         int headerLength;
1397         INT16 orderLength;
1398         rdpUpdate* update = context->update;
1399
1400         flags = 0;
1401         headerLength = 6;
1402
1403         update_check_flush(context, headerLength + update_approximate_cache_brush_order(cache_brush, &flags));
1404
1405         s = update->us;
1406         bm = Stream_GetPosition(s);
1407
1408         Stream_EnsureRemainingCapacity(s, headerLength);
1409         Stream_Seek(s, headerLength);
1410
1411         update_write_cache_brush_order(s, cache_brush, &flags);
1412         em = Stream_GetPosition(s);
1413
1414         orderLength = (em - bm) - 13;
1415
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);
1422
1423         update->numberOrders++;
1424 }
1425
1426 /**
1427  * Alternate Secondary Drawing Orders
1428  */
1429
1430 static void update_send_create_offscreen_bitmap_order(rdpContext* context, CREATE_OFFSCREEN_BITMAP_ORDER* create_offscreen_bitmap)
1431 {
1432         wStream* s;
1433         int bm, em;
1434         BYTE orderType;
1435         BYTE controlFlags;
1436         int headerLength;
1437         rdpUpdate* update = context->update;
1438
1439         headerLength = 1;
1440         orderType = ORDER_TYPE_CREATE_OFFSCREEN_BITMAP;
1441         controlFlags = ORDER_SECONDARY | (orderType << 2);
1442
1443         update_check_flush(context, headerLength + update_approximate_create_offscreen_bitmap_order(create_offscreen_bitmap));
1444
1445         s = update->us;
1446         bm = Stream_GetPosition(s);
1447
1448         Stream_EnsureRemainingCapacity(s, headerLength);
1449         Stream_Seek(s, headerLength);
1450
1451         update_write_create_offscreen_bitmap_order(s, create_offscreen_bitmap);
1452         em = Stream_GetPosition(s);
1453
1454         Stream_SetPosition(s, bm);
1455         Stream_Write_UINT8(s, controlFlags); /* controlFlags (1 byte) */
1456         Stream_SetPosition(s, em);
1457
1458         update->numberOrders++;
1459 }
1460
1461 static void update_send_switch_surface_order(rdpContext* context, SWITCH_SURFACE_ORDER* switch_surface)
1462 {
1463         wStream* s;
1464         int bm, em;
1465         BYTE orderType;
1466         BYTE controlFlags;
1467         int headerLength;
1468         rdpUpdate* update = context->update;
1469
1470         headerLength = 1;
1471         orderType = ORDER_TYPE_SWITCH_SURFACE;
1472         controlFlags = ORDER_SECONDARY | (orderType << 2);
1473
1474         update_check_flush(context, headerLength + update_approximate_switch_surface_order(switch_surface));
1475
1476         s = update->us;
1477         bm = Stream_GetPosition(s);
1478
1479         Stream_EnsureRemainingCapacity(s, headerLength);
1480         Stream_Seek(s, headerLength);
1481
1482         update_write_switch_surface_order(s, switch_surface);
1483         em = Stream_GetPosition(s);
1484
1485         Stream_SetPosition(s, bm);
1486         Stream_Write_UINT8(s, controlFlags); /* controlFlags (1 byte) */
1487         Stream_SetPosition(s, em);
1488
1489         update->numberOrders++;
1490 }
1491
1492 static void update_send_pointer_system(rdpContext* context, POINTER_SYSTEM_UPDATE* pointer_system)
1493 {
1494         wStream* s;
1495         BYTE updateCode;
1496         rdpRdp* rdp = context->rdp;
1497
1498         s = fastpath_update_pdu_init(rdp->fastpath);
1499
1500         if (pointer_system->type == SYSPTR_NULL)
1501                 updateCode = FASTPATH_UPDATETYPE_PTR_NULL;
1502         else
1503                 updateCode = FASTPATH_UPDATETYPE_PTR_DEFAULT;
1504
1505         fastpath_send_update_pdu(rdp->fastpath, updateCode, s);
1506         Stream_Release(s);
1507 }
1508
1509 static void update_write_pointer_color(wStream* s, POINTER_COLOR_UPDATE* pointer_color)
1510 {
1511         Stream_EnsureRemainingCapacity(s, 15 + (int) pointer_color->lengthAndMask + (int) pointer_color->lengthXorMask);
1512
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);
1520
1521         if (pointer_color->lengthXorMask > 0)
1522                 Stream_Write(s, pointer_color->xorMaskData, pointer_color->lengthXorMask);
1523
1524         if (pointer_color->lengthAndMask > 0)
1525                 Stream_Write(s, pointer_color->andMaskData, pointer_color->lengthAndMask);
1526
1527         Stream_Write_UINT8(s, 0); /* pad (1 byte) */
1528 }
1529
1530 static void update_send_pointer_color(rdpContext* context, POINTER_COLOR_UPDATE* pointer_color)
1531 {
1532         wStream* s;
1533         rdpRdp* rdp = context->rdp;
1534
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);
1538         Stream_Release(s);
1539 }
1540
1541 static void update_send_pointer_new(rdpContext* context, POINTER_NEW_UPDATE* pointer_new)
1542 {
1543         wStream* s;
1544         rdpRdp* rdp = context->rdp;
1545
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);
1550         Stream_Release(s);
1551 }
1552
1553 static void update_send_pointer_cached(rdpContext* context, POINTER_CACHED_UPDATE* pointer_cached)
1554 {
1555         wStream* s;
1556         rdpRdp* rdp = context->rdp;
1557
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);
1561         Stream_Release(s);
1562 }
1563
1564 BOOL update_read_refresh_rect(rdpUpdate* update, wStream* s)
1565 {
1566         int index;
1567         BYTE numberOfAreas;
1568         RECTANGLE_16* areas;
1569
1570         if (Stream_GetRemainingLength(s) < 4)
1571                 return FALSE;
1572
1573         Stream_Read_UINT8(s, numberOfAreas);
1574         Stream_Seek(s, 3); /* pad3Octects */
1575
1576         if (Stream_GetRemainingLength(s) < ((size_t) numberOfAreas * 4 * 2))
1577                 return FALSE;
1578
1579         areas = (RECTANGLE_16*) malloc(sizeof(RECTANGLE_16) * numberOfAreas);
1580
1581         for (index = 0; index < numberOfAreas; index++)
1582         {
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);
1587         }
1588
1589         IFCALL(update->RefreshRect, update->context, numberOfAreas, areas);
1590
1591         free(areas);
1592
1593         return TRUE;
1594 }
1595
1596 BOOL update_read_suppress_output(rdpUpdate* update, wStream* s)
1597 {
1598         BYTE allowDisplayUpdates;
1599
1600         if (Stream_GetRemainingLength(s) < 4)
1601                 return FALSE;
1602
1603         Stream_Read_UINT8(s, allowDisplayUpdates);
1604         Stream_Seek(s, 3); /* pad3Octects */
1605
1606         if (allowDisplayUpdates > 0 && Stream_GetRemainingLength(s) < 8)
1607                 return FALSE;
1608
1609         IFCALL(update->SuppressOutput, update->context, allowDisplayUpdates,
1610                 allowDisplayUpdates > 0 ? (RECTANGLE_16*) Stream_Pointer(s) : NULL);
1611
1612         return TRUE;
1613 }
1614
1615 void update_register_server_callbacks(rdpUpdate* update)
1616 {
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;
1648 }
1649
1650 void update_register_client_callbacks(rdpUpdate* update)
1651 {
1652         update->RefreshRect = update_send_refresh_rect;
1653         update->SuppressOutput = update_send_suppress_output;
1654         update->SurfaceFrameAcknowledge = update_send_frame_acknowledge;
1655 }
1656
1657 int update_process_messages(rdpUpdate* update)
1658 {
1659         return update_message_queue_process_pending_messages(update);
1660 }
1661
1662 static void update_free_queued_message(void *obj)
1663 {
1664         wMessage *msg = (wMessage*)obj;
1665
1666         update_message_queue_free_message(msg);
1667 }
1668
1669 rdpUpdate* update_new(rdpRdp* rdp)
1670 {
1671         const wObject cb = { NULL, NULL, NULL,  update_free_queued_message, NULL };
1672         rdpUpdate* update;
1673
1674         update = (rdpUpdate*) malloc(sizeof(rdpUpdate));
1675
1676         if (update)
1677         {
1678                 OFFSCREEN_DELETE_LIST* deleteList;
1679
1680                 ZeroMemory(update, sizeof(rdpUpdate));
1681
1682                 WLog_Init();
1683                 update->log = WLog_Get("com.freerdp.core.update");
1684
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);
1688
1689                 update->pointer = (rdpPointerUpdate*) malloc(sizeof(rdpPointerUpdate));
1690                 ZeroMemory(update->pointer, sizeof(rdpPointerUpdate));
1691
1692                 update->primary = (rdpPrimaryUpdate*) malloc(sizeof(rdpPrimaryUpdate));
1693                 ZeroMemory(update->primary, sizeof(rdpPrimaryUpdate));
1694
1695                 update->secondary = (rdpSecondaryUpdate*) malloc(sizeof(rdpSecondaryUpdate));
1696                 ZeroMemory(update->secondary, sizeof(rdpSecondaryUpdate));
1697
1698                 update->altsec = (rdpAltSecUpdate*) malloc(sizeof(rdpAltSecUpdate));
1699                 ZeroMemory(update->altsec, sizeof(rdpAltSecUpdate));
1700
1701                 update->window = (rdpWindowUpdate*) malloc(sizeof(rdpWindowUpdate));
1702                 ZeroMemory(update->window, sizeof(rdpWindowUpdate));
1703
1704                 deleteList = &(update->altsec->create_offscreen_bitmap.deleteList);
1705                 deleteList->sIndices = 64;
1706                 deleteList->indices = malloc(deleteList->sIndices * 2);
1707                 deleteList->cIndices = 0;
1708
1709                 update->SuppressOutput = update_send_suppress_output;
1710
1711                 update->initialState = TRUE;
1712
1713                 update->queue = MessageQueue_New(&cb);
1714         }
1715
1716         return update;
1717 }
1718
1719 void update_free(rdpUpdate* update)
1720 {
1721         if (update != NULL)
1722         {
1723                 OFFSCREEN_DELETE_LIST* deleteList;
1724
1725                 deleteList = &(update->altsec->create_offscreen_bitmap.deleteList);
1726                 free(deleteList->indices);
1727
1728                 free(update->bitmap_update.rectangles);
1729
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);
1735
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);
1741
1742                 free(update->secondary);
1743                 free(update->altsec);
1744                 free(update->window);
1745
1746                 MessageQueue_Free(update->queue);
1747
1748                 free(update);
1749         }
1750 }