Initial commit - from Precise source
[freerdp-ubuntu-pcb-backport.git] / libfreerdp-core / update.c
1 /**
2  * FreeRDP: A Remote Desktop Protocol Client
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 #include "update.h"
21 #include "surface.h"
22 #include <freerdp/utils/rect.h>
23 #include <freerdp/codec/bitmap.h>
24
25 /*
26 static const char* const UPDATE_TYPE_STRINGS[] =
27 {
28         "Orders",
29         "Bitmap",
30         "Palette",
31         "Synchronize"
32 };
33 */
34
35 void update_recv_orders(rdpUpdate* update, STREAM* s)
36 {
37         uint16 numberOrders;
38
39         stream_seek_uint16(s); /* pad2OctetsA (2 bytes) */
40         stream_read_uint16(s, numberOrders); /* numberOrders (2 bytes) */
41         stream_seek_uint16(s); /* pad2OctetsB (2 bytes) */
42
43         while (numberOrders > 0)
44         {
45                 update_recv_order(update, s);
46                 numberOrders--;
47         }
48 }
49
50 void update_read_bitmap_data(STREAM* s, BITMAP_DATA* bitmap_data)
51 {
52         stream_read_uint16(s, bitmap_data->destLeft);
53         stream_read_uint16(s, bitmap_data->destTop);
54         stream_read_uint16(s, bitmap_data->destRight);
55         stream_read_uint16(s, bitmap_data->destBottom);
56         stream_read_uint16(s, bitmap_data->width);
57         stream_read_uint16(s, bitmap_data->height);
58         stream_read_uint16(s, bitmap_data->bitsPerPixel);
59         stream_read_uint16(s, bitmap_data->flags);
60         stream_read_uint16(s, bitmap_data->bitmapLength);
61
62         if (bitmap_data->flags & BITMAP_COMPRESSION)
63         {
64                 if (!(bitmap_data->flags & NO_BITMAP_COMPRESSION_HDR))
65                 {
66                         stream_read_uint16(s, bitmap_data->cbCompFirstRowSize); /* cbCompFirstRowSize (2 bytes) */
67                         stream_read_uint16(s, bitmap_data->cbCompMainBodySize); /* cbCompMainBodySize (2 bytes) */
68                         stream_read_uint16(s, bitmap_data->cbScanWidth); /* cbScanWidth (2 bytes) */
69                         stream_read_uint16(s, bitmap_data->cbUncompressedSize); /* cbUncompressedSize (2 bytes) */
70                         bitmap_data->bitmapLength = bitmap_data->cbCompMainBodySize;
71                 }
72
73                 bitmap_data->compressed = true;
74                 stream_get_mark(s, bitmap_data->bitmapDataStream);
75                 stream_seek(s, bitmap_data->bitmapLength);
76         }
77         else
78         {
79                 bitmap_data->compressed = false;
80                 stream_get_mark(s, bitmap_data->bitmapDataStream);
81                 stream_seek(s, bitmap_data->bitmapLength);
82         }
83 }
84
85 void update_read_bitmap(rdpUpdate* update, STREAM* s, BITMAP_UPDATE* bitmap_update)
86 {
87         int i;
88
89         stream_read_uint16(s, bitmap_update->number); /* numberRectangles (2 bytes) */
90
91         if (bitmap_update->number > bitmap_update->count)
92         {
93                 uint16 count;
94
95                 count = bitmap_update->number * 2;
96
97                 bitmap_update->rectangles = (BITMAP_DATA*) xrealloc(bitmap_update->rectangles,
98                                 sizeof(BITMAP_DATA) * count);
99
100                 memset(&bitmap_update->rectangles[bitmap_update->count], 0,
101                                 sizeof(BITMAP_DATA) * (count - bitmap_update->count));
102
103                 bitmap_update->count = count;
104         }
105
106         /* rectangles */
107         for (i = 0; i < (int) bitmap_update->number; i++)
108         {
109                 update_read_bitmap_data(s, &bitmap_update->rectangles[i]);
110         }
111 }
112
113 void update_read_palette(rdpUpdate* update, STREAM* s, PALETTE_UPDATE* palette_update)
114 {
115         int i;
116         PALETTE_ENTRY* entry;
117
118         stream_seek_uint16(s); /* pad2Octets (2 bytes) */
119         stream_read_uint32(s, palette_update->number); /* numberColors (4 bytes), must be set to 256 */
120
121         if (palette_update->number > 256)
122                 palette_update->number = 256;
123
124         /* paletteEntries */
125         for (i = 0; i < (int) palette_update->number; i++)
126         {
127                 entry = &palette_update->entries[i];
128
129                 stream_read_uint8(s, entry->blue);
130                 stream_read_uint8(s, entry->green);
131                 stream_read_uint8(s, entry->red);
132         }
133 }
134
135 void update_read_synchronize(rdpUpdate* update, STREAM* s)
136 {
137         stream_seek_uint16(s); /* pad2Octets (2 bytes) */
138
139         /**
140          * The Synchronize Update is an artifact from the
141          * T.128 protocol and should be ignored.
142          */
143 }
144
145 void update_read_play_sound(STREAM* s, PLAY_SOUND_UPDATE* play_sound)
146 {
147         stream_read_uint32(s, play_sound->duration); /* duration (4 bytes) */
148         stream_read_uint32(s, play_sound->frequency); /* frequency (4 bytes) */
149 }
150
151 void update_recv_play_sound(rdpUpdate* update, STREAM* s)
152 {
153         update_read_play_sound(s, &update->play_sound);
154         IFCALL(update->PlaySound, update->context, &update->play_sound);
155 }
156
157 void update_read_pointer_position(STREAM* s, POINTER_POSITION_UPDATE* pointer_position)
158 {
159         stream_read_uint16(s, pointer_position->xPos); /* xPos (2 bytes) */
160         stream_read_uint16(s, pointer_position->yPos); /* yPos (2 bytes) */
161 }
162
163 void update_read_pointer_system(STREAM* s, POINTER_SYSTEM_UPDATE* pointer_system)
164 {
165         stream_read_uint32(s, pointer_system->type); /* systemPointerType (4 bytes) */
166 }
167
168 void update_read_pointer_color(STREAM* s, POINTER_COLOR_UPDATE* pointer_color)
169 {
170         stream_read_uint16(s, pointer_color->cacheIndex); /* cacheIndex (2 bytes) */
171         stream_read_uint16(s, pointer_color->xPos); /* xPos (2 bytes) */
172         stream_read_uint16(s, pointer_color->yPos); /* yPos (2 bytes) */
173         stream_read_uint16(s, pointer_color->width); /* width (2 bytes) */
174         stream_read_uint16(s, pointer_color->height); /* height (2 bytes) */
175         stream_read_uint16(s, pointer_color->lengthAndMask); /* lengthAndMask (2 bytes) */
176         stream_read_uint16(s, pointer_color->lengthXorMask); /* lengthXorMask (2 bytes) */
177
178         if (pointer_color->lengthXorMask > 0)
179         {
180                 pointer_color->xorMaskData = (uint8*) xmalloc(pointer_color->lengthXorMask);
181                 stream_read(s, pointer_color->xorMaskData, pointer_color->lengthXorMask);
182         }
183
184         if (pointer_color->lengthAndMask > 0)
185         {
186                 pointer_color->andMaskData = (uint8*) xmalloc(pointer_color->lengthAndMask);
187                 stream_read(s, pointer_color->andMaskData, pointer_color->lengthAndMask);
188         }
189
190         if (stream_get_left(s) > 0)
191                 stream_seek_uint8(s); /* pad (1 byte) */
192 }
193
194 void update_read_pointer_new(STREAM* s, POINTER_NEW_UPDATE* pointer_new)
195 {
196         stream_read_uint16(s, pointer_new->xorBpp); /* xorBpp (2 bytes) */
197         update_read_pointer_color(s, &pointer_new->colorPtrAttr); /* colorPtrAttr */
198 }
199
200 void update_read_pointer_cached(STREAM* s, POINTER_CACHED_UPDATE* pointer_cached)
201 {
202         stream_read_uint16(s, pointer_cached->cacheIndex); /* cacheIndex (2 bytes) */
203 }
204
205 void update_recv_pointer(rdpUpdate* update, STREAM* s)
206 {
207         uint16 messageType;
208         rdpContext* context = update->context;
209         rdpPointerUpdate* pointer = update->pointer;
210
211         stream_read_uint16(s, messageType); /* messageType (2 bytes) */
212         stream_seek_uint16(s); /* pad2Octets (2 bytes) */
213
214         switch (messageType)
215         {
216                 case PTR_MSG_TYPE_POSITION:
217                         update_read_pointer_position(s, &pointer->pointer_position);
218                         IFCALL(pointer->PointerPosition, context, &pointer->pointer_position);
219                         break;
220
221                 case PTR_MSG_TYPE_SYSTEM:
222                         update_read_pointer_system(s, &pointer->pointer_system);
223                         IFCALL(pointer->PointerSystem, context, &pointer->pointer_system);
224                         break;
225
226                 case PTR_MSG_TYPE_COLOR:
227                         update_read_pointer_color(s, &pointer->pointer_color);
228                         IFCALL(pointer->PointerColor, context, &pointer->pointer_color);
229                         break;
230
231                 case PTR_MSG_TYPE_POINTER:
232                         update_read_pointer_new(s, &pointer->pointer_new);
233                         IFCALL(pointer->PointerNew, context, &pointer->pointer_new);
234                         break;
235
236                 case PTR_MSG_TYPE_CACHED:
237                         update_read_pointer_cached(s, &pointer->pointer_cached);
238                         IFCALL(pointer->PointerCached, context, &pointer->pointer_cached);
239                         break;
240
241                 default:
242                         break;
243         }
244 }
245
246 void update_recv(rdpUpdate* update, STREAM* s)
247 {
248         uint16 updateType;
249         rdpContext* context = update->context;
250
251         stream_read_uint16(s, updateType); /* updateType (2 bytes) */
252
253         //printf("%s Update Data PDU\n", UPDATE_TYPE_STRINGS[updateType]);
254
255         IFCALL(update->BeginPaint, context);
256
257         switch (updateType)
258         {
259                 case UPDATE_TYPE_ORDERS:
260                         update_recv_orders(update, s);
261                         break;
262
263                 case UPDATE_TYPE_BITMAP:
264                         update_read_bitmap(update, s, &update->bitmap_update);
265                         IFCALL(update->BitmapUpdate, context, &update->bitmap_update);
266                         break;
267
268                 case UPDATE_TYPE_PALETTE:
269                         update_read_palette(update, s, &update->palette_update);
270                         IFCALL(update->Palette, context, &update->palette_update);
271                         break;
272
273                 case UPDATE_TYPE_SYNCHRONIZE:
274                         update_read_synchronize(update, s);
275                         IFCALL(update->Synchronize, context);
276                         break;
277         }
278
279         IFCALL(update->EndPaint, context);
280
281         if (stream_get_left(s) > RDP_SHARE_DATA_HEADER_LENGTH)
282         {
283                 uint16 pduType;
284                 uint16 length;
285                 uint16 source;
286
287                 rdp_read_share_control_header(s, &length, &pduType, &source);
288
289                 if (pduType != PDU_TYPE_DATA)
290                         return;
291
292                 rdp_recv_data_pdu(update->context->rdp, s);
293         }
294 }
295
296 void update_reset_state(rdpUpdate* update)
297 {
298         rdpPrimaryUpdate* primary = update->primary;
299         rdpAltSecUpdate* altsec = update->altsec;
300
301         memset(&primary->order_info, 0, sizeof(ORDER_INFO));
302         memset(&primary->dstblt, 0, sizeof(DSTBLT_ORDER));
303         memset(&primary->patblt, 0, sizeof(PATBLT_ORDER));
304         memset(&primary->scrblt, 0, sizeof(SCRBLT_ORDER));
305         memset(&primary->opaque_rect, 0, sizeof(OPAQUE_RECT_ORDER));
306         memset(&primary->draw_nine_grid, 0, sizeof(DRAW_NINE_GRID_ORDER));
307         memset(&primary->multi_dstblt, 0, sizeof(MULTI_DSTBLT_ORDER));
308         memset(&primary->multi_patblt, 0, sizeof(MULTI_PATBLT_ORDER));
309         memset(&primary->multi_scrblt, 0, sizeof(MULTI_SCRBLT_ORDER));
310         memset(&primary->multi_opaque_rect, 0, sizeof(MULTI_OPAQUE_RECT_ORDER));
311         memset(&primary->multi_draw_nine_grid, 0, sizeof(MULTI_DRAW_NINE_GRID_ORDER));
312         memset(&primary->line_to, 0, sizeof(LINE_TO_ORDER));
313         memset(&primary->polyline, 0, sizeof(POLYLINE_ORDER));
314         memset(&primary->memblt, 0, sizeof(MEMBLT_ORDER));
315         memset(&primary->mem3blt, 0, sizeof(MEM3BLT_ORDER));
316         memset(&primary->save_bitmap, 0, sizeof(SAVE_BITMAP_ORDER));
317         memset(&primary->glyph_index, 0, sizeof(GLYPH_INDEX_ORDER));
318         memset(&primary->fast_index, 0, sizeof(FAST_INDEX_ORDER));
319         memset(&primary->fast_glyph, 0, sizeof(FAST_GLYPH_ORDER));
320         memset(&primary->polygon_sc, 0, sizeof(POLYGON_SC_ORDER));
321         memset(&primary->polygon_cb, 0, sizeof(POLYGON_CB_ORDER));
322         memset(&primary->ellipse_sc, 0, sizeof(ELLIPSE_SC_ORDER));
323         memset(&primary->ellipse_cb, 0, sizeof(ELLIPSE_CB_ORDER));
324
325         primary->order_info.orderType = ORDER_TYPE_PATBLT;
326         altsec->switch_surface.bitmapId = SCREEN_BITMAP_SURFACE;
327         IFCALL(altsec->SwitchSurface, update->context, &(altsec->switch_surface));
328 }
329
330 static void update_begin_paint(rdpContext* context)
331 {
332
333 }
334
335 static void update_end_paint(rdpContext* context)
336 {
337
338 }
339
340 static void update_write_refresh_rect(STREAM* s, uint8 count, RECTANGLE_16* areas)
341 {
342         int i;
343
344         stream_write_uint8(s, count); /* numberOfAreas (1 byte) */
345         stream_seek(s, 3); /* pad3Octets (3 bytes) */
346
347         for (i = 0; i < count; i++)
348                 freerdp_write_rectangle_16(s, &areas[i]);
349 }
350
351 static void update_send_refresh_rect(rdpContext* context, uint8 count, RECTANGLE_16* areas)
352 {
353         STREAM* s;
354         rdpRdp* rdp = context->rdp;
355
356         s = rdp_data_pdu_init(rdp);
357         update_write_refresh_rect(s, count, areas);
358
359         rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_REFRESH_RECT, rdp->mcs->user_id);
360 }
361
362 static void update_write_suppress_output(STREAM* s, uint8 allow, RECTANGLE_16* area)
363 {
364         stream_write_uint8(s, allow); /* allowDisplayUpdates (1 byte) */
365         stream_seek(s, 3); /* pad3Octets (3 bytes) */
366
367         if (allow > 0)
368                 freerdp_write_rectangle_16(s, area);
369 }
370
371 static void update_send_suppress_output(rdpContext* context, uint8 allow, RECTANGLE_16* area)
372 {
373         STREAM* s;
374         rdpRdp* rdp = context->rdp;
375
376         s = rdp_data_pdu_init(rdp);
377         update_write_suppress_output(s, allow, area);
378
379         rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SUPPRESS_OUTPUT, rdp->mcs->user_id);
380 }
381
382 static void update_send_surface_command(rdpContext* context, STREAM* s)
383 {
384         STREAM* update;
385         rdpRdp* rdp = context->rdp;
386
387         update = fastpath_update_pdu_init(rdp->fastpath);
388         stream_check_size(update, stream_get_length(s));
389         stream_write(update, stream_get_head(s), stream_get_length(s));
390         fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, update);
391 }
392
393 static void update_send_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits_command)
394 {
395         STREAM* s;
396         rdpRdp* rdp = context->rdp;
397
398         s = fastpath_update_pdu_init(rdp->fastpath);
399         stream_check_size(s, SURFCMD_SURFACE_BITS_HEADER_LENGTH + (int) surface_bits_command->bitmapDataLength);
400         update_write_surfcmd_surface_bits_header(s, surface_bits_command);
401         stream_write(s, surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength);
402         fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, s);
403 }
404
405 static void update_send_surface_frame_marker(rdpContext* context, SURFACE_FRAME_MARKER* surface_frame_marker)
406 {
407         STREAM* s;
408         rdpRdp* rdp = context->rdp;
409
410         s = fastpath_update_pdu_init(rdp->fastpath);
411         update_write_surfcmd_frame_marker(s, surface_frame_marker->frameAction, surface_frame_marker->frameId);
412         fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, s);
413 }
414
415 static void update_send_synchronize(rdpContext* context)
416 {
417         STREAM* s;
418         rdpRdp* rdp = context->rdp;
419
420         s = fastpath_update_pdu_init(rdp->fastpath);
421         stream_write_zero(s, 2); /* pad2Octets (2 bytes) */
422         fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SYNCHRONIZE, s);
423 }
424
425 static void update_send_desktop_resize(rdpContext* context)
426 {
427         rdp_server_reactivate(context->rdp);
428 }
429
430 static void update_send_scrblt(rdpContext* context, SCRBLT_ORDER* scrblt)
431 {
432         STREAM* s;
433         rdpRdp* rdp = context->rdp;
434
435         s = fastpath_update_pdu_init(rdp->fastpath);
436
437         stream_write_uint16(s, 1); /* numberOrders (2 bytes) */
438         stream_write_uint8(s, ORDER_STANDARD | ORDER_TYPE_CHANGE); /* controlFlags (1 byte) */
439         stream_write_uint8(s, ORDER_TYPE_SCRBLT); /* orderType (1 byte) */
440         stream_write_uint8(s, 0x7F); /* fieldFlags (variable) */
441
442         stream_write_uint16(s, scrblt->nLeftRect);
443         stream_write_uint16(s, scrblt->nTopRect);
444         stream_write_uint16(s, scrblt->nWidth);
445         stream_write_uint16(s, scrblt->nHeight);
446         stream_write_uint8(s, scrblt->bRop);
447         stream_write_uint16(s, scrblt->nXSrc);
448         stream_write_uint16(s, scrblt->nYSrc);
449
450         fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_ORDERS, s);
451 }
452
453 static void update_send_pointer_system(rdpContext* context, POINTER_SYSTEM_UPDATE* pointer_system)
454 {
455         STREAM* s;
456         uint8 updateCode;
457         rdpRdp* rdp = context->rdp;
458
459         s = fastpath_update_pdu_init(rdp->fastpath);
460         if (pointer_system->type == SYSPTR_NULL)
461                 updateCode = FASTPATH_UPDATETYPE_PTR_NULL;
462         else
463                 updateCode = FASTPATH_UPDATETYPE_PTR_DEFAULT;
464         fastpath_send_update_pdu(rdp->fastpath, updateCode, s);
465 }
466
467 static void update_write_pointer_color(STREAM* s, POINTER_COLOR_UPDATE* pointer_color)
468 {
469         stream_check_size(s, 15 + (int) pointer_color->lengthAndMask + (int) pointer_color->lengthXorMask);
470         stream_write_uint16(s, pointer_color->cacheIndex);
471         stream_write_uint16(s, pointer_color->xPos);
472         stream_write_uint16(s, pointer_color->yPos);
473         stream_write_uint16(s, pointer_color->width);
474         stream_write_uint16(s, pointer_color->height);
475         stream_write_uint16(s, pointer_color->lengthAndMask);
476         stream_write_uint16(s, pointer_color->lengthXorMask);
477         if (pointer_color->lengthXorMask > 0)
478                 stream_write(s, pointer_color->xorMaskData, pointer_color->lengthXorMask);
479         if (pointer_color->lengthAndMask > 0)
480                 stream_write(s, pointer_color->andMaskData, pointer_color->lengthAndMask);
481         stream_write_uint8(s, 0); /* pad (1 byte) */
482 }
483
484 static void update_send_pointer_color(rdpContext* context, POINTER_COLOR_UPDATE* pointer_color)
485 {
486         STREAM* s;
487         rdpRdp* rdp = context->rdp;
488
489         s = fastpath_update_pdu_init(rdp->fastpath);
490         update_write_pointer_color(s, pointer_color);
491         fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_COLOR, s);
492 }
493
494 static void update_send_pointer_new(rdpContext* context, POINTER_NEW_UPDATE* pointer_new)
495 {
496         STREAM* s;
497         rdpRdp* rdp = context->rdp;
498
499         s = fastpath_update_pdu_init(rdp->fastpath);
500         stream_write_uint16(s, pointer_new->xorBpp); /* xorBpp (2 bytes) */
501         update_write_pointer_color(s, &pointer_new->colorPtrAttr);
502         fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_POINTER, s);
503 }
504
505 static void update_send_pointer_cached(rdpContext* context, POINTER_CACHED_UPDATE* pointer_cached)
506 {
507         STREAM* s;
508         rdpRdp* rdp = context->rdp;
509
510         s = fastpath_update_pdu_init(rdp->fastpath);
511         stream_write_uint16(s, pointer_cached->cacheIndex); /* cacheIndex (2 bytes) */
512         fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_CACHED, s);
513 }
514
515 void update_register_server_callbacks(rdpUpdate* update)
516 {
517         update->BeginPaint = update_begin_paint;
518         update->EndPaint = update_end_paint;
519         update->Synchronize = update_send_synchronize;
520         update->DesktopResize = update_send_desktop_resize;
521         update->RefreshRect = update_send_refresh_rect;
522         update->SuppressOutput = update_send_suppress_output;
523         update->SurfaceBits = update_send_surface_bits;
524         update->SurfaceFrameMarker = update_send_surface_frame_marker;
525         update->SurfaceCommand = update_send_surface_command;
526         update->primary->ScrBlt = update_send_scrblt;
527         update->pointer->PointerSystem = update_send_pointer_system;
528         update->pointer->PointerColor = update_send_pointer_color;
529         update->pointer->PointerNew = update_send_pointer_new;
530         update->pointer->PointerCached = update_send_pointer_cached;
531 }
532
533 rdpUpdate* update_new(rdpRdp* rdp)
534 {
535         rdpUpdate* update;
536
537         update = (rdpUpdate*) xzalloc(sizeof(rdpUpdate));
538
539         if (update != NULL)
540         {
541                 OFFSCREEN_DELETE_LIST* deleteList;
542
543                 update->bitmap_update.count = 64;
544                 update->bitmap_update.rectangles = (BITMAP_DATA*) xzalloc(sizeof(BITMAP_DATA) * update->bitmap_update.count);
545
546                 update->pointer = xnew(rdpPointerUpdate);
547                 update->primary = xnew(rdpPrimaryUpdate);
548                 update->secondary = xnew(rdpSecondaryUpdate);
549                 update->altsec = xnew(rdpAltSecUpdate);
550                 update->window = xnew(rdpWindowUpdate);
551
552                 deleteList = &(update->altsec->create_offscreen_bitmap.deleteList);
553                 deleteList->sIndices = 64;
554                 deleteList->indices = xmalloc(deleteList->sIndices * 2);
555                 deleteList->cIndices = 0;
556
557                 update->SuppressOutput = update_send_suppress_output;
558         }
559
560         return update;
561 }
562
563 void update_free(rdpUpdate* update)
564 {
565         if (update != NULL)
566         {
567                 OFFSCREEN_DELETE_LIST* deleteList;
568                 deleteList = &(update->altsec->create_offscreen_bitmap.deleteList);
569                 xfree(deleteList->indices);
570
571                 xfree(update->bitmap_update.rectangles);
572                 xfree(update->pointer);
573                 xfree(update->primary);
574                 xfree(update->secondary);
575                 xfree(update->altsec);
576                 xfree(update->window);
577                 xfree(update);
578         }
579 }
580