6db92b07b84d11bd4748d4245e1ee43180412c75
[platform/upstream/freerdp.git] / libfreerdp / core / orders.c
1 /**
2  * FreeRDP: A Remote Desktop Protocol Implementation
3  * Drawing Orders
4  *
5  * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6  * Copyright 2016 Armin Novak <armin.novak@thincast.com>
7  * Copyright 2016 Thincast Technologies GmbH
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *     http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include "window.h"
27
28 #include <winpr/wtypes.h>
29 #include <winpr/crt.h>
30
31 #include <freerdp/api.h>
32 #include <freerdp/log.h>
33 #include <freerdp/graphics.h>
34 #include <freerdp/codec/bitmap.h>
35 #include <freerdp/gdi/gdi.h>
36
37 #include "orders.h"
38
39 #include "../cache/glyph.h"
40 #include "../cache/bitmap.h"
41 #include "../cache/brush.h"
42 #include "../cache/cache.h"
43
44 #define TAG FREERDP_TAG("core.orders")
45
46 BYTE get_primary_drawing_order_field_bytes(UINT32 orderType, BOOL* pValid)
47 {
48         if (pValid)
49                 *pValid = TRUE;
50         switch (orderType)
51         {
52                 case 0:
53                         return DSTBLT_ORDER_FIELD_BYTES;
54                 case 1:
55                         return PATBLT_ORDER_FIELD_BYTES;
56                 case 2:
57                         return SCRBLT_ORDER_FIELD_BYTES;
58                 case 3:
59                         return 0;
60                 case 4:
61                         return 0;
62                 case 5:
63                         return 0;
64                 case 6:
65                         return 0;
66                 case 7:
67                         return DRAW_NINE_GRID_ORDER_FIELD_BYTES;
68                 case 8:
69                         return MULTI_DRAW_NINE_GRID_ORDER_FIELD_BYTES;
70                 case 9:
71                         return LINE_TO_ORDER_FIELD_BYTES;
72                 case 10:
73                         return OPAQUE_RECT_ORDER_FIELD_BYTES;
74                 case 11:
75                         return SAVE_BITMAP_ORDER_FIELD_BYTES;
76                 case 12:
77                         return 0;
78                 case 13:
79                         return MEMBLT_ORDER_FIELD_BYTES;
80                 case 14:
81                         return MEM3BLT_ORDER_FIELD_BYTES;
82                 case 15:
83                         return MULTI_DSTBLT_ORDER_FIELD_BYTES;
84                 case 16:
85                         return MULTI_PATBLT_ORDER_FIELD_BYTES;
86                 case 17:
87                         return MULTI_SCRBLT_ORDER_FIELD_BYTES;
88                 case 18:
89                         return MULTI_OPAQUE_RECT_ORDER_FIELD_BYTES;
90                 case 19:
91                         return FAST_INDEX_ORDER_FIELD_BYTES;
92                 case 20:
93                         return POLYGON_SC_ORDER_FIELD_BYTES;
94                 case 21:
95                         return POLYGON_CB_ORDER_FIELD_BYTES;
96                 case 22:
97                         return POLYLINE_ORDER_FIELD_BYTES;
98                 case 23:
99                         return 0;
100                 case 24:
101                         return FAST_GLYPH_ORDER_FIELD_BYTES;
102                 case 25:
103                         return ELLIPSE_SC_ORDER_FIELD_BYTES;
104                 case 26:
105                         return ELLIPSE_CB_ORDER_FIELD_BYTES;
106                 case 27:
107                         return GLYPH_INDEX_ORDER_FIELD_BYTES;
108                 default:
109                         if (pValid)
110                                 *pValid = FALSE;
111                         WLog_WARN(TAG, "Invalid orderType 0x%08X received", orderType);
112                         return 0;
113         }
114 }
115
116 static BYTE get_cbr2_bpp(UINT32 bpp, BOOL* pValid)
117 {
118         if (pValid)
119                 *pValid = TRUE;
120         switch (bpp)
121         {
122                 case 3:
123                         return 8;
124                 case 4:
125                         return 16;
126                 case 5:
127                         return 24;
128                 case 6:
129                         return 32;
130                 default:
131                         WLog_WARN(TAG, "Invalid bpp %" PRIu32, bpp);
132                         if (pValid)
133                                 *pValid = FALSE;
134                         return 0;
135         }
136 }
137
138 static BYTE get_bmf_bpp(UINT32 bmf, BOOL* pValid)
139 {
140         if (pValid)
141                 *pValid = TRUE;
142         /* Mask out highest bit */
143         switch (bmf & (~CACHED_BRUSH))
144         {
145                 case 1:
146                         return 1;
147                 case 3:
148                         return 8;
149                 case 4:
150                         return 16;
151                 case 5:
152                         return 24;
153                 case 6:
154                         return 32;
155                 default:
156                         WLog_WARN(TAG, "Invalid bmf %" PRIu32, bmf);
157                         if (pValid)
158                                 *pValid = FALSE;
159                         return 0;
160         }
161 }
162 static BYTE get_bpp_bmf(UINT32 bpp, BOOL* pValid)
163 {
164         if (pValid)
165                 *pValid = TRUE;
166         switch (bpp)
167         {
168                 case 1:
169                         return 1;
170                 case 8:
171                         return 3;
172                 case 16:
173                         return 4;
174                 case 24:
175                         return 5;
176                 case 32:
177                         return 6;
178                 default:
179                         WLog_WARN(TAG, "Invalid color depth %" PRIu32, bpp);
180                         if (pValid)
181                                 *pValid = FALSE;
182                         return 0;
183         }
184 }
185
186 static BOOL check_order_activated(wLog* log, rdpSettings* settings, const char* orderName,
187                                   BOOL condition, const char* extendedMessage)
188 {
189         if (!condition)
190         {
191                 if (settings->AllowUnanouncedOrdersFromServer)
192                 {
193                         WLog_Print(log, WLOG_WARN,
194                                    "%s - SERVER BUG: The support for this feature was not announced!",
195                                    orderName);
196                         if (extendedMessage)
197                                 WLog_Print(log, WLOG_WARN, "%s", extendedMessage);
198                         return TRUE;
199                 }
200                 else
201                 {
202                         WLog_Print(log, WLOG_ERROR,
203                                    "%s - SERVER BUG: The support for this feature was not announced! Use "
204                                    "/relax-order-checks to ignore",
205                                    orderName);
206                         if (extendedMessage)
207                                 WLog_Print(log, WLOG_WARN, "%s", extendedMessage);
208                         return FALSE;
209                 }
210         }
211
212         return TRUE;
213 }
214
215 static BOOL check_alt_order_supported(wLog* log, rdpSettings* settings, BYTE orderType,
216                                       const char* orderName)
217 {
218         const char* extendedMessage = NULL;
219         BOOL condition = FALSE;
220
221         switch (orderType)
222         {
223                 case ORDER_TYPE_CREATE_OFFSCREEN_BITMAP:
224                 case ORDER_TYPE_SWITCH_SURFACE:
225                         condition = settings->OffscreenSupportLevel != 0;
226                         extendedMessage = "Adding +offscreen-cache might mitigate";
227                         break;
228
229                 case ORDER_TYPE_CREATE_NINE_GRID_BITMAP:
230                         condition = settings->DrawNineGridEnabled;
231                         break;
232
233                 case ORDER_TYPE_FRAME_MARKER:
234                         condition = settings->FrameMarkerCommandEnabled;
235                         break;
236
237                 case ORDER_TYPE_GDIPLUS_FIRST:
238                 case ORDER_TYPE_GDIPLUS_NEXT:
239                 case ORDER_TYPE_GDIPLUS_END:
240                 case ORDER_TYPE_GDIPLUS_CACHE_FIRST:
241                 case ORDER_TYPE_GDIPLUS_CACHE_NEXT:
242                 case ORDER_TYPE_GDIPLUS_CACHE_END:
243                         condition = settings->DrawGdiPlusCacheEnabled;
244                         break;
245
246                 case ORDER_TYPE_WINDOW:
247                         condition = settings->RemoteWndSupportLevel != WINDOW_LEVEL_NOT_SUPPORTED;
248                         break;
249
250                 case ORDER_TYPE_STREAM_BITMAP_FIRST:
251                 case ORDER_TYPE_STREAM_BITMAP_NEXT:
252                 case ORDER_TYPE_COMPDESK_FIRST:
253                         condition = TRUE;
254                         break;
255
256                 default:
257                         WLog_Print(log, WLOG_WARN, "%s - Alternate Secondary Drawing Order UNKNOWN", orderName);
258                         condition = FALSE;
259                         break;
260         }
261
262         return check_order_activated(log, settings, orderName, condition, extendedMessage);
263 }
264
265 static BOOL check_secondary_order_supported(wLog* log, rdpSettings* settings, BYTE orderType,
266                                             const char* orderName)
267 {
268         const char* extendedMessage = NULL;
269         BOOL condition = FALSE;
270
271         switch (orderType)
272         {
273                 case ORDER_TYPE_BITMAP_UNCOMPRESSED:
274                 case ORDER_TYPE_CACHE_BITMAP_COMPRESSED:
275                         condition = settings->BitmapCacheEnabled;
276                         extendedMessage = "Adding +bitmap-cache might mitigate";
277                         break;
278
279                 case ORDER_TYPE_BITMAP_UNCOMPRESSED_V2:
280                 case ORDER_TYPE_BITMAP_COMPRESSED_V2:
281                         condition = settings->BitmapCacheEnabled;
282                         extendedMessage = "Adding +bitmap-cache might mitigate";
283                         break;
284
285                 case ORDER_TYPE_BITMAP_COMPRESSED_V3:
286                         condition = settings->BitmapCacheV3Enabled;
287                         extendedMessage = "Adding +bitmap-cache might mitigate";
288                         break;
289
290                 case ORDER_TYPE_CACHE_COLOR_TABLE:
291                         condition = (settings->OrderSupport[NEG_MEMBLT_INDEX] ||
292                                      settings->OrderSupport[NEG_MEM3BLT_INDEX]);
293                         break;
294
295                 case ORDER_TYPE_CACHE_GLYPH:
296                 {
297                         switch (settings->GlyphSupportLevel)
298                         {
299                                 case GLYPH_SUPPORT_PARTIAL:
300                                 case GLYPH_SUPPORT_FULL:
301                                 case GLYPH_SUPPORT_ENCODE:
302                                         condition = TRUE;
303                                         break;
304
305                                 case GLYPH_SUPPORT_NONE:
306                                 default:
307                                         condition = FALSE;
308                                         break;
309                         }
310                 }
311                 break;
312
313                 case ORDER_TYPE_CACHE_BRUSH:
314                         condition = TRUE;
315                         break;
316
317                 default:
318                         WLog_Print(log, WLOG_WARN, "SECONDARY ORDER %s not supported", orderName);
319                         break;
320         }
321
322         return check_order_activated(log, settings, orderName, condition, extendedMessage);
323 }
324
325 static BOOL check_primary_order_supported(wLog* log, rdpSettings* settings, UINT32 orderType,
326                                           const char* orderName)
327 {
328         const char* extendedMessage = NULL;
329         BOOL condition = FALSE;
330
331         switch (orderType)
332         {
333                 case ORDER_TYPE_DSTBLT:
334                         condition = settings->OrderSupport[NEG_DSTBLT_INDEX];
335                         break;
336
337                 case ORDER_TYPE_SCRBLT:
338                         condition = settings->OrderSupport[NEG_SCRBLT_INDEX];
339                         break;
340
341                 case ORDER_TYPE_DRAW_NINE_GRID:
342                         condition = settings->OrderSupport[NEG_DRAWNINEGRID_INDEX];
343                         break;
344
345                 case ORDER_TYPE_MULTI_DRAW_NINE_GRID:
346                         condition = settings->OrderSupport[NEG_MULTI_DRAWNINEGRID_INDEX];
347                         break;
348
349                 case ORDER_TYPE_LINE_TO:
350                         condition = settings->OrderSupport[NEG_LINETO_INDEX];
351                         break;
352
353                 /* [MS-RDPEGDI] 2.2.2.2.1.1.2.5 OpaqueRect (OPAQUERECT_ORDER)
354                  * suggests that PatBlt and OpaqueRect imply each other. */
355                 case ORDER_TYPE_PATBLT:
356                 case ORDER_TYPE_OPAQUE_RECT:
357                         condition = settings->OrderSupport[NEG_OPAQUE_RECT_INDEX] ||
358                                     settings->OrderSupport[NEG_PATBLT_INDEX];
359                         break;
360
361                 case ORDER_TYPE_SAVE_BITMAP:
362                         condition = settings->OrderSupport[NEG_SAVEBITMAP_INDEX];
363                         break;
364
365                 case ORDER_TYPE_MEMBLT:
366                         condition = settings->OrderSupport[NEG_MEMBLT_INDEX];
367                         break;
368
369                 case ORDER_TYPE_MEM3BLT:
370                         condition = settings->OrderSupport[NEG_MEM3BLT_INDEX];
371                         break;
372
373                 case ORDER_TYPE_MULTI_DSTBLT:
374                         condition = settings->OrderSupport[NEG_MULTIDSTBLT_INDEX];
375                         break;
376
377                 case ORDER_TYPE_MULTI_PATBLT:
378                         condition = settings->OrderSupport[NEG_MULTIPATBLT_INDEX];
379                         break;
380
381                 case ORDER_TYPE_MULTI_SCRBLT:
382                         condition = settings->OrderSupport[NEG_MULTIDSTBLT_INDEX];
383                         break;
384
385                 case ORDER_TYPE_MULTI_OPAQUE_RECT:
386                         condition = settings->OrderSupport[NEG_MULTIOPAQUERECT_INDEX];
387                         break;
388
389                 case ORDER_TYPE_FAST_INDEX:
390                         condition = settings->OrderSupport[NEG_FAST_INDEX_INDEX];
391                         break;
392
393                 case ORDER_TYPE_POLYGON_SC:
394                         condition = settings->OrderSupport[NEG_POLYGON_SC_INDEX];
395                         break;
396
397                 case ORDER_TYPE_POLYGON_CB:
398                         condition = settings->OrderSupport[NEG_POLYGON_CB_INDEX];
399                         break;
400
401                 case ORDER_TYPE_POLYLINE:
402                         condition = settings->OrderSupport[NEG_POLYLINE_INDEX];
403                         break;
404
405                 case ORDER_TYPE_FAST_GLYPH:
406                         condition = settings->OrderSupport[NEG_FAST_GLYPH_INDEX];
407                         break;
408
409                 case ORDER_TYPE_ELLIPSE_SC:
410                         condition = settings->OrderSupport[NEG_ELLIPSE_SC_INDEX];
411                         break;
412
413                 case ORDER_TYPE_ELLIPSE_CB:
414                         condition = settings->OrderSupport[NEG_ELLIPSE_CB_INDEX];
415                         break;
416
417                 case ORDER_TYPE_GLYPH_INDEX:
418                         condition = settings->OrderSupport[NEG_GLYPH_INDEX_INDEX];
419                         break;
420
421                 default:
422                         WLog_Print(log, WLOG_WARN, "%s Primary Drawing Order not supported", orderName);
423                         break;
424         }
425
426         return check_order_activated(log, settings, orderName, condition, extendedMessage);
427 }
428
429 static const char* primary_order_string(UINT32 orderType)
430 {
431         const char* orders[] = { "[0x%02" PRIx8 "] DstBlt",
432                                      "[0x%02" PRIx8 "] PatBlt",
433                                      "[0x%02" PRIx8 "] ScrBlt",
434                                      "[0x%02" PRIx8 "] UNUSED",
435                                      "[0x%02" PRIx8 "] UNUSED",
436                                      "[0x%02" PRIx8 "] UNUSED",
437                                      "[0x%02" PRIx8 "] UNUSED",
438                                      "[0x%02" PRIx8 "] DrawNineGrid",
439                                      "[0x%02" PRIx8 "] MultiDrawNineGrid",
440                                      "[0x%02" PRIx8 "] LineTo",
441                                      "[0x%02" PRIx8 "] OpaqueRect",
442                                      "[0x%02" PRIx8 "] SaveBitmap",
443                                      "[0x%02" PRIx8 "] UNUSED",
444                                      "[0x%02" PRIx8 "] MemBlt",
445                                      "[0x%02" PRIx8 "] Mem3Blt",
446                                      "[0x%02" PRIx8 "] MultiDstBlt",
447                                      "[0x%02" PRIx8 "] MultiPatBlt",
448                                      "[0x%02" PRIx8 "] MultiScrBlt",
449                                      "[0x%02" PRIx8 "] MultiOpaqueRect",
450                                      "[0x%02" PRIx8 "] FastIndex",
451                                      "[0x%02" PRIx8 "] PolygonSC",
452                                      "[0x%02" PRIx8 "] PolygonCB",
453                                      "[0x%02" PRIx8 "] Polyline",
454                                      "[0x%02" PRIx8 "] UNUSED",
455                                      "[0x%02" PRIx8 "] FastGlyph",
456                                      "[0x%02" PRIx8 "] EllipseSC",
457                                      "[0x%02" PRIx8 "] EllipseCB",
458                                      "[0x%02" PRIx8 "] GlyphIndex" };
459         const char* fmt = "[0x%02" PRIx8 "] UNKNOWN";
460         static char buffer[64] = { 0 };
461
462         if (orderType < ARRAYSIZE(orders))
463                 fmt = orders[orderType];
464
465         sprintf_s(buffer, ARRAYSIZE(buffer), fmt, orderType);
466         return buffer;
467 }
468 static const char* secondary_order_string(UINT32 orderType)
469 {
470         const char* orders[] = { "[0x%02" PRIx8 "] Cache Bitmap",
471                                      "[0x%02" PRIx8 "] Cache Color Table",
472                                      "[0x%02" PRIx8 "] Cache Bitmap (Compressed)",
473                                      "[0x%02" PRIx8 "] Cache Glyph",
474                                      "[0x%02" PRIx8 "] Cache Bitmap V2",
475                                      "[0x%02" PRIx8 "] Cache Bitmap V2 (Compressed)",
476                                      "[0x%02" PRIx8 "] UNUSED",
477                                      "[0x%02" PRIx8 "] Cache Brush",
478                                      "[0x%02" PRIx8 "] Cache Bitmap V3" };
479         const char* fmt = "[0x%02" PRIx8 "] UNKNOWN";
480         static char buffer[64] = { 0 };
481
482         if (orderType < ARRAYSIZE(orders))
483                 fmt = orders[orderType];
484
485         sprintf_s(buffer, ARRAYSIZE(buffer), fmt, orderType);
486         return buffer;
487 }
488 static const char* altsec_order_string(BYTE orderType)
489 {
490         const char* orders[] = {
491                 "[0x%02" PRIx8 "] Switch Surface",         "[0x%02" PRIx8 "] Create Offscreen Bitmap",
492                 "[0x%02" PRIx8 "] Stream Bitmap First",    "[0x%02" PRIx8 "] Stream Bitmap Next",
493                 "[0x%02" PRIx8 "] Create NineGrid Bitmap", "[0x%02" PRIx8 "] Draw GDI+ First",
494                 "[0x%02" PRIx8 "] Draw GDI+ Next",         "[0x%02" PRIx8 "] Draw GDI+ End",
495                 "[0x%02" PRIx8 "] Draw GDI+ Cache First",  "[0x%02" PRIx8 "] Draw GDI+ Cache Next",
496                 "[0x%02" PRIx8 "] Draw GDI+ Cache End",    "[0x%02" PRIx8 "] Windowing",
497                 "[0x%02" PRIx8 "] Desktop Composition",    "[0x%02" PRIx8 "] Frame Marker"
498         };
499         const char* fmt = "[0x%02" PRIx8 "] UNKNOWN";
500         static char buffer[64] = { 0 };
501
502         if (orderType < ARRAYSIZE(orders))
503                 fmt = orders[orderType];
504
505         sprintf_s(buffer, ARRAYSIZE(buffer), fmt, orderType);
506         return buffer;
507 }
508
509 static INLINE BOOL update_read_coord(wStream* s, INT32* coord, BOOL delta)
510 {
511         INT8 lsi8;
512         INT16 lsi16;
513
514         if (delta)
515         {
516                 if (Stream_GetRemainingLength(s) < 1)
517                         return FALSE;
518
519                 Stream_Read_INT8(s, lsi8);
520                 *coord += lsi8;
521         }
522         else
523         {
524                 if (Stream_GetRemainingLength(s) < 2)
525                         return FALSE;
526
527                 Stream_Read_INT16(s, lsi16);
528                 *coord = lsi16;
529         }
530
531         return TRUE;
532 }
533 static INLINE BOOL update_write_coord(wStream* s, INT32 coord)
534 {
535         Stream_Write_UINT16(s, coord);
536         return TRUE;
537 }
538 static INLINE BOOL update_read_color(wStream* s, UINT32* color)
539 {
540         BYTE byte;
541
542         if (Stream_GetRemainingLength(s) < 3)
543                 return FALSE;
544
545         *color = 0;
546         Stream_Read_UINT8(s, byte);
547         *color = (UINT32)byte;
548         Stream_Read_UINT8(s, byte);
549         *color |= ((UINT32)byte << 8) & 0xFF00;
550         Stream_Read_UINT8(s, byte);
551         *color |= ((UINT32)byte << 16) & 0xFF0000;
552         return TRUE;
553 }
554 static INLINE BOOL update_write_color(wStream* s, UINT32 color)
555 {
556         BYTE byte;
557         byte = (color & 0xFF);
558         Stream_Write_UINT8(s, byte);
559         byte = ((color >> 8) & 0xFF);
560         Stream_Write_UINT8(s, byte);
561         byte = ((color >> 16) & 0xFF);
562         Stream_Write_UINT8(s, byte);
563         return TRUE;
564 }
565 static INLINE BOOL update_read_colorref(wStream* s, UINT32* color)
566 {
567         BYTE byte;
568
569         if (Stream_GetRemainingLength(s) < 4)
570                 return FALSE;
571
572         *color = 0;
573         Stream_Read_UINT8(s, byte);
574         *color = byte;
575         Stream_Read_UINT8(s, byte);
576         *color |= ((UINT32)byte << 8);
577         Stream_Read_UINT8(s, byte);
578         *color |= ((UINT32)byte << 16);
579         Stream_Seek_UINT8(s);
580         return TRUE;
581 }
582 static INLINE BOOL update_read_color_quad(wStream* s, UINT32* color)
583 {
584         return update_read_colorref(s, color);
585 }
586 static INLINE void update_write_color_quad(wStream* s, UINT32 color)
587 {
588         BYTE byte;
589         byte = (color >> 16) & 0xFF;
590         Stream_Write_UINT8(s, byte);
591         byte = (color >> 8) & 0xFF;
592         Stream_Write_UINT8(s, byte);
593         byte = color & 0xFF;
594         Stream_Write_UINT8(s, byte);
595 }
596 static INLINE BOOL update_read_2byte_unsigned(wStream* s, UINT32* value)
597 {
598         BYTE byte;
599
600         if (Stream_GetRemainingLength(s) < 1)
601                 return FALSE;
602
603         Stream_Read_UINT8(s, byte);
604
605         if (byte & 0x80)
606         {
607                 if (Stream_GetRemainingLength(s) < 1)
608                         return FALSE;
609
610                 *value = (byte & 0x7F) << 8;
611                 Stream_Read_UINT8(s, byte);
612                 *value |= byte;
613         }
614         else
615         {
616                 *value = (byte & 0x7F);
617         }
618
619         return TRUE;
620 }
621 static INLINE BOOL update_write_2byte_unsigned(wStream* s, UINT32 value)
622 {
623         BYTE byte;
624
625         if (value > 0x7FFF)
626                 return FALSE;
627
628         if (value >= 0x7F)
629         {
630                 byte = ((value & 0x7F00) >> 8);
631                 Stream_Write_UINT8(s, byte | 0x80);
632                 byte = (value & 0xFF);
633                 Stream_Write_UINT8(s, byte);
634         }
635         else
636         {
637                 byte = (value & 0x7F);
638                 Stream_Write_UINT8(s, byte);
639         }
640
641         return TRUE;
642 }
643 static INLINE BOOL update_read_2byte_signed(wStream* s, INT32* value)
644 {
645         BYTE byte;
646         BOOL negative;
647
648         if (Stream_GetRemainingLength(s) < 1)
649                 return FALSE;
650
651         Stream_Read_UINT8(s, byte);
652         negative = (byte & 0x40) ? TRUE : FALSE;
653         *value = (byte & 0x3F);
654
655         if (byte & 0x80)
656         {
657                 if (Stream_GetRemainingLength(s) < 1)
658                         return FALSE;
659
660                 Stream_Read_UINT8(s, byte);
661                 *value = (*value << 8) | byte;
662         }
663
664         if (negative)
665                 *value *= -1;
666
667         return TRUE;
668 }
669 static INLINE BOOL update_write_2byte_signed(wStream* s, INT32 value)
670 {
671         BYTE byte;
672         BOOL negative = FALSE;
673
674         if (value < 0)
675         {
676                 negative = TRUE;
677                 value *= -1;
678         }
679
680         if (value > 0x3FFF)
681                 return FALSE;
682
683         if (value >= 0x3F)
684         {
685                 byte = ((value & 0x3F00) >> 8);
686
687                 if (negative)
688                         byte |= 0x40;
689
690                 Stream_Write_UINT8(s, byte | 0x80);
691                 byte = (value & 0xFF);
692                 Stream_Write_UINT8(s, byte);
693         }
694         else
695         {
696                 byte = (value & 0x3F);
697
698                 if (negative)
699                         byte |= 0x40;
700
701                 Stream_Write_UINT8(s, byte);
702         }
703
704         return TRUE;
705 }
706 static INLINE BOOL update_read_4byte_unsigned(wStream* s, UINT32* value)
707 {
708         BYTE byte;
709         BYTE count;
710
711         if (Stream_GetRemainingLength(s) < 1)
712                 return FALSE;
713
714         Stream_Read_UINT8(s, byte);
715         count = (byte & 0xC0) >> 6;
716
717         if (Stream_GetRemainingLength(s) < count)
718                 return FALSE;
719
720         switch (count)
721         {
722                 case 0:
723                         *value = (byte & 0x3F);
724                         break;
725
726                 case 1:
727                         *value = (byte & 0x3F) << 8;
728                         Stream_Read_UINT8(s, byte);
729                         *value |= byte;
730                         break;
731
732                 case 2:
733                         *value = (byte & 0x3F) << 16;
734                         Stream_Read_UINT8(s, byte);
735                         *value |= (byte << 8);
736                         Stream_Read_UINT8(s, byte);
737                         *value |= byte;
738                         break;
739
740                 case 3:
741                         *value = (byte & 0x3F) << 24;
742                         Stream_Read_UINT8(s, byte);
743                         *value |= (byte << 16);
744                         Stream_Read_UINT8(s, byte);
745                         *value |= (byte << 8);
746                         Stream_Read_UINT8(s, byte);
747                         *value |= byte;
748                         break;
749
750                 default:
751                         break;
752         }
753
754         return TRUE;
755 }
756 static INLINE BOOL update_write_4byte_unsigned(wStream* s, UINT32 value)
757 {
758         BYTE byte;
759
760         if (value <= 0x3F)
761         {
762                 Stream_Write_UINT8(s, value);
763         }
764         else if (value <= 0x3FFF)
765         {
766                 byte = (value >> 8) & 0x3F;
767                 Stream_Write_UINT8(s, byte | 0x40);
768                 byte = (value & 0xFF);
769                 Stream_Write_UINT8(s, byte);
770         }
771         else if (value <= 0x3FFFFF)
772         {
773                 byte = (value >> 16) & 0x3F;
774                 Stream_Write_UINT8(s, byte | 0x80);
775                 byte = (value >> 8) & 0xFF;
776                 Stream_Write_UINT8(s, byte);
777                 byte = (value & 0xFF);
778                 Stream_Write_UINT8(s, byte);
779         }
780         else if (value <= 0x3FFFFFFF)
781         {
782                 byte = (value >> 24) & 0x3F;
783                 Stream_Write_UINT8(s, byte | 0xC0);
784                 byte = (value >> 16) & 0xFF;
785                 Stream_Write_UINT8(s, byte);
786                 byte = (value >> 8) & 0xFF;
787                 Stream_Write_UINT8(s, byte);
788                 byte = (value & 0xFF);
789                 Stream_Write_UINT8(s, byte);
790         }
791         else
792                 return FALSE;
793
794         return TRUE;
795 }
796 static INLINE BOOL update_read_delta(wStream* s, INT32* value)
797 {
798         BYTE byte;
799
800         if (Stream_GetRemainingLength(s) < 1)
801         {
802                 WLog_ERR(TAG, "Stream_GetRemainingLength(s) < 1");
803                 return FALSE;
804         }
805
806         Stream_Read_UINT8(s, byte);
807
808         if (byte & 0x40)
809                 *value = (byte | ~0x3F);
810         else
811                 *value = (byte & 0x3F);
812
813         if (byte & 0x80)
814         {
815                 if (Stream_GetRemainingLength(s) < 1)
816                 {
817                         WLog_ERR(TAG, "Stream_GetRemainingLength(s) < 1");
818                         return FALSE;
819                 }
820
821                 Stream_Read_UINT8(s, byte);
822                 *value = (*value << 8) | byte;
823         }
824
825         return TRUE;
826 }
827 #if 0
828 static INLINE void update_read_glyph_delta(wStream* s, UINT16* value)
829 {
830         BYTE byte;
831         Stream_Read_UINT8(s, byte);
832
833         if (byte == 0x80)
834                 Stream_Read_UINT16(s, *value);
835         else
836                 *value = (byte & 0x3F);
837 }
838 static INLINE void update_seek_glyph_delta(wStream* s)
839 {
840         BYTE byte;
841         Stream_Read_UINT8(s, byte);
842
843         if (byte & 0x80)
844                 Stream_Seek_UINT8(s);
845 }
846 #endif
847 static INLINE BOOL update_read_brush(wStream* s, rdpBrush* brush, BYTE fieldFlags)
848 {
849         if (fieldFlags & ORDER_FIELD_01)
850         {
851                 if (Stream_GetRemainingLength(s) < 1)
852                         return FALSE;
853
854                 Stream_Read_UINT8(s, brush->x);
855         }
856
857         if (fieldFlags & ORDER_FIELD_02)
858         {
859                 if (Stream_GetRemainingLength(s) < 1)
860                         return FALSE;
861
862                 Stream_Read_UINT8(s, brush->y);
863         }
864
865         if (fieldFlags & ORDER_FIELD_03)
866         {
867                 if (Stream_GetRemainingLength(s) < 1)
868                         return FALSE;
869
870                 Stream_Read_UINT8(s, brush->style);
871         }
872
873         if (fieldFlags & ORDER_FIELD_04)
874         {
875                 if (Stream_GetRemainingLength(s) < 1)
876                         return FALSE;
877
878                 Stream_Read_UINT8(s, brush->hatch);
879         }
880
881         if (brush->style & CACHED_BRUSH)
882         {
883                 BOOL rc;
884                 brush->index = brush->hatch;
885                 brush->bpp = get_bmf_bpp(brush->style, &rc);
886                 if (!rc)
887                         return FALSE;
888                 if (brush->bpp == 0)
889                         brush->bpp = 1;
890         }
891
892         if (fieldFlags & ORDER_FIELD_05)
893         {
894                 if (Stream_GetRemainingLength(s) < 7)
895                         return FALSE;
896
897                 brush->data = (BYTE*)brush->p8x8;
898                 Stream_Read_UINT8(s, brush->data[7]);
899                 Stream_Read_UINT8(s, brush->data[6]);
900                 Stream_Read_UINT8(s, brush->data[5]);
901                 Stream_Read_UINT8(s, brush->data[4]);
902                 Stream_Read_UINT8(s, brush->data[3]);
903                 Stream_Read_UINT8(s, brush->data[2]);
904                 Stream_Read_UINT8(s, brush->data[1]);
905                 brush->data[0] = brush->hatch;
906         }
907
908         return TRUE;
909 }
910 static INLINE BOOL update_write_brush(wStream* s, rdpBrush* brush, BYTE fieldFlags)
911 {
912         if (fieldFlags & ORDER_FIELD_01)
913         {
914                 Stream_Write_UINT8(s, brush->x);
915         }
916
917         if (fieldFlags & ORDER_FIELD_02)
918         {
919                 Stream_Write_UINT8(s, brush->y);
920         }
921
922         if (fieldFlags & ORDER_FIELD_03)
923         {
924                 Stream_Write_UINT8(s, brush->style);
925         }
926
927         if (brush->style & CACHED_BRUSH)
928         {
929                 BOOL rc;
930                 brush->hatch = brush->index;
931                 brush->bpp = get_bmf_bpp(brush->style, &rc);
932                 if (!rc)
933                         return FALSE;
934                 if (brush->bpp == 0)
935                         brush->bpp = 1;
936         }
937
938         if (fieldFlags & ORDER_FIELD_04)
939         {
940                 Stream_Write_UINT8(s, brush->hatch);
941         }
942
943         if (fieldFlags & ORDER_FIELD_05)
944         {
945                 brush->data = (BYTE*)brush->p8x8;
946                 Stream_Write_UINT8(s, brush->data[7]);
947                 Stream_Write_UINT8(s, brush->data[6]);
948                 Stream_Write_UINT8(s, brush->data[5]);
949                 Stream_Write_UINT8(s, brush->data[4]);
950                 Stream_Write_UINT8(s, brush->data[3]);
951                 Stream_Write_UINT8(s, brush->data[2]);
952                 Stream_Write_UINT8(s, brush->data[1]);
953                 brush->data[0] = brush->hatch;
954         }
955
956         return TRUE;
957 }
958 static INLINE BOOL update_read_delta_rects(wStream* s, DELTA_RECT* rectangles, UINT32* nr)
959 {
960         UINT32 number = *nr;
961         UINT32 i;
962         BYTE flags = 0;
963         BYTE* zeroBits;
964         UINT32 zeroBitsSize;
965
966         if (number > 45)
967         {
968                 WLog_WARN(TAG, "Invalid number of delta rectangles %" PRIu32, number);
969                 return FALSE;
970         }
971
972         zeroBitsSize = ((number + 1) / 2);
973
974         if (Stream_GetRemainingLength(s) < zeroBitsSize)
975                 return FALSE;
976
977         Stream_GetPointer(s, zeroBits);
978         Stream_Seek(s, zeroBitsSize);
979         ZeroMemory(rectangles, sizeof(DELTA_RECT) * number);
980
981         for (i = 0; i < number; i++)
982         {
983                 if (i % 2 == 0)
984                         flags = zeroBits[i / 2];
985
986                 if ((~flags & 0x80) && !update_read_delta(s, &rectangles[i].left))
987                         return FALSE;
988
989                 if ((~flags & 0x40) && !update_read_delta(s, &rectangles[i].top))
990                         return FALSE;
991
992                 if (~flags & 0x20)
993                 {
994                         if (!update_read_delta(s, &rectangles[i].width))
995                                 return FALSE;
996                 }
997                 else if (i > 0)
998                         rectangles[i].width = rectangles[i - 1].width;
999                 else
1000                         rectangles[i].width = 0;
1001
1002                 if (~flags & 0x10)
1003                 {
1004                         if (!update_read_delta(s, &rectangles[i].height))
1005                                 return FALSE;
1006                 }
1007                 else if (i > 0)
1008                         rectangles[i].height = rectangles[i - 1].height;
1009                 else
1010                         rectangles[i].height = 0;
1011
1012                 if (i > 0)
1013                 {
1014                         rectangles[i].left += rectangles[i - 1].left;
1015                         rectangles[i].top += rectangles[i - 1].top;
1016                 }
1017
1018                 flags <<= 4;
1019         }
1020
1021         return TRUE;
1022 }
1023 static INLINE BOOL update_read_delta_points(wStream* s, DELTA_POINT* points, int number, INT16 x,
1024                                             INT16 y)
1025 {
1026         int i;
1027         BYTE flags = 0;
1028         BYTE* zeroBits;
1029         UINT32 zeroBitsSize;
1030         zeroBitsSize = ((number + 3) / 4);
1031
1032         if (Stream_GetRemainingLength(s) < zeroBitsSize)
1033         {
1034                 WLog_ERR(TAG, "Stream_GetRemainingLength(s) < %" PRIu32 "", zeroBitsSize);
1035                 return FALSE;
1036         }
1037
1038         Stream_GetPointer(s, zeroBits);
1039         Stream_Seek(s, zeroBitsSize);
1040         ZeroMemory(points, sizeof(DELTA_POINT) * number);
1041
1042         for (i = 0; i < number; i++)
1043         {
1044                 if (i % 4 == 0)
1045                         flags = zeroBits[i / 4];
1046
1047                 if ((~flags & 0x80) && !update_read_delta(s, &points[i].x))
1048                 {
1049                         WLog_ERR(TAG, "update_read_delta(x) failed");
1050                         return FALSE;
1051                 }
1052
1053                 if ((~flags & 0x40) && !update_read_delta(s, &points[i].y))
1054                 {
1055                         WLog_ERR(TAG, "update_read_delta(y) failed");
1056                         return FALSE;
1057                 }
1058
1059                 flags <<= 2;
1060         }
1061
1062         return TRUE;
1063 }
1064
1065 static INLINE BOOL read_order_field_byte(const ORDER_INFO* orderInfo, wStream* s, BYTE number,
1066                                          UINT32* target, BOOL optional)
1067 {
1068         const BOOL set = orderInfo->fieldFlags & (1 << (number - 1));
1069         if (!set)
1070                 return TRUE;
1071         if (Stream_GetRemainingLength(s) < 1)
1072                 return FALSE;
1073         Stream_Read_UINT8(s, *target);
1074         return TRUE;
1075 }
1076
1077 static INLINE BOOL read_order_field_2bytes(const ORDER_INFO* orderInfo, wStream* s, BYTE number,
1078                                            UINT32* target1, UINT32* target2, BOOL optional)
1079 {
1080         const BOOL set = orderInfo->fieldFlags & (1 << (number - 1));
1081         if (!set)
1082                 return TRUE;
1083         if (Stream_GetRemainingLength(s) < 2)
1084                 return FALSE;
1085         Stream_Read_UINT8(s, *target1);
1086         Stream_Read_UINT8(s, *target2);
1087         return TRUE;
1088 }
1089
1090 static INLINE BOOL read_order_field_uint16(const ORDER_INFO* orderInfo, wStream* s, BYTE number,
1091                                            UINT32* target, BOOL optional)
1092 {
1093         const BOOL set = orderInfo->fieldFlags & (1 << (number - 1));
1094         if (!set)
1095                 return TRUE;
1096
1097         if (Stream_GetRemainingLength(s) < 2)
1098                 return FALSE;
1099
1100         Stream_Read_UINT16(s, *target);
1101         return TRUE;
1102 }
1103
1104 static INLINE BOOL read_order_field_int16(const ORDER_INFO* orderInfo, wStream* s, BYTE number,
1105                                           INT32* target, BOOL optional)
1106 {
1107         const BOOL set = orderInfo->fieldFlags & (1 << (number - 1));
1108         if (!set)
1109                 return TRUE;
1110
1111         if (Stream_GetRemainingLength(s) < 2)
1112                 return FALSE;
1113
1114         Stream_Read_INT16(s, *target);
1115         return TRUE;
1116 }
1117
1118 static INLINE BOOL read_order_field_uint32(const ORDER_INFO* orderInfo, wStream* s, BYTE number,
1119                                            UINT32* target, BOOL optional)
1120 {
1121         const BOOL set = orderInfo->fieldFlags & (1 << (number - 1));
1122         if (!set)
1123                 return TRUE;
1124         if (Stream_GetRemainingLength(s) < 4)
1125                 return FALSE;
1126
1127         Stream_Read_UINT32(s, *target);
1128         return TRUE;
1129 }
1130
1131 static INLINE BOOL read_order_field_coord(const ORDER_INFO* orderInfo, wStream* s, UINT32 NO,
1132                                           INT32* TARGET, BOOL optional)
1133 {
1134         const BOOL set = (orderInfo->fieldFlags & (1 << (NO - 1)));
1135         if (!TARGET || !orderInfo)
1136                 return FALSE;
1137         if (!set)
1138                 return TRUE;
1139
1140         return update_read_coord(s, TARGET, orderInfo->deltaCoordinates);
1141 }
1142
1143 static INLINE BOOL read_order_field_color(const ORDER_INFO* orderInfo, wStream* s, UINT32 NO,
1144                                           UINT32* TARGET, BOOL optional)
1145 {
1146         const BOOL set = (orderInfo->fieldFlags & (1 << (NO - 1)));
1147         if (!TARGET || !orderInfo)
1148                 return FALSE;
1149         if (!set)
1150                 return TRUE;
1151
1152         if (!update_read_color(s, TARGET))
1153                 return FALSE;
1154
1155         return TRUE;
1156 }
1157 static INLINE BOOL FIELD_SKIP_BUFFER16(wStream* s, UINT32 TARGET_LEN)
1158 {
1159         if (Stream_GetRemainingLength(s) < 2)
1160                 return FALSE;
1161
1162         Stream_Read_UINT16(s, TARGET_LEN);
1163
1164         if (!Stream_SafeSeek(s, TARGET_LEN))
1165         {
1166                 WLog_ERR(TAG, "error skipping %" PRIu32 " bytes", TARGET_LEN);
1167                 return FALSE;
1168         }
1169
1170         return TRUE;
1171 }
1172 /* Primary Drawing Orders */
1173 static BOOL update_read_dstblt_order(wStream* s, const ORDER_INFO* orderInfo, DSTBLT_ORDER* dstblt)
1174 {
1175         if (!read_order_field_coord(orderInfo, s, 1, &dstblt->nLeftRect, FALSE) ||
1176             !read_order_field_coord(orderInfo, s, 2, &dstblt->nTopRect, FALSE) ||
1177             !read_order_field_coord(orderInfo, s, 3, &dstblt->nWidth, FALSE) ||
1178             !read_order_field_coord(orderInfo, s, 4, &dstblt->nHeight, FALSE) ||
1179             !read_order_field_byte(orderInfo, s, 5, &dstblt->bRop, TRUE))
1180                 return FALSE;
1181         return TRUE;
1182 }
1183 int update_approximate_dstblt_order(ORDER_INFO* orderInfo, const DSTBLT_ORDER* dstblt)
1184 {
1185         return 32;
1186 }
1187 BOOL update_write_dstblt_order(wStream* s, ORDER_INFO* orderInfo, const DSTBLT_ORDER* dstblt)
1188 {
1189         if (!Stream_EnsureRemainingCapacity(s, update_approximate_dstblt_order(orderInfo, dstblt)))
1190                 return FALSE;
1191
1192         orderInfo->fieldFlags = 0;
1193         orderInfo->fieldFlags |= ORDER_FIELD_01;
1194         update_write_coord(s, dstblt->nLeftRect);
1195         orderInfo->fieldFlags |= ORDER_FIELD_02;
1196         update_write_coord(s, dstblt->nTopRect);
1197         orderInfo->fieldFlags |= ORDER_FIELD_03;
1198         update_write_coord(s, dstblt->nWidth);
1199         orderInfo->fieldFlags |= ORDER_FIELD_04;
1200         update_write_coord(s, dstblt->nHeight);
1201         orderInfo->fieldFlags |= ORDER_FIELD_05;
1202         Stream_Write_UINT8(s, dstblt->bRop);
1203         return TRUE;
1204 }
1205 static BOOL update_read_patblt_order(wStream* s, const ORDER_INFO* orderInfo, PATBLT_ORDER* patblt)
1206 {
1207         if (!read_order_field_coord(orderInfo, s, 1, &patblt->nLeftRect, FALSE) ||
1208             !read_order_field_coord(orderInfo, s, 2, &patblt->nTopRect, FALSE) ||
1209             !read_order_field_coord(orderInfo, s, 3, &patblt->nWidth, FALSE) ||
1210             !read_order_field_coord(orderInfo, s, 4, &patblt->nHeight, FALSE) ||
1211             !read_order_field_byte(orderInfo, s, 5, &patblt->bRop, TRUE) ||
1212             !read_order_field_color(orderInfo, s, 6, &patblt->backColor, TRUE) ||
1213             !read_order_field_color(orderInfo, s, 7, &patblt->foreColor, TRUE))
1214                 return FALSE;
1215         return update_read_brush(s, &patblt->brush, orderInfo->fieldFlags >> 7);
1216 }
1217 int update_approximate_patblt_order(ORDER_INFO* orderInfo, PATBLT_ORDER* patblt)
1218 {
1219         return 32;
1220 }
1221 BOOL update_write_patblt_order(wStream* s, ORDER_INFO* orderInfo, PATBLT_ORDER* patblt)
1222 {
1223         if (!Stream_EnsureRemainingCapacity(s, update_approximate_patblt_order(orderInfo, patblt)))
1224                 return FALSE;
1225
1226         orderInfo->fieldFlags = 0;
1227         orderInfo->fieldFlags |= ORDER_FIELD_01;
1228         update_write_coord(s, patblt->nLeftRect);
1229         orderInfo->fieldFlags |= ORDER_FIELD_02;
1230         update_write_coord(s, patblt->nTopRect);
1231         orderInfo->fieldFlags |= ORDER_FIELD_03;
1232         update_write_coord(s, patblt->nWidth);
1233         orderInfo->fieldFlags |= ORDER_FIELD_04;
1234         update_write_coord(s, patblt->nHeight);
1235         orderInfo->fieldFlags |= ORDER_FIELD_05;
1236         Stream_Write_UINT8(s, patblt->bRop);
1237         orderInfo->fieldFlags |= ORDER_FIELD_06;
1238         update_write_color(s, patblt->backColor);
1239         orderInfo->fieldFlags |= ORDER_FIELD_07;
1240         update_write_color(s, patblt->foreColor);
1241         orderInfo->fieldFlags |= ORDER_FIELD_08;
1242         orderInfo->fieldFlags |= ORDER_FIELD_09;
1243         orderInfo->fieldFlags |= ORDER_FIELD_10;
1244         orderInfo->fieldFlags |= ORDER_FIELD_11;
1245         orderInfo->fieldFlags |= ORDER_FIELD_12;
1246         update_write_brush(s, &patblt->brush, orderInfo->fieldFlags >> 7);
1247         return TRUE;
1248 }
1249 static BOOL update_read_scrblt_order(wStream* s, const ORDER_INFO* orderInfo, SCRBLT_ORDER* scrblt)
1250 {
1251         if (!read_order_field_coord(orderInfo, s, 1, &scrblt->nLeftRect, FALSE) ||
1252             !read_order_field_coord(orderInfo, s, 2, &scrblt->nTopRect, FALSE) ||
1253             !read_order_field_coord(orderInfo, s, 3, &scrblt->nWidth, FALSE) ||
1254             !read_order_field_coord(orderInfo, s, 4, &scrblt->nHeight, FALSE) ||
1255             !read_order_field_byte(orderInfo, s, 5, &scrblt->bRop, TRUE) ||
1256             !read_order_field_coord(orderInfo, s, 6, &scrblt->nXSrc, FALSE) ||
1257             !read_order_field_coord(orderInfo, s, 7, &scrblt->nYSrc, FALSE))
1258                 return FALSE;
1259         return TRUE;
1260 }
1261 int update_approximate_scrblt_order(ORDER_INFO* orderInfo, const SCRBLT_ORDER* scrblt)
1262 {
1263         return 32;
1264 }
1265 BOOL update_write_scrblt_order(wStream* s, ORDER_INFO* orderInfo, const SCRBLT_ORDER* scrblt)
1266 {
1267         if (!Stream_EnsureRemainingCapacity(s, update_approximate_scrblt_order(orderInfo, scrblt)))
1268                 return FALSE;
1269
1270         orderInfo->fieldFlags = 0;
1271         orderInfo->fieldFlags |= ORDER_FIELD_01;
1272         update_write_coord(s, scrblt->nLeftRect);
1273         orderInfo->fieldFlags |= ORDER_FIELD_02;
1274         update_write_coord(s, scrblt->nTopRect);
1275         orderInfo->fieldFlags |= ORDER_FIELD_03;
1276         update_write_coord(s, scrblt->nWidth);
1277         orderInfo->fieldFlags |= ORDER_FIELD_04;
1278         update_write_coord(s, scrblt->nHeight);
1279         orderInfo->fieldFlags |= ORDER_FIELD_05;
1280         Stream_Write_UINT8(s, scrblt->bRop);
1281         orderInfo->fieldFlags |= ORDER_FIELD_06;
1282         update_write_coord(s, scrblt->nXSrc);
1283         orderInfo->fieldFlags |= ORDER_FIELD_07;
1284         update_write_coord(s, scrblt->nYSrc);
1285         return TRUE;
1286 }
1287 static BOOL update_read_opaque_rect_order(wStream* s, const ORDER_INFO* orderInfo,
1288                                           OPAQUE_RECT_ORDER* opaque_rect)
1289 {
1290         BYTE byte;
1291         if (!read_order_field_coord(orderInfo, s, 1, &opaque_rect->nLeftRect, FALSE) ||
1292             !read_order_field_coord(orderInfo, s, 2, &opaque_rect->nTopRect, FALSE) ||
1293             !read_order_field_coord(orderInfo, s, 3, &opaque_rect->nWidth, FALSE) ||
1294             !read_order_field_coord(orderInfo, s, 4, &opaque_rect->nHeight, FALSE))
1295                 return FALSE;
1296
1297         if ((orderInfo->fieldFlags & ORDER_FIELD_05) != 0)
1298         {
1299                 if (Stream_GetRemainingLength(s) < 1)
1300                         return FALSE;
1301
1302                 Stream_Read_UINT8(s, byte);
1303                 opaque_rect->color = (opaque_rect->color & 0x00FFFF00) | ((UINT32)byte);
1304         }
1305
1306         if ((orderInfo->fieldFlags & ORDER_FIELD_06) != 0)
1307         {
1308                 if (Stream_GetRemainingLength(s) < 1)
1309                         return FALSE;
1310
1311                 Stream_Read_UINT8(s, byte);
1312                 opaque_rect->color = (opaque_rect->color & 0x00FF00FF) | ((UINT32)byte << 8);
1313         }
1314
1315         if ((orderInfo->fieldFlags & ORDER_FIELD_07) != 0)
1316         {
1317                 if (Stream_GetRemainingLength(s) < 1)
1318                         return FALSE;
1319
1320                 Stream_Read_UINT8(s, byte);
1321                 opaque_rect->color = (opaque_rect->color & 0x0000FFFF) | ((UINT32)byte << 16);
1322         }
1323
1324         return TRUE;
1325 }
1326 int update_approximate_opaque_rect_order(ORDER_INFO* orderInfo,
1327                                          const OPAQUE_RECT_ORDER* opaque_rect)
1328 {
1329         return 32;
1330 }
1331 BOOL update_write_opaque_rect_order(wStream* s, ORDER_INFO* orderInfo,
1332                                     const OPAQUE_RECT_ORDER* opaque_rect)
1333 {
1334         BYTE byte;
1335         int inf = update_approximate_opaque_rect_order(orderInfo, opaque_rect);
1336
1337         if (!Stream_EnsureRemainingCapacity(s, inf))
1338                 return FALSE;
1339
1340         // TODO: Color format conversion
1341         orderInfo->fieldFlags = 0;
1342         orderInfo->fieldFlags |= ORDER_FIELD_01;
1343         update_write_coord(s, opaque_rect->nLeftRect);
1344         orderInfo->fieldFlags |= ORDER_FIELD_02;
1345         update_write_coord(s, opaque_rect->nTopRect);
1346         orderInfo->fieldFlags |= ORDER_FIELD_03;
1347         update_write_coord(s, opaque_rect->nWidth);
1348         orderInfo->fieldFlags |= ORDER_FIELD_04;
1349         update_write_coord(s, opaque_rect->nHeight);
1350         orderInfo->fieldFlags |= ORDER_FIELD_05;
1351         byte = opaque_rect->color & 0x000000FF;
1352         Stream_Write_UINT8(s, byte);
1353         orderInfo->fieldFlags |= ORDER_FIELD_06;
1354         byte = (opaque_rect->color & 0x0000FF00) >> 8;
1355         Stream_Write_UINT8(s, byte);
1356         orderInfo->fieldFlags |= ORDER_FIELD_07;
1357         byte = (opaque_rect->color & 0x00FF0000) >> 16;
1358         Stream_Write_UINT8(s, byte);
1359         return TRUE;
1360 }
1361 static BOOL update_read_draw_nine_grid_order(wStream* s, const ORDER_INFO* orderInfo,
1362                                              DRAW_NINE_GRID_ORDER* draw_nine_grid)
1363 {
1364         if (!read_order_field_coord(orderInfo, s, 1, &draw_nine_grid->srcLeft, FALSE) ||
1365             !read_order_field_coord(orderInfo, s, 2, &draw_nine_grid->srcTop, FALSE) ||
1366             !read_order_field_coord(orderInfo, s, 3, &draw_nine_grid->srcRight, FALSE) ||
1367             !read_order_field_coord(orderInfo, s, 4, &draw_nine_grid->srcBottom, FALSE) ||
1368             !read_order_field_uint16(orderInfo, s, 5, &draw_nine_grid->bitmapId, FALSE))
1369                 return FALSE;
1370         return TRUE;
1371 }
1372 static BOOL update_read_multi_dstblt_order(wStream* s, const ORDER_INFO* orderInfo,
1373                                            MULTI_DSTBLT_ORDER* multi_dstblt)
1374 {
1375         if (!read_order_field_coord(orderInfo, s, 1, &multi_dstblt->nLeftRect, FALSE) ||
1376             !read_order_field_coord(orderInfo, s, 2, &multi_dstblt->nTopRect, FALSE) ||
1377             !read_order_field_coord(orderInfo, s, 3, &multi_dstblt->nWidth, FALSE) ||
1378             !read_order_field_coord(orderInfo, s, 4, &multi_dstblt->nHeight, FALSE) ||
1379             !read_order_field_byte(orderInfo, s, 5, &multi_dstblt->bRop, TRUE) ||
1380             !read_order_field_byte(orderInfo, s, 6, &multi_dstblt->numRectangles, TRUE))
1381                 return FALSE;
1382
1383         if ((orderInfo->fieldFlags & ORDER_FIELD_07) != 0)
1384         {
1385                 if (Stream_GetRemainingLength(s) < 2)
1386                         return FALSE;
1387
1388                 Stream_Read_UINT16(s, multi_dstblt->cbData);
1389                 return update_read_delta_rects(s, multi_dstblt->rectangles, &multi_dstblt->numRectangles);
1390         }
1391
1392         return TRUE;
1393 }
1394 static BOOL update_read_multi_patblt_order(wStream* s, const ORDER_INFO* orderInfo,
1395                                            MULTI_PATBLT_ORDER* multi_patblt)
1396 {
1397         if (!read_order_field_coord(orderInfo, s, 1, &multi_patblt->nLeftRect, FALSE) ||
1398             !read_order_field_coord(orderInfo, s, 2, &multi_patblt->nTopRect, FALSE) ||
1399             !read_order_field_coord(orderInfo, s, 3, &multi_patblt->nWidth, FALSE) ||
1400             !read_order_field_coord(orderInfo, s, 4, &multi_patblt->nHeight, FALSE) ||
1401             !read_order_field_byte(orderInfo, s, 5, &multi_patblt->bRop, TRUE) ||
1402             !read_order_field_color(orderInfo, s, 6, &multi_patblt->backColor, TRUE) ||
1403             !read_order_field_color(orderInfo, s, 7, &multi_patblt->foreColor, TRUE))
1404                 return FALSE;
1405
1406         if (!update_read_brush(s, &multi_patblt->brush, orderInfo->fieldFlags >> 7))
1407                 return FALSE;
1408
1409         if (!read_order_field_byte(orderInfo, s, 13, &multi_patblt->numRectangles, TRUE))
1410                 return FALSE;
1411
1412         if ((orderInfo->fieldFlags & ORDER_FIELD_14) != 0)
1413         {
1414                 if (Stream_GetRemainingLength(s) < 2)
1415                         return FALSE;
1416
1417                 Stream_Read_UINT16(s, multi_patblt->cbData);
1418
1419                 if (!update_read_delta_rects(s, multi_patblt->rectangles, &multi_patblt->numRectangles))
1420                         return FALSE;
1421         }
1422
1423         return TRUE;
1424 }
1425 static BOOL update_read_multi_scrblt_order(wStream* s, const ORDER_INFO* orderInfo,
1426                                            MULTI_SCRBLT_ORDER* multi_scrblt)
1427 {
1428         if (!read_order_field_coord(orderInfo, s, 1, &multi_scrblt->nLeftRect, FALSE) ||
1429             !read_order_field_coord(orderInfo, s, 2, &multi_scrblt->nTopRect, FALSE) ||
1430             !read_order_field_coord(orderInfo, s, 3, &multi_scrblt->nWidth, FALSE) ||
1431             !read_order_field_coord(orderInfo, s, 4, &multi_scrblt->nHeight, FALSE) ||
1432             !read_order_field_byte(orderInfo, s, 5, &multi_scrblt->bRop, TRUE) ||
1433             !read_order_field_coord(orderInfo, s, 6, &multi_scrblt->nXSrc, FALSE) ||
1434             !read_order_field_coord(orderInfo, s, 7, &multi_scrblt->nYSrc, FALSE) ||
1435             !read_order_field_byte(orderInfo, s, 8, &multi_scrblt->numRectangles, TRUE))
1436                 return FALSE;
1437
1438         if ((orderInfo->fieldFlags & ORDER_FIELD_09) != 0)
1439         {
1440                 if (Stream_GetRemainingLength(s) < 2)
1441                         return FALSE;
1442
1443                 Stream_Read_UINT16(s, multi_scrblt->cbData);
1444                 return update_read_delta_rects(s, multi_scrblt->rectangles, &multi_scrblt->numRectangles);
1445         }
1446
1447         return TRUE;
1448 }
1449 static BOOL update_read_multi_opaque_rect_order(wStream* s, const ORDER_INFO* orderInfo,
1450                                                 MULTI_OPAQUE_RECT_ORDER* multi_opaque_rect)
1451 {
1452         BYTE byte;
1453         if (!read_order_field_coord(orderInfo, s, 1, &multi_opaque_rect->nLeftRect, FALSE) ||
1454             !read_order_field_coord(orderInfo, s, 2, &multi_opaque_rect->nTopRect, FALSE) ||
1455             !read_order_field_coord(orderInfo, s, 3, &multi_opaque_rect->nWidth, FALSE) ||
1456             !read_order_field_coord(orderInfo, s, 4, &multi_opaque_rect->nHeight, FALSE))
1457                 return FALSE;
1458
1459         if ((orderInfo->fieldFlags & ORDER_FIELD_05) != 0)
1460         {
1461                 if (Stream_GetRemainingLength(s) < 1)
1462                         return FALSE;
1463
1464                 Stream_Read_UINT8(s, byte);
1465                 multi_opaque_rect->color = (multi_opaque_rect->color & 0x00FFFF00) | ((UINT32)byte);
1466         }
1467
1468         if ((orderInfo->fieldFlags & ORDER_FIELD_06) != 0)
1469         {
1470                 if (Stream_GetRemainingLength(s) < 1)
1471                         return FALSE;
1472
1473                 Stream_Read_UINT8(s, byte);
1474                 multi_opaque_rect->color = (multi_opaque_rect->color & 0x00FF00FF) | ((UINT32)byte << 8);
1475         }
1476
1477         if ((orderInfo->fieldFlags & ORDER_FIELD_07) != 0)
1478         {
1479                 if (Stream_GetRemainingLength(s) < 1)
1480                         return FALSE;
1481
1482                 Stream_Read_UINT8(s, byte);
1483                 multi_opaque_rect->color = (multi_opaque_rect->color & 0x0000FFFF) | ((UINT32)byte << 16);
1484         }
1485
1486         if (!read_order_field_byte(orderInfo, s, 8, &multi_opaque_rect->numRectangles, TRUE))
1487                 return FALSE;
1488
1489         if ((orderInfo->fieldFlags & ORDER_FIELD_09) != 0)
1490         {
1491                 if (Stream_GetRemainingLength(s) < 2)
1492                         return FALSE;
1493
1494                 Stream_Read_UINT16(s, multi_opaque_rect->cbData);
1495                 return update_read_delta_rects(s, multi_opaque_rect->rectangles,
1496                                                &multi_opaque_rect->numRectangles);
1497         }
1498
1499         return TRUE;
1500 }
1501 static BOOL update_read_multi_draw_nine_grid_order(wStream* s, const ORDER_INFO* orderInfo,
1502                                                    MULTI_DRAW_NINE_GRID_ORDER* multi_draw_nine_grid)
1503 {
1504         if (!read_order_field_coord(orderInfo, s, 1, &multi_draw_nine_grid->srcLeft, FALSE) ||
1505             !read_order_field_coord(orderInfo, s, 2, &multi_draw_nine_grid->srcTop, FALSE) ||
1506             !read_order_field_coord(orderInfo, s, 3, &multi_draw_nine_grid->srcRight, FALSE) ||
1507             !read_order_field_coord(orderInfo, s, 4, &multi_draw_nine_grid->srcBottom, FALSE) ||
1508             !read_order_field_uint16(orderInfo, s, 5, &multi_draw_nine_grid->bitmapId, TRUE) ||
1509             !read_order_field_byte(orderInfo, s, 6, &multi_draw_nine_grid->nDeltaEntries, TRUE))
1510                 return FALSE;
1511
1512         if ((orderInfo->fieldFlags & ORDER_FIELD_07) != 0)
1513         {
1514                 if (Stream_GetRemainingLength(s) < 2)
1515                         return FALSE;
1516
1517                 Stream_Read_UINT16(s, multi_draw_nine_grid->cbData);
1518                 return update_read_delta_rects(s, multi_draw_nine_grid->rectangles,
1519                                                &multi_draw_nine_grid->nDeltaEntries);
1520         }
1521
1522         return TRUE;
1523 }
1524 static BOOL update_read_line_to_order(wStream* s, const ORDER_INFO* orderInfo,
1525                                       LINE_TO_ORDER* line_to)
1526 {
1527         if (!read_order_field_uint16(orderInfo, s, 1, &line_to->backMode, TRUE) ||
1528             !read_order_field_coord(orderInfo, s, 2, &line_to->nXStart, FALSE) ||
1529             !read_order_field_coord(orderInfo, s, 3, &line_to->nYStart, FALSE) ||
1530             !read_order_field_coord(orderInfo, s, 4, &line_to->nXEnd, FALSE) ||
1531             !read_order_field_coord(orderInfo, s, 5, &line_to->nYEnd, FALSE) ||
1532             !read_order_field_color(orderInfo, s, 6, &line_to->backColor, TRUE) ||
1533             !read_order_field_byte(orderInfo, s, 7, &line_to->bRop2, TRUE) ||
1534             !read_order_field_byte(orderInfo, s, 8, &line_to->penStyle, TRUE) ||
1535             !read_order_field_byte(orderInfo, s, 9, &line_to->penWidth, TRUE) ||
1536             !read_order_field_color(orderInfo, s, 10, &line_to->penColor, TRUE))
1537                 return FALSE;
1538         return TRUE;
1539 }
1540 int update_approximate_line_to_order(ORDER_INFO* orderInfo, const LINE_TO_ORDER* line_to)
1541 {
1542         return 32;
1543 }
1544 BOOL update_write_line_to_order(wStream* s, ORDER_INFO* orderInfo, const LINE_TO_ORDER* line_to)
1545 {
1546         if (!Stream_EnsureRemainingCapacity(s, update_approximate_line_to_order(orderInfo, line_to)))
1547                 return FALSE;
1548
1549         orderInfo->fieldFlags = 0;
1550         orderInfo->fieldFlags |= ORDER_FIELD_01;
1551         Stream_Write_UINT16(s, line_to->backMode);
1552         orderInfo->fieldFlags |= ORDER_FIELD_02;
1553         update_write_coord(s, line_to->nXStart);
1554         orderInfo->fieldFlags |= ORDER_FIELD_03;
1555         update_write_coord(s, line_to->nYStart);
1556         orderInfo->fieldFlags |= ORDER_FIELD_04;
1557         update_write_coord(s, line_to->nXEnd);
1558         orderInfo->fieldFlags |= ORDER_FIELD_05;
1559         update_write_coord(s, line_to->nYEnd);
1560         orderInfo->fieldFlags |= ORDER_FIELD_06;
1561         update_write_color(s, line_to->backColor);
1562         orderInfo->fieldFlags |= ORDER_FIELD_07;
1563         Stream_Write_UINT8(s, line_to->bRop2);
1564         orderInfo->fieldFlags |= ORDER_FIELD_08;
1565         Stream_Write_UINT8(s, line_to->penStyle);
1566         orderInfo->fieldFlags |= ORDER_FIELD_09;
1567         Stream_Write_UINT8(s, line_to->penWidth);
1568         orderInfo->fieldFlags |= ORDER_FIELD_10;
1569         update_write_color(s, line_to->penColor);
1570         return TRUE;
1571 }
1572 static BOOL update_read_polyline_order(wStream* s, const ORDER_INFO* orderInfo,
1573                                        POLYLINE_ORDER* polyline)
1574 {
1575         UINT32 word;
1576         UINT32 new_num = polyline->numDeltaEntries;
1577         if (!read_order_field_coord(orderInfo, s, 1, &polyline->xStart, FALSE) ||
1578             !read_order_field_coord(orderInfo, s, 2, &polyline->yStart, FALSE) ||
1579             !read_order_field_byte(orderInfo, s, 3, &polyline->bRop2, TRUE) ||
1580             !read_order_field_uint16(orderInfo, s, 4, &word, TRUE) ||
1581             !read_order_field_color(orderInfo, s, 5, &polyline->penColor, TRUE) ||
1582             !read_order_field_byte(orderInfo, s, 6, &new_num, TRUE))
1583                 return FALSE;
1584
1585         if ((orderInfo->fieldFlags & ORDER_FIELD_07) != 0)
1586         {
1587                 DELTA_POINT* new_points;
1588
1589                 if (new_num == 0)
1590                         return FALSE;
1591
1592                 if (Stream_GetRemainingLength(s) < 1)
1593                 {
1594                         WLog_ERR(TAG, "Stream_GetRemainingLength(s) < 1");
1595                         return FALSE;
1596                 }
1597
1598                 Stream_Read_UINT8(s, polyline->cbData);
1599                 new_points = (DELTA_POINT*)realloc(polyline->points, sizeof(DELTA_POINT) * new_num);
1600
1601                 if (!new_points)
1602                 {
1603                         WLog_ERR(TAG, "realloc(%" PRIu32 ") failed", new_num);
1604                         return FALSE;
1605                 }
1606
1607                 polyline->points = new_points;
1608                 polyline->numDeltaEntries = new_num;
1609                 return update_read_delta_points(s, polyline->points, polyline->numDeltaEntries,
1610                                                 polyline->xStart, polyline->yStart);
1611         }
1612
1613         return TRUE;
1614 }
1615 static BOOL update_read_memblt_order(wStream* s, const ORDER_INFO* orderInfo, MEMBLT_ORDER* memblt)
1616 {
1617         if (!s || !orderInfo || !memblt)
1618                 return FALSE;
1619
1620         if (!read_order_field_uint16(orderInfo, s, 1, &memblt->cacheId, TRUE) ||
1621             !read_order_field_coord(orderInfo, s, 2, &memblt->nLeftRect, FALSE) ||
1622             !read_order_field_coord(orderInfo, s, 3, &memblt->nTopRect, FALSE) ||
1623             !read_order_field_coord(orderInfo, s, 4, &memblt->nWidth, FALSE) ||
1624             !read_order_field_coord(orderInfo, s, 5, &memblt->nHeight, FALSE) ||
1625             !read_order_field_byte(orderInfo, s, 6, &memblt->bRop, TRUE) ||
1626             !read_order_field_coord(orderInfo, s, 7, &memblt->nXSrc, FALSE) ||
1627             !read_order_field_coord(orderInfo, s, 8, &memblt->nYSrc, FALSE) ||
1628             !read_order_field_uint16(orderInfo, s, 9, &memblt->cacheIndex, TRUE))
1629                 return FALSE;
1630         memblt->colorIndex = (memblt->cacheId >> 8);
1631         memblt->cacheId = (memblt->cacheId & 0xFF);
1632         memblt->bitmap = NULL;
1633         return TRUE;
1634 }
1635 int update_approximate_memblt_order(ORDER_INFO* orderInfo, const MEMBLT_ORDER* memblt)
1636 {
1637         return 64;
1638 }
1639 BOOL update_write_memblt_order(wStream* s, ORDER_INFO* orderInfo, const MEMBLT_ORDER* memblt)
1640 {
1641         UINT16 cacheId;
1642
1643         if (!Stream_EnsureRemainingCapacity(s, update_approximate_memblt_order(orderInfo, memblt)))
1644                 return FALSE;
1645
1646         cacheId = (memblt->cacheId & 0xFF) | ((memblt->colorIndex & 0xFF) << 8);
1647         orderInfo->fieldFlags |= ORDER_FIELD_01;
1648         Stream_Write_UINT16(s, cacheId);
1649         orderInfo->fieldFlags |= ORDER_FIELD_02;
1650         update_write_coord(s, memblt->nLeftRect);
1651         orderInfo->fieldFlags |= ORDER_FIELD_03;
1652         update_write_coord(s, memblt->nTopRect);
1653         orderInfo->fieldFlags |= ORDER_FIELD_04;
1654         update_write_coord(s, memblt->nWidth);
1655         orderInfo->fieldFlags |= ORDER_FIELD_05;
1656         update_write_coord(s, memblt->nHeight);
1657         orderInfo->fieldFlags |= ORDER_FIELD_06;
1658         Stream_Write_UINT8(s, memblt->bRop);
1659         orderInfo->fieldFlags |= ORDER_FIELD_07;
1660         update_write_coord(s, memblt->nXSrc);
1661         orderInfo->fieldFlags |= ORDER_FIELD_08;
1662         update_write_coord(s, memblt->nYSrc);
1663         orderInfo->fieldFlags |= ORDER_FIELD_09;
1664         Stream_Write_UINT16(s, memblt->cacheIndex);
1665         return TRUE;
1666 }
1667 static BOOL update_read_mem3blt_order(wStream* s, const ORDER_INFO* orderInfo,
1668                                       MEM3BLT_ORDER* mem3blt)
1669 {
1670         if (!read_order_field_uint16(orderInfo, s, 1, &mem3blt->cacheId, TRUE) ||
1671             !read_order_field_coord(orderInfo, s, 2, &mem3blt->nLeftRect, FALSE) ||
1672             !read_order_field_coord(orderInfo, s, 3, &mem3blt->nTopRect, FALSE) ||
1673             !read_order_field_coord(orderInfo, s, 4, &mem3blt->nWidth, FALSE) ||
1674             !read_order_field_coord(orderInfo, s, 5, &mem3blt->nHeight, FALSE) ||
1675             !read_order_field_byte(orderInfo, s, 6, &mem3blt->bRop, TRUE) ||
1676             !read_order_field_coord(orderInfo, s, 7, &mem3blt->nXSrc, FALSE) ||
1677             !read_order_field_coord(orderInfo, s, 8, &mem3blt->nYSrc, FALSE) ||
1678             !read_order_field_color(orderInfo, s, 9, &mem3blt->backColor, TRUE) ||
1679             !read_order_field_color(orderInfo, s, 10, &mem3blt->foreColor, TRUE))
1680                 return FALSE;
1681
1682         if (!update_read_brush(s, &mem3blt->brush, orderInfo->fieldFlags >> 10) ||
1683             !read_order_field_uint16(orderInfo, s, 16, &mem3blt->cacheIndex, TRUE))
1684                 return FALSE;
1685         mem3blt->colorIndex = (mem3blt->cacheId >> 8);
1686         mem3blt->cacheId = (mem3blt->cacheId & 0xFF);
1687         mem3blt->bitmap = NULL;
1688         return TRUE;
1689 }
1690 static BOOL update_read_save_bitmap_order(wStream* s, const ORDER_INFO* orderInfo,
1691                                           SAVE_BITMAP_ORDER* save_bitmap)
1692 {
1693         if (!read_order_field_uint32(orderInfo, s, 1, &save_bitmap->savedBitmapPosition, TRUE) ||
1694             !read_order_field_coord(orderInfo, s, 2, &save_bitmap->nLeftRect, FALSE) ||
1695             !read_order_field_coord(orderInfo, s, 3, &save_bitmap->nTopRect, FALSE) ||
1696             !read_order_field_coord(orderInfo, s, 4, &save_bitmap->nRightRect, FALSE) ||
1697             !read_order_field_coord(orderInfo, s, 5, &save_bitmap->nBottomRect, FALSE) ||
1698             !read_order_field_byte(orderInfo, s, 6, &save_bitmap->operation, TRUE))
1699                 return FALSE;
1700         return TRUE;
1701 }
1702 static BOOL update_read_glyph_index_order(wStream* s, const ORDER_INFO* orderInfo,
1703                                           GLYPH_INDEX_ORDER* glyph_index)
1704 {
1705         if (!read_order_field_byte(orderInfo, s, 1, &glyph_index->cacheId, TRUE) ||
1706             !read_order_field_byte(orderInfo, s, 2, &glyph_index->flAccel, TRUE) ||
1707             !read_order_field_byte(orderInfo, s, 3, &glyph_index->ulCharInc, TRUE) ||
1708             !read_order_field_byte(orderInfo, s, 4, &glyph_index->fOpRedundant, TRUE) ||
1709             !read_order_field_color(orderInfo, s, 5, &glyph_index->backColor, TRUE) ||
1710             !read_order_field_color(orderInfo, s, 6, &glyph_index->foreColor, TRUE) ||
1711             !read_order_field_int16(orderInfo, s, 7, &glyph_index->bkLeft, TRUE) ||
1712             !read_order_field_int16(orderInfo, s, 8, &glyph_index->bkTop, TRUE) ||
1713             !read_order_field_int16(orderInfo, s, 9, &glyph_index->bkRight, TRUE) ||
1714             !read_order_field_int16(orderInfo, s, 10, &glyph_index->bkBottom, TRUE) ||
1715             !read_order_field_int16(orderInfo, s, 11, &glyph_index->opLeft, TRUE) ||
1716             !read_order_field_int16(orderInfo, s, 12, &glyph_index->opTop, TRUE) ||
1717             !read_order_field_int16(orderInfo, s, 13, &glyph_index->opRight, TRUE) ||
1718             !read_order_field_int16(orderInfo, s, 14, &glyph_index->opBottom, TRUE) ||
1719             !update_read_brush(s, &glyph_index->brush, orderInfo->fieldFlags >> 14) ||
1720             !read_order_field_int16(orderInfo, s, 20, &glyph_index->x, TRUE) ||
1721             !read_order_field_int16(orderInfo, s, 21, &glyph_index->y, TRUE))
1722                 return FALSE;
1723
1724         if ((orderInfo->fieldFlags & ORDER_FIELD_22) != 0)
1725         {
1726                 if (Stream_GetRemainingLength(s) < 1)
1727                         return FALSE;
1728
1729                 Stream_Read_UINT8(s, glyph_index->cbData);
1730
1731                 if (Stream_GetRemainingLength(s) < glyph_index->cbData)
1732                         return FALSE;
1733
1734                 CopyMemory(glyph_index->data, Stream_Pointer(s), glyph_index->cbData);
1735                 Stream_Seek(s, glyph_index->cbData);
1736         }
1737
1738         return TRUE;
1739 }
1740 int update_approximate_glyph_index_order(ORDER_INFO* orderInfo,
1741                                          const GLYPH_INDEX_ORDER* glyph_index)
1742 {
1743         return 64;
1744 }
1745 BOOL update_write_glyph_index_order(wStream* s, ORDER_INFO* orderInfo,
1746                                     GLYPH_INDEX_ORDER* glyph_index)
1747 {
1748         int inf = update_approximate_glyph_index_order(orderInfo, glyph_index);
1749
1750         if (!Stream_EnsureRemainingCapacity(s, inf))
1751                 return FALSE;
1752
1753         orderInfo->fieldFlags = 0;
1754         orderInfo->fieldFlags |= ORDER_FIELD_01;
1755         Stream_Write_UINT8(s, glyph_index->cacheId);
1756         orderInfo->fieldFlags |= ORDER_FIELD_02;
1757         Stream_Write_UINT8(s, glyph_index->flAccel);
1758         orderInfo->fieldFlags |= ORDER_FIELD_03;
1759         Stream_Write_UINT8(s, glyph_index->ulCharInc);
1760         orderInfo->fieldFlags |= ORDER_FIELD_04;
1761         Stream_Write_UINT8(s, glyph_index->fOpRedundant);
1762         orderInfo->fieldFlags |= ORDER_FIELD_05;
1763         update_write_color(s, glyph_index->backColor);
1764         orderInfo->fieldFlags |= ORDER_FIELD_06;
1765         update_write_color(s, glyph_index->foreColor);
1766         orderInfo->fieldFlags |= ORDER_FIELD_07;
1767         Stream_Write_UINT16(s, glyph_index->bkLeft);
1768         orderInfo->fieldFlags |= ORDER_FIELD_08;
1769         Stream_Write_UINT16(s, glyph_index->bkTop);
1770         orderInfo->fieldFlags |= ORDER_FIELD_09;
1771         Stream_Write_UINT16(s, glyph_index->bkRight);
1772         orderInfo->fieldFlags |= ORDER_FIELD_10;
1773         Stream_Write_UINT16(s, glyph_index->bkBottom);
1774         orderInfo->fieldFlags |= ORDER_FIELD_11;
1775         Stream_Write_UINT16(s, glyph_index->opLeft);
1776         orderInfo->fieldFlags |= ORDER_FIELD_12;
1777         Stream_Write_UINT16(s, glyph_index->opTop);
1778         orderInfo->fieldFlags |= ORDER_FIELD_13;
1779         Stream_Write_UINT16(s, glyph_index->opRight);
1780         orderInfo->fieldFlags |= ORDER_FIELD_14;
1781         Stream_Write_UINT16(s, glyph_index->opBottom);
1782         orderInfo->fieldFlags |= ORDER_FIELD_15;
1783         orderInfo->fieldFlags |= ORDER_FIELD_16;
1784         orderInfo->fieldFlags |= ORDER_FIELD_17;
1785         orderInfo->fieldFlags |= ORDER_FIELD_18;
1786         orderInfo->fieldFlags |= ORDER_FIELD_19;
1787         update_write_brush(s, &glyph_index->brush, orderInfo->fieldFlags >> 14);
1788         orderInfo->fieldFlags |= ORDER_FIELD_20;
1789         Stream_Write_UINT16(s, glyph_index->x);
1790         orderInfo->fieldFlags |= ORDER_FIELD_21;
1791         Stream_Write_UINT16(s, glyph_index->y);
1792         orderInfo->fieldFlags |= ORDER_FIELD_22;
1793         Stream_Write_UINT8(s, glyph_index->cbData);
1794         Stream_Write(s, glyph_index->data, glyph_index->cbData);
1795         return TRUE;
1796 }
1797 static BOOL update_read_fast_index_order(wStream* s, const ORDER_INFO* orderInfo,
1798                                          FAST_INDEX_ORDER* fast_index)
1799 {
1800         if (!read_order_field_byte(orderInfo, s, 1, &fast_index->cacheId, TRUE) ||
1801             !read_order_field_2bytes(orderInfo, s, 2, &fast_index->ulCharInc, &fast_index->flAccel,
1802                                      TRUE) ||
1803             !read_order_field_color(orderInfo, s, 3, &fast_index->backColor, TRUE) ||
1804             !read_order_field_color(orderInfo, s, 4, &fast_index->foreColor, TRUE) ||
1805             !read_order_field_coord(orderInfo, s, 5, &fast_index->bkLeft, FALSE) ||
1806             !read_order_field_coord(orderInfo, s, 6, &fast_index->bkTop, FALSE) ||
1807             !read_order_field_coord(orderInfo, s, 7, &fast_index->bkRight, FALSE) ||
1808             !read_order_field_coord(orderInfo, s, 8, &fast_index->bkBottom, FALSE) ||
1809             !read_order_field_coord(orderInfo, s, 9, &fast_index->opLeft, FALSE) ||
1810             !read_order_field_coord(orderInfo, s, 10, &fast_index->opTop, FALSE) ||
1811             !read_order_field_coord(orderInfo, s, 11, &fast_index->opRight, FALSE) ||
1812             !read_order_field_coord(orderInfo, s, 12, &fast_index->opBottom, FALSE) ||
1813             !read_order_field_coord(orderInfo, s, 13, &fast_index->x, FALSE) ||
1814             !read_order_field_coord(orderInfo, s, 14, &fast_index->y, FALSE))
1815                 return FALSE;
1816
1817         if ((orderInfo->fieldFlags & ORDER_FIELD_15) != 0)
1818         {
1819                 if (Stream_GetRemainingLength(s) < 1)
1820                         return FALSE;
1821
1822                 Stream_Read_UINT8(s, fast_index->cbData);
1823
1824                 if (Stream_GetRemainingLength(s) < fast_index->cbData)
1825                         return FALSE;
1826
1827                 CopyMemory(fast_index->data, Stream_Pointer(s), fast_index->cbData);
1828                 Stream_Seek(s, fast_index->cbData);
1829         }
1830
1831         return TRUE;
1832 }
1833 static BOOL update_read_fast_glyph_order(wStream* s, const ORDER_INFO* orderInfo,
1834                                          FAST_GLYPH_ORDER* fastGlyph)
1835 {
1836         GLYPH_DATA_V2* glyph = &fastGlyph->glyphData;
1837         if (!read_order_field_byte(orderInfo, s, 1, &fastGlyph->cacheId, TRUE))
1838                 return FALSE;
1839         if (fastGlyph->cacheId > 9)
1840                 return FALSE;
1841         if (!read_order_field_2bytes(orderInfo, s, 2, &fastGlyph->ulCharInc, &fastGlyph->flAccel,
1842                                      TRUE) ||
1843             !read_order_field_color(orderInfo, s, 3, &fastGlyph->backColor, TRUE) ||
1844             !read_order_field_color(orderInfo, s, 4, &fastGlyph->foreColor, TRUE) ||
1845             !read_order_field_coord(orderInfo, s, 5, &fastGlyph->bkLeft, FALSE) ||
1846             !read_order_field_coord(orderInfo, s, 6, &fastGlyph->bkTop, FALSE) ||
1847             !read_order_field_coord(orderInfo, s, 7, &fastGlyph->bkRight, FALSE) ||
1848             !read_order_field_coord(orderInfo, s, 8, &fastGlyph->bkBottom, FALSE) ||
1849             !read_order_field_coord(orderInfo, s, 9, &fastGlyph->opLeft, FALSE) ||
1850             !read_order_field_coord(orderInfo, s, 10, &fastGlyph->opTop, FALSE) ||
1851             !read_order_field_coord(orderInfo, s, 11, &fastGlyph->opRight, FALSE) ||
1852             !read_order_field_coord(orderInfo, s, 12, &fastGlyph->opBottom, FALSE) ||
1853             !read_order_field_coord(orderInfo, s, 13, &fastGlyph->x, FALSE) ||
1854             !read_order_field_coord(orderInfo, s, 14, &fastGlyph->y, FALSE))
1855                 return FALSE;
1856
1857         if ((orderInfo->fieldFlags & ORDER_FIELD_15) != 0)
1858         {
1859                 const BYTE* src;
1860                 wStream sub;
1861                 if (Stream_GetRemainingLength(s) < 1)
1862                         return FALSE;
1863
1864                 Stream_Read_UINT8(s, fastGlyph->cbData);
1865
1866                 src = Stream_Pointer(s);
1867                 if (!Stream_SafeSeek(s, fastGlyph->cbData) || (fastGlyph->cbData == 0))
1868                         return FALSE;
1869
1870                 CopyMemory(fastGlyph->data, src, fastGlyph->cbData);
1871                 Stream_StaticInit(&sub, fastGlyph->data, fastGlyph->cbData);
1872
1873                 Stream_Read_UINT8(&sub, glyph->cacheIndex);
1874
1875                 if (fastGlyph->cbData > 1)
1876                 {
1877                         if (!update_read_2byte_signed(&sub, &glyph->x) ||
1878                             !update_read_2byte_signed(&sub, &glyph->y) ||
1879                             !update_read_2byte_unsigned(&sub, &glyph->cx) ||
1880                             !update_read_2byte_unsigned(&sub, &glyph->cy))
1881                                 return FALSE;
1882
1883                         glyph->cb = Stream_GetRemainingLength(&sub);
1884                         if (glyph->cb > 0)
1885                         {
1886                                 BYTE* new_aj = (BYTE*)realloc(glyph->aj, glyph->cb);
1887
1888                                 if (!new_aj)
1889                                         return FALSE;
1890
1891                                 glyph->aj = new_aj;
1892                                 Stream_Read(&sub, glyph->aj, glyph->cb);
1893                         }
1894                         else
1895                         {
1896                                 free(glyph->aj);
1897                                 glyph->aj = NULL;
1898                         }
1899                 }
1900         }
1901
1902         return TRUE;
1903 }
1904 static BOOL update_read_polygon_sc_order(wStream* s, const ORDER_INFO* orderInfo,
1905                                          POLYGON_SC_ORDER* polygon_sc)
1906 {
1907         UINT32 num = polygon_sc->numPoints;
1908         if (!read_order_field_coord(orderInfo, s, 1, &polygon_sc->xStart, FALSE) ||
1909             !read_order_field_coord(orderInfo, s, 2, &polygon_sc->yStart, FALSE) ||
1910             !read_order_field_byte(orderInfo, s, 3, &polygon_sc->bRop2, TRUE) ||
1911             !read_order_field_byte(orderInfo, s, 4, &polygon_sc->fillMode, TRUE) ||
1912             !read_order_field_color(orderInfo, s, 5, &polygon_sc->brushColor, TRUE) ||
1913             !read_order_field_byte(orderInfo, s, 6, &num, TRUE))
1914                 return FALSE;
1915
1916         if ((orderInfo->fieldFlags & ORDER_FIELD_07) != 0)
1917         {
1918                 DELTA_POINT* newpoints;
1919
1920                 if (num == 0)
1921                         return FALSE;
1922
1923                 if (Stream_GetRemainingLength(s) < 1)
1924                         return FALSE;
1925
1926                 Stream_Read_UINT8(s, polygon_sc->cbData);
1927                 newpoints = (DELTA_POINT*)realloc(polygon_sc->points, sizeof(DELTA_POINT) * num);
1928
1929                 if (!newpoints)
1930                         return FALSE;
1931
1932                 polygon_sc->points = newpoints;
1933                 polygon_sc->numPoints = num;
1934                 return update_read_delta_points(s, polygon_sc->points, polygon_sc->numPoints,
1935                                                 polygon_sc->xStart, polygon_sc->yStart);
1936         }
1937
1938         return TRUE;
1939 }
1940 static BOOL update_read_polygon_cb_order(wStream* s, const ORDER_INFO* orderInfo,
1941                                          POLYGON_CB_ORDER* polygon_cb)
1942 {
1943         UINT32 num = polygon_cb->numPoints;
1944         if (!read_order_field_coord(orderInfo, s, 1, &polygon_cb->xStart, FALSE) ||
1945             !read_order_field_coord(orderInfo, s, 2, &polygon_cb->yStart, FALSE) ||
1946             !read_order_field_byte(orderInfo, s, 3, &polygon_cb->bRop2, TRUE) ||
1947             !read_order_field_byte(orderInfo, s, 4, &polygon_cb->fillMode, TRUE) ||
1948             !read_order_field_color(orderInfo, s, 5, &polygon_cb->backColor, TRUE) ||
1949             !read_order_field_color(orderInfo, s, 6, &polygon_cb->foreColor, TRUE))
1950                 return FALSE;
1951
1952         if (!update_read_brush(s, &polygon_cb->brush, orderInfo->fieldFlags >> 6))
1953                 return FALSE;
1954
1955         if (!read_order_field_byte(orderInfo, s, 12, &num, TRUE))
1956                 return FALSE;
1957
1958         if ((orderInfo->fieldFlags & ORDER_FIELD_13) != 0)
1959         {
1960                 DELTA_POINT* newpoints;
1961
1962                 if (num == 0)
1963                         return FALSE;
1964
1965                 if (Stream_GetRemainingLength(s) < 1)
1966                         return FALSE;
1967
1968                 Stream_Read_UINT8(s, polygon_cb->cbData);
1969                 newpoints = (DELTA_POINT*)realloc(polygon_cb->points, sizeof(DELTA_POINT) * num);
1970
1971                 if (!newpoints)
1972                         return FALSE;
1973
1974                 polygon_cb->points = newpoints;
1975                 polygon_cb->numPoints = num;
1976
1977                 if (!update_read_delta_points(s, polygon_cb->points, polygon_cb->numPoints,
1978                                               polygon_cb->xStart, polygon_cb->yStart))
1979                         return FALSE;
1980         }
1981
1982         polygon_cb->backMode = (polygon_cb->bRop2 & 0x80) ? BACKMODE_TRANSPARENT : BACKMODE_OPAQUE;
1983         polygon_cb->bRop2 = (polygon_cb->bRop2 & 0x1F);
1984         return TRUE;
1985 }
1986 static BOOL update_read_ellipse_sc_order(wStream* s, const ORDER_INFO* orderInfo,
1987                                          ELLIPSE_SC_ORDER* ellipse_sc)
1988 {
1989         if (!read_order_field_coord(orderInfo, s, 1, &ellipse_sc->leftRect, FALSE) ||
1990             !read_order_field_coord(orderInfo, s, 2, &ellipse_sc->topRect, FALSE) ||
1991             !read_order_field_coord(orderInfo, s, 3, &ellipse_sc->rightRect, FALSE) ||
1992             !read_order_field_coord(orderInfo, s, 4, &ellipse_sc->bottomRect, FALSE) ||
1993             !read_order_field_byte(orderInfo, s, 5, &ellipse_sc->bRop2, TRUE) ||
1994             !read_order_field_byte(orderInfo, s, 6, &ellipse_sc->fillMode, TRUE) ||
1995             !read_order_field_color(orderInfo, s, 7, &ellipse_sc->color, TRUE))
1996                 return FALSE;
1997         return TRUE;
1998 }
1999 static BOOL update_read_ellipse_cb_order(wStream* s, const ORDER_INFO* orderInfo,
2000                                          ELLIPSE_CB_ORDER* ellipse_cb)
2001 {
2002         if (!read_order_field_coord(orderInfo, s, 1, &ellipse_cb->leftRect, FALSE) ||
2003             !read_order_field_coord(orderInfo, s, 2, &ellipse_cb->topRect, FALSE) ||
2004             !read_order_field_coord(orderInfo, s, 3, &ellipse_cb->rightRect, FALSE) ||
2005             !read_order_field_coord(orderInfo, s, 4, &ellipse_cb->bottomRect, FALSE) ||
2006             !read_order_field_byte(orderInfo, s, 5, &ellipse_cb->bRop2, TRUE) ||
2007             !read_order_field_byte(orderInfo, s, 6, &ellipse_cb->fillMode, TRUE) ||
2008             !read_order_field_color(orderInfo, s, 7, &ellipse_cb->backColor, TRUE) ||
2009             !read_order_field_color(orderInfo, s, 8, &ellipse_cb->foreColor, TRUE))
2010                 return FALSE;
2011         return update_read_brush(s, &ellipse_cb->brush, orderInfo->fieldFlags >> 8);
2012 }
2013 /* Secondary Drawing Orders */
2014 static CACHE_BITMAP_ORDER* update_read_cache_bitmap_order(rdpUpdate* update, wStream* s,
2015                                                           BOOL compressed, UINT16 flags)
2016 {
2017         CACHE_BITMAP_ORDER* cache_bitmap;
2018
2019         if (!update || !s)
2020                 return NULL;
2021
2022         cache_bitmap = calloc(1, sizeof(CACHE_BITMAP_ORDER));
2023
2024         if (!cache_bitmap)
2025                 goto fail;
2026
2027         if (Stream_GetRemainingLength(s) < 9)
2028                 goto fail;
2029
2030         Stream_Read_UINT8(s, cache_bitmap->cacheId);      /* cacheId (1 byte) */
2031         Stream_Seek_UINT8(s);                             /* pad1Octet (1 byte) */
2032         Stream_Read_UINT8(s, cache_bitmap->bitmapWidth);  /* bitmapWidth (1 byte) */
2033         Stream_Read_UINT8(s, cache_bitmap->bitmapHeight); /* bitmapHeight (1 byte) */
2034         Stream_Read_UINT8(s, cache_bitmap->bitmapBpp);    /* bitmapBpp (1 byte) */
2035
2036         if ((cache_bitmap->bitmapBpp < 1) || (cache_bitmap->bitmapBpp > 32))
2037         {
2038                 WLog_Print(update->log, WLOG_ERROR, "invalid bitmap bpp %" PRIu32 "",
2039                            cache_bitmap->bitmapBpp);
2040                 goto fail;
2041         }
2042
2043         Stream_Read_UINT16(s, cache_bitmap->bitmapLength); /* bitmapLength (2 bytes) */
2044         Stream_Read_UINT16(s, cache_bitmap->cacheIndex);   /* cacheIndex (2 bytes) */
2045
2046         if (compressed)
2047         {
2048                 if ((flags & NO_BITMAP_COMPRESSION_HDR) == 0)
2049                 {
2050                         BYTE* bitmapComprHdr = (BYTE*)&(cache_bitmap->bitmapComprHdr);
2051
2052                         if (Stream_GetRemainingLength(s) < 8)
2053                                 goto fail;
2054
2055                         Stream_Read(s, bitmapComprHdr, 8); /* bitmapComprHdr (8 bytes) */
2056                         cache_bitmap->bitmapLength -= 8;
2057                 }
2058         }
2059
2060         if (cache_bitmap->bitmapLength == 0)
2061                 goto fail;
2062
2063         if (Stream_GetRemainingLength(s) < cache_bitmap->bitmapLength)
2064                 goto fail;
2065
2066         cache_bitmap->bitmapDataStream = malloc(cache_bitmap->bitmapLength);
2067
2068         if (!cache_bitmap->bitmapDataStream)
2069                 goto fail;
2070
2071         Stream_Read(s, cache_bitmap->bitmapDataStream, cache_bitmap->bitmapLength);
2072         cache_bitmap->compressed = compressed;
2073         return cache_bitmap;
2074 fail:
2075         free_cache_bitmap_order(update->context, cache_bitmap);
2076         return NULL;
2077 }
2078 int update_approximate_cache_bitmap_order(const CACHE_BITMAP_ORDER* cache_bitmap, BOOL compressed,
2079                                           UINT16* flags)
2080 {
2081         return 64 + cache_bitmap->bitmapLength;
2082 }
2083 BOOL update_write_cache_bitmap_order(wStream* s, const CACHE_BITMAP_ORDER* cache_bitmap,
2084                                      BOOL compressed, UINT16* flags)
2085 {
2086         UINT32 bitmapLength = cache_bitmap->bitmapLength;
2087         int inf = update_approximate_cache_bitmap_order(cache_bitmap, compressed, flags);
2088
2089         if (!Stream_EnsureRemainingCapacity(s, inf))
2090                 return FALSE;
2091
2092         *flags = NO_BITMAP_COMPRESSION_HDR;
2093
2094         if ((*flags & NO_BITMAP_COMPRESSION_HDR) == 0)
2095                 bitmapLength += 8;
2096
2097         Stream_Write_UINT8(s, cache_bitmap->cacheId);      /* cacheId (1 byte) */
2098         Stream_Write_UINT8(s, 0);                          /* pad1Octet (1 byte) */
2099         Stream_Write_UINT8(s, cache_bitmap->bitmapWidth);  /* bitmapWidth (1 byte) */
2100         Stream_Write_UINT8(s, cache_bitmap->bitmapHeight); /* bitmapHeight (1 byte) */
2101         Stream_Write_UINT8(s, cache_bitmap->bitmapBpp);    /* bitmapBpp (1 byte) */
2102         Stream_Write_UINT16(s, bitmapLength);              /* bitmapLength (2 bytes) */
2103         Stream_Write_UINT16(s, cache_bitmap->cacheIndex);  /* cacheIndex (2 bytes) */
2104
2105         if (compressed)
2106         {
2107                 if ((*flags & NO_BITMAP_COMPRESSION_HDR) == 0)
2108                 {
2109                         BYTE* bitmapComprHdr = (BYTE*)&(cache_bitmap->bitmapComprHdr);
2110                         Stream_Write(s, bitmapComprHdr, 8); /* bitmapComprHdr (8 bytes) */
2111                         bitmapLength -= 8;
2112                 }
2113
2114                 Stream_Write(s, cache_bitmap->bitmapDataStream, bitmapLength);
2115         }
2116         else
2117         {
2118                 Stream_Write(s, cache_bitmap->bitmapDataStream, bitmapLength);
2119         }
2120
2121         return TRUE;
2122 }
2123 static CACHE_BITMAP_V2_ORDER* update_read_cache_bitmap_v2_order(rdpUpdate* update, wStream* s,
2124                                                                 BOOL compressed, UINT16 flags)
2125 {
2126         BOOL rc;
2127         BYTE bitsPerPixelId;
2128         CACHE_BITMAP_V2_ORDER* cache_bitmap_v2;
2129
2130         if (!update || !s)
2131                 return NULL;
2132
2133         cache_bitmap_v2 = calloc(1, sizeof(CACHE_BITMAP_V2_ORDER));
2134
2135         if (!cache_bitmap_v2)
2136                 goto fail;
2137
2138         cache_bitmap_v2->cacheId = flags & 0x0003;
2139         cache_bitmap_v2->flags = (flags & 0xFF80) >> 7;
2140         bitsPerPixelId = (flags & 0x0078) >> 3;
2141         cache_bitmap_v2->bitmapBpp = get_cbr2_bpp(bitsPerPixelId, &rc);
2142         if (!rc)
2143                 goto fail;
2144
2145         if (cache_bitmap_v2->flags & CBR2_PERSISTENT_KEY_PRESENT)
2146         {
2147                 if (Stream_GetRemainingLength(s) < 8)
2148                         goto fail;
2149
2150                 Stream_Read_UINT32(s, cache_bitmap_v2->key1); /* key1 (4 bytes) */
2151                 Stream_Read_UINT32(s, cache_bitmap_v2->key2); /* key2 (4 bytes) */
2152         }
2153
2154         if (cache_bitmap_v2->flags & CBR2_HEIGHT_SAME_AS_WIDTH)
2155         {
2156                 if (!update_read_2byte_unsigned(s, &cache_bitmap_v2->bitmapWidth)) /* bitmapWidth */
2157                         goto fail;
2158
2159                 cache_bitmap_v2->bitmapHeight = cache_bitmap_v2->bitmapWidth;
2160         }
2161         else
2162         {
2163                 if (!update_read_2byte_unsigned(s, &cache_bitmap_v2->bitmapWidth) || /* bitmapWidth */
2164                     !update_read_2byte_unsigned(s, &cache_bitmap_v2->bitmapHeight))  /* bitmapHeight */
2165                         goto fail;
2166         }
2167
2168         if (!update_read_4byte_unsigned(s, &cache_bitmap_v2->bitmapLength) || /* bitmapLength */
2169             !update_read_2byte_unsigned(s, &cache_bitmap_v2->cacheIndex))     /* cacheIndex */
2170                 goto fail;
2171
2172         if (cache_bitmap_v2->flags & CBR2_DO_NOT_CACHE)
2173                 cache_bitmap_v2->cacheIndex = BITMAP_CACHE_WAITING_LIST_INDEX;
2174
2175         if (compressed)
2176         {
2177                 if (!(cache_bitmap_v2->flags & CBR2_NO_BITMAP_COMPRESSION_HDR))
2178                 {
2179                         if (Stream_GetRemainingLength(s) < 8)
2180                                 goto fail;
2181
2182                         Stream_Read_UINT16(
2183                             s, cache_bitmap_v2->cbCompFirstRowSize); /* cbCompFirstRowSize (2 bytes) */
2184                         Stream_Read_UINT16(
2185                             s, cache_bitmap_v2->cbCompMainBodySize);         /* cbCompMainBodySize (2 bytes) */
2186                         Stream_Read_UINT16(s, cache_bitmap_v2->cbScanWidth); /* cbScanWidth (2 bytes) */
2187                         Stream_Read_UINT16(
2188                             s, cache_bitmap_v2->cbUncompressedSize); /* cbUncompressedSize (2 bytes) */
2189                         cache_bitmap_v2->bitmapLength = cache_bitmap_v2->cbCompMainBodySize;
2190                 }
2191         }
2192
2193         if (cache_bitmap_v2->bitmapLength == 0)
2194                 goto fail;
2195
2196         if (Stream_GetRemainingLength(s) < cache_bitmap_v2->bitmapLength)
2197                 goto fail;
2198
2199         if (cache_bitmap_v2->bitmapLength == 0)
2200                 goto fail;
2201
2202         cache_bitmap_v2->bitmapDataStream = malloc(cache_bitmap_v2->bitmapLength);
2203
2204         if (!cache_bitmap_v2->bitmapDataStream)
2205                 goto fail;
2206
2207         Stream_Read(s, cache_bitmap_v2->bitmapDataStream, cache_bitmap_v2->bitmapLength);
2208         cache_bitmap_v2->compressed = compressed;
2209         return cache_bitmap_v2;
2210 fail:
2211         free_cache_bitmap_v2_order(update->context, cache_bitmap_v2);
2212         return NULL;
2213 }
2214 int update_approximate_cache_bitmap_v2_order(CACHE_BITMAP_V2_ORDER* cache_bitmap_v2,
2215                                              BOOL compressed, UINT16* flags)
2216 {
2217         return 64 + cache_bitmap_v2->bitmapLength;
2218 }
2219 BOOL update_write_cache_bitmap_v2_order(wStream* s, CACHE_BITMAP_V2_ORDER* cache_bitmap_v2,
2220                                         BOOL compressed, UINT16* flags)
2221 {
2222         BOOL rc;
2223         BYTE bitsPerPixelId;
2224
2225         if (!Stream_EnsureRemainingCapacity(
2226                 s, update_approximate_cache_bitmap_v2_order(cache_bitmap_v2, compressed, flags)))
2227                 return FALSE;
2228
2229         bitsPerPixelId = get_bpp_bmf(cache_bitmap_v2->bitmapBpp, &rc);
2230         if (!rc)
2231                 return FALSE;
2232         *flags = (cache_bitmap_v2->cacheId & 0x0003) | (bitsPerPixelId << 3) |
2233                  ((cache_bitmap_v2->flags << 7) & 0xFF80);
2234
2235         if (cache_bitmap_v2->flags & CBR2_PERSISTENT_KEY_PRESENT)
2236         {
2237                 Stream_Write_UINT32(s, cache_bitmap_v2->key1); /* key1 (4 bytes) */
2238                 Stream_Write_UINT32(s, cache_bitmap_v2->key2); /* key2 (4 bytes) */
2239         }
2240
2241         if (cache_bitmap_v2->flags & CBR2_HEIGHT_SAME_AS_WIDTH)
2242         {
2243                 if (!update_write_2byte_unsigned(s, cache_bitmap_v2->bitmapWidth)) /* bitmapWidth */
2244                         return FALSE;
2245         }
2246         else
2247         {
2248                 if (!update_write_2byte_unsigned(s, cache_bitmap_v2->bitmapWidth) || /* bitmapWidth */
2249                     !update_write_2byte_unsigned(s, cache_bitmap_v2->bitmapHeight))  /* bitmapHeight */
2250                         return FALSE;
2251         }
2252
2253         if (cache_bitmap_v2->flags & CBR2_DO_NOT_CACHE)
2254                 cache_bitmap_v2->cacheIndex = BITMAP_CACHE_WAITING_LIST_INDEX;
2255
2256         if (!update_write_4byte_unsigned(s, cache_bitmap_v2->bitmapLength) || /* bitmapLength */
2257             !update_write_2byte_unsigned(s, cache_bitmap_v2->cacheIndex))     /* cacheIndex */
2258                 return FALSE;
2259
2260         if (compressed)
2261         {
2262                 if (!(cache_bitmap_v2->flags & CBR2_NO_BITMAP_COMPRESSION_HDR))
2263                 {
2264                         Stream_Write_UINT16(
2265                             s, cache_bitmap_v2->cbCompFirstRowSize); /* cbCompFirstRowSize (2 bytes) */
2266                         Stream_Write_UINT16(
2267                             s, cache_bitmap_v2->cbCompMainBodySize);          /* cbCompMainBodySize (2 bytes) */
2268                         Stream_Write_UINT16(s, cache_bitmap_v2->cbScanWidth); /* cbScanWidth (2 bytes) */
2269                         Stream_Write_UINT16(
2270                             s, cache_bitmap_v2->cbUncompressedSize); /* cbUncompressedSize (2 bytes) */
2271                         cache_bitmap_v2->bitmapLength = cache_bitmap_v2->cbCompMainBodySize;
2272                 }
2273
2274                 if (!Stream_EnsureRemainingCapacity(s, cache_bitmap_v2->bitmapLength))
2275                         return FALSE;
2276
2277                 Stream_Write(s, cache_bitmap_v2->bitmapDataStream, cache_bitmap_v2->bitmapLength);
2278         }
2279         else
2280         {
2281                 if (!Stream_EnsureRemainingCapacity(s, cache_bitmap_v2->bitmapLength))
2282                         return FALSE;
2283
2284                 Stream_Write(s, cache_bitmap_v2->bitmapDataStream, cache_bitmap_v2->bitmapLength);
2285         }
2286
2287         cache_bitmap_v2->compressed = compressed;
2288         return TRUE;
2289 }
2290 static CACHE_BITMAP_V3_ORDER* update_read_cache_bitmap_v3_order(rdpUpdate* update, wStream* s,
2291                                                                 UINT16 flags)
2292 {
2293         BOOL rc;
2294         BYTE bitsPerPixelId;
2295         BITMAP_DATA_EX* bitmapData;
2296         UINT32 new_len;
2297         BYTE* new_data;
2298         CACHE_BITMAP_V3_ORDER* cache_bitmap_v3;
2299
2300         if (!update || !s)
2301                 return NULL;
2302
2303         cache_bitmap_v3 = calloc(1, sizeof(CACHE_BITMAP_V3_ORDER));
2304
2305         if (!cache_bitmap_v3)
2306                 goto fail;
2307
2308         cache_bitmap_v3->cacheId = flags & 0x00000003;
2309         cache_bitmap_v3->flags = (flags & 0x0000FF80) >> 7;
2310         bitsPerPixelId = (flags & 0x00000078) >> 3;
2311         cache_bitmap_v3->bpp = get_cbr2_bpp(bitsPerPixelId, &rc);
2312         if (!rc)
2313                 goto fail;
2314
2315         if (Stream_GetRemainingLength(s) < 21)
2316                 goto fail;
2317
2318         Stream_Read_UINT16(s, cache_bitmap_v3->cacheIndex); /* cacheIndex (2 bytes) */
2319         Stream_Read_UINT32(s, cache_bitmap_v3->key1);       /* key1 (4 bytes) */
2320         Stream_Read_UINT32(s, cache_bitmap_v3->key2);       /* key2 (4 bytes) */
2321         bitmapData = &cache_bitmap_v3->bitmapData;
2322         Stream_Read_UINT8(s, bitmapData->bpp);
2323
2324         if ((bitmapData->bpp < 1) || (bitmapData->bpp > 32))
2325         {
2326                 WLog_Print(update->log, WLOG_ERROR, "invalid bpp value %" PRIu32 "", bitmapData->bpp);
2327                 goto fail;
2328         }
2329
2330         Stream_Seek_UINT8(s);                      /* reserved1 (1 byte) */
2331         Stream_Seek_UINT8(s);                      /* reserved2 (1 byte) */
2332         Stream_Read_UINT8(s, bitmapData->codecID); /* codecID (1 byte) */
2333         Stream_Read_UINT16(s, bitmapData->width);  /* width (2 bytes) */
2334         Stream_Read_UINT16(s, bitmapData->height); /* height (2 bytes) */
2335         Stream_Read_UINT32(s, new_len);            /* length (4 bytes) */
2336
2337         if ((new_len == 0) || (Stream_GetRemainingLength(s) < new_len))
2338                 goto fail;
2339
2340         new_data = (BYTE*)realloc(bitmapData->data, new_len);
2341
2342         if (!new_data)
2343                 goto fail;
2344
2345         bitmapData->data = new_data;
2346         bitmapData->length = new_len;
2347         Stream_Read(s, bitmapData->data, bitmapData->length);
2348         return cache_bitmap_v3;
2349 fail:
2350         free_cache_bitmap_v3_order(update->context, cache_bitmap_v3);
2351         return NULL;
2352 }
2353 int update_approximate_cache_bitmap_v3_order(CACHE_BITMAP_V3_ORDER* cache_bitmap_v3, UINT16* flags)
2354 {
2355         BITMAP_DATA_EX* bitmapData = &cache_bitmap_v3->bitmapData;
2356         return 64 + bitmapData->length;
2357 }
2358 BOOL update_write_cache_bitmap_v3_order(wStream* s, CACHE_BITMAP_V3_ORDER* cache_bitmap_v3,
2359                                         UINT16* flags)
2360 {
2361         BOOL rc;
2362         BYTE bitsPerPixelId;
2363         BITMAP_DATA_EX* bitmapData;
2364
2365         if (!Stream_EnsureRemainingCapacity(
2366                 s, update_approximate_cache_bitmap_v3_order(cache_bitmap_v3, flags)))
2367                 return FALSE;
2368
2369         bitmapData = &cache_bitmap_v3->bitmapData;
2370         bitsPerPixelId = get_bpp_bmf(cache_bitmap_v3->bpp, &rc);
2371         if (!rc)
2372                 return FALSE;
2373         *flags = (cache_bitmap_v3->cacheId & 0x00000003) |
2374                  ((cache_bitmap_v3->flags << 7) & 0x0000FF80) | ((bitsPerPixelId << 3) & 0x00000078);
2375         Stream_Write_UINT16(s, cache_bitmap_v3->cacheIndex); /* cacheIndex (2 bytes) */
2376         Stream_Write_UINT32(s, cache_bitmap_v3->key1);       /* key1 (4 bytes) */
2377         Stream_Write_UINT32(s, cache_bitmap_v3->key2);       /* key2 (4 bytes) */
2378         Stream_Write_UINT8(s, bitmapData->bpp);
2379         Stream_Write_UINT8(s, 0);                   /* reserved1 (1 byte) */
2380         Stream_Write_UINT8(s, 0);                   /* reserved2 (1 byte) */
2381         Stream_Write_UINT8(s, bitmapData->codecID); /* codecID (1 byte) */
2382         Stream_Write_UINT16(s, bitmapData->width);  /* width (2 bytes) */
2383         Stream_Write_UINT16(s, bitmapData->height); /* height (2 bytes) */
2384         Stream_Write_UINT32(s, bitmapData->length); /* length (4 bytes) */
2385         Stream_Write(s, bitmapData->data, bitmapData->length);
2386         return TRUE;
2387 }
2388 static CACHE_COLOR_TABLE_ORDER* update_read_cache_color_table_order(rdpUpdate* update, wStream* s,
2389                                                                     UINT16 flags)
2390 {
2391         int i;
2392         UINT32* colorTable;
2393         CACHE_COLOR_TABLE_ORDER* cache_color_table = calloc(1, sizeof(CACHE_COLOR_TABLE_ORDER));
2394
2395         if (!cache_color_table)
2396                 goto fail;
2397
2398         if (Stream_GetRemainingLength(s) < 3)
2399                 goto fail;
2400
2401         Stream_Read_UINT8(s, cache_color_table->cacheIndex);    /* cacheIndex (1 byte) */
2402         Stream_Read_UINT16(s, cache_color_table->numberColors); /* numberColors (2 bytes) */
2403
2404         if (cache_color_table->numberColors != 256)
2405         {
2406                 /* This field MUST be set to 256 */
2407                 goto fail;
2408         }
2409
2410         if (Stream_GetRemainingLength(s) < cache_color_table->numberColors * 4)
2411                 goto fail;
2412
2413         colorTable = (UINT32*)&cache_color_table->colorTable;
2414
2415         for (i = 0; i < (int)cache_color_table->numberColors; i++)
2416                 update_read_color_quad(s, &colorTable[i]);
2417
2418         return cache_color_table;
2419 fail:
2420         free_cache_color_table_order(update->context, cache_color_table);
2421         return NULL;
2422 }
2423 int update_approximate_cache_color_table_order(const CACHE_COLOR_TABLE_ORDER* cache_color_table,
2424                                                UINT16* flags)
2425 {
2426         return 16 + (256 * 4);
2427 }
2428 BOOL update_write_cache_color_table_order(wStream* s,
2429                                           const CACHE_COLOR_TABLE_ORDER* cache_color_table,
2430                                           UINT16* flags)
2431 {
2432         int i, inf;
2433         UINT32* colorTable;
2434
2435         if (cache_color_table->numberColors != 256)
2436                 return FALSE;
2437
2438         inf = update_approximate_cache_color_table_order(cache_color_table, flags);
2439
2440         if (!Stream_EnsureRemainingCapacity(s, inf))
2441                 return FALSE;
2442
2443         Stream_Write_UINT8(s, cache_color_table->cacheIndex);    /* cacheIndex (1 byte) */
2444         Stream_Write_UINT16(s, cache_color_table->numberColors); /* numberColors (2 bytes) */
2445         colorTable = (UINT32*)&cache_color_table->colorTable;
2446
2447         for (i = 0; i < (int)cache_color_table->numberColors; i++)
2448         {
2449                 update_write_color_quad(s, colorTable[i]);
2450         }
2451
2452         return TRUE;
2453 }
2454 static CACHE_GLYPH_ORDER* update_read_cache_glyph_order(rdpUpdate* update, wStream* s, UINT16 flags)
2455 {
2456         UINT32 i;
2457         CACHE_GLYPH_ORDER* cache_glyph_order = calloc(1, sizeof(CACHE_GLYPH_ORDER));
2458
2459         if (!cache_glyph_order || !update || !s)
2460                 goto fail;
2461
2462         if (Stream_GetRemainingLength(s) < 2)
2463                 goto fail;
2464
2465         Stream_Read_UINT8(s, cache_glyph_order->cacheId); /* cacheId (1 byte) */
2466         Stream_Read_UINT8(s, cache_glyph_order->cGlyphs); /* cGlyphs (1 byte) */
2467
2468         for (i = 0; i < cache_glyph_order->cGlyphs; i++)
2469         {
2470                 GLYPH_DATA* glyph = &cache_glyph_order->glyphData[i];
2471
2472                 if (Stream_GetRemainingLength(s) < 10)
2473                         goto fail;
2474
2475                 Stream_Read_UINT16(s, glyph->cacheIndex);
2476                 Stream_Read_INT16(s, glyph->x);
2477                 Stream_Read_INT16(s, glyph->y);
2478                 Stream_Read_UINT16(s, glyph->cx);
2479                 Stream_Read_UINT16(s, glyph->cy);
2480                 glyph->cb = ((glyph->cx + 7) / 8) * glyph->cy;
2481                 glyph->cb += ((glyph->cb % 4) > 0) ? 4 - (glyph->cb % 4) : 0;
2482
2483                 if (Stream_GetRemainingLength(s) < glyph->cb)
2484                         goto fail;
2485
2486                 glyph->aj = (BYTE*)malloc(glyph->cb);
2487
2488                 if (!glyph->aj)
2489                         goto fail;
2490
2491                 Stream_Read(s, glyph->aj, glyph->cb);
2492         }
2493
2494         if ((flags & CG_GLYPH_UNICODE_PRESENT) && (cache_glyph_order->cGlyphs > 0))
2495         {
2496                 cache_glyph_order->unicodeCharacters = calloc(cache_glyph_order->cGlyphs, sizeof(WCHAR));
2497
2498                 if (!cache_glyph_order->unicodeCharacters)
2499                         goto fail;
2500
2501                 if (Stream_GetRemainingLength(s) < sizeof(WCHAR) * cache_glyph_order->cGlyphs)
2502                         goto fail;
2503
2504                 Stream_Read_UTF16_String(s, cache_glyph_order->unicodeCharacters,
2505                                          cache_glyph_order->cGlyphs);
2506         }
2507
2508         return cache_glyph_order;
2509 fail:
2510         free_cache_glyph_order(update->context, cache_glyph_order);
2511         return NULL;
2512 }
2513 int update_approximate_cache_glyph_order(const CACHE_GLYPH_ORDER* cache_glyph, UINT16* flags)
2514 {
2515         return 2 + cache_glyph->cGlyphs * 32;
2516 }
2517 BOOL update_write_cache_glyph_order(wStream* s, const CACHE_GLYPH_ORDER* cache_glyph, UINT16* flags)
2518 {
2519         int i, inf;
2520         INT16 lsi16;
2521         const GLYPH_DATA* glyph;
2522         inf = update_approximate_cache_glyph_order(cache_glyph, flags);
2523
2524         if (!Stream_EnsureRemainingCapacity(s, inf))
2525                 return FALSE;
2526
2527         Stream_Write_UINT8(s, cache_glyph->cacheId); /* cacheId (1 byte) */
2528         Stream_Write_UINT8(s, cache_glyph->cGlyphs); /* cGlyphs (1 byte) */
2529
2530         for (i = 0; i < (int)cache_glyph->cGlyphs; i++)
2531         {
2532                 UINT32 cb;
2533                 glyph = &cache_glyph->glyphData[i];
2534                 Stream_Write_UINT16(s, glyph->cacheIndex); /* cacheIndex (2 bytes) */
2535                 lsi16 = glyph->x;
2536                 Stream_Write_UINT16(s, lsi16); /* x (2 bytes) */
2537                 lsi16 = glyph->y;
2538                 Stream_Write_UINT16(s, lsi16);     /* y (2 bytes) */
2539                 Stream_Write_UINT16(s, glyph->cx); /* cx (2 bytes) */
2540                 Stream_Write_UINT16(s, glyph->cy); /* cy (2 bytes) */
2541                 cb = ((glyph->cx + 7) / 8) * glyph->cy;
2542                 cb += ((cb % 4) > 0) ? 4 - (cb % 4) : 0;
2543                 Stream_Write(s, glyph->aj, cb);
2544         }
2545
2546         if (*flags & CG_GLYPH_UNICODE_PRESENT)
2547         {
2548                 Stream_Zero(s, cache_glyph->cGlyphs * 2);
2549         }
2550
2551         return TRUE;
2552 }
2553 static CACHE_GLYPH_V2_ORDER* update_read_cache_glyph_v2_order(rdpUpdate* update, wStream* s,
2554                                                               UINT16 flags)
2555 {
2556         UINT32 i;
2557         CACHE_GLYPH_V2_ORDER* cache_glyph_v2 = calloc(1, sizeof(CACHE_GLYPH_V2_ORDER));
2558
2559         if (!cache_glyph_v2)
2560                 goto fail;
2561
2562         cache_glyph_v2->cacheId = (flags & 0x000F);
2563         cache_glyph_v2->flags = (flags & 0x00F0) >> 4;
2564         cache_glyph_v2->cGlyphs = (flags & 0xFF00) >> 8;
2565
2566         for (i = 0; i < cache_glyph_v2->cGlyphs; i++)
2567         {
2568                 GLYPH_DATA_V2* glyph = &cache_glyph_v2->glyphData[i];
2569
2570                 if (Stream_GetRemainingLength(s) < 1)
2571                         goto fail;
2572
2573                 Stream_Read_UINT8(s, glyph->cacheIndex);
2574
2575                 if (!update_read_2byte_signed(s, &glyph->x) || !update_read_2byte_signed(s, &glyph->y) ||
2576                     !update_read_2byte_unsigned(s, &glyph->cx) ||
2577                     !update_read_2byte_unsigned(s, &glyph->cy))
2578                 {
2579                         goto fail;
2580                 }
2581
2582                 glyph->cb = ((glyph->cx + 7) / 8) * glyph->cy;
2583                 glyph->cb += ((glyph->cb % 4) > 0) ? 4 - (glyph->cb % 4) : 0;
2584
2585                 if (Stream_GetRemainingLength(s) < glyph->cb)
2586                         goto fail;
2587
2588                 glyph->aj = (BYTE*)malloc(glyph->cb);
2589
2590                 if (!glyph->aj)
2591                         goto fail;
2592
2593                 Stream_Read(s, glyph->aj, glyph->cb);
2594         }
2595
2596         if ((flags & CG_GLYPH_UNICODE_PRESENT) && (cache_glyph_v2->cGlyphs > 0))
2597         {
2598                 cache_glyph_v2->unicodeCharacters = calloc(cache_glyph_v2->cGlyphs, sizeof(WCHAR));
2599
2600                 if (!cache_glyph_v2->unicodeCharacters)
2601                         goto fail;
2602
2603                 if (Stream_GetRemainingLength(s) < sizeof(WCHAR) * cache_glyph_v2->cGlyphs)
2604                         goto fail;
2605
2606                 Stream_Read_UTF16_String(s, cache_glyph_v2->unicodeCharacters, cache_glyph_v2->cGlyphs);
2607         }
2608
2609         return cache_glyph_v2;
2610 fail:
2611         free_cache_glyph_v2_order(update->context, cache_glyph_v2);
2612         return NULL;
2613 }
2614 int update_approximate_cache_glyph_v2_order(const CACHE_GLYPH_V2_ORDER* cache_glyph_v2,
2615                                             UINT16* flags)
2616 {
2617         return 8 + cache_glyph_v2->cGlyphs * 32;
2618 }
2619 BOOL update_write_cache_glyph_v2_order(wStream* s, const CACHE_GLYPH_V2_ORDER* cache_glyph_v2,
2620                                        UINT16* flags)
2621 {
2622         UINT32 i, inf;
2623         inf = update_approximate_cache_glyph_v2_order(cache_glyph_v2, flags);
2624
2625         if (!Stream_EnsureRemainingCapacity(s, inf))
2626                 return FALSE;
2627
2628         *flags = (cache_glyph_v2->cacheId & 0x000F) | ((cache_glyph_v2->flags & 0x000F) << 4) |
2629                  ((cache_glyph_v2->cGlyphs & 0x00FF) << 8);
2630
2631         for (i = 0; i < cache_glyph_v2->cGlyphs; i++)
2632         {
2633                 UINT32 cb;
2634                 const GLYPH_DATA_V2* glyph = &cache_glyph_v2->glyphData[i];
2635                 Stream_Write_UINT8(s, glyph->cacheIndex);
2636
2637                 if (!update_write_2byte_signed(s, glyph->x) || !update_write_2byte_signed(s, glyph->y) ||
2638                     !update_write_2byte_unsigned(s, glyph->cx) ||
2639                     !update_write_2byte_unsigned(s, glyph->cy))
2640                 {
2641                         return FALSE;
2642                 }
2643
2644                 cb = ((glyph->cx + 7) / 8) * glyph->cy;
2645                 cb += ((cb % 4) > 0) ? 4 - (cb % 4) : 0;
2646                 Stream_Write(s, glyph->aj, cb);
2647         }
2648
2649         if (*flags & CG_GLYPH_UNICODE_PRESENT)
2650         {
2651                 Stream_Zero(s, cache_glyph_v2->cGlyphs * 2);
2652         }
2653
2654         return TRUE;
2655 }
2656 static BOOL update_decompress_brush(wStream* s, BYTE* output, size_t outSize, BYTE bpp)
2657 {
2658         size_t x, k;
2659         INT8 y;
2660         BYTE byte = 0;
2661         const BYTE* palette = Stream_Pointer(s) + 16;
2662         const size_t bytesPerPixel = ((bpp + 1) / 8);
2663
2664         if (Stream_GetRemainingLength(s) < 16 + bytesPerPixel * 4)
2665                 return FALSE;
2666
2667         for (y = 7; y >= 0; y--)
2668         {
2669                 for (x = 0; x < 8; x++)
2670                 {
2671                         UINT32 index;
2672                         if ((x % 4) == 0)
2673                                 Stream_Read_UINT8(s, byte);
2674
2675                         index = ((byte >> ((3 - (x % 4)) * 2)) & 0x03);
2676
2677                         for (k = 0; k < bytesPerPixel; k++)
2678                         {
2679                                 const size_t dstIndex = ((y * 8 + x) * bytesPerPixel) + k;
2680                                 const size_t srcIndex = (index * bytesPerPixel) + k;
2681                                 if (dstIndex >= outSize)
2682                                         return FALSE;
2683                                 output[dstIndex] = palette[srcIndex];
2684                         }
2685                 }
2686         }
2687
2688         return TRUE;
2689 }
2690 static BOOL update_compress_brush(wStream* s, const BYTE* input, BYTE bpp)
2691 {
2692         return FALSE;
2693 }
2694 static CACHE_BRUSH_ORDER* update_read_cache_brush_order(rdpUpdate* update, wStream* s, UINT16 flags)
2695 {
2696         int i;
2697         BOOL rc;
2698         BYTE iBitmapFormat;
2699         BOOL compressed = FALSE;
2700         CACHE_BRUSH_ORDER* cache_brush = calloc(1, sizeof(CACHE_BRUSH_ORDER));
2701
2702         if (!cache_brush)
2703                 goto fail;
2704
2705         if (Stream_GetRemainingLength(s) < 6)
2706                 goto fail;
2707
2708         Stream_Read_UINT8(s, cache_brush->index); /* cacheEntry (1 byte) */
2709         Stream_Read_UINT8(s, iBitmapFormat);      /* iBitmapFormat (1 byte) */
2710
2711         cache_brush->bpp = get_bmf_bpp(iBitmapFormat, &rc);
2712         if (!rc)
2713                 goto fail;
2714
2715         Stream_Read_UINT8(s, cache_brush->cx);     /* cx (1 byte) */
2716         Stream_Read_UINT8(s, cache_brush->cy);     /* cy (1 byte) */
2717         /* according to  Section 2.2.2.2.1.2.7 errata the windows implementation sets this filed is set
2718          * to 0x00 */
2719         Stream_Read_UINT8(s, cache_brush->style);  /* style (1 byte) */
2720         Stream_Read_UINT8(s, cache_brush->length); /* iBytes (1 byte) */
2721
2722         if ((cache_brush->cx == 8) && (cache_brush->cy == 8))
2723         {
2724                 if (cache_brush->bpp == 1)
2725                 {
2726                         if (cache_brush->length != 8)
2727                         {
2728                                 WLog_Print(update->log, WLOG_ERROR, "incompatible 1bpp brush of length:%" PRIu32 "",
2729                                            cache_brush->length);
2730                                 goto fail;
2731                         }
2732
2733                         if (Stream_GetRemainingLength(s) < 8)
2734                                 goto fail;
2735
2736                         /* rows are encoded in reverse order */
2737                         for (i = 7; i >= 0; i--)
2738                                 Stream_Read_UINT8(s, cache_brush->data[i]);
2739                 }
2740                 else
2741                 {
2742                         if ((iBitmapFormat == BMF_8BPP) && (cache_brush->length == 20))
2743                                 compressed = TRUE;
2744                         else if ((iBitmapFormat == BMF_16BPP) && (cache_brush->length == 24))
2745                                 compressed = TRUE;
2746                         else if ((iBitmapFormat == BMF_24BPP) && (cache_brush->length == 28))
2747                                 compressed = TRUE;
2748                         else if ((iBitmapFormat == BMF_32BPP) && (cache_brush->length == 32))
2749                                 compressed = TRUE;
2750
2751                         if (compressed != FALSE)
2752                         {
2753                                 /* compressed brush */
2754                                 if (!update_decompress_brush(s, cache_brush->data, sizeof(cache_brush->data),
2755                                                              cache_brush->bpp))
2756                                         goto fail;
2757                         }
2758                         else
2759                         {
2760                                 /* uncompressed brush */
2761                                 UINT32 scanline = (cache_brush->bpp / 8) * 8;
2762
2763                                 if (Stream_GetRemainingLength(s) < scanline * 8)
2764                                         goto fail;
2765
2766                                 for (i = 7; i >= 0; i--)
2767                                 {
2768                                         Stream_Read(s, &cache_brush->data[i * scanline], scanline);
2769                                 }
2770                         }
2771                 }
2772         }
2773
2774         return cache_brush;
2775 fail:
2776         free_cache_brush_order(update->context, cache_brush);
2777         return NULL;
2778 }
2779 int update_approximate_cache_brush_order(const CACHE_BRUSH_ORDER* cache_brush, UINT16* flags)
2780 {
2781         return 64;
2782 }
2783 BOOL update_write_cache_brush_order(wStream* s, const CACHE_BRUSH_ORDER* cache_brush, UINT16* flags)
2784 {
2785         int i;
2786         BYTE iBitmapFormat;
2787         BOOL rc;
2788         BOOL compressed = FALSE;
2789
2790         if (!Stream_EnsureRemainingCapacity(s,
2791                                             update_approximate_cache_brush_order(cache_brush, flags)))
2792                 return FALSE;
2793
2794         iBitmapFormat = get_bpp_bmf(cache_brush->bpp, &rc);
2795         if (!rc)
2796                 return FALSE;
2797         Stream_Write_UINT8(s, cache_brush->index);  /* cacheEntry (1 byte) */
2798         Stream_Write_UINT8(s, iBitmapFormat);       /* iBitmapFormat (1 byte) */
2799         Stream_Write_UINT8(s, cache_brush->cx);     /* cx (1 byte) */
2800         Stream_Write_UINT8(s, cache_brush->cy);     /* cy (1 byte) */
2801         Stream_Write_UINT8(s, cache_brush->style);  /* style (1 byte) */
2802         Stream_Write_UINT8(s, cache_brush->length); /* iBytes (1 byte) */
2803
2804         if ((cache_brush->cx == 8) && (cache_brush->cy == 8))
2805         {
2806                 if (cache_brush->bpp == 1)
2807                 {
2808                         if (cache_brush->length != 8)
2809                         {
2810                                 WLog_ERR(TAG, "incompatible 1bpp brush of length:%" PRIu32 "", cache_brush->length);
2811                                 return FALSE;
2812                         }
2813
2814                         for (i = 7; i >= 0; i--)
2815                         {
2816                                 Stream_Write_UINT8(s, cache_brush->data[i]);
2817                         }
2818                 }
2819                 else
2820                 {
2821                         if ((iBitmapFormat == BMF_8BPP) && (cache_brush->length == 20))
2822                                 compressed = TRUE;
2823                         else if ((iBitmapFormat == BMF_16BPP) && (cache_brush->length == 24))
2824                                 compressed = TRUE;
2825                         else if ((iBitmapFormat == BMF_32BPP) && (cache_brush->length == 32))
2826                                 compressed = TRUE;
2827
2828                         if (compressed != FALSE)
2829                         {
2830                                 /* compressed brush */
2831                                 if (!update_compress_brush(s, cache_brush->data, cache_brush->bpp))
2832                                         return FALSE;
2833                         }
2834                         else
2835                         {
2836                                 /* uncompressed brush */
2837                                 int scanline = (cache_brush->bpp / 8) * 8;
2838
2839                                 for (i = 7; i >= 0; i--)
2840                                 {
2841                                         Stream_Write(s, &cache_brush->data[i * scanline], scanline);
2842                                 }
2843                         }
2844                 }
2845         }
2846
2847         return TRUE;
2848 }
2849 /* Alternate Secondary Drawing Orders */
2850 static BOOL
2851 update_read_create_offscreen_bitmap_order(wStream* s,
2852                                           CREATE_OFFSCREEN_BITMAP_ORDER* create_offscreen_bitmap)
2853 {
2854         UINT16 flags;
2855         BOOL deleteListPresent;
2856         OFFSCREEN_DELETE_LIST* deleteList;
2857
2858         if (Stream_GetRemainingLength(s) < 6)
2859                 return FALSE;
2860
2861         Stream_Read_UINT16(s, flags); /* flags (2 bytes) */
2862         create_offscreen_bitmap->id = flags & 0x7FFF;
2863         deleteListPresent = (flags & 0x8000) ? TRUE : FALSE;
2864         Stream_Read_UINT16(s, create_offscreen_bitmap->cx); /* cx (2 bytes) */
2865         Stream_Read_UINT16(s, create_offscreen_bitmap->cy); /* cy (2 bytes) */
2866         deleteList = &(create_offscreen_bitmap->deleteList);
2867
2868         if (deleteListPresent)
2869         {
2870                 UINT32 i;
2871
2872                 if (Stream_GetRemainingLength(s) < 2)
2873                         return FALSE;
2874
2875                 Stream_Read_UINT16(s, deleteList->cIndices);
2876
2877                 if (deleteList->cIndices > deleteList->sIndices)
2878                 {
2879                         UINT16* new_indices;
2880                         new_indices = (UINT16*)realloc(deleteList->indices, deleteList->cIndices * 2);
2881
2882                         if (!new_indices)
2883                                 return FALSE;
2884
2885                         deleteList->sIndices = deleteList->cIndices;
2886                         deleteList->indices = new_indices;
2887                 }
2888
2889                 if (Stream_GetRemainingLength(s) < 2 * deleteList->cIndices)
2890                         return FALSE;
2891
2892                 for (i = 0; i < deleteList->cIndices; i++)
2893                 {
2894                         Stream_Read_UINT16(s, deleteList->indices[i]);
2895                 }
2896         }
2897         else
2898         {
2899                 deleteList->cIndices = 0;
2900         }
2901
2902         return TRUE;
2903 }
2904 int update_approximate_create_offscreen_bitmap_order(
2905     const CREATE_OFFSCREEN_BITMAP_ORDER* create_offscreen_bitmap)
2906 {
2907         const OFFSCREEN_DELETE_LIST* deleteList = &(create_offscreen_bitmap->deleteList);
2908         return 32 + deleteList->cIndices * 2;
2909 }
2910 BOOL update_write_create_offscreen_bitmap_order(
2911     wStream* s, const CREATE_OFFSCREEN_BITMAP_ORDER* create_offscreen_bitmap)
2912 {
2913         UINT16 flags;
2914         BOOL deleteListPresent;
2915         const OFFSCREEN_DELETE_LIST* deleteList;
2916
2917         if (!Stream_EnsureRemainingCapacity(
2918                 s, update_approximate_create_offscreen_bitmap_order(create_offscreen_bitmap)))
2919                 return FALSE;
2920
2921         deleteList = &(create_offscreen_bitmap->deleteList);
2922         flags = create_offscreen_bitmap->id & 0x7FFF;
2923         deleteListPresent = (deleteList->cIndices > 0) ? TRUE : FALSE;
2924
2925         if (deleteListPresent)
2926                 flags |= 0x8000;
2927
2928         Stream_Write_UINT16(s, flags);                       /* flags (2 bytes) */
2929         Stream_Write_UINT16(s, create_offscreen_bitmap->cx); /* cx (2 bytes) */
2930         Stream_Write_UINT16(s, create_offscreen_bitmap->cy); /* cy (2 bytes) */
2931
2932         if (deleteListPresent)
2933         {
2934                 int i;
2935                 Stream_Write_UINT16(s, deleteList->cIndices);
2936
2937                 for (i = 0; i < (int)deleteList->cIndices; i++)
2938                 {
2939                         Stream_Write_UINT16(s, deleteList->indices[i]);
2940                 }
2941         }
2942
2943         return TRUE;
2944 }
2945 static BOOL update_read_switch_surface_order(wStream* s, SWITCH_SURFACE_ORDER* switch_surface)
2946 {
2947         if (Stream_GetRemainingLength(s) < 2)
2948                 return FALSE;
2949
2950         Stream_Read_UINT16(s, switch_surface->bitmapId); /* bitmapId (2 bytes) */
2951         return TRUE;
2952 }
2953 int update_approximate_switch_surface_order(const SWITCH_SURFACE_ORDER* switch_surface)
2954 {
2955         return 2;
2956 }
2957 BOOL update_write_switch_surface_order(wStream* s, const SWITCH_SURFACE_ORDER* switch_surface)
2958 {
2959         int inf = update_approximate_switch_surface_order(switch_surface);
2960
2961         if (!Stream_EnsureRemainingCapacity(s, inf))
2962                 return FALSE;
2963
2964         Stream_Write_UINT16(s, switch_surface->bitmapId); /* bitmapId (2 bytes) */
2965         return TRUE;
2966 }
2967 static BOOL
2968 update_read_create_nine_grid_bitmap_order(wStream* s,
2969                                           CREATE_NINE_GRID_BITMAP_ORDER* create_nine_grid_bitmap)
2970 {
2971         NINE_GRID_BITMAP_INFO* nineGridInfo;
2972
2973         if (Stream_GetRemainingLength(s) < 19)
2974                 return FALSE;
2975
2976         Stream_Read_UINT8(s, create_nine_grid_bitmap->bitmapBpp); /* bitmapBpp (1 byte) */
2977
2978         if ((create_nine_grid_bitmap->bitmapBpp < 1) || (create_nine_grid_bitmap->bitmapBpp > 32))
2979         {
2980                 WLog_ERR(TAG, "invalid bpp value %" PRIu32 "", create_nine_grid_bitmap->bitmapBpp);
2981                 return FALSE;
2982         }
2983
2984         Stream_Read_UINT16(s, create_nine_grid_bitmap->bitmapId); /* bitmapId (2 bytes) */
2985         nineGridInfo = &(create_nine_grid_bitmap->nineGridInfo);
2986         Stream_Read_UINT32(s, nineGridInfo->flFlags);          /* flFlags (4 bytes) */
2987         Stream_Read_UINT16(s, nineGridInfo->ulLeftWidth);      /* ulLeftWidth (2 bytes) */
2988         Stream_Read_UINT16(s, nineGridInfo->ulRightWidth);     /* ulRightWidth (2 bytes) */
2989         Stream_Read_UINT16(s, nineGridInfo->ulTopHeight);      /* ulTopHeight (2 bytes) */
2990         Stream_Read_UINT16(s, nineGridInfo->ulBottomHeight);   /* ulBottomHeight (2 bytes) */
2991         update_read_colorref(s, &nineGridInfo->crTransparent); /* crTransparent (4 bytes) */
2992         return TRUE;
2993 }
2994 static BOOL update_read_frame_marker_order(wStream* s, FRAME_MARKER_ORDER* frame_marker)
2995 {
2996         if (Stream_GetRemainingLength(s) < 4)
2997                 return FALSE;
2998
2999         Stream_Read_UINT32(s, frame_marker->action); /* action (4 bytes) */
3000         return TRUE;
3001 }
3002 static BOOL update_read_stream_bitmap_first_order(wStream* s,
3003                                                   STREAM_BITMAP_FIRST_ORDER* stream_bitmap_first)
3004 {
3005         if (Stream_GetRemainingLength(s) < 10) // 8 + 2 at least
3006                 return FALSE;
3007
3008         Stream_Read_UINT8(s, stream_bitmap_first->bitmapFlags); /* bitmapFlags (1 byte) */
3009         Stream_Read_UINT8(s, stream_bitmap_first->bitmapBpp);   /* bitmapBpp (1 byte) */
3010
3011         if ((stream_bitmap_first->bitmapBpp < 1) || (stream_bitmap_first->bitmapBpp > 32))
3012         {
3013                 WLog_ERR(TAG, "invalid bpp value %" PRIu32 "", stream_bitmap_first->bitmapBpp);
3014                 return FALSE;
3015         }
3016
3017         Stream_Read_UINT16(s, stream_bitmap_first->bitmapType);   /* bitmapType (2 bytes) */
3018         Stream_Read_UINT16(s, stream_bitmap_first->bitmapWidth);  /* bitmapWidth (2 bytes) */
3019         Stream_Read_UINT16(s, stream_bitmap_first->bitmapHeight); /* bitmapHeigth (2 bytes) */
3020
3021         if (stream_bitmap_first->bitmapFlags & STREAM_BITMAP_V2)
3022         {
3023                 if (Stream_GetRemainingLength(s) < 4)
3024                         return FALSE;
3025
3026                 Stream_Read_UINT32(s, stream_bitmap_first->bitmapSize); /* bitmapSize (4 bytes) */
3027         }
3028         else
3029         {
3030                 if (Stream_GetRemainingLength(s) < 2)
3031                         return FALSE;
3032
3033                 Stream_Read_UINT16(s, stream_bitmap_first->bitmapSize); /* bitmapSize (2 bytes) */
3034         }
3035
3036         FIELD_SKIP_BUFFER16(
3037             s, stream_bitmap_first->bitmapBlockSize); /* bitmapBlockSize(2 bytes) + bitmapBlock */
3038         return TRUE;
3039 }
3040 static BOOL update_read_stream_bitmap_next_order(wStream* s,
3041                                                  STREAM_BITMAP_NEXT_ORDER* stream_bitmap_next)
3042 {
3043         if (Stream_GetRemainingLength(s) < 5)
3044                 return FALSE;
3045
3046         Stream_Read_UINT8(s, stream_bitmap_next->bitmapFlags); /* bitmapFlags (1 byte) */
3047         Stream_Read_UINT16(s, stream_bitmap_next->bitmapType); /* bitmapType (2 bytes) */
3048         FIELD_SKIP_BUFFER16(
3049             s, stream_bitmap_next->bitmapBlockSize); /* bitmapBlockSize(2 bytes) + bitmapBlock */
3050         return TRUE;
3051 }
3052 static BOOL update_read_draw_gdiplus_first_order(wStream* s,
3053                                                  DRAW_GDIPLUS_FIRST_ORDER* draw_gdiplus_first)
3054 {
3055         if (Stream_GetRemainingLength(s) < 11)
3056                 return FALSE;
3057
3058         Stream_Seek_UINT8(s);                                      /* pad1Octet (1 byte) */
3059         Stream_Read_UINT16(s, draw_gdiplus_first->cbSize);         /* cbSize (2 bytes) */
3060         Stream_Read_UINT32(s, draw_gdiplus_first->cbTotalSize);    /* cbTotalSize (4 bytes) */
3061         Stream_Read_UINT32(s, draw_gdiplus_first->cbTotalEmfSize); /* cbTotalEmfSize (4 bytes) */
3062         return Stream_SafeSeek(s, draw_gdiplus_first->cbSize);     /* emfRecords */
3063 }
3064 static BOOL update_read_draw_gdiplus_next_order(wStream* s,
3065                                                 DRAW_GDIPLUS_NEXT_ORDER* draw_gdiplus_next)
3066 {
3067         if (Stream_GetRemainingLength(s) < 3)
3068                 return FALSE;
3069
3070         Stream_Seek_UINT8(s);                              /* pad1Octet (1 byte) */
3071         FIELD_SKIP_BUFFER16(s, draw_gdiplus_next->cbSize); /* cbSize(2 bytes) + emfRecords */
3072         return TRUE;
3073 }
3074 static BOOL update_read_draw_gdiplus_end_order(wStream* s, DRAW_GDIPLUS_END_ORDER* draw_gdiplus_end)
3075 {
3076         if (Stream_GetRemainingLength(s) < 11)
3077                 return FALSE;
3078
3079         Stream_Seek_UINT8(s);                                    /* pad1Octet (1 byte) */
3080         Stream_Read_UINT16(s, draw_gdiplus_end->cbSize);         /* cbSize (2 bytes) */
3081         Stream_Read_UINT32(s, draw_gdiplus_end->cbTotalSize);    /* cbTotalSize (4 bytes) */
3082         Stream_Read_UINT32(s, draw_gdiplus_end->cbTotalEmfSize); /* cbTotalEmfSize (4 bytes) */
3083         return Stream_SafeSeek(s, draw_gdiplus_end->cbSize);     /* emfRecords */
3084 }
3085 static BOOL
3086 update_read_draw_gdiplus_cache_first_order(wStream* s,
3087                                            DRAW_GDIPLUS_CACHE_FIRST_ORDER* draw_gdiplus_cache_first)
3088 {
3089         if (Stream_GetRemainingLength(s) < 11)
3090                 return FALSE;
3091
3092         Stream_Read_UINT8(s, draw_gdiplus_cache_first->flags);        /* flags (1 byte) */
3093         Stream_Read_UINT16(s, draw_gdiplus_cache_first->cacheType);   /* cacheType (2 bytes) */
3094         Stream_Read_UINT16(s, draw_gdiplus_cache_first->cacheIndex);  /* cacheIndex (2 bytes) */
3095         Stream_Read_UINT16(s, draw_gdiplus_cache_first->cbSize);      /* cbSize (2 bytes) */
3096         Stream_Read_UINT32(s, draw_gdiplus_cache_first->cbTotalSize); /* cbTotalSize (4 bytes) */
3097         return Stream_SafeSeek(s, draw_gdiplus_cache_first->cbSize);  /* emfRecords */
3098 }
3099 static BOOL
3100 update_read_draw_gdiplus_cache_next_order(wStream* s,
3101                                           DRAW_GDIPLUS_CACHE_NEXT_ORDER* draw_gdiplus_cache_next)
3102 {
3103         if (Stream_GetRemainingLength(s) < 7)
3104                 return FALSE;
3105
3106         Stream_Read_UINT8(s, draw_gdiplus_cache_next->flags);       /* flags (1 byte) */
3107         Stream_Read_UINT16(s, draw_gdiplus_cache_next->cacheType);  /* cacheType (2 bytes) */
3108         Stream_Read_UINT16(s, draw_gdiplus_cache_next->cacheIndex); /* cacheIndex (2 bytes) */
3109         FIELD_SKIP_BUFFER16(s, draw_gdiplus_cache_next->cbSize);    /* cbSize(2 bytes) + emfRecords */
3110         return TRUE;
3111 }
3112 static BOOL
3113 update_read_draw_gdiplus_cache_end_order(wStream* s,
3114                                          DRAW_GDIPLUS_CACHE_END_ORDER* draw_gdiplus_cache_end)
3115 {
3116         if (Stream_GetRemainingLength(s) < 11)
3117                 return FALSE;
3118
3119         Stream_Read_UINT8(s, draw_gdiplus_cache_end->flags);        /* flags (1 byte) */
3120         Stream_Read_UINT16(s, draw_gdiplus_cache_end->cacheType);   /* cacheType (2 bytes) */
3121         Stream_Read_UINT16(s, draw_gdiplus_cache_end->cacheIndex);  /* cacheIndex (2 bytes) */
3122         Stream_Read_UINT16(s, draw_gdiplus_cache_end->cbSize);      /* cbSize (2 bytes) */
3123         Stream_Read_UINT32(s, draw_gdiplus_cache_end->cbTotalSize); /* cbTotalSize (4 bytes) */
3124         return Stream_SafeSeek(s, draw_gdiplus_cache_end->cbSize);  /* emfRecords */
3125 }
3126 static BOOL update_read_field_flags(wStream* s, UINT32* fieldFlags, BYTE flags, BYTE fieldBytes)
3127 {
3128         int i;
3129         BYTE byte;
3130
3131         if (flags & ORDER_ZERO_FIELD_BYTE_BIT0)
3132                 fieldBytes--;
3133
3134         if (flags & ORDER_ZERO_FIELD_BYTE_BIT1)
3135         {
3136                 if (fieldBytes > 1)
3137                         fieldBytes -= 2;
3138                 else
3139                         fieldBytes = 0;
3140         }
3141
3142         if (Stream_GetRemainingLength(s) < fieldBytes)
3143                 return FALSE;
3144
3145         *fieldFlags = 0;
3146
3147         for (i = 0; i < fieldBytes; i++)
3148         {
3149                 Stream_Read_UINT8(s, byte);
3150                 *fieldFlags |= byte << (i * 8);
3151         }
3152
3153         return TRUE;
3154 }
3155 BOOL update_write_field_flags(wStream* s, UINT32 fieldFlags, BYTE flags, BYTE fieldBytes)
3156 {
3157         BYTE byte;
3158
3159         if (fieldBytes == 1)
3160         {
3161                 byte = fieldFlags & 0xFF;
3162                 Stream_Write_UINT8(s, byte);
3163         }
3164         else if (fieldBytes == 2)
3165         {
3166                 byte = fieldFlags & 0xFF;
3167                 Stream_Write_UINT8(s, byte);
3168                 byte = (fieldFlags >> 8) & 0xFF;
3169                 Stream_Write_UINT8(s, byte);
3170         }
3171         else if (fieldBytes == 3)
3172         {
3173                 byte = fieldFlags & 0xFF;
3174                 Stream_Write_UINT8(s, byte);
3175                 byte = (fieldFlags >> 8) & 0xFF;
3176                 Stream_Write_UINT8(s, byte);
3177                 byte = (fieldFlags >> 16) & 0xFF;
3178                 Stream_Write_UINT8(s, byte);
3179         }
3180         else
3181         {
3182                 return FALSE;
3183         }
3184
3185         return TRUE;
3186 }
3187 static BOOL update_read_bounds(wStream* s, rdpBounds* bounds)
3188 {
3189         BYTE flags;
3190
3191         if (Stream_GetRemainingLength(s) < 1)
3192                 return FALSE;
3193
3194         Stream_Read_UINT8(s, flags); /* field flags */
3195
3196         if (flags & BOUND_LEFT)
3197         {
3198                 if (!update_read_coord(s, &bounds->left, FALSE))
3199                         return FALSE;
3200         }
3201         else if (flags & BOUND_DELTA_LEFT)
3202         {
3203                 if (!update_read_coord(s, &bounds->left, TRUE))
3204                         return FALSE;
3205         }
3206
3207         if (flags & BOUND_TOP)
3208         {
3209                 if (!update_read_coord(s, &bounds->top, FALSE))
3210                         return FALSE;
3211         }
3212         else if (flags & BOUND_DELTA_TOP)
3213         {
3214                 if (!update_read_coord(s, &bounds->top, TRUE))
3215                         return FALSE;
3216         }
3217
3218         if (flags & BOUND_RIGHT)
3219         {
3220                 if (!update_read_coord(s, &bounds->right, FALSE))
3221                         return FALSE;
3222         }
3223         else if (flags & BOUND_DELTA_RIGHT)
3224         {
3225                 if (!update_read_coord(s, &bounds->right, TRUE))
3226                         return FALSE;
3227         }
3228
3229         if (flags & BOUND_BOTTOM)
3230         {
3231                 if (!update_read_coord(s, &bounds->bottom, FALSE))
3232                         return FALSE;
3233         }
3234         else if (flags & BOUND_DELTA_BOTTOM)
3235         {
3236                 if (!update_read_coord(s, &bounds->bottom, TRUE))
3237                         return FALSE;
3238         }
3239
3240         return TRUE;
3241 }
3242 BOOL update_write_bounds(wStream* s, ORDER_INFO* orderInfo)
3243 {
3244         if (!(orderInfo->controlFlags & ORDER_BOUNDS))
3245                 return TRUE;
3246
3247         if (orderInfo->controlFlags & ORDER_ZERO_BOUNDS_DELTAS)
3248                 return TRUE;
3249
3250         Stream_Write_UINT8(s, orderInfo->boundsFlags); /* field flags */
3251
3252         if (orderInfo->boundsFlags & BOUND_LEFT)
3253         {
3254                 if (!update_write_coord(s, orderInfo->bounds.left))
3255                         return FALSE;
3256         }
3257         else if (orderInfo->boundsFlags & BOUND_DELTA_LEFT)
3258         {
3259         }
3260
3261         if (orderInfo->boundsFlags & BOUND_TOP)
3262         {
3263                 if (!update_write_coord(s, orderInfo->bounds.top))
3264                         return FALSE;
3265         }
3266         else if (orderInfo->boundsFlags & BOUND_DELTA_TOP)
3267         {
3268         }
3269
3270         if (orderInfo->boundsFlags & BOUND_RIGHT)
3271         {
3272                 if (!update_write_coord(s, orderInfo->bounds.right))
3273                         return FALSE;
3274         }
3275         else if (orderInfo->boundsFlags & BOUND_DELTA_RIGHT)
3276         {
3277         }
3278
3279         if (orderInfo->boundsFlags & BOUND_BOTTOM)
3280         {
3281                 if (!update_write_coord(s, orderInfo->bounds.bottom))
3282                         return FALSE;
3283         }
3284         else if (orderInfo->boundsFlags & BOUND_DELTA_BOTTOM)
3285         {
3286         }
3287
3288         return TRUE;
3289 }
3290
3291 static BOOL read_primary_order(wLog* log, const char* orderName, wStream* s,
3292                                const ORDER_INFO* orderInfo, rdpPrimaryUpdate* primary)
3293 {
3294         BOOL rc = FALSE;
3295
3296         if (!s || !orderInfo || !primary || !orderName)
3297                 return FALSE;
3298
3299         switch (orderInfo->orderType)
3300         {
3301                 case ORDER_TYPE_DSTBLT:
3302                         rc = update_read_dstblt_order(s, orderInfo, &(primary->dstblt));
3303                         break;
3304
3305                 case ORDER_TYPE_PATBLT:
3306                         rc = update_read_patblt_order(s, orderInfo, &(primary->patblt));
3307                         break;
3308
3309                 case ORDER_TYPE_SCRBLT:
3310                         rc = update_read_scrblt_order(s, orderInfo, &(primary->scrblt));
3311                         break;
3312
3313                 case ORDER_TYPE_OPAQUE_RECT:
3314                         rc = update_read_opaque_rect_order(s, orderInfo, &(primary->opaque_rect));
3315                         break;
3316
3317                 case ORDER_TYPE_DRAW_NINE_GRID:
3318                         rc = update_read_draw_nine_grid_order(s, orderInfo, &(primary->draw_nine_grid));
3319                         break;
3320
3321                 case ORDER_TYPE_MULTI_DSTBLT:
3322                         rc = update_read_multi_dstblt_order(s, orderInfo, &(primary->multi_dstblt));
3323                         break;
3324
3325                 case ORDER_TYPE_MULTI_PATBLT:
3326                         rc = update_read_multi_patblt_order(s, orderInfo, &(primary->multi_patblt));
3327                         break;
3328
3329                 case ORDER_TYPE_MULTI_SCRBLT:
3330                         rc = update_read_multi_scrblt_order(s, orderInfo, &(primary->multi_scrblt));
3331                         break;
3332
3333                 case ORDER_TYPE_MULTI_OPAQUE_RECT:
3334                         rc = update_read_multi_opaque_rect_order(s, orderInfo, &(primary->multi_opaque_rect));
3335                         break;
3336
3337                 case ORDER_TYPE_MULTI_DRAW_NINE_GRID:
3338                         rc = update_read_multi_draw_nine_grid_order(s, orderInfo,
3339                                                                     &(primary->multi_draw_nine_grid));
3340                         break;
3341
3342                 case ORDER_TYPE_LINE_TO:
3343                         rc = update_read_line_to_order(s, orderInfo, &(primary->line_to));
3344                         break;
3345
3346                 case ORDER_TYPE_POLYLINE:
3347                         rc = update_read_polyline_order(s, orderInfo, &(primary->polyline));
3348                         break;
3349
3350                 case ORDER_TYPE_MEMBLT:
3351                         rc = update_read_memblt_order(s, orderInfo, &(primary->memblt));
3352                         break;
3353
3354                 case ORDER_TYPE_MEM3BLT:
3355                         rc = update_read_mem3blt_order(s, orderInfo, &(primary->mem3blt));
3356                         break;
3357
3358                 case ORDER_TYPE_SAVE_BITMAP:
3359                         rc = update_read_save_bitmap_order(s, orderInfo, &(primary->save_bitmap));
3360                         break;
3361
3362                 case ORDER_TYPE_GLYPH_INDEX:
3363                         rc = update_read_glyph_index_order(s, orderInfo, &(primary->glyph_index));
3364                         break;
3365
3366                 case ORDER_TYPE_FAST_INDEX:
3367                         rc = update_read_fast_index_order(s, orderInfo, &(primary->fast_index));
3368                         break;
3369
3370                 case ORDER_TYPE_FAST_GLYPH:
3371                         rc = update_read_fast_glyph_order(s, orderInfo, &(primary->fast_glyph));
3372                         break;
3373
3374                 case ORDER_TYPE_POLYGON_SC:
3375                         rc = update_read_polygon_sc_order(s, orderInfo, &(primary->polygon_sc));
3376                         break;
3377
3378                 case ORDER_TYPE_POLYGON_CB:
3379                         rc = update_read_polygon_cb_order(s, orderInfo, &(primary->polygon_cb));
3380                         break;
3381
3382                 case ORDER_TYPE_ELLIPSE_SC:
3383                         rc = update_read_ellipse_sc_order(s, orderInfo, &(primary->ellipse_sc));
3384                         break;
3385
3386                 case ORDER_TYPE_ELLIPSE_CB:
3387                         rc = update_read_ellipse_cb_order(s, orderInfo, &(primary->ellipse_cb));
3388                         break;
3389
3390                 default:
3391                         WLog_Print(log, WLOG_WARN, "Primary Drawing Order %s not supported, ignoring",
3392                                    orderName);
3393                         rc = TRUE;
3394                         break;
3395         }
3396
3397         if (!rc)
3398         {
3399                 WLog_Print(log, WLOG_ERROR, "%s - update_read_dstblt_order() failed", orderName);
3400                 return FALSE;
3401         }
3402
3403         return TRUE;
3404 }
3405
3406 static BOOL update_recv_primary_order(rdpUpdate* update, wStream* s, BYTE flags)
3407 {
3408         BYTE field;
3409         BOOL rc = FALSE;
3410         rdpContext* context = update->context;
3411         rdpPrimaryUpdate* primary = update->primary;
3412         ORDER_INFO* orderInfo = &(primary->order_info);
3413         rdpSettings* settings = context->settings;
3414         const char* orderName;
3415
3416         if (flags & ORDER_TYPE_CHANGE)
3417         {
3418                 if (Stream_GetRemainingLength(s) < 1)
3419                 {
3420                         WLog_Print(update->log, WLOG_ERROR, "Stream_GetRemainingLength(s) < 1");
3421                         return FALSE;
3422                 }
3423
3424                 Stream_Read_UINT8(s, orderInfo->orderType); /* orderType (1 byte) */
3425         }
3426
3427         orderName = primary_order_string(orderInfo->orderType);
3428
3429         if (!check_primary_order_supported(update->log, settings, orderInfo->orderType, orderName))
3430                 return FALSE;
3431
3432         field = get_primary_drawing_order_field_bytes(orderInfo->orderType, &rc);
3433         if (!rc)
3434                 return FALSE;
3435
3436         if (!update_read_field_flags(s, &(orderInfo->fieldFlags), flags, field))
3437         {
3438                 WLog_Print(update->log, WLOG_ERROR, "update_read_field_flags() failed");
3439                 return FALSE;
3440         }
3441
3442         if (flags & ORDER_BOUNDS)
3443         {
3444                 if (!(flags & ORDER_ZERO_BOUNDS_DELTAS))
3445                 {
3446                         if (!update_read_bounds(s, &orderInfo->bounds))
3447                         {
3448                                 WLog_Print(update->log, WLOG_ERROR, "update_read_bounds() failed");
3449                                 return FALSE;
3450                         }
3451                 }
3452
3453                 rc = IFCALLRESULT(FALSE, update->SetBounds, context, &orderInfo->bounds);
3454
3455                 if (!rc)
3456                         return FALSE;
3457         }
3458
3459         orderInfo->deltaCoordinates = (flags & ORDER_DELTA_COORDINATES) ? TRUE : FALSE;
3460
3461         if (!read_primary_order(update->log, orderName, s, orderInfo, primary))
3462                 return FALSE;
3463
3464         switch (orderInfo->orderType)
3465         {
3466                 case ORDER_TYPE_DSTBLT:
3467                 {
3468                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s rop=%s [0x%08" PRIx32 "]",
3469                                    orderName, gdi_rop3_code_string(primary->dstblt.bRop),
3470                                    gdi_rop3_code(primary->dstblt.bRop));
3471                         rc = IFCALLRESULT(FALSE, primary->DstBlt, context, &primary->dstblt);
3472                 }
3473                 break;
3474
3475                 case ORDER_TYPE_PATBLT:
3476                 {
3477                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s rop=%s [0x%08" PRIx32 "]",
3478                                    orderName, gdi_rop3_code_string(primary->patblt.bRop),
3479                                    gdi_rop3_code(primary->patblt.bRop));
3480                         rc = IFCALLRESULT(FALSE, primary->PatBlt, context, &primary->patblt);
3481                 }
3482                 break;
3483
3484                 case ORDER_TYPE_SCRBLT:
3485                 {
3486                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s rop=%s [0x%08" PRIx32 "]",
3487                                    orderName, gdi_rop3_code_string(primary->scrblt.bRop),
3488                                    gdi_rop3_code(primary->scrblt.bRop));
3489                         rc = IFCALLRESULT(FALSE, primary->ScrBlt, context, &primary->scrblt);
3490                 }
3491                 break;
3492
3493                 case ORDER_TYPE_OPAQUE_RECT:
3494                 {
3495                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3496                         rc = IFCALLRESULT(FALSE, primary->OpaqueRect, context, &primary->opaque_rect);
3497                 }
3498                 break;
3499
3500                 case ORDER_TYPE_DRAW_NINE_GRID:
3501                 {
3502                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3503                         rc = IFCALLRESULT(FALSE, primary->DrawNineGrid, context, &primary->draw_nine_grid);
3504                 }
3505                 break;
3506
3507                 case ORDER_TYPE_MULTI_DSTBLT:
3508                 {
3509                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s rop=%s [0x%08" PRIx32 "]",
3510                                    orderName, gdi_rop3_code_string(primary->multi_dstblt.bRop),
3511                                    gdi_rop3_code(primary->multi_dstblt.bRop));
3512                         rc = IFCALLRESULT(FALSE, primary->MultiDstBlt, context, &primary->multi_dstblt);
3513                 }
3514                 break;
3515
3516                 case ORDER_TYPE_MULTI_PATBLT:
3517                 {
3518                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s rop=%s [0x%08" PRIx32 "]",
3519                                    orderName, gdi_rop3_code_string(primary->multi_patblt.bRop),
3520                                    gdi_rop3_code(primary->multi_patblt.bRop));
3521                         rc = IFCALLRESULT(FALSE, primary->MultiPatBlt, context, &primary->multi_patblt);
3522                 }
3523                 break;
3524
3525                 case ORDER_TYPE_MULTI_SCRBLT:
3526                 {
3527                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s rop=%s [0x%08" PRIx32 "]",
3528                                    orderName, gdi_rop3_code_string(primary->multi_scrblt.bRop),
3529                                    gdi_rop3_code(primary->multi_scrblt.bRop));
3530                         rc = IFCALLRESULT(FALSE, primary->MultiScrBlt, context, &primary->multi_scrblt);
3531                 }
3532                 break;
3533
3534                 case ORDER_TYPE_MULTI_OPAQUE_RECT:
3535                 {
3536                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3537                         rc =
3538                             IFCALLRESULT(FALSE, primary->MultiOpaqueRect, context, &primary->multi_opaque_rect);
3539                 }
3540                 break;
3541
3542                 case ORDER_TYPE_MULTI_DRAW_NINE_GRID:
3543                 {
3544                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3545                         rc = IFCALLRESULT(FALSE, primary->MultiDrawNineGrid, context,
3546                                           &primary->multi_draw_nine_grid);
3547                 }
3548                 break;
3549
3550                 case ORDER_TYPE_LINE_TO:
3551                 {
3552                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3553                         rc = IFCALLRESULT(FALSE, primary->LineTo, context, &primary->line_to);
3554                 }
3555                 break;
3556
3557                 case ORDER_TYPE_POLYLINE:
3558                 {
3559                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3560                         rc = IFCALLRESULT(FALSE, primary->Polyline, context, &primary->polyline);
3561                 }
3562                 break;
3563
3564                 case ORDER_TYPE_MEMBLT:
3565                 {
3566                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s rop=%s [0x%08" PRIx32 "]",
3567                                    orderName, gdi_rop3_code_string(primary->memblt.bRop),
3568                                    gdi_rop3_code(primary->memblt.bRop));
3569                         rc = IFCALLRESULT(FALSE, primary->MemBlt, context, &primary->memblt);
3570                 }
3571                 break;
3572
3573                 case ORDER_TYPE_MEM3BLT:
3574                 {
3575                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s rop=%s [0x%08" PRIx32 "]",
3576                                    orderName, gdi_rop3_code_string(primary->mem3blt.bRop),
3577                                    gdi_rop3_code(primary->mem3blt.bRop));
3578                         rc = IFCALLRESULT(FALSE, primary->Mem3Blt, context, &primary->mem3blt);
3579                 }
3580                 break;
3581
3582                 case ORDER_TYPE_SAVE_BITMAP:
3583                 {
3584                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3585                         rc = IFCALLRESULT(FALSE, primary->SaveBitmap, context, &primary->save_bitmap);
3586                 }
3587                 break;
3588
3589                 case ORDER_TYPE_GLYPH_INDEX:
3590                 {
3591                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3592                         rc = IFCALLRESULT(FALSE, primary->GlyphIndex, context, &primary->glyph_index);
3593                 }
3594                 break;
3595
3596                 case ORDER_TYPE_FAST_INDEX:
3597                 {
3598                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3599                         rc = IFCALLRESULT(FALSE, primary->FastIndex, context, &primary->fast_index);
3600                 }
3601                 break;
3602
3603                 case ORDER_TYPE_FAST_GLYPH:
3604                 {
3605                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3606                         rc = IFCALLRESULT(FALSE, primary->FastGlyph, context, &primary->fast_glyph);
3607                 }
3608                 break;
3609
3610                 case ORDER_TYPE_POLYGON_SC:
3611                 {
3612                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3613                         rc = IFCALLRESULT(FALSE, primary->PolygonSC, context, &primary->polygon_sc);
3614                 }
3615                 break;
3616
3617                 case ORDER_TYPE_POLYGON_CB:
3618                 {
3619                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3620                         rc = IFCALLRESULT(FALSE, primary->PolygonCB, context, &primary->polygon_cb);
3621                 }
3622                 break;
3623
3624                 case ORDER_TYPE_ELLIPSE_SC:
3625                 {
3626                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3627                         rc = IFCALLRESULT(FALSE, primary->EllipseSC, context, &primary->ellipse_sc);
3628                 }
3629                 break;
3630
3631                 case ORDER_TYPE_ELLIPSE_CB:
3632                 {
3633                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3634                         rc = IFCALLRESULT(FALSE, primary->EllipseCB, context, &primary->ellipse_cb);
3635                 }
3636                 break;
3637
3638                 default:
3639                         WLog_Print(update->log, WLOG_WARN, "Primary Drawing Order %s not supported", orderName);
3640                         break;
3641         }
3642
3643         if (!rc)
3644         {
3645                 WLog_Print(update->log, WLOG_WARN, "Primary Drawing Order %s failed", orderName);
3646                 return FALSE;
3647         }
3648
3649         if (flags & ORDER_BOUNDS)
3650         {
3651                 rc = IFCALLRESULT(FALSE, update->SetBounds, context, NULL);
3652         }
3653
3654         return rc;
3655 }
3656
3657 static BOOL update_recv_secondary_order(rdpUpdate* update, wStream* s, BYTE flags)
3658 {
3659         BOOL rc = FALSE;
3660         size_t start, end, pos, diff;
3661         BYTE orderType;
3662         UINT16 extraFlags;
3663         UINT16 orderLength;
3664         rdpContext* context = update->context;
3665         rdpSettings* settings = context->settings;
3666         rdpSecondaryUpdate* secondary = update->secondary;
3667         const char* name;
3668
3669         if (Stream_GetRemainingLength(s) < 5)
3670         {
3671                 WLog_Print(update->log, WLOG_ERROR, "Stream_GetRemainingLength(s) < 5");
3672                 return FALSE;
3673         }
3674
3675         Stream_Read_UINT16(s, orderLength); /* orderLength (2 bytes) */
3676         Stream_Read_UINT16(s, extraFlags);  /* extraFlags (2 bytes) */
3677         Stream_Read_UINT8(s, orderType);    /* orderType (1 byte) */
3678         /*
3679          * According to [MS-RDPEGDI] 2.2.2.2.1.2.1.1 the order length must be increased by 13 bytes
3680          * including the header. As we already read the header 7 left
3681          */
3682         if (Stream_GetRemainingLength(s) < orderLength + 7U)
3683         {
3684                 WLog_Print(update->log, WLOG_ERROR, "Stream_GetRemainingLength(s) %" PRIuz " < %" PRIu16,
3685                            Stream_GetRemainingLength(s), orderLength + 7);
3686                 return FALSE;
3687         }
3688
3689         start = Stream_GetPosition(s);
3690         name = secondary_order_string(orderType);
3691         WLog_Print(update->log, WLOG_DEBUG, "Secondary Drawing Order %s", name);
3692
3693         if (!check_secondary_order_supported(update->log, settings, orderType, name))
3694                 return FALSE;
3695
3696         switch (orderType)
3697         {
3698                 case ORDER_TYPE_BITMAP_UNCOMPRESSED:
3699                 case ORDER_TYPE_CACHE_BITMAP_COMPRESSED:
3700                 {
3701                         const BOOL compressed = (orderType == ORDER_TYPE_CACHE_BITMAP_COMPRESSED);
3702                         CACHE_BITMAP_ORDER* order =
3703                             update_read_cache_bitmap_order(update, s, compressed, extraFlags);
3704
3705                         if (order)
3706                         {
3707                                 rc = IFCALLRESULT(FALSE, secondary->CacheBitmap, context, order);
3708                                 free_cache_bitmap_order(context, order);
3709                         }
3710                 }
3711                 break;
3712
3713                 case ORDER_TYPE_BITMAP_UNCOMPRESSED_V2:
3714                 case ORDER_TYPE_BITMAP_COMPRESSED_V2:
3715                 {
3716                         const BOOL compressed = (orderType == ORDER_TYPE_BITMAP_COMPRESSED_V2);
3717                         CACHE_BITMAP_V2_ORDER* order =
3718                             update_read_cache_bitmap_v2_order(update, s, compressed, extraFlags);
3719
3720                         if (order)
3721                         {
3722                                 rc = IFCALLRESULT(FALSE, secondary->CacheBitmapV2, context, order);
3723                                 free_cache_bitmap_v2_order(context, order);
3724                         }
3725                 }
3726                 break;
3727
3728                 case ORDER_TYPE_BITMAP_COMPRESSED_V3:
3729                 {
3730                         CACHE_BITMAP_V3_ORDER* order = update_read_cache_bitmap_v3_order(update, s, extraFlags);
3731
3732                         if (order)
3733                         {
3734                                 rc = IFCALLRESULT(FALSE, secondary->CacheBitmapV3, context, order);
3735                                 free_cache_bitmap_v3_order(context, order);
3736                         }
3737                 }
3738                 break;
3739
3740                 case ORDER_TYPE_CACHE_COLOR_TABLE:
3741                 {
3742                         CACHE_COLOR_TABLE_ORDER* order =
3743                             update_read_cache_color_table_order(update, s, extraFlags);
3744
3745                         if (order)
3746                         {
3747                                 rc = IFCALLRESULT(FALSE, secondary->CacheColorTable, context, order);
3748                                 free_cache_color_table_order(context, order);
3749                         }
3750                 }
3751                 break;
3752
3753                 case ORDER_TYPE_CACHE_GLYPH:
3754                 {
3755                         switch (settings->GlyphSupportLevel)
3756                         {
3757                                 case GLYPH_SUPPORT_PARTIAL:
3758                                 case GLYPH_SUPPORT_FULL:
3759                                 {
3760                                         CACHE_GLYPH_ORDER* order = update_read_cache_glyph_order(update, s, extraFlags);
3761
3762                                         if (order)
3763                                         {
3764                                                 rc = IFCALLRESULT(FALSE, secondary->CacheGlyph, context, order);
3765                                                 free_cache_glyph_order(context, order);
3766                                         }
3767                                 }
3768                                 break;
3769
3770                                 case GLYPH_SUPPORT_ENCODE:
3771                                 {
3772                                         CACHE_GLYPH_V2_ORDER* order =
3773                                             update_read_cache_glyph_v2_order(update, s, extraFlags);
3774
3775                                         if (order)
3776                                         {
3777                                                 rc = IFCALLRESULT(FALSE, secondary->CacheGlyphV2, context, order);
3778                                                 free_cache_glyph_v2_order(context, order);
3779                                         }
3780                                 }
3781                                 break;
3782
3783                                 case GLYPH_SUPPORT_NONE:
3784                                 default:
3785                                         break;
3786                         }
3787                 }
3788                 break;
3789
3790                 case ORDER_TYPE_CACHE_BRUSH:
3791                         /* [MS-RDPEGDI] 2.2.2.2.1.2.7 Cache Brush (CACHE_BRUSH_ORDER) */
3792                         {
3793                                 CACHE_BRUSH_ORDER* order = update_read_cache_brush_order(update, s, extraFlags);
3794
3795                                 if (order)
3796                                 {
3797                                         rc = IFCALLRESULT(FALSE, secondary->CacheBrush, context, order);
3798                                         free_cache_brush_order(context, order);
3799                                 }
3800                         }
3801                         break;
3802
3803                 default:
3804                         WLog_Print(update->log, WLOG_WARN, "SECONDARY ORDER %s not supported", name);
3805                         break;
3806         }
3807
3808         if (!rc)
3809         {
3810                 WLog_Print(update->log, WLOG_ERROR, "SECONDARY ORDER %s failed", name);
3811         }
3812
3813         end = start + orderLength + 7;
3814         pos = Stream_GetPosition(s);
3815         if (pos > end)
3816         {
3817                 WLog_Print(update->log, WLOG_WARN, "SECONDARY_ORDER %s: read %" PRIuz "bytes too much",
3818                            name, pos - end);
3819                 return FALSE;
3820         }
3821         diff = end - pos;
3822         if (diff > 0)
3823         {
3824                 WLog_Print(update->log, WLOG_DEBUG,
3825                            "SECONDARY_ORDER %s: read %" PRIuz "bytes short, skipping", name, diff);
3826                 if (!Stream_SafeSeek(s, diff))
3827                         return FALSE;
3828         }
3829         return rc;
3830 }
3831
3832 static BOOL read_altsec_order(wStream* s, BYTE orderType, rdpAltSecUpdate* altsec)
3833 {
3834         BOOL rc = FALSE;
3835
3836         switch (orderType)
3837         {
3838                 case ORDER_TYPE_CREATE_OFFSCREEN_BITMAP:
3839                         rc = update_read_create_offscreen_bitmap_order(s, &(altsec->create_offscreen_bitmap));
3840                         break;
3841
3842                 case ORDER_TYPE_SWITCH_SURFACE:
3843                         rc = update_read_switch_surface_order(s, &(altsec->switch_surface));
3844                         break;
3845
3846                 case ORDER_TYPE_CREATE_NINE_GRID_BITMAP:
3847                         rc = update_read_create_nine_grid_bitmap_order(s, &(altsec->create_nine_grid_bitmap));
3848                         break;
3849
3850                 case ORDER_TYPE_FRAME_MARKER:
3851                         rc = update_read_frame_marker_order(s, &(altsec->frame_marker));
3852                         break;
3853
3854                 case ORDER_TYPE_STREAM_BITMAP_FIRST:
3855                         rc = update_read_stream_bitmap_first_order(s, &(altsec->stream_bitmap_first));
3856                         break;
3857
3858                 case ORDER_TYPE_STREAM_BITMAP_NEXT:
3859                         rc = update_read_stream_bitmap_next_order(s, &(altsec->stream_bitmap_next));
3860                         break;
3861
3862                 case ORDER_TYPE_GDIPLUS_FIRST:
3863                         rc = update_read_draw_gdiplus_first_order(s, &(altsec->draw_gdiplus_first));
3864                         break;
3865
3866                 case ORDER_TYPE_GDIPLUS_NEXT:
3867                         rc = update_read_draw_gdiplus_next_order(s, &(altsec->draw_gdiplus_next));
3868                         break;
3869
3870                 case ORDER_TYPE_GDIPLUS_END:
3871                         rc = update_read_draw_gdiplus_end_order(s, &(altsec->draw_gdiplus_end));
3872                         break;
3873
3874                 case ORDER_TYPE_GDIPLUS_CACHE_FIRST:
3875                         rc = update_read_draw_gdiplus_cache_first_order(s, &(altsec->draw_gdiplus_cache_first));
3876                         break;
3877
3878                 case ORDER_TYPE_GDIPLUS_CACHE_NEXT:
3879                         rc = update_read_draw_gdiplus_cache_next_order(s, &(altsec->draw_gdiplus_cache_next));
3880                         break;
3881
3882                 case ORDER_TYPE_GDIPLUS_CACHE_END:
3883                         rc = update_read_draw_gdiplus_cache_end_order(s, &(altsec->draw_gdiplus_cache_end));
3884                         break;
3885
3886                 case ORDER_TYPE_WINDOW:
3887                         /* This order is handled elsewhere. */
3888                         rc = TRUE;
3889                         break;
3890
3891                 case ORDER_TYPE_COMPDESK_FIRST:
3892                         rc = TRUE;
3893                         break;
3894
3895                 default:
3896                         break;
3897         }
3898
3899         return rc;
3900 }
3901
3902 static BOOL update_recv_altsec_order(rdpUpdate* update, wStream* s, BYTE flags)
3903 {
3904         BYTE orderType = flags >>= 2; /* orderType is in higher 6 bits of flags field */
3905         BOOL rc = FALSE;
3906         rdpContext* context = update->context;
3907         rdpSettings* settings = context->settings;
3908         rdpAltSecUpdate* altsec = update->altsec;
3909         const char* orderName = altsec_order_string(orderType);
3910         WLog_Print(update->log, WLOG_DEBUG, "Alternate Secondary Drawing Order %s", orderName);
3911
3912         if (!check_alt_order_supported(update->log, settings, orderType, orderName))
3913                 return FALSE;
3914
3915         if (!read_altsec_order(s, orderType, altsec))
3916                 return FALSE;
3917
3918         switch (orderType)
3919         {
3920                 case ORDER_TYPE_CREATE_OFFSCREEN_BITMAP:
3921                         IFCALLRET(altsec->CreateOffscreenBitmap, rc, context,
3922                                   &(altsec->create_offscreen_bitmap));
3923                         break;
3924
3925                 case ORDER_TYPE_SWITCH_SURFACE:
3926                         IFCALLRET(altsec->SwitchSurface, rc, context, &(altsec->switch_surface));
3927                         break;
3928
3929                 case ORDER_TYPE_CREATE_NINE_GRID_BITMAP:
3930                         IFCALLRET(altsec->CreateNineGridBitmap, rc, context,
3931                                   &(altsec->create_nine_grid_bitmap));
3932                         break;
3933
3934                 case ORDER_TYPE_FRAME_MARKER:
3935                         IFCALLRET(altsec->FrameMarker, rc, context, &(altsec->frame_marker));
3936                         break;
3937
3938                 case ORDER_TYPE_STREAM_BITMAP_FIRST:
3939                         IFCALLRET(altsec->StreamBitmapFirst, rc, context, &(altsec->stream_bitmap_first));
3940                         break;
3941
3942                 case ORDER_TYPE_STREAM_BITMAP_NEXT:
3943                         IFCALLRET(altsec->StreamBitmapNext, rc, context, &(altsec->stream_bitmap_next));
3944                         break;
3945
3946                 case ORDER_TYPE_GDIPLUS_FIRST:
3947                         IFCALLRET(altsec->DrawGdiPlusFirst, rc, context, &(altsec->draw_gdiplus_first));
3948                         break;
3949
3950                 case ORDER_TYPE_GDIPLUS_NEXT:
3951                         IFCALLRET(altsec->DrawGdiPlusNext, rc, context, &(altsec->draw_gdiplus_next));
3952                         break;
3953
3954                 case ORDER_TYPE_GDIPLUS_END:
3955                         IFCALLRET(altsec->DrawGdiPlusEnd, rc, context, &(altsec->draw_gdiplus_end));
3956                         break;
3957
3958                 case ORDER_TYPE_GDIPLUS_CACHE_FIRST:
3959                         IFCALLRET(altsec->DrawGdiPlusCacheFirst, rc, context,
3960                                   &(altsec->draw_gdiplus_cache_first));
3961                         break;
3962
3963                 case ORDER_TYPE_GDIPLUS_CACHE_NEXT:
3964                         IFCALLRET(altsec->DrawGdiPlusCacheNext, rc, context,
3965                                   &(altsec->draw_gdiplus_cache_next));
3966                         break;
3967
3968                 case ORDER_TYPE_GDIPLUS_CACHE_END:
3969                         IFCALLRET(altsec->DrawGdiPlusCacheEnd, rc, context, &(altsec->draw_gdiplus_cache_end));
3970                         break;
3971
3972                 case ORDER_TYPE_WINDOW:
3973                         rc = update_recv_altsec_window_order(update, s);
3974                         break;
3975
3976                 case ORDER_TYPE_COMPDESK_FIRST:
3977                         rc = TRUE;
3978                         break;
3979
3980                 default:
3981                         break;
3982         }
3983
3984         if (!rc)
3985         {
3986                 WLog_Print(update->log, WLOG_WARN, "Alternate Secondary Drawing Order %s failed",
3987                            orderName);
3988         }
3989
3990         return rc;
3991 }
3992 BOOL update_recv_order(rdpUpdate* update, wStream* s)
3993 {
3994         BOOL rc;
3995         BYTE controlFlags;
3996
3997         if (Stream_GetRemainingLength(s) < 1)
3998         {
3999                 WLog_Print(update->log, WLOG_ERROR, "Stream_GetRemainingLength(s) < 1");
4000                 return FALSE;
4001         }
4002
4003         Stream_Read_UINT8(s, controlFlags); /* controlFlags (1 byte) */
4004
4005         if (!(controlFlags & ORDER_STANDARD))
4006                 rc = update_recv_altsec_order(update, s, controlFlags);
4007         else if (controlFlags & ORDER_SECONDARY)
4008                 rc = update_recv_secondary_order(update, s, controlFlags);
4009         else
4010                 rc = update_recv_primary_order(update, s, controlFlags);
4011
4012         if (!rc)
4013                 WLog_Print(update->log, WLOG_ERROR, "order flags %02" PRIx8 " failed", controlFlags);
4014
4015         return rc;
4016 }