Fixed remarks.
[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 TRUE;
1181         return FALSE;
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             update_read_brush(s, &patblt->brush, orderInfo->fieldFlags >> 7))
1215                 return TRUE;
1216         return FALSE;
1217 }
1218 int update_approximate_patblt_order(ORDER_INFO* orderInfo, PATBLT_ORDER* patblt)
1219 {
1220         return 32;
1221 }
1222 BOOL update_write_patblt_order(wStream* s, ORDER_INFO* orderInfo, PATBLT_ORDER* patblt)
1223 {
1224         if (!Stream_EnsureRemainingCapacity(s, update_approximate_patblt_order(orderInfo, patblt)))
1225                 return FALSE;
1226
1227         orderInfo->fieldFlags = 0;
1228         orderInfo->fieldFlags |= ORDER_FIELD_01;
1229         update_write_coord(s, patblt->nLeftRect);
1230         orderInfo->fieldFlags |= ORDER_FIELD_02;
1231         update_write_coord(s, patblt->nTopRect);
1232         orderInfo->fieldFlags |= ORDER_FIELD_03;
1233         update_write_coord(s, patblt->nWidth);
1234         orderInfo->fieldFlags |= ORDER_FIELD_04;
1235         update_write_coord(s, patblt->nHeight);
1236         orderInfo->fieldFlags |= ORDER_FIELD_05;
1237         Stream_Write_UINT8(s, patblt->bRop);
1238         orderInfo->fieldFlags |= ORDER_FIELD_06;
1239         update_write_color(s, patblt->backColor);
1240         orderInfo->fieldFlags |= ORDER_FIELD_07;
1241         update_write_color(s, patblt->foreColor);
1242         orderInfo->fieldFlags |= ORDER_FIELD_08;
1243         orderInfo->fieldFlags |= ORDER_FIELD_09;
1244         orderInfo->fieldFlags |= ORDER_FIELD_10;
1245         orderInfo->fieldFlags |= ORDER_FIELD_11;
1246         orderInfo->fieldFlags |= ORDER_FIELD_12;
1247         update_write_brush(s, &patblt->brush, orderInfo->fieldFlags >> 7);
1248         return TRUE;
1249 }
1250 static BOOL update_read_scrblt_order(wStream* s, const ORDER_INFO* orderInfo, SCRBLT_ORDER* scrblt)
1251 {
1252         if (read_order_field_coord(orderInfo, s, 1, &scrblt->nLeftRect, FALSE) &&
1253             read_order_field_coord(orderInfo, s, 2, &scrblt->nTopRect, FALSE) &&
1254             read_order_field_coord(orderInfo, s, 3, &scrblt->nWidth, FALSE) &&
1255             read_order_field_coord(orderInfo, s, 4, &scrblt->nHeight, FALSE) &&
1256             read_order_field_byte(orderInfo, s, 5, &scrblt->bRop, TRUE) &&
1257             read_order_field_coord(orderInfo, s, 6, &scrblt->nXSrc, FALSE) &&
1258             read_order_field_coord(orderInfo, s, 7, &scrblt->nYSrc, FALSE))
1259                 return TRUE;
1260         return FALSE;
1261 }
1262 int update_approximate_scrblt_order(ORDER_INFO* orderInfo, const SCRBLT_ORDER* scrblt)
1263 {
1264         return 32;
1265 }
1266 BOOL update_write_scrblt_order(wStream* s, ORDER_INFO* orderInfo, const SCRBLT_ORDER* scrblt)
1267 {
1268         if (!Stream_EnsureRemainingCapacity(s, update_approximate_scrblt_order(orderInfo, scrblt)))
1269                 return FALSE;
1270
1271         orderInfo->fieldFlags = 0;
1272         orderInfo->fieldFlags |= ORDER_FIELD_01;
1273         update_write_coord(s, scrblt->nLeftRect);
1274         orderInfo->fieldFlags |= ORDER_FIELD_02;
1275         update_write_coord(s, scrblt->nTopRect);
1276         orderInfo->fieldFlags |= ORDER_FIELD_03;
1277         update_write_coord(s, scrblt->nWidth);
1278         orderInfo->fieldFlags |= ORDER_FIELD_04;
1279         update_write_coord(s, scrblt->nHeight);
1280         orderInfo->fieldFlags |= ORDER_FIELD_05;
1281         Stream_Write_UINT8(s, scrblt->bRop);
1282         orderInfo->fieldFlags |= ORDER_FIELD_06;
1283         update_write_coord(s, scrblt->nXSrc);
1284         orderInfo->fieldFlags |= ORDER_FIELD_07;
1285         update_write_coord(s, scrblt->nYSrc);
1286         return TRUE;
1287 }
1288 static BOOL update_read_opaque_rect_order(wStream* s, const ORDER_INFO* orderInfo,
1289                                           OPAQUE_RECT_ORDER* opaque_rect)
1290 {
1291         BYTE byte;
1292         if (!read_order_field_coord(orderInfo, s, 1, &opaque_rect->nLeftRect, FALSE) ||
1293             !read_order_field_coord(orderInfo, s, 2, &opaque_rect->nTopRect, FALSE) ||
1294             !read_order_field_coord(orderInfo, s, 3, &opaque_rect->nWidth, FALSE) ||
1295             !read_order_field_coord(orderInfo, s, 4, &opaque_rect->nHeight, FALSE))
1296                 return FALSE;
1297
1298         if ((orderInfo->fieldFlags & ORDER_FIELD_05) != 0)
1299         {
1300                 if (Stream_GetRemainingLength(s) < 1)
1301                         return FALSE;
1302
1303                 Stream_Read_UINT8(s, byte);
1304                 opaque_rect->color = (opaque_rect->color & 0x00FFFF00) | ((UINT32)byte);
1305         }
1306
1307         if ((orderInfo->fieldFlags & ORDER_FIELD_06) != 0)
1308         {
1309                 if (Stream_GetRemainingLength(s) < 1)
1310                         return FALSE;
1311
1312                 Stream_Read_UINT8(s, byte);
1313                 opaque_rect->color = (opaque_rect->color & 0x00FF00FF) | ((UINT32)byte << 8);
1314         }
1315
1316         if ((orderInfo->fieldFlags & ORDER_FIELD_07) != 0)
1317         {
1318                 if (Stream_GetRemainingLength(s) < 1)
1319                         return FALSE;
1320
1321                 Stream_Read_UINT8(s, byte);
1322                 opaque_rect->color = (opaque_rect->color & 0x0000FFFF) | ((UINT32)byte << 16);
1323         }
1324
1325         return TRUE;
1326 }
1327 int update_approximate_opaque_rect_order(ORDER_INFO* orderInfo,
1328                                          const OPAQUE_RECT_ORDER* opaque_rect)
1329 {
1330         return 32;
1331 }
1332 BOOL update_write_opaque_rect_order(wStream* s, ORDER_INFO* orderInfo,
1333                                     const OPAQUE_RECT_ORDER* opaque_rect)
1334 {
1335         BYTE byte;
1336         int inf = update_approximate_opaque_rect_order(orderInfo, opaque_rect);
1337
1338         if (!Stream_EnsureRemainingCapacity(s, inf))
1339                 return FALSE;
1340
1341         // TODO: Color format conversion
1342         orderInfo->fieldFlags = 0;
1343         orderInfo->fieldFlags |= ORDER_FIELD_01;
1344         update_write_coord(s, opaque_rect->nLeftRect);
1345         orderInfo->fieldFlags |= ORDER_FIELD_02;
1346         update_write_coord(s, opaque_rect->nTopRect);
1347         orderInfo->fieldFlags |= ORDER_FIELD_03;
1348         update_write_coord(s, opaque_rect->nWidth);
1349         orderInfo->fieldFlags |= ORDER_FIELD_04;
1350         update_write_coord(s, opaque_rect->nHeight);
1351         orderInfo->fieldFlags |= ORDER_FIELD_05;
1352         byte = opaque_rect->color & 0x000000FF;
1353         Stream_Write_UINT8(s, byte);
1354         orderInfo->fieldFlags |= ORDER_FIELD_06;
1355         byte = (opaque_rect->color & 0x0000FF00) >> 8;
1356         Stream_Write_UINT8(s, byte);
1357         orderInfo->fieldFlags |= ORDER_FIELD_07;
1358         byte = (opaque_rect->color & 0x00FF0000) >> 16;
1359         Stream_Write_UINT8(s, byte);
1360         return TRUE;
1361 }
1362 static BOOL update_read_draw_nine_grid_order(wStream* s, const ORDER_INFO* orderInfo,
1363                                              DRAW_NINE_GRID_ORDER* draw_nine_grid)
1364 {
1365         if (read_order_field_coord(orderInfo, s, 1, &draw_nine_grid->srcLeft, FALSE) &&
1366             read_order_field_coord(orderInfo, s, 2, &draw_nine_grid->srcTop, FALSE) &&
1367             read_order_field_coord(orderInfo, s, 3, &draw_nine_grid->srcRight, FALSE) &&
1368             read_order_field_coord(orderInfo, s, 4, &draw_nine_grid->srcBottom, FALSE) &&
1369             read_order_field_uint16(orderInfo, s, 5, &draw_nine_grid->bitmapId, FALSE))
1370                 return TRUE;
1371         return FALSE;
1372 }
1373 static BOOL update_read_multi_dstblt_order(wStream* s, const ORDER_INFO* orderInfo,
1374                                            MULTI_DSTBLT_ORDER* multi_dstblt)
1375 {
1376         if (!read_order_field_coord(orderInfo, s, 1, &multi_dstblt->nLeftRect, FALSE) ||
1377             !read_order_field_coord(orderInfo, s, 2, &multi_dstblt->nTopRect, FALSE) ||
1378             !read_order_field_coord(orderInfo, s, 3, &multi_dstblt->nWidth, FALSE) ||
1379             !read_order_field_coord(orderInfo, s, 4, &multi_dstblt->nHeight, FALSE) ||
1380             !read_order_field_byte(orderInfo, s, 5, &multi_dstblt->bRop, TRUE) ||
1381             !read_order_field_byte(orderInfo, s, 6, &multi_dstblt->numRectangles, TRUE))
1382                 return FALSE;
1383
1384         if ((orderInfo->fieldFlags & ORDER_FIELD_07) != 0)
1385         {
1386                 if (Stream_GetRemainingLength(s) < 2)
1387                         return FALSE;
1388
1389                 Stream_Read_UINT16(s, multi_dstblt->cbData);
1390                 return update_read_delta_rects(s, multi_dstblt->rectangles, &multi_dstblt->numRectangles);
1391         }
1392
1393         return TRUE;
1394 }
1395 static BOOL update_read_multi_patblt_order(wStream* s, const ORDER_INFO* orderInfo,
1396                                            MULTI_PATBLT_ORDER* multi_patblt)
1397 {
1398         if (!read_order_field_coord(orderInfo, s, 1, &multi_patblt->nLeftRect, FALSE) ||
1399             !read_order_field_coord(orderInfo, s, 2, &multi_patblt->nTopRect, FALSE) ||
1400             !read_order_field_coord(orderInfo, s, 3, &multi_patblt->nWidth, FALSE) ||
1401             !read_order_field_coord(orderInfo, s, 4, &multi_patblt->nHeight, FALSE) ||
1402             !read_order_field_byte(orderInfo, s, 5, &multi_patblt->bRop, TRUE) ||
1403             !read_order_field_color(orderInfo, s, 6, &multi_patblt->backColor, TRUE) ||
1404             !read_order_field_color(orderInfo, s, 7, &multi_patblt->foreColor, TRUE))
1405                 return FALSE;
1406
1407         if (!update_read_brush(s, &multi_patblt->brush, orderInfo->fieldFlags >> 7))
1408                 return FALSE;
1409
1410         if (!read_order_field_byte(orderInfo, s, 13, &multi_patblt->numRectangles, TRUE))
1411                 return FALSE;
1412
1413         if ((orderInfo->fieldFlags & ORDER_FIELD_14) != 0)
1414         {
1415                 if (Stream_GetRemainingLength(s) < 2)
1416                         return FALSE;
1417
1418                 Stream_Read_UINT16(s, multi_patblt->cbData);
1419
1420                 if (!update_read_delta_rects(s, multi_patblt->rectangles, &multi_patblt->numRectangles))
1421                         return FALSE;
1422         }
1423
1424         return TRUE;
1425 }
1426 static BOOL update_read_multi_scrblt_order(wStream* s, const ORDER_INFO* orderInfo,
1427                                            MULTI_SCRBLT_ORDER* multi_scrblt)
1428 {
1429         if (!read_order_field_coord(orderInfo, s, 1, &multi_scrblt->nLeftRect, FALSE) ||
1430             !read_order_field_coord(orderInfo, s, 2, &multi_scrblt->nTopRect, FALSE) ||
1431             !read_order_field_coord(orderInfo, s, 3, &multi_scrblt->nWidth, FALSE) ||
1432             !read_order_field_coord(orderInfo, s, 4, &multi_scrblt->nHeight, FALSE) ||
1433             !read_order_field_byte(orderInfo, s, 5, &multi_scrblt->bRop, TRUE) ||
1434             !read_order_field_coord(orderInfo, s, 6, &multi_scrblt->nXSrc, FALSE) ||
1435             !read_order_field_coord(orderInfo, s, 7, &multi_scrblt->nYSrc, FALSE) ||
1436             !read_order_field_byte(orderInfo, s, 8, &multi_scrblt->numRectangles, TRUE))
1437                 return FALSE;
1438
1439         if ((orderInfo->fieldFlags & ORDER_FIELD_09) != 0)
1440         {
1441                 if (Stream_GetRemainingLength(s) < 2)
1442                         return FALSE;
1443
1444                 Stream_Read_UINT16(s, multi_scrblt->cbData);
1445                 return update_read_delta_rects(s, multi_scrblt->rectangles, &multi_scrblt->numRectangles);
1446         }
1447
1448         return TRUE;
1449 }
1450 static BOOL update_read_multi_opaque_rect_order(wStream* s, const ORDER_INFO* orderInfo,
1451                                                 MULTI_OPAQUE_RECT_ORDER* multi_opaque_rect)
1452 {
1453         BYTE byte;
1454         if (!read_order_field_coord(orderInfo, s, 1, &multi_opaque_rect->nLeftRect, FALSE) ||
1455             !read_order_field_coord(orderInfo, s, 2, &multi_opaque_rect->nTopRect, FALSE) ||
1456             !read_order_field_coord(orderInfo, s, 3, &multi_opaque_rect->nWidth, FALSE) ||
1457             !read_order_field_coord(orderInfo, s, 4, &multi_opaque_rect->nHeight, FALSE))
1458                 return FALSE;
1459
1460         if ((orderInfo->fieldFlags & ORDER_FIELD_05) != 0)
1461         {
1462                 if (Stream_GetRemainingLength(s) < 1)
1463                         return FALSE;
1464
1465                 Stream_Read_UINT8(s, byte);
1466                 multi_opaque_rect->color = (multi_opaque_rect->color & 0x00FFFF00) | ((UINT32)byte);
1467         }
1468
1469         if ((orderInfo->fieldFlags & ORDER_FIELD_06) != 0)
1470         {
1471                 if (Stream_GetRemainingLength(s) < 1)
1472                         return FALSE;
1473
1474                 Stream_Read_UINT8(s, byte);
1475                 multi_opaque_rect->color = (multi_opaque_rect->color & 0x00FF00FF) | ((UINT32)byte << 8);
1476         }
1477
1478         if ((orderInfo->fieldFlags & ORDER_FIELD_07) != 0)
1479         {
1480                 if (Stream_GetRemainingLength(s) < 1)
1481                         return FALSE;
1482
1483                 Stream_Read_UINT8(s, byte);
1484                 multi_opaque_rect->color = (multi_opaque_rect->color & 0x0000FFFF) | ((UINT32)byte << 16);
1485         }
1486
1487         if (!read_order_field_byte(orderInfo, s, 8, &multi_opaque_rect->numRectangles, TRUE))
1488                 return FALSE;
1489
1490         if ((orderInfo->fieldFlags & ORDER_FIELD_09) != 0)
1491         {
1492                 if (Stream_GetRemainingLength(s) < 2)
1493                         return FALSE;
1494
1495                 Stream_Read_UINT16(s, multi_opaque_rect->cbData);
1496                 return update_read_delta_rects(s, multi_opaque_rect->rectangles,
1497                                                &multi_opaque_rect->numRectangles);
1498         }
1499
1500         return TRUE;
1501 }
1502 static BOOL update_read_multi_draw_nine_grid_order(wStream* s, const ORDER_INFO* orderInfo,
1503                                                    MULTI_DRAW_NINE_GRID_ORDER* multi_draw_nine_grid)
1504 {
1505         if (!read_order_field_coord(orderInfo, s, 1, &multi_draw_nine_grid->srcLeft, FALSE) ||
1506             !read_order_field_coord(orderInfo, s, 2, &multi_draw_nine_grid->srcTop, FALSE) ||
1507             !read_order_field_coord(orderInfo, s, 3, &multi_draw_nine_grid->srcRight, FALSE) ||
1508             !read_order_field_coord(orderInfo, s, 4, &multi_draw_nine_grid->srcBottom, FALSE) ||
1509             !read_order_field_uint16(orderInfo, s, 5, &multi_draw_nine_grid->bitmapId, TRUE) ||
1510             !read_order_field_byte(orderInfo, s, 6, &multi_draw_nine_grid->nDeltaEntries, TRUE))
1511                 return FALSE;
1512
1513         if ((orderInfo->fieldFlags & ORDER_FIELD_07) != 0)
1514         {
1515                 if (Stream_GetRemainingLength(s) < 2)
1516                         return FALSE;
1517
1518                 Stream_Read_UINT16(s, multi_draw_nine_grid->cbData);
1519                 return update_read_delta_rects(s, multi_draw_nine_grid->rectangles,
1520                                                &multi_draw_nine_grid->nDeltaEntries);
1521         }
1522
1523         return TRUE;
1524 }
1525 static BOOL update_read_line_to_order(wStream* s, const ORDER_INFO* orderInfo,
1526                                       LINE_TO_ORDER* line_to)
1527 {
1528         if (read_order_field_uint16(orderInfo, s, 1, &line_to->backMode, TRUE) &&
1529             read_order_field_coord(orderInfo, s, 2, &line_to->nXStart, FALSE) &&
1530             read_order_field_coord(orderInfo, s, 3, &line_to->nYStart, FALSE) &&
1531             read_order_field_coord(orderInfo, s, 4, &line_to->nXEnd, FALSE) &&
1532             read_order_field_coord(orderInfo, s, 5, &line_to->nYEnd, FALSE) &&
1533             read_order_field_color(orderInfo, s, 6, &line_to->backColor, TRUE) &&
1534             read_order_field_byte(orderInfo, s, 7, &line_to->bRop2, TRUE) &&
1535             read_order_field_byte(orderInfo, s, 8, &line_to->penStyle, TRUE) &&
1536             read_order_field_byte(orderInfo, s, 9, &line_to->penWidth, TRUE) &&
1537             read_order_field_color(orderInfo, s, 10, &line_to->penColor, TRUE))
1538                 return TRUE;
1539         return FALSE;
1540 }
1541 int update_approximate_line_to_order(ORDER_INFO* orderInfo, const LINE_TO_ORDER* line_to)
1542 {
1543         return 32;
1544 }
1545 BOOL update_write_line_to_order(wStream* s, ORDER_INFO* orderInfo, const LINE_TO_ORDER* line_to)
1546 {
1547         if (!Stream_EnsureRemainingCapacity(s, update_approximate_line_to_order(orderInfo, line_to)))
1548                 return FALSE;
1549
1550         orderInfo->fieldFlags = 0;
1551         orderInfo->fieldFlags |= ORDER_FIELD_01;
1552         Stream_Write_UINT16(s, line_to->backMode);
1553         orderInfo->fieldFlags |= ORDER_FIELD_02;
1554         update_write_coord(s, line_to->nXStart);
1555         orderInfo->fieldFlags |= ORDER_FIELD_03;
1556         update_write_coord(s, line_to->nYStart);
1557         orderInfo->fieldFlags |= ORDER_FIELD_04;
1558         update_write_coord(s, line_to->nXEnd);
1559         orderInfo->fieldFlags |= ORDER_FIELD_05;
1560         update_write_coord(s, line_to->nYEnd);
1561         orderInfo->fieldFlags |= ORDER_FIELD_06;
1562         update_write_color(s, line_to->backColor);
1563         orderInfo->fieldFlags |= ORDER_FIELD_07;
1564         Stream_Write_UINT8(s, line_to->bRop2);
1565         orderInfo->fieldFlags |= ORDER_FIELD_08;
1566         Stream_Write_UINT8(s, line_to->penStyle);
1567         orderInfo->fieldFlags |= ORDER_FIELD_09;
1568         Stream_Write_UINT8(s, line_to->penWidth);
1569         orderInfo->fieldFlags |= ORDER_FIELD_10;
1570         update_write_color(s, line_to->penColor);
1571         return TRUE;
1572 }
1573 static BOOL update_read_polyline_order(wStream* s, const ORDER_INFO* orderInfo,
1574                                        POLYLINE_ORDER* polyline)
1575 {
1576         UINT32 word;
1577         UINT32 new_num = polyline->numDeltaEntries;
1578         if (!read_order_field_coord(orderInfo, s, 1, &polyline->xStart, FALSE) ||
1579             !read_order_field_coord(orderInfo, s, 2, &polyline->yStart, FALSE) ||
1580             !read_order_field_byte(orderInfo, s, 3, &polyline->bRop2, TRUE) ||
1581             !read_order_field_uint16(orderInfo, s, 4, &word, TRUE) ||
1582             !read_order_field_color(orderInfo, s, 5, &polyline->penColor, TRUE) ||
1583             !read_order_field_byte(orderInfo, s, 6, &new_num, TRUE))
1584                 return FALSE;
1585
1586         if ((orderInfo->fieldFlags & ORDER_FIELD_07) != 0)
1587         {
1588                 DELTA_POINT* new_points;
1589
1590                 if (new_num == 0)
1591                         return FALSE;
1592
1593                 if (Stream_GetRemainingLength(s) < 1)
1594                 {
1595                         WLog_ERR(TAG, "Stream_GetRemainingLength(s) < 1");
1596                         return FALSE;
1597                 }
1598
1599                 Stream_Read_UINT8(s, polyline->cbData);
1600                 new_points = (DELTA_POINT*)realloc(polyline->points, sizeof(DELTA_POINT) * new_num);
1601
1602                 if (!new_points)
1603                 {
1604                         WLog_ERR(TAG, "realloc(%" PRIu32 ") failed", new_num);
1605                         return FALSE;
1606                 }
1607
1608                 polyline->points = new_points;
1609                 polyline->numDeltaEntries = new_num;
1610                 return update_read_delta_points(s, polyline->points, polyline->numDeltaEntries,
1611                                                 polyline->xStart, polyline->yStart);
1612         }
1613
1614         return TRUE;
1615 }
1616 static BOOL update_read_memblt_order(wStream* s, const ORDER_INFO* orderInfo, MEMBLT_ORDER* memblt)
1617 {
1618         if (!s || !orderInfo || !memblt)
1619                 return FALSE;
1620
1621         if (!read_order_field_uint16(orderInfo, s, 1, &memblt->cacheId, TRUE) ||
1622             !read_order_field_coord(orderInfo, s, 2, &memblt->nLeftRect, FALSE) ||
1623             !read_order_field_coord(orderInfo, s, 3, &memblt->nTopRect, FALSE) ||
1624             !read_order_field_coord(orderInfo, s, 4, &memblt->nWidth, FALSE) ||
1625             !read_order_field_coord(orderInfo, s, 5, &memblt->nHeight, FALSE) ||
1626             !read_order_field_byte(orderInfo, s, 6, &memblt->bRop, TRUE) ||
1627             !read_order_field_coord(orderInfo, s, 7, &memblt->nXSrc, FALSE) ||
1628             !read_order_field_coord(orderInfo, s, 8, &memblt->nYSrc, FALSE) ||
1629             !read_order_field_uint16(orderInfo, s, 9, &memblt->cacheIndex, TRUE))
1630                 return FALSE;
1631         memblt->colorIndex = (memblt->cacheId >> 8);
1632         memblt->cacheId = (memblt->cacheId & 0xFF);
1633         memblt->bitmap = NULL;
1634         return TRUE;
1635 }
1636 int update_approximate_memblt_order(ORDER_INFO* orderInfo, const MEMBLT_ORDER* memblt)
1637 {
1638         return 64;
1639 }
1640 BOOL update_write_memblt_order(wStream* s, ORDER_INFO* orderInfo, const MEMBLT_ORDER* memblt)
1641 {
1642         UINT16 cacheId;
1643
1644         if (!Stream_EnsureRemainingCapacity(s, update_approximate_memblt_order(orderInfo, memblt)))
1645                 return FALSE;
1646
1647         cacheId = (memblt->cacheId & 0xFF) | ((memblt->colorIndex & 0xFF) << 8);
1648         orderInfo->fieldFlags |= ORDER_FIELD_01;
1649         Stream_Write_UINT16(s, cacheId);
1650         orderInfo->fieldFlags |= ORDER_FIELD_02;
1651         update_write_coord(s, memblt->nLeftRect);
1652         orderInfo->fieldFlags |= ORDER_FIELD_03;
1653         update_write_coord(s, memblt->nTopRect);
1654         orderInfo->fieldFlags |= ORDER_FIELD_04;
1655         update_write_coord(s, memblt->nWidth);
1656         orderInfo->fieldFlags |= ORDER_FIELD_05;
1657         update_write_coord(s, memblt->nHeight);
1658         orderInfo->fieldFlags |= ORDER_FIELD_06;
1659         Stream_Write_UINT8(s, memblt->bRop);
1660         orderInfo->fieldFlags |= ORDER_FIELD_07;
1661         update_write_coord(s, memblt->nXSrc);
1662         orderInfo->fieldFlags |= ORDER_FIELD_08;
1663         update_write_coord(s, memblt->nYSrc);
1664         orderInfo->fieldFlags |= ORDER_FIELD_09;
1665         Stream_Write_UINT16(s, memblt->cacheIndex);
1666         return TRUE;
1667 }
1668 static BOOL update_read_mem3blt_order(wStream* s, const ORDER_INFO* orderInfo,
1669                                       MEM3BLT_ORDER* mem3blt)
1670 {
1671         if (!read_order_field_uint16(orderInfo, s, 1, &mem3blt->cacheId, TRUE) ||
1672             !read_order_field_coord(orderInfo, s, 2, &mem3blt->nLeftRect, FALSE) ||
1673             !read_order_field_coord(orderInfo, s, 3, &mem3blt->nTopRect, FALSE) ||
1674             !read_order_field_coord(orderInfo, s, 4, &mem3blt->nWidth, FALSE) ||
1675             !read_order_field_coord(orderInfo, s, 5, &mem3blt->nHeight, FALSE) ||
1676             !read_order_field_byte(orderInfo, s, 6, &mem3blt->bRop, TRUE) ||
1677             !read_order_field_coord(orderInfo, s, 7, &mem3blt->nXSrc, FALSE) ||
1678             !read_order_field_coord(orderInfo, s, 8, &mem3blt->nYSrc, FALSE) ||
1679             !read_order_field_color(orderInfo, s, 9, &mem3blt->backColor, TRUE) ||
1680             !read_order_field_color(orderInfo, s, 10, &mem3blt->foreColor, TRUE))
1681                 return FALSE;
1682
1683         if (!update_read_brush(s, &mem3blt->brush, orderInfo->fieldFlags >> 10) ||
1684             !read_order_field_uint16(orderInfo, s, 16, &mem3blt->cacheIndex, TRUE))
1685                 return FALSE;
1686         mem3blt->colorIndex = (mem3blt->cacheId >> 8);
1687         mem3blt->cacheId = (mem3blt->cacheId & 0xFF);
1688         mem3blt->bitmap = NULL;
1689         return TRUE;
1690 }
1691 static BOOL update_read_save_bitmap_order(wStream* s, const ORDER_INFO* orderInfo,
1692                                           SAVE_BITMAP_ORDER* save_bitmap)
1693 {
1694         if (read_order_field_uint32(orderInfo, s, 1, &save_bitmap->savedBitmapPosition, TRUE) &&
1695             read_order_field_coord(orderInfo, s, 2, &save_bitmap->nLeftRect, FALSE) &&
1696             read_order_field_coord(orderInfo, s, 3, &save_bitmap->nTopRect, FALSE) &&
1697             read_order_field_coord(orderInfo, s, 4, &save_bitmap->nRightRect, FALSE) &&
1698             read_order_field_coord(orderInfo, s, 5, &save_bitmap->nBottomRect, FALSE) &&
1699             read_order_field_byte(orderInfo, s, 6, &save_bitmap->operation, TRUE))
1700                 return TRUE;
1701         return FALSE;
1702 }
1703 static BOOL update_read_glyph_index_order(wStream* s, const ORDER_INFO* orderInfo,
1704                                           GLYPH_INDEX_ORDER* glyph_index)
1705 {
1706         if (!read_order_field_byte(orderInfo, s, 1, &glyph_index->cacheId, TRUE) ||
1707             !read_order_field_byte(orderInfo, s, 2, &glyph_index->flAccel, TRUE) ||
1708             !read_order_field_byte(orderInfo, s, 3, &glyph_index->ulCharInc, TRUE) ||
1709             !read_order_field_byte(orderInfo, s, 4, &glyph_index->fOpRedundant, TRUE) ||
1710             !read_order_field_color(orderInfo, s, 5, &glyph_index->backColor, TRUE) ||
1711             !read_order_field_color(orderInfo, s, 6, &glyph_index->foreColor, TRUE) ||
1712             !read_order_field_int16(orderInfo, s, 7, &glyph_index->bkLeft, TRUE) ||
1713             !read_order_field_int16(orderInfo, s, 8, &glyph_index->bkTop, TRUE) ||
1714             !read_order_field_int16(orderInfo, s, 9, &glyph_index->bkRight, TRUE) ||
1715             !read_order_field_int16(orderInfo, s, 10, &glyph_index->bkBottom, TRUE) ||
1716             !read_order_field_int16(orderInfo, s, 11, &glyph_index->opLeft, TRUE) ||
1717             !read_order_field_int16(orderInfo, s, 12, &glyph_index->opTop, TRUE) ||
1718             !read_order_field_int16(orderInfo, s, 13, &glyph_index->opRight, TRUE) ||
1719             !read_order_field_int16(orderInfo, s, 14, &glyph_index->opBottom, TRUE) ||
1720             !update_read_brush(s, &glyph_index->brush, orderInfo->fieldFlags >> 14) ||
1721             !read_order_field_int16(orderInfo, s, 20, &glyph_index->x, TRUE) ||
1722             !read_order_field_int16(orderInfo, s, 21, &glyph_index->y, TRUE))
1723                 return FALSE;
1724
1725         if ((orderInfo->fieldFlags & ORDER_FIELD_22) != 0)
1726         {
1727                 if (Stream_GetRemainingLength(s) < 1)
1728                         return FALSE;
1729
1730                 Stream_Read_UINT8(s, glyph_index->cbData);
1731
1732                 if (Stream_GetRemainingLength(s) < glyph_index->cbData)
1733                         return FALSE;
1734
1735                 CopyMemory(glyph_index->data, Stream_Pointer(s), glyph_index->cbData);
1736                 Stream_Seek(s, glyph_index->cbData);
1737         }
1738
1739         return TRUE;
1740 }
1741 int update_approximate_glyph_index_order(ORDER_INFO* orderInfo,
1742                                          const GLYPH_INDEX_ORDER* glyph_index)
1743 {
1744         return 64;
1745 }
1746 BOOL update_write_glyph_index_order(wStream* s, ORDER_INFO* orderInfo,
1747                                     GLYPH_INDEX_ORDER* glyph_index)
1748 {
1749         int inf = update_approximate_glyph_index_order(orderInfo, glyph_index);
1750
1751         if (!Stream_EnsureRemainingCapacity(s, inf))
1752                 return FALSE;
1753
1754         orderInfo->fieldFlags = 0;
1755         orderInfo->fieldFlags |= ORDER_FIELD_01;
1756         Stream_Write_UINT8(s, glyph_index->cacheId);
1757         orderInfo->fieldFlags |= ORDER_FIELD_02;
1758         Stream_Write_UINT8(s, glyph_index->flAccel);
1759         orderInfo->fieldFlags |= ORDER_FIELD_03;
1760         Stream_Write_UINT8(s, glyph_index->ulCharInc);
1761         orderInfo->fieldFlags |= ORDER_FIELD_04;
1762         Stream_Write_UINT8(s, glyph_index->fOpRedundant);
1763         orderInfo->fieldFlags |= ORDER_FIELD_05;
1764         update_write_color(s, glyph_index->backColor);
1765         orderInfo->fieldFlags |= ORDER_FIELD_06;
1766         update_write_color(s, glyph_index->foreColor);
1767         orderInfo->fieldFlags |= ORDER_FIELD_07;
1768         Stream_Write_UINT16(s, glyph_index->bkLeft);
1769         orderInfo->fieldFlags |= ORDER_FIELD_08;
1770         Stream_Write_UINT16(s, glyph_index->bkTop);
1771         orderInfo->fieldFlags |= ORDER_FIELD_09;
1772         Stream_Write_UINT16(s, glyph_index->bkRight);
1773         orderInfo->fieldFlags |= ORDER_FIELD_10;
1774         Stream_Write_UINT16(s, glyph_index->bkBottom);
1775         orderInfo->fieldFlags |= ORDER_FIELD_11;
1776         Stream_Write_UINT16(s, glyph_index->opLeft);
1777         orderInfo->fieldFlags |= ORDER_FIELD_12;
1778         Stream_Write_UINT16(s, glyph_index->opTop);
1779         orderInfo->fieldFlags |= ORDER_FIELD_13;
1780         Stream_Write_UINT16(s, glyph_index->opRight);
1781         orderInfo->fieldFlags |= ORDER_FIELD_14;
1782         Stream_Write_UINT16(s, glyph_index->opBottom);
1783         orderInfo->fieldFlags |= ORDER_FIELD_15;
1784         orderInfo->fieldFlags |= ORDER_FIELD_16;
1785         orderInfo->fieldFlags |= ORDER_FIELD_17;
1786         orderInfo->fieldFlags |= ORDER_FIELD_18;
1787         orderInfo->fieldFlags |= ORDER_FIELD_19;
1788         update_write_brush(s, &glyph_index->brush, orderInfo->fieldFlags >> 14);
1789         orderInfo->fieldFlags |= ORDER_FIELD_20;
1790         Stream_Write_UINT16(s, glyph_index->x);
1791         orderInfo->fieldFlags |= ORDER_FIELD_21;
1792         Stream_Write_UINT16(s, glyph_index->y);
1793         orderInfo->fieldFlags |= ORDER_FIELD_22;
1794         Stream_Write_UINT8(s, glyph_index->cbData);
1795         Stream_Write(s, glyph_index->data, glyph_index->cbData);
1796         return TRUE;
1797 }
1798 static BOOL update_read_fast_index_order(wStream* s, const ORDER_INFO* orderInfo,
1799                                          FAST_INDEX_ORDER* fast_index)
1800 {
1801         if (!read_order_field_byte(orderInfo, s, 1, &fast_index->cacheId, TRUE) ||
1802             !read_order_field_2bytes(orderInfo, s, 2, &fast_index->ulCharInc, &fast_index->flAccel,
1803                                      TRUE) ||
1804             !read_order_field_color(orderInfo, s, 3, &fast_index->backColor, TRUE) ||
1805             !read_order_field_color(orderInfo, s, 4, &fast_index->foreColor, TRUE) ||
1806             !read_order_field_coord(orderInfo, s, 5, &fast_index->bkLeft, FALSE) ||
1807             !read_order_field_coord(orderInfo, s, 6, &fast_index->bkTop, FALSE) ||
1808             !read_order_field_coord(orderInfo, s, 7, &fast_index->bkRight, FALSE) ||
1809             !read_order_field_coord(orderInfo, s, 8, &fast_index->bkBottom, FALSE) ||
1810             !read_order_field_coord(orderInfo, s, 9, &fast_index->opLeft, FALSE) ||
1811             !read_order_field_coord(orderInfo, s, 10, &fast_index->opTop, FALSE) ||
1812             !read_order_field_coord(orderInfo, s, 11, &fast_index->opRight, FALSE) ||
1813             !read_order_field_coord(orderInfo, s, 12, &fast_index->opBottom, FALSE) ||
1814             !read_order_field_coord(orderInfo, s, 13, &fast_index->x, FALSE) ||
1815             !read_order_field_coord(orderInfo, s, 14, &fast_index->y, FALSE))
1816                 return FALSE;
1817
1818         if ((orderInfo->fieldFlags & ORDER_FIELD_15) != 0)
1819         {
1820                 if (Stream_GetRemainingLength(s) < 1)
1821                         return FALSE;
1822
1823                 Stream_Read_UINT8(s, fast_index->cbData);
1824
1825                 if (Stream_GetRemainingLength(s) < fast_index->cbData)
1826                         return FALSE;
1827
1828                 CopyMemory(fast_index->data, Stream_Pointer(s), fast_index->cbData);
1829                 Stream_Seek(s, fast_index->cbData);
1830         }
1831
1832         return TRUE;
1833 }
1834 static BOOL update_read_fast_glyph_order(wStream* s, const ORDER_INFO* orderInfo,
1835                                          FAST_GLYPH_ORDER* fastGlyph)
1836 {
1837         GLYPH_DATA_V2* glyph = &fastGlyph->glyphData;
1838         if (!read_order_field_byte(orderInfo, s, 1, &fastGlyph->cacheId, TRUE))
1839                 return FALSE;
1840         if (fastGlyph->cacheId > 9)
1841                 return FALSE;
1842         if (!read_order_field_2bytes(orderInfo, s, 2, &fastGlyph->ulCharInc, &fastGlyph->flAccel,
1843                                      TRUE) ||
1844             !read_order_field_color(orderInfo, s, 3, &fastGlyph->backColor, TRUE) ||
1845             !read_order_field_color(orderInfo, s, 4, &fastGlyph->foreColor, TRUE) ||
1846             !read_order_field_coord(orderInfo, s, 5, &fastGlyph->bkLeft, FALSE) ||
1847             !read_order_field_coord(orderInfo, s, 6, &fastGlyph->bkTop, FALSE) ||
1848             !read_order_field_coord(orderInfo, s, 7, &fastGlyph->bkRight, FALSE) ||
1849             !read_order_field_coord(orderInfo, s, 8, &fastGlyph->bkBottom, FALSE) ||
1850             !read_order_field_coord(orderInfo, s, 9, &fastGlyph->opLeft, FALSE) ||
1851             !read_order_field_coord(orderInfo, s, 10, &fastGlyph->opTop, FALSE) ||
1852             !read_order_field_coord(orderInfo, s, 11, &fastGlyph->opRight, FALSE) ||
1853             !read_order_field_coord(orderInfo, s, 12, &fastGlyph->opBottom, FALSE) ||
1854             !read_order_field_coord(orderInfo, s, 13, &fastGlyph->x, FALSE) ||
1855             !read_order_field_coord(orderInfo, s, 14, &fastGlyph->y, FALSE))
1856                 return FALSE;
1857
1858         if ((orderInfo->fieldFlags & ORDER_FIELD_15) != 0)
1859         {
1860                 const BYTE* src;
1861                 wStream sub;
1862                 if (Stream_GetRemainingLength(s) < 1)
1863                         return FALSE;
1864
1865                 Stream_Read_UINT8(s, fastGlyph->cbData);
1866
1867                 src = Stream_Pointer(s);
1868                 if (!Stream_SafeSeek(s, fastGlyph->cbData) || (fastGlyph->cbData == 0))
1869                         return FALSE;
1870
1871                 CopyMemory(fastGlyph->data, src, fastGlyph->cbData);
1872                 Stream_StaticInit(&sub, fastGlyph->data, fastGlyph->cbData);
1873
1874                 Stream_Read_UINT8(&sub, glyph->cacheIndex);
1875
1876                 if (fastGlyph->cbData > 1)
1877                 {
1878                         if (!update_read_2byte_signed(&sub, &glyph->x) ||
1879                             !update_read_2byte_signed(&sub, &glyph->y) ||
1880                             !update_read_2byte_unsigned(&sub, &glyph->cx) ||
1881                             !update_read_2byte_unsigned(&sub, &glyph->cy))
1882                                 return FALSE;
1883
1884                         glyph->cb = Stream_GetRemainingLength(&sub);
1885                         if (glyph->cb > 0)
1886                         {
1887                                 BYTE* new_aj = (BYTE*)realloc(glyph->aj, glyph->cb);
1888
1889                                 if (!new_aj)
1890                                         return FALSE;
1891
1892                                 glyph->aj = new_aj;
1893                                 Stream_Read(&sub, glyph->aj, glyph->cb);
1894                         }
1895                         else
1896                         {
1897                                 free(glyph->aj);
1898                                 glyph->aj = NULL;
1899                         }
1900                 }
1901         }
1902
1903         return TRUE;
1904 }
1905 static BOOL update_read_polygon_sc_order(wStream* s, const ORDER_INFO* orderInfo,
1906                                          POLYGON_SC_ORDER* polygon_sc)
1907 {
1908         UINT32 num = polygon_sc->numPoints;
1909         if (!read_order_field_coord(orderInfo, s, 1, &polygon_sc->xStart, FALSE) ||
1910             !read_order_field_coord(orderInfo, s, 2, &polygon_sc->yStart, FALSE) ||
1911             !read_order_field_byte(orderInfo, s, 3, &polygon_sc->bRop2, TRUE) ||
1912             !read_order_field_byte(orderInfo, s, 4, &polygon_sc->fillMode, TRUE) ||
1913             !read_order_field_color(orderInfo, s, 5, &polygon_sc->brushColor, TRUE) ||
1914             !read_order_field_byte(orderInfo, s, 6, &num, TRUE))
1915                 return FALSE;
1916
1917         if ((orderInfo->fieldFlags & ORDER_FIELD_07) != 0)
1918         {
1919                 DELTA_POINT* newpoints;
1920
1921                 if (num == 0)
1922                         return FALSE;
1923
1924                 if (Stream_GetRemainingLength(s) < 1)
1925                         return FALSE;
1926
1927                 Stream_Read_UINT8(s, polygon_sc->cbData);
1928                 newpoints = (DELTA_POINT*)realloc(polygon_sc->points, sizeof(DELTA_POINT) * num);
1929
1930                 if (!newpoints)
1931                         return FALSE;
1932
1933                 polygon_sc->points = newpoints;
1934                 polygon_sc->numPoints = num;
1935                 return update_read_delta_points(s, polygon_sc->points, polygon_sc->numPoints,
1936                                                 polygon_sc->xStart, polygon_sc->yStart);
1937         }
1938
1939         return TRUE;
1940 }
1941 static BOOL update_read_polygon_cb_order(wStream* s, const ORDER_INFO* orderInfo,
1942                                          POLYGON_CB_ORDER* polygon_cb)
1943 {
1944         UINT32 num = polygon_cb->numPoints;
1945         if (!read_order_field_coord(orderInfo, s, 1, &polygon_cb->xStart, FALSE) ||
1946             !read_order_field_coord(orderInfo, s, 2, &polygon_cb->yStart, FALSE) ||
1947             !read_order_field_byte(orderInfo, s, 3, &polygon_cb->bRop2, TRUE) ||
1948             !read_order_field_byte(orderInfo, s, 4, &polygon_cb->fillMode, TRUE) ||
1949             !read_order_field_color(orderInfo, s, 5, &polygon_cb->backColor, TRUE) ||
1950             !read_order_field_color(orderInfo, s, 6, &polygon_cb->foreColor, TRUE))
1951                 return FALSE;
1952
1953         if (!update_read_brush(s, &polygon_cb->brush, orderInfo->fieldFlags >> 6))
1954                 return FALSE;
1955
1956         if (!read_order_field_byte(orderInfo, s, 12, &num, TRUE))
1957                 return FALSE;
1958
1959         if ((orderInfo->fieldFlags & ORDER_FIELD_13) != 0)
1960         {
1961                 DELTA_POINT* newpoints;
1962
1963                 if (num == 0)
1964                         return FALSE;
1965
1966                 if (Stream_GetRemainingLength(s) < 1)
1967                         return FALSE;
1968
1969                 Stream_Read_UINT8(s, polygon_cb->cbData);
1970                 newpoints = (DELTA_POINT*)realloc(polygon_cb->points, sizeof(DELTA_POINT) * num);
1971
1972                 if (!newpoints)
1973                         return FALSE;
1974
1975                 polygon_cb->points = newpoints;
1976                 polygon_cb->numPoints = num;
1977
1978                 if (!update_read_delta_points(s, polygon_cb->points, polygon_cb->numPoints,
1979                                               polygon_cb->xStart, polygon_cb->yStart))
1980                         return FALSE;
1981         }
1982
1983         polygon_cb->backMode = (polygon_cb->bRop2 & 0x80) ? BACKMODE_TRANSPARENT : BACKMODE_OPAQUE;
1984         polygon_cb->bRop2 = (polygon_cb->bRop2 & 0x1F);
1985         return TRUE;
1986 }
1987 static BOOL update_read_ellipse_sc_order(wStream* s, const ORDER_INFO* orderInfo,
1988                                          ELLIPSE_SC_ORDER* ellipse_sc)
1989 {
1990         if (read_order_field_coord(orderInfo, s, 1, &ellipse_sc->leftRect, FALSE) &&
1991             read_order_field_coord(orderInfo, s, 2, &ellipse_sc->topRect, FALSE) &&
1992             read_order_field_coord(orderInfo, s, 3, &ellipse_sc->rightRect, FALSE) &&
1993             read_order_field_coord(orderInfo, s, 4, &ellipse_sc->bottomRect, FALSE) &&
1994             read_order_field_byte(orderInfo, s, 5, &ellipse_sc->bRop2, TRUE) &&
1995             read_order_field_byte(orderInfo, s, 6, &ellipse_sc->fillMode, TRUE) &&
1996             read_order_field_color(orderInfo, s, 7, &ellipse_sc->color, TRUE))
1997                 return TRUE;
1998         return FALSE;
1999 }
2000 static BOOL update_read_ellipse_cb_order(wStream* s, const ORDER_INFO* orderInfo,
2001                                          ELLIPSE_CB_ORDER* ellipse_cb)
2002 {
2003         if (read_order_field_coord(orderInfo, s, 1, &ellipse_cb->leftRect, FALSE) &&
2004             read_order_field_coord(orderInfo, s, 2, &ellipse_cb->topRect, FALSE) &&
2005             read_order_field_coord(orderInfo, s, 3, &ellipse_cb->rightRect, FALSE) &&
2006             read_order_field_coord(orderInfo, s, 4, &ellipse_cb->bottomRect, FALSE) &&
2007             read_order_field_byte(orderInfo, s, 5, &ellipse_cb->bRop2, TRUE) &&
2008             read_order_field_byte(orderInfo, s, 6, &ellipse_cb->fillMode, TRUE) &&
2009             read_order_field_color(orderInfo, s, 7, &ellipse_cb->backColor, TRUE) &&
2010             read_order_field_color(orderInfo, s, 8, &ellipse_cb->foreColor, TRUE) &&
2011             update_read_brush(s, &ellipse_cb->brush, orderInfo->fieldFlags >> 8))
2012                 return TRUE;
2013         return FALSE;
2014 }
2015 /* Secondary Drawing Orders */
2016 static CACHE_BITMAP_ORDER* update_read_cache_bitmap_order(rdpUpdate* update, wStream* s,
2017                                                           BOOL compressed, UINT16 flags)
2018 {
2019         CACHE_BITMAP_ORDER* cache_bitmap;
2020
2021         if (!update || !s)
2022                 return NULL;
2023
2024         cache_bitmap = calloc(1, sizeof(CACHE_BITMAP_ORDER));
2025
2026         if (!cache_bitmap)
2027                 goto fail;
2028
2029         if (Stream_GetRemainingLength(s) < 9)
2030                 goto fail;
2031
2032         Stream_Read_UINT8(s, cache_bitmap->cacheId);      /* cacheId (1 byte) */
2033         Stream_Seek_UINT8(s);                             /* pad1Octet (1 byte) */
2034         Stream_Read_UINT8(s, cache_bitmap->bitmapWidth);  /* bitmapWidth (1 byte) */
2035         Stream_Read_UINT8(s, cache_bitmap->bitmapHeight); /* bitmapHeight (1 byte) */
2036         Stream_Read_UINT8(s, cache_bitmap->bitmapBpp);    /* bitmapBpp (1 byte) */
2037
2038         if ((cache_bitmap->bitmapBpp < 1) || (cache_bitmap->bitmapBpp > 32))
2039         {
2040                 WLog_Print(update->log, WLOG_ERROR, "invalid bitmap bpp %" PRIu32 "",
2041                            cache_bitmap->bitmapBpp);
2042                 goto fail;
2043         }
2044
2045         Stream_Read_UINT16(s, cache_bitmap->bitmapLength); /* bitmapLength (2 bytes) */
2046         Stream_Read_UINT16(s, cache_bitmap->cacheIndex);   /* cacheIndex (2 bytes) */
2047
2048         if (compressed)
2049         {
2050                 if ((flags & NO_BITMAP_COMPRESSION_HDR) == 0)
2051                 {
2052                         BYTE* bitmapComprHdr = (BYTE*)&(cache_bitmap->bitmapComprHdr);
2053
2054                         if (Stream_GetRemainingLength(s) < 8)
2055                                 goto fail;
2056
2057                         Stream_Read(s, bitmapComprHdr, 8); /* bitmapComprHdr (8 bytes) */
2058                         cache_bitmap->bitmapLength -= 8;
2059                 }
2060         }
2061
2062         if (cache_bitmap->bitmapLength == 0)
2063                 goto fail;
2064
2065         if (Stream_GetRemainingLength(s) < cache_bitmap->bitmapLength)
2066                 goto fail;
2067
2068         cache_bitmap->bitmapDataStream = malloc(cache_bitmap->bitmapLength);
2069
2070         if (!cache_bitmap->bitmapDataStream)
2071                 goto fail;
2072
2073         Stream_Read(s, cache_bitmap->bitmapDataStream, cache_bitmap->bitmapLength);
2074         cache_bitmap->compressed = compressed;
2075         return cache_bitmap;
2076 fail:
2077         free_cache_bitmap_order(update->context, cache_bitmap);
2078         return NULL;
2079 }
2080 int update_approximate_cache_bitmap_order(const CACHE_BITMAP_ORDER* cache_bitmap, BOOL compressed,
2081                                           UINT16* flags)
2082 {
2083         return 64 + cache_bitmap->bitmapLength;
2084 }
2085 BOOL update_write_cache_bitmap_order(wStream* s, const CACHE_BITMAP_ORDER* cache_bitmap,
2086                                      BOOL compressed, UINT16* flags)
2087 {
2088         UINT32 bitmapLength = cache_bitmap->bitmapLength;
2089         int inf = update_approximate_cache_bitmap_order(cache_bitmap, compressed, flags);
2090
2091         if (!Stream_EnsureRemainingCapacity(s, inf))
2092                 return FALSE;
2093
2094         *flags = NO_BITMAP_COMPRESSION_HDR;
2095
2096         if ((*flags & NO_BITMAP_COMPRESSION_HDR) == 0)
2097                 bitmapLength += 8;
2098
2099         Stream_Write_UINT8(s, cache_bitmap->cacheId);      /* cacheId (1 byte) */
2100         Stream_Write_UINT8(s, 0);                          /* pad1Octet (1 byte) */
2101         Stream_Write_UINT8(s, cache_bitmap->bitmapWidth);  /* bitmapWidth (1 byte) */
2102         Stream_Write_UINT8(s, cache_bitmap->bitmapHeight); /* bitmapHeight (1 byte) */
2103         Stream_Write_UINT8(s, cache_bitmap->bitmapBpp);    /* bitmapBpp (1 byte) */
2104         Stream_Write_UINT16(s, bitmapLength);              /* bitmapLength (2 bytes) */
2105         Stream_Write_UINT16(s, cache_bitmap->cacheIndex);  /* cacheIndex (2 bytes) */
2106
2107         if (compressed)
2108         {
2109                 if ((*flags & NO_BITMAP_COMPRESSION_HDR) == 0)
2110                 {
2111                         BYTE* bitmapComprHdr = (BYTE*)&(cache_bitmap->bitmapComprHdr);
2112                         Stream_Write(s, bitmapComprHdr, 8); /* bitmapComprHdr (8 bytes) */
2113                         bitmapLength -= 8;
2114                 }
2115
2116                 Stream_Write(s, cache_bitmap->bitmapDataStream, bitmapLength);
2117         }
2118         else
2119         {
2120                 Stream_Write(s, cache_bitmap->bitmapDataStream, bitmapLength);
2121         }
2122
2123         return TRUE;
2124 }
2125 static CACHE_BITMAP_V2_ORDER* update_read_cache_bitmap_v2_order(rdpUpdate* update, wStream* s,
2126                                                                 BOOL compressed, UINT16 flags)
2127 {
2128         BOOL rc;
2129         BYTE bitsPerPixelId;
2130         CACHE_BITMAP_V2_ORDER* cache_bitmap_v2;
2131
2132         if (!update || !s)
2133                 return NULL;
2134
2135         cache_bitmap_v2 = calloc(1, sizeof(CACHE_BITMAP_V2_ORDER));
2136
2137         if (!cache_bitmap_v2)
2138                 goto fail;
2139
2140         cache_bitmap_v2->cacheId = flags & 0x0003;
2141         cache_bitmap_v2->flags = (flags & 0xFF80) >> 7;
2142         bitsPerPixelId = (flags & 0x0078) >> 3;
2143         cache_bitmap_v2->bitmapBpp = get_cbr2_bpp(bitsPerPixelId, &rc);
2144         if (!rc)
2145                 goto fail;
2146
2147         if (cache_bitmap_v2->flags & CBR2_PERSISTENT_KEY_PRESENT)
2148         {
2149                 if (Stream_GetRemainingLength(s) < 8)
2150                         goto fail;
2151
2152                 Stream_Read_UINT32(s, cache_bitmap_v2->key1); /* key1 (4 bytes) */
2153                 Stream_Read_UINT32(s, cache_bitmap_v2->key2); /* key2 (4 bytes) */
2154         }
2155
2156         if (cache_bitmap_v2->flags & CBR2_HEIGHT_SAME_AS_WIDTH)
2157         {
2158                 if (!update_read_2byte_unsigned(s, &cache_bitmap_v2->bitmapWidth)) /* bitmapWidth */
2159                         goto fail;
2160
2161                 cache_bitmap_v2->bitmapHeight = cache_bitmap_v2->bitmapWidth;
2162         }
2163         else
2164         {
2165                 if (!update_read_2byte_unsigned(s, &cache_bitmap_v2->bitmapWidth) || /* bitmapWidth */
2166                     !update_read_2byte_unsigned(s, &cache_bitmap_v2->bitmapHeight))  /* bitmapHeight */
2167                         goto fail;
2168         }
2169
2170         if (!update_read_4byte_unsigned(s, &cache_bitmap_v2->bitmapLength) || /* bitmapLength */
2171             !update_read_2byte_unsigned(s, &cache_bitmap_v2->cacheIndex))     /* cacheIndex */
2172                 goto fail;
2173
2174         if (cache_bitmap_v2->flags & CBR2_DO_NOT_CACHE)
2175                 cache_bitmap_v2->cacheIndex = BITMAP_CACHE_WAITING_LIST_INDEX;
2176
2177         if (compressed)
2178         {
2179                 if (!(cache_bitmap_v2->flags & CBR2_NO_BITMAP_COMPRESSION_HDR))
2180                 {
2181                         if (Stream_GetRemainingLength(s) < 8)
2182                                 goto fail;
2183
2184                         Stream_Read_UINT16(
2185                             s, cache_bitmap_v2->cbCompFirstRowSize); /* cbCompFirstRowSize (2 bytes) */
2186                         Stream_Read_UINT16(
2187                             s, cache_bitmap_v2->cbCompMainBodySize);         /* cbCompMainBodySize (2 bytes) */
2188                         Stream_Read_UINT16(s, cache_bitmap_v2->cbScanWidth); /* cbScanWidth (2 bytes) */
2189                         Stream_Read_UINT16(
2190                             s, cache_bitmap_v2->cbUncompressedSize); /* cbUncompressedSize (2 bytes) */
2191                         cache_bitmap_v2->bitmapLength = cache_bitmap_v2->cbCompMainBodySize;
2192                 }
2193         }
2194
2195         if (cache_bitmap_v2->bitmapLength == 0)
2196                 goto fail;
2197
2198         if (Stream_GetRemainingLength(s) < cache_bitmap_v2->bitmapLength)
2199                 goto fail;
2200
2201         if (cache_bitmap_v2->bitmapLength == 0)
2202                 goto fail;
2203
2204         cache_bitmap_v2->bitmapDataStream = malloc(cache_bitmap_v2->bitmapLength);
2205
2206         if (!cache_bitmap_v2->bitmapDataStream)
2207                 goto fail;
2208
2209         Stream_Read(s, cache_bitmap_v2->bitmapDataStream, cache_bitmap_v2->bitmapLength);
2210         cache_bitmap_v2->compressed = compressed;
2211         return cache_bitmap_v2;
2212 fail:
2213         free_cache_bitmap_v2_order(update->context, cache_bitmap_v2);
2214         return NULL;
2215 }
2216 int update_approximate_cache_bitmap_v2_order(CACHE_BITMAP_V2_ORDER* cache_bitmap_v2,
2217                                              BOOL compressed, UINT16* flags)
2218 {
2219         return 64 + cache_bitmap_v2->bitmapLength;
2220 }
2221 BOOL update_write_cache_bitmap_v2_order(wStream* s, CACHE_BITMAP_V2_ORDER* cache_bitmap_v2,
2222                                         BOOL compressed, UINT16* flags)
2223 {
2224         BOOL rc;
2225         BYTE bitsPerPixelId;
2226
2227         if (!Stream_EnsureRemainingCapacity(
2228                 s, update_approximate_cache_bitmap_v2_order(cache_bitmap_v2, compressed, flags)))
2229                 return FALSE;
2230
2231         bitsPerPixelId = get_bpp_bmf(cache_bitmap_v2->bitmapBpp, &rc);
2232         if (!rc)
2233                 return FALSE;
2234         *flags = (cache_bitmap_v2->cacheId & 0x0003) | (bitsPerPixelId << 3) |
2235                  ((cache_bitmap_v2->flags << 7) & 0xFF80);
2236
2237         if (cache_bitmap_v2->flags & CBR2_PERSISTENT_KEY_PRESENT)
2238         {
2239                 Stream_Write_UINT32(s, cache_bitmap_v2->key1); /* key1 (4 bytes) */
2240                 Stream_Write_UINT32(s, cache_bitmap_v2->key2); /* key2 (4 bytes) */
2241         }
2242
2243         if (cache_bitmap_v2->flags & CBR2_HEIGHT_SAME_AS_WIDTH)
2244         {
2245                 if (!update_write_2byte_unsigned(s, cache_bitmap_v2->bitmapWidth)) /* bitmapWidth */
2246                         return FALSE;
2247         }
2248         else
2249         {
2250                 if (!update_write_2byte_unsigned(s, cache_bitmap_v2->bitmapWidth) || /* bitmapWidth */
2251                     !update_write_2byte_unsigned(s, cache_bitmap_v2->bitmapHeight))  /* bitmapHeight */
2252                         return FALSE;
2253         }
2254
2255         if (cache_bitmap_v2->flags & CBR2_DO_NOT_CACHE)
2256                 cache_bitmap_v2->cacheIndex = BITMAP_CACHE_WAITING_LIST_INDEX;
2257
2258         if (!update_write_4byte_unsigned(s, cache_bitmap_v2->bitmapLength) || /* bitmapLength */
2259             !update_write_2byte_unsigned(s, cache_bitmap_v2->cacheIndex))     /* cacheIndex */
2260                 return FALSE;
2261
2262         if (compressed)
2263         {
2264                 if (!(cache_bitmap_v2->flags & CBR2_NO_BITMAP_COMPRESSION_HDR))
2265                 {
2266                         Stream_Write_UINT16(
2267                             s, cache_bitmap_v2->cbCompFirstRowSize); /* cbCompFirstRowSize (2 bytes) */
2268                         Stream_Write_UINT16(
2269                             s, cache_bitmap_v2->cbCompMainBodySize);          /* cbCompMainBodySize (2 bytes) */
2270                         Stream_Write_UINT16(s, cache_bitmap_v2->cbScanWidth); /* cbScanWidth (2 bytes) */
2271                         Stream_Write_UINT16(
2272                             s, cache_bitmap_v2->cbUncompressedSize); /* cbUncompressedSize (2 bytes) */
2273                         cache_bitmap_v2->bitmapLength = cache_bitmap_v2->cbCompMainBodySize;
2274                 }
2275
2276                 if (!Stream_EnsureRemainingCapacity(s, cache_bitmap_v2->bitmapLength))
2277                         return FALSE;
2278
2279                 Stream_Write(s, cache_bitmap_v2->bitmapDataStream, cache_bitmap_v2->bitmapLength);
2280         }
2281         else
2282         {
2283                 if (!Stream_EnsureRemainingCapacity(s, cache_bitmap_v2->bitmapLength))
2284                         return FALSE;
2285
2286                 Stream_Write(s, cache_bitmap_v2->bitmapDataStream, cache_bitmap_v2->bitmapLength);
2287         }
2288
2289         cache_bitmap_v2->compressed = compressed;
2290         return TRUE;
2291 }
2292 static CACHE_BITMAP_V3_ORDER* update_read_cache_bitmap_v3_order(rdpUpdate* update, wStream* s,
2293                                                                 UINT16 flags)
2294 {
2295         BOOL rc;
2296         BYTE bitsPerPixelId;
2297         BITMAP_DATA_EX* bitmapData;
2298         UINT32 new_len;
2299         BYTE* new_data;
2300         CACHE_BITMAP_V3_ORDER* cache_bitmap_v3;
2301
2302         if (!update || !s)
2303                 return NULL;
2304
2305         cache_bitmap_v3 = calloc(1, sizeof(CACHE_BITMAP_V3_ORDER));
2306
2307         if (!cache_bitmap_v3)
2308                 goto fail;
2309
2310         cache_bitmap_v3->cacheId = flags & 0x00000003;
2311         cache_bitmap_v3->flags = (flags & 0x0000FF80) >> 7;
2312         bitsPerPixelId = (flags & 0x00000078) >> 3;
2313         cache_bitmap_v3->bpp = get_cbr2_bpp(bitsPerPixelId, &rc);
2314         if (!rc)
2315                 goto fail;
2316
2317         if (Stream_GetRemainingLength(s) < 21)
2318                 goto fail;
2319
2320         Stream_Read_UINT16(s, cache_bitmap_v3->cacheIndex); /* cacheIndex (2 bytes) */
2321         Stream_Read_UINT32(s, cache_bitmap_v3->key1);       /* key1 (4 bytes) */
2322         Stream_Read_UINT32(s, cache_bitmap_v3->key2);       /* key2 (4 bytes) */
2323         bitmapData = &cache_bitmap_v3->bitmapData;
2324         Stream_Read_UINT8(s, bitmapData->bpp);
2325
2326         if ((bitmapData->bpp < 1) || (bitmapData->bpp > 32))
2327         {
2328                 WLog_Print(update->log, WLOG_ERROR, "invalid bpp value %" PRIu32 "", bitmapData->bpp);
2329                 goto fail;
2330         }
2331
2332         Stream_Seek_UINT8(s);                      /* reserved1 (1 byte) */
2333         Stream_Seek_UINT8(s);                      /* reserved2 (1 byte) */
2334         Stream_Read_UINT8(s, bitmapData->codecID); /* codecID (1 byte) */
2335         Stream_Read_UINT16(s, bitmapData->width);  /* width (2 bytes) */
2336         Stream_Read_UINT16(s, bitmapData->height); /* height (2 bytes) */
2337         Stream_Read_UINT32(s, new_len);            /* length (4 bytes) */
2338
2339         if ((new_len == 0) || (Stream_GetRemainingLength(s) < new_len))
2340                 goto fail;
2341
2342         new_data = (BYTE*)realloc(bitmapData->data, new_len);
2343
2344         if (!new_data)
2345                 goto fail;
2346
2347         bitmapData->data = new_data;
2348         bitmapData->length = new_len;
2349         Stream_Read(s, bitmapData->data, bitmapData->length);
2350         return cache_bitmap_v3;
2351 fail:
2352         free_cache_bitmap_v3_order(update->context, cache_bitmap_v3);
2353         return NULL;
2354 }
2355 int update_approximate_cache_bitmap_v3_order(CACHE_BITMAP_V3_ORDER* cache_bitmap_v3, UINT16* flags)
2356 {
2357         BITMAP_DATA_EX* bitmapData = &cache_bitmap_v3->bitmapData;
2358         return 64 + bitmapData->length;
2359 }
2360 BOOL update_write_cache_bitmap_v3_order(wStream* s, CACHE_BITMAP_V3_ORDER* cache_bitmap_v3,
2361                                         UINT16* flags)
2362 {
2363         BOOL rc;
2364         BYTE bitsPerPixelId;
2365         BITMAP_DATA_EX* bitmapData;
2366
2367         if (!Stream_EnsureRemainingCapacity(
2368                 s, update_approximate_cache_bitmap_v3_order(cache_bitmap_v3, flags)))
2369                 return FALSE;
2370
2371         bitmapData = &cache_bitmap_v3->bitmapData;
2372         bitsPerPixelId = get_bpp_bmf(cache_bitmap_v3->bpp, &rc);
2373         if (!rc)
2374                 return FALSE;
2375         *flags = (cache_bitmap_v3->cacheId & 0x00000003) |
2376                  ((cache_bitmap_v3->flags << 7) & 0x0000FF80) | ((bitsPerPixelId << 3) & 0x00000078);
2377         Stream_Write_UINT16(s, cache_bitmap_v3->cacheIndex); /* cacheIndex (2 bytes) */
2378         Stream_Write_UINT32(s, cache_bitmap_v3->key1);       /* key1 (4 bytes) */
2379         Stream_Write_UINT32(s, cache_bitmap_v3->key2);       /* key2 (4 bytes) */
2380         Stream_Write_UINT8(s, bitmapData->bpp);
2381         Stream_Write_UINT8(s, 0);                   /* reserved1 (1 byte) */
2382         Stream_Write_UINT8(s, 0);                   /* reserved2 (1 byte) */
2383         Stream_Write_UINT8(s, bitmapData->codecID); /* codecID (1 byte) */
2384         Stream_Write_UINT16(s, bitmapData->width);  /* width (2 bytes) */
2385         Stream_Write_UINT16(s, bitmapData->height); /* height (2 bytes) */
2386         Stream_Write_UINT32(s, bitmapData->length); /* length (4 bytes) */
2387         Stream_Write(s, bitmapData->data, bitmapData->length);
2388         return TRUE;
2389 }
2390 static CACHE_COLOR_TABLE_ORDER* update_read_cache_color_table_order(rdpUpdate* update, wStream* s,
2391                                                                     UINT16 flags)
2392 {
2393         int i;
2394         UINT32* colorTable;
2395         CACHE_COLOR_TABLE_ORDER* cache_color_table = calloc(1, sizeof(CACHE_COLOR_TABLE_ORDER));
2396
2397         if (!cache_color_table)
2398                 goto fail;
2399
2400         if (Stream_GetRemainingLength(s) < 3)
2401                 goto fail;
2402
2403         Stream_Read_UINT8(s, cache_color_table->cacheIndex);    /* cacheIndex (1 byte) */
2404         Stream_Read_UINT16(s, cache_color_table->numberColors); /* numberColors (2 bytes) */
2405
2406         if (cache_color_table->numberColors != 256)
2407         {
2408                 /* This field MUST be set to 256 */
2409                 goto fail;
2410         }
2411
2412         if (Stream_GetRemainingLength(s) < cache_color_table->numberColors * 4)
2413                 goto fail;
2414
2415         colorTable = (UINT32*)&cache_color_table->colorTable;
2416
2417         for (i = 0; i < (int)cache_color_table->numberColors; i++)
2418                 update_read_color_quad(s, &colorTable[i]);
2419
2420         return cache_color_table;
2421 fail:
2422         free_cache_color_table_order(update->context, cache_color_table);
2423         return NULL;
2424 }
2425 int update_approximate_cache_color_table_order(const CACHE_COLOR_TABLE_ORDER* cache_color_table,
2426                                                UINT16* flags)
2427 {
2428         return 16 + (256 * 4);
2429 }
2430 BOOL update_write_cache_color_table_order(wStream* s,
2431                                           const CACHE_COLOR_TABLE_ORDER* cache_color_table,
2432                                           UINT16* flags)
2433 {
2434         int i, inf;
2435         UINT32* colorTable;
2436
2437         if (cache_color_table->numberColors != 256)
2438                 return FALSE;
2439
2440         inf = update_approximate_cache_color_table_order(cache_color_table, flags);
2441
2442         if (!Stream_EnsureRemainingCapacity(s, inf))
2443                 return FALSE;
2444
2445         Stream_Write_UINT8(s, cache_color_table->cacheIndex);    /* cacheIndex (1 byte) */
2446         Stream_Write_UINT16(s, cache_color_table->numberColors); /* numberColors (2 bytes) */
2447         colorTable = (UINT32*)&cache_color_table->colorTable;
2448
2449         for (i = 0; i < (int)cache_color_table->numberColors; i++)
2450         {
2451                 update_write_color_quad(s, colorTable[i]);
2452         }
2453
2454         return TRUE;
2455 }
2456 static CACHE_GLYPH_ORDER* update_read_cache_glyph_order(rdpUpdate* update, wStream* s, UINT16 flags)
2457 {
2458         UINT32 i;
2459         CACHE_GLYPH_ORDER* cache_glyph_order = calloc(1, sizeof(CACHE_GLYPH_ORDER));
2460
2461         if (!cache_glyph_order || !update || !s)
2462                 goto fail;
2463
2464         if (Stream_GetRemainingLength(s) < 2)
2465                 goto fail;
2466
2467         Stream_Read_UINT8(s, cache_glyph_order->cacheId); /* cacheId (1 byte) */
2468         Stream_Read_UINT8(s, cache_glyph_order->cGlyphs); /* cGlyphs (1 byte) */
2469
2470         for (i = 0; i < cache_glyph_order->cGlyphs; i++)
2471         {
2472                 GLYPH_DATA* glyph = &cache_glyph_order->glyphData[i];
2473
2474                 if (Stream_GetRemainingLength(s) < 10)
2475                         goto fail;
2476
2477                 Stream_Read_UINT16(s, glyph->cacheIndex);
2478                 Stream_Read_INT16(s, glyph->x);
2479                 Stream_Read_INT16(s, glyph->y);
2480                 Stream_Read_UINT16(s, glyph->cx);
2481                 Stream_Read_UINT16(s, glyph->cy);
2482                 glyph->cb = ((glyph->cx + 7) / 8) * glyph->cy;
2483                 glyph->cb += ((glyph->cb % 4) > 0) ? 4 - (glyph->cb % 4) : 0;
2484
2485                 if (Stream_GetRemainingLength(s) < glyph->cb)
2486                         goto fail;
2487
2488                 glyph->aj = (BYTE*)malloc(glyph->cb);
2489
2490                 if (!glyph->aj)
2491                         goto fail;
2492
2493                 Stream_Read(s, glyph->aj, glyph->cb);
2494         }
2495
2496         if ((flags & CG_GLYPH_UNICODE_PRESENT) && (cache_glyph_order->cGlyphs > 0))
2497         {
2498                 cache_glyph_order->unicodeCharacters = calloc(cache_glyph_order->cGlyphs, sizeof(WCHAR));
2499
2500                 if (!cache_glyph_order->unicodeCharacters)
2501                         goto fail;
2502
2503                 if (Stream_GetRemainingLength(s) < sizeof(WCHAR) * cache_glyph_order->cGlyphs)
2504                         goto fail;
2505
2506                 Stream_Read_UTF16_String(s, cache_glyph_order->unicodeCharacters,
2507                                          cache_glyph_order->cGlyphs);
2508         }
2509
2510         return cache_glyph_order;
2511 fail:
2512         free_cache_glyph_order(update->context, cache_glyph_order);
2513         return NULL;
2514 }
2515 int update_approximate_cache_glyph_order(const CACHE_GLYPH_ORDER* cache_glyph, UINT16* flags)
2516 {
2517         return 2 + cache_glyph->cGlyphs * 32;
2518 }
2519 BOOL update_write_cache_glyph_order(wStream* s, const CACHE_GLYPH_ORDER* cache_glyph, UINT16* flags)
2520 {
2521         int i, inf;
2522         INT16 lsi16;
2523         const GLYPH_DATA* glyph;
2524         inf = update_approximate_cache_glyph_order(cache_glyph, flags);
2525
2526         if (!Stream_EnsureRemainingCapacity(s, inf))
2527                 return FALSE;
2528
2529         Stream_Write_UINT8(s, cache_glyph->cacheId); /* cacheId (1 byte) */
2530         Stream_Write_UINT8(s, cache_glyph->cGlyphs); /* cGlyphs (1 byte) */
2531
2532         for (i = 0; i < (int)cache_glyph->cGlyphs; i++)
2533         {
2534                 UINT32 cb;
2535                 glyph = &cache_glyph->glyphData[i];
2536                 Stream_Write_UINT16(s, glyph->cacheIndex); /* cacheIndex (2 bytes) */
2537                 lsi16 = glyph->x;
2538                 Stream_Write_UINT16(s, lsi16); /* x (2 bytes) */
2539                 lsi16 = glyph->y;
2540                 Stream_Write_UINT16(s, lsi16);     /* y (2 bytes) */
2541                 Stream_Write_UINT16(s, glyph->cx); /* cx (2 bytes) */
2542                 Stream_Write_UINT16(s, glyph->cy); /* cy (2 bytes) */
2543                 cb = ((glyph->cx + 7) / 8) * glyph->cy;
2544                 cb += ((cb % 4) > 0) ? 4 - (cb % 4) : 0;
2545                 Stream_Write(s, glyph->aj, cb);
2546         }
2547
2548         if (*flags & CG_GLYPH_UNICODE_PRESENT)
2549         {
2550                 Stream_Zero(s, cache_glyph->cGlyphs * 2);
2551         }
2552
2553         return TRUE;
2554 }
2555 static CACHE_GLYPH_V2_ORDER* update_read_cache_glyph_v2_order(rdpUpdate* update, wStream* s,
2556                                                               UINT16 flags)
2557 {
2558         UINT32 i;
2559         CACHE_GLYPH_V2_ORDER* cache_glyph_v2 = calloc(1, sizeof(CACHE_GLYPH_V2_ORDER));
2560
2561         if (!cache_glyph_v2)
2562                 goto fail;
2563
2564         cache_glyph_v2->cacheId = (flags & 0x000F);
2565         cache_glyph_v2->flags = (flags & 0x00F0) >> 4;
2566         cache_glyph_v2->cGlyphs = (flags & 0xFF00) >> 8;
2567
2568         for (i = 0; i < cache_glyph_v2->cGlyphs; i++)
2569         {
2570                 GLYPH_DATA_V2* glyph = &cache_glyph_v2->glyphData[i];
2571
2572                 if (Stream_GetRemainingLength(s) < 1)
2573                         goto fail;
2574
2575                 Stream_Read_UINT8(s, glyph->cacheIndex);
2576
2577                 if (!update_read_2byte_signed(s, &glyph->x) || !update_read_2byte_signed(s, &glyph->y) ||
2578                     !update_read_2byte_unsigned(s, &glyph->cx) ||
2579                     !update_read_2byte_unsigned(s, &glyph->cy))
2580                 {
2581                         goto fail;
2582                 }
2583
2584                 glyph->cb = ((glyph->cx + 7) / 8) * glyph->cy;
2585                 glyph->cb += ((glyph->cb % 4) > 0) ? 4 - (glyph->cb % 4) : 0;
2586
2587                 if (Stream_GetRemainingLength(s) < glyph->cb)
2588                         goto fail;
2589
2590                 glyph->aj = (BYTE*)malloc(glyph->cb);
2591
2592                 if (!glyph->aj)
2593                         goto fail;
2594
2595                 Stream_Read(s, glyph->aj, glyph->cb);
2596         }
2597
2598         if ((flags & CG_GLYPH_UNICODE_PRESENT) && (cache_glyph_v2->cGlyphs > 0))
2599         {
2600                 cache_glyph_v2->unicodeCharacters = calloc(cache_glyph_v2->cGlyphs, sizeof(WCHAR));
2601
2602                 if (!cache_glyph_v2->unicodeCharacters)
2603                         goto fail;
2604
2605                 if (Stream_GetRemainingLength(s) < sizeof(WCHAR) * cache_glyph_v2->cGlyphs)
2606                         goto fail;
2607
2608                 Stream_Read_UTF16_String(s, cache_glyph_v2->unicodeCharacters, cache_glyph_v2->cGlyphs);
2609         }
2610
2611         return cache_glyph_v2;
2612 fail:
2613         free_cache_glyph_v2_order(update->context, cache_glyph_v2);
2614         return NULL;
2615 }
2616 int update_approximate_cache_glyph_v2_order(const CACHE_GLYPH_V2_ORDER* cache_glyph_v2,
2617                                             UINT16* flags)
2618 {
2619         return 8 + cache_glyph_v2->cGlyphs * 32;
2620 }
2621 BOOL update_write_cache_glyph_v2_order(wStream* s, const CACHE_GLYPH_V2_ORDER* cache_glyph_v2,
2622                                        UINT16* flags)
2623 {
2624         UINT32 i, inf;
2625         inf = update_approximate_cache_glyph_v2_order(cache_glyph_v2, flags);
2626
2627         if (!Stream_EnsureRemainingCapacity(s, inf))
2628                 return FALSE;
2629
2630         *flags = (cache_glyph_v2->cacheId & 0x000F) | ((cache_glyph_v2->flags & 0x000F) << 4) |
2631                  ((cache_glyph_v2->cGlyphs & 0x00FF) << 8);
2632
2633         for (i = 0; i < cache_glyph_v2->cGlyphs; i++)
2634         {
2635                 UINT32 cb;
2636                 const GLYPH_DATA_V2* glyph = &cache_glyph_v2->glyphData[i];
2637                 Stream_Write_UINT8(s, glyph->cacheIndex);
2638
2639                 if (!update_write_2byte_signed(s, glyph->x) || !update_write_2byte_signed(s, glyph->y) ||
2640                     !update_write_2byte_unsigned(s, glyph->cx) ||
2641                     !update_write_2byte_unsigned(s, glyph->cy))
2642                 {
2643                         return FALSE;
2644                 }
2645
2646                 cb = ((glyph->cx + 7) / 8) * glyph->cy;
2647                 cb += ((cb % 4) > 0) ? 4 - (cb % 4) : 0;
2648                 Stream_Write(s, glyph->aj, cb);
2649         }
2650
2651         if (*flags & CG_GLYPH_UNICODE_PRESENT)
2652         {
2653                 Stream_Zero(s, cache_glyph_v2->cGlyphs * 2);
2654         }
2655
2656         return TRUE;
2657 }
2658 static BOOL update_decompress_brush(wStream* s, BYTE* output, size_t outSize, BYTE bpp)
2659 {
2660         size_t x, k;
2661         INT8 y;
2662         BYTE byte = 0;
2663         const BYTE* palette = Stream_Pointer(s) + 16;
2664         const size_t bytesPerPixel = ((bpp + 1) / 8);
2665
2666         if (Stream_GetRemainingLength(s) < 16 + bytesPerPixel * 4)
2667                 return FALSE;
2668
2669         for (y = 7; y >= 0; y--)
2670         {
2671                 for (x = 0; x < 8; x++)
2672                 {
2673                         UINT32 index;
2674                         if ((x % 4) == 0)
2675                                 Stream_Read_UINT8(s, byte);
2676
2677                         index = ((byte >> ((3 - (x % 4)) * 2)) & 0x03);
2678
2679                         for (k = 0; k < bytesPerPixel; k++)
2680                         {
2681                                 const size_t dstIndex = ((y * 8 + x) * bytesPerPixel) + k;
2682                                 const size_t srcIndex = (index * bytesPerPixel) + k;
2683                                 if (dstIndex >= outSize)
2684                                         return FALSE;
2685                                 output[dstIndex] = palette[srcIndex];
2686                         }
2687                 }
2688         }
2689
2690         return TRUE;
2691 }
2692 static BOOL update_compress_brush(wStream* s, const BYTE* input, BYTE bpp)
2693 {
2694         return FALSE;
2695 }
2696 static CACHE_BRUSH_ORDER* update_read_cache_brush_order(rdpUpdate* update, wStream* s, UINT16 flags)
2697 {
2698         int i;
2699         BOOL rc;
2700         BYTE iBitmapFormat;
2701         BOOL compressed = FALSE;
2702         CACHE_BRUSH_ORDER* cache_brush = calloc(1, sizeof(CACHE_BRUSH_ORDER));
2703
2704         if (!cache_brush)
2705                 goto fail;
2706
2707         if (Stream_GetRemainingLength(s) < 6)
2708                 goto fail;
2709
2710         Stream_Read_UINT8(s, cache_brush->index); /* cacheEntry (1 byte) */
2711         Stream_Read_UINT8(s, iBitmapFormat);      /* iBitmapFormat (1 byte) */
2712
2713         cache_brush->bpp = get_bmf_bpp(iBitmapFormat, &rc);
2714         if (!rc)
2715                 goto fail;
2716
2717         Stream_Read_UINT8(s, cache_brush->cx);     /* cx (1 byte) */
2718         Stream_Read_UINT8(s, cache_brush->cy);     /* cy (1 byte) */
2719         /* according to  Section 2.2.2.2.1.2.7 errata the windows implementation sets this filed is set
2720          * to 0x00 */
2721         Stream_Read_UINT8(s, cache_brush->style);  /* style (1 byte) */
2722         Stream_Read_UINT8(s, cache_brush->length); /* iBytes (1 byte) */
2723
2724         if ((cache_brush->cx == 8) && (cache_brush->cy == 8))
2725         {
2726                 if (cache_brush->bpp == 1)
2727                 {
2728                         if (cache_brush->length != 8)
2729                         {
2730                                 WLog_Print(update->log, WLOG_ERROR, "incompatible 1bpp brush of length:%" PRIu32 "",
2731                                            cache_brush->length);
2732                                 goto fail;
2733                         }
2734
2735                         if (Stream_GetRemainingLength(s) < 8)
2736                                 goto fail;
2737
2738                         /* rows are encoded in reverse order */
2739                         for (i = 7; i >= 0; i--)
2740                                 Stream_Read_UINT8(s, cache_brush->data[i]);
2741                 }
2742                 else
2743                 {
2744                         if ((iBitmapFormat == BMF_8BPP) && (cache_brush->length == 20))
2745                                 compressed = TRUE;
2746                         else if ((iBitmapFormat == BMF_16BPP) && (cache_brush->length == 24))
2747                                 compressed = TRUE;
2748                         else if ((iBitmapFormat == BMF_24BPP) && (cache_brush->length == 28))
2749                                 compressed = TRUE;
2750                         else if ((iBitmapFormat == BMF_32BPP) && (cache_brush->length == 32))
2751                                 compressed = TRUE;
2752
2753                         if (compressed != FALSE)
2754                         {
2755                                 /* compressed brush */
2756                                 if (!update_decompress_brush(s, cache_brush->data, sizeof(cache_brush->data),
2757                                                              cache_brush->bpp))
2758                                         goto fail;
2759                         }
2760                         else
2761                         {
2762                                 /* uncompressed brush */
2763                                 UINT32 scanline = (cache_brush->bpp / 8) * 8;
2764
2765                                 if (Stream_GetRemainingLength(s) < scanline * 8)
2766                                         goto fail;
2767
2768                                 for (i = 7; i >= 0; i--)
2769                                 {
2770                                         Stream_Read(s, &cache_brush->data[i * scanline], scanline);
2771                                 }
2772                         }
2773                 }
2774         }
2775
2776         return cache_brush;
2777 fail:
2778         free_cache_brush_order(update->context, cache_brush);
2779         return NULL;
2780 }
2781 int update_approximate_cache_brush_order(const CACHE_BRUSH_ORDER* cache_brush, UINT16* flags)
2782 {
2783         return 64;
2784 }
2785 BOOL update_write_cache_brush_order(wStream* s, const CACHE_BRUSH_ORDER* cache_brush, UINT16* flags)
2786 {
2787         int i;
2788         BYTE iBitmapFormat;
2789         BOOL rc;
2790         BOOL compressed = FALSE;
2791
2792         if (!Stream_EnsureRemainingCapacity(s,
2793                                             update_approximate_cache_brush_order(cache_brush, flags)))
2794                 return FALSE;
2795
2796         iBitmapFormat = get_bpp_bmf(cache_brush->bpp, &rc);
2797         if (!rc)
2798                 return FALSE;
2799         Stream_Write_UINT8(s, cache_brush->index);  /* cacheEntry (1 byte) */
2800         Stream_Write_UINT8(s, iBitmapFormat);       /* iBitmapFormat (1 byte) */
2801         Stream_Write_UINT8(s, cache_brush->cx);     /* cx (1 byte) */
2802         Stream_Write_UINT8(s, cache_brush->cy);     /* cy (1 byte) */
2803         Stream_Write_UINT8(s, cache_brush->style);  /* style (1 byte) */
2804         Stream_Write_UINT8(s, cache_brush->length); /* iBytes (1 byte) */
2805
2806         if ((cache_brush->cx == 8) && (cache_brush->cy == 8))
2807         {
2808                 if (cache_brush->bpp == 1)
2809                 {
2810                         if (cache_brush->length != 8)
2811                         {
2812                                 WLog_ERR(TAG, "incompatible 1bpp brush of length:%" PRIu32 "", cache_brush->length);
2813                                 return FALSE;
2814                         }
2815
2816                         for (i = 7; i >= 0; i--)
2817                         {
2818                                 Stream_Write_UINT8(s, cache_brush->data[i]);
2819                         }
2820                 }
2821                 else
2822                 {
2823                         if ((iBitmapFormat == BMF_8BPP) && (cache_brush->length == 20))
2824                                 compressed = TRUE;
2825                         else if ((iBitmapFormat == BMF_16BPP) && (cache_brush->length == 24))
2826                                 compressed = TRUE;
2827                         else if ((iBitmapFormat == BMF_32BPP) && (cache_brush->length == 32))
2828                                 compressed = TRUE;
2829
2830                         if (compressed != FALSE)
2831                         {
2832                                 /* compressed brush */
2833                                 if (!update_compress_brush(s, cache_brush->data, cache_brush->bpp))
2834                                         return FALSE;
2835                         }
2836                         else
2837                         {
2838                                 /* uncompressed brush */
2839                                 int scanline = (cache_brush->bpp / 8) * 8;
2840
2841                                 for (i = 7; i >= 0; i--)
2842                                 {
2843                                         Stream_Write(s, &cache_brush->data[i * scanline], scanline);
2844                                 }
2845                         }
2846                 }
2847         }
2848
2849         return TRUE;
2850 }
2851 /* Alternate Secondary Drawing Orders */
2852 static BOOL
2853 update_read_create_offscreen_bitmap_order(wStream* s,
2854                                           CREATE_OFFSCREEN_BITMAP_ORDER* create_offscreen_bitmap)
2855 {
2856         UINT16 flags;
2857         BOOL deleteListPresent;
2858         OFFSCREEN_DELETE_LIST* deleteList;
2859
2860         if (Stream_GetRemainingLength(s) < 6)
2861                 return FALSE;
2862
2863         Stream_Read_UINT16(s, flags); /* flags (2 bytes) */
2864         create_offscreen_bitmap->id = flags & 0x7FFF;
2865         deleteListPresent = (flags & 0x8000) ? TRUE : FALSE;
2866         Stream_Read_UINT16(s, create_offscreen_bitmap->cx); /* cx (2 bytes) */
2867         Stream_Read_UINT16(s, create_offscreen_bitmap->cy); /* cy (2 bytes) */
2868         deleteList = &(create_offscreen_bitmap->deleteList);
2869
2870         if (deleteListPresent)
2871         {
2872                 UINT32 i;
2873
2874                 if (Stream_GetRemainingLength(s) < 2)
2875                         return FALSE;
2876
2877                 Stream_Read_UINT16(s, deleteList->cIndices);
2878
2879                 if (deleteList->cIndices > deleteList->sIndices)
2880                 {
2881                         UINT16* new_indices;
2882                         new_indices = (UINT16*)realloc(deleteList->indices, deleteList->cIndices * 2);
2883
2884                         if (!new_indices)
2885                                 return FALSE;
2886
2887                         deleteList->sIndices = deleteList->cIndices;
2888                         deleteList->indices = new_indices;
2889                 }
2890
2891                 if (Stream_GetRemainingLength(s) < 2 * deleteList->cIndices)
2892                         return FALSE;
2893
2894                 for (i = 0; i < deleteList->cIndices; i++)
2895                 {
2896                         Stream_Read_UINT16(s, deleteList->indices[i]);
2897                 }
2898         }
2899         else
2900         {
2901                 deleteList->cIndices = 0;
2902         }
2903
2904         return TRUE;
2905 }
2906 int update_approximate_create_offscreen_bitmap_order(
2907     const CREATE_OFFSCREEN_BITMAP_ORDER* create_offscreen_bitmap)
2908 {
2909         const OFFSCREEN_DELETE_LIST* deleteList = &(create_offscreen_bitmap->deleteList);
2910         return 32 + deleteList->cIndices * 2;
2911 }
2912 BOOL update_write_create_offscreen_bitmap_order(
2913     wStream* s, const CREATE_OFFSCREEN_BITMAP_ORDER* create_offscreen_bitmap)
2914 {
2915         UINT16 flags;
2916         BOOL deleteListPresent;
2917         const OFFSCREEN_DELETE_LIST* deleteList;
2918
2919         if (!Stream_EnsureRemainingCapacity(
2920                 s, update_approximate_create_offscreen_bitmap_order(create_offscreen_bitmap)))
2921                 return FALSE;
2922
2923         deleteList = &(create_offscreen_bitmap->deleteList);
2924         flags = create_offscreen_bitmap->id & 0x7FFF;
2925         deleteListPresent = (deleteList->cIndices > 0) ? TRUE : FALSE;
2926
2927         if (deleteListPresent)
2928                 flags |= 0x8000;
2929
2930         Stream_Write_UINT16(s, flags);                       /* flags (2 bytes) */
2931         Stream_Write_UINT16(s, create_offscreen_bitmap->cx); /* cx (2 bytes) */
2932         Stream_Write_UINT16(s, create_offscreen_bitmap->cy); /* cy (2 bytes) */
2933
2934         if (deleteListPresent)
2935         {
2936                 int i;
2937                 Stream_Write_UINT16(s, deleteList->cIndices);
2938
2939                 for (i = 0; i < (int)deleteList->cIndices; i++)
2940                 {
2941                         Stream_Write_UINT16(s, deleteList->indices[i]);
2942                 }
2943         }
2944
2945         return TRUE;
2946 }
2947 static BOOL update_read_switch_surface_order(wStream* s, SWITCH_SURFACE_ORDER* switch_surface)
2948 {
2949         if (Stream_GetRemainingLength(s) < 2)
2950                 return FALSE;
2951
2952         Stream_Read_UINT16(s, switch_surface->bitmapId); /* bitmapId (2 bytes) */
2953         return TRUE;
2954 }
2955 int update_approximate_switch_surface_order(const SWITCH_SURFACE_ORDER* switch_surface)
2956 {
2957         return 2;
2958 }
2959 BOOL update_write_switch_surface_order(wStream* s, const SWITCH_SURFACE_ORDER* switch_surface)
2960 {
2961         int inf = update_approximate_switch_surface_order(switch_surface);
2962
2963         if (!Stream_EnsureRemainingCapacity(s, inf))
2964                 return FALSE;
2965
2966         Stream_Write_UINT16(s, switch_surface->bitmapId); /* bitmapId (2 bytes) */
2967         return TRUE;
2968 }
2969 static BOOL
2970 update_read_create_nine_grid_bitmap_order(wStream* s,
2971                                           CREATE_NINE_GRID_BITMAP_ORDER* create_nine_grid_bitmap)
2972 {
2973         NINE_GRID_BITMAP_INFO* nineGridInfo;
2974
2975         if (Stream_GetRemainingLength(s) < 19)
2976                 return FALSE;
2977
2978         Stream_Read_UINT8(s, create_nine_grid_bitmap->bitmapBpp); /* bitmapBpp (1 byte) */
2979
2980         if ((create_nine_grid_bitmap->bitmapBpp < 1) || (create_nine_grid_bitmap->bitmapBpp > 32))
2981         {
2982                 WLog_ERR(TAG, "invalid bpp value %" PRIu32 "", create_nine_grid_bitmap->bitmapBpp);
2983                 return FALSE;
2984         }
2985
2986         Stream_Read_UINT16(s, create_nine_grid_bitmap->bitmapId); /* bitmapId (2 bytes) */
2987         nineGridInfo = &(create_nine_grid_bitmap->nineGridInfo);
2988         Stream_Read_UINT32(s, nineGridInfo->flFlags);          /* flFlags (4 bytes) */
2989         Stream_Read_UINT16(s, nineGridInfo->ulLeftWidth);      /* ulLeftWidth (2 bytes) */
2990         Stream_Read_UINT16(s, nineGridInfo->ulRightWidth);     /* ulRightWidth (2 bytes) */
2991         Stream_Read_UINT16(s, nineGridInfo->ulTopHeight);      /* ulTopHeight (2 bytes) */
2992         Stream_Read_UINT16(s, nineGridInfo->ulBottomHeight);   /* ulBottomHeight (2 bytes) */
2993         update_read_colorref(s, &nineGridInfo->crTransparent); /* crTransparent (4 bytes) */
2994         return TRUE;
2995 }
2996 static BOOL update_read_frame_marker_order(wStream* s, FRAME_MARKER_ORDER* frame_marker)
2997 {
2998         if (Stream_GetRemainingLength(s) < 4)
2999                 return FALSE;
3000
3001         Stream_Read_UINT32(s, frame_marker->action); /* action (4 bytes) */
3002         return TRUE;
3003 }
3004 static BOOL update_read_stream_bitmap_first_order(wStream* s,
3005                                                   STREAM_BITMAP_FIRST_ORDER* stream_bitmap_first)
3006 {
3007         if (Stream_GetRemainingLength(s) < 10) // 8 + 2 at least
3008                 return FALSE;
3009
3010         Stream_Read_UINT8(s, stream_bitmap_first->bitmapFlags); /* bitmapFlags (1 byte) */
3011         Stream_Read_UINT8(s, stream_bitmap_first->bitmapBpp);   /* bitmapBpp (1 byte) */
3012
3013         if ((stream_bitmap_first->bitmapBpp < 1) || (stream_bitmap_first->bitmapBpp > 32))
3014         {
3015                 WLog_ERR(TAG, "invalid bpp value %" PRIu32 "", stream_bitmap_first->bitmapBpp);
3016                 return FALSE;
3017         }
3018
3019         Stream_Read_UINT16(s, stream_bitmap_first->bitmapType);   /* bitmapType (2 bytes) */
3020         Stream_Read_UINT16(s, stream_bitmap_first->bitmapWidth);  /* bitmapWidth (2 bytes) */
3021         Stream_Read_UINT16(s, stream_bitmap_first->bitmapHeight); /* bitmapHeigth (2 bytes) */
3022
3023         if (stream_bitmap_first->bitmapFlags & STREAM_BITMAP_V2)
3024         {
3025                 if (Stream_GetRemainingLength(s) < 4)
3026                         return FALSE;
3027
3028                 Stream_Read_UINT32(s, stream_bitmap_first->bitmapSize); /* bitmapSize (4 bytes) */
3029         }
3030         else
3031         {
3032                 if (Stream_GetRemainingLength(s) < 2)
3033                         return FALSE;
3034
3035                 Stream_Read_UINT16(s, stream_bitmap_first->bitmapSize); /* bitmapSize (2 bytes) */
3036         }
3037
3038         FIELD_SKIP_BUFFER16(
3039             s, stream_bitmap_first->bitmapBlockSize); /* bitmapBlockSize(2 bytes) + bitmapBlock */
3040         return TRUE;
3041 }
3042 static BOOL update_read_stream_bitmap_next_order(wStream* s,
3043                                                  STREAM_BITMAP_NEXT_ORDER* stream_bitmap_next)
3044 {
3045         if (Stream_GetRemainingLength(s) < 5)
3046                 return FALSE;
3047
3048         Stream_Read_UINT8(s, stream_bitmap_next->bitmapFlags); /* bitmapFlags (1 byte) */
3049         Stream_Read_UINT16(s, stream_bitmap_next->bitmapType); /* bitmapType (2 bytes) */
3050         FIELD_SKIP_BUFFER16(
3051             s, stream_bitmap_next->bitmapBlockSize); /* bitmapBlockSize(2 bytes) + bitmapBlock */
3052         return TRUE;
3053 }
3054 static BOOL update_read_draw_gdiplus_first_order(wStream* s,
3055                                                  DRAW_GDIPLUS_FIRST_ORDER* draw_gdiplus_first)
3056 {
3057         if (Stream_GetRemainingLength(s) < 11)
3058                 return FALSE;
3059
3060         Stream_Seek_UINT8(s);                                      /* pad1Octet (1 byte) */
3061         Stream_Read_UINT16(s, draw_gdiplus_first->cbSize);         /* cbSize (2 bytes) */
3062         Stream_Read_UINT32(s, draw_gdiplus_first->cbTotalSize);    /* cbTotalSize (4 bytes) */
3063         Stream_Read_UINT32(s, draw_gdiplus_first->cbTotalEmfSize); /* cbTotalEmfSize (4 bytes) */
3064         return Stream_SafeSeek(s, draw_gdiplus_first->cbSize);     /* emfRecords */
3065 }
3066 static BOOL update_read_draw_gdiplus_next_order(wStream* s,
3067                                                 DRAW_GDIPLUS_NEXT_ORDER* draw_gdiplus_next)
3068 {
3069         if (Stream_GetRemainingLength(s) < 3)
3070                 return FALSE;
3071
3072         Stream_Seek_UINT8(s);                              /* pad1Octet (1 byte) */
3073         FIELD_SKIP_BUFFER16(s, draw_gdiplus_next->cbSize); /* cbSize(2 bytes) + emfRecords */
3074         return TRUE;
3075 }
3076 static BOOL update_read_draw_gdiplus_end_order(wStream* s, DRAW_GDIPLUS_END_ORDER* draw_gdiplus_end)
3077 {
3078         if (Stream_GetRemainingLength(s) < 11)
3079                 return FALSE;
3080
3081         Stream_Seek_UINT8(s);                                    /* pad1Octet (1 byte) */
3082         Stream_Read_UINT16(s, draw_gdiplus_end->cbSize);         /* cbSize (2 bytes) */
3083         Stream_Read_UINT32(s, draw_gdiplus_end->cbTotalSize);    /* cbTotalSize (4 bytes) */
3084         Stream_Read_UINT32(s, draw_gdiplus_end->cbTotalEmfSize); /* cbTotalEmfSize (4 bytes) */
3085         return Stream_SafeSeek(s, draw_gdiplus_end->cbSize);     /* emfRecords */
3086 }
3087 static BOOL
3088 update_read_draw_gdiplus_cache_first_order(wStream* s,
3089                                            DRAW_GDIPLUS_CACHE_FIRST_ORDER* draw_gdiplus_cache_first)
3090 {
3091         if (Stream_GetRemainingLength(s) < 11)
3092                 return FALSE;
3093
3094         Stream_Read_UINT8(s, draw_gdiplus_cache_first->flags);        /* flags (1 byte) */
3095         Stream_Read_UINT16(s, draw_gdiplus_cache_first->cacheType);   /* cacheType (2 bytes) */
3096         Stream_Read_UINT16(s, draw_gdiplus_cache_first->cacheIndex);  /* cacheIndex (2 bytes) */
3097         Stream_Read_UINT16(s, draw_gdiplus_cache_first->cbSize);      /* cbSize (2 bytes) */
3098         Stream_Read_UINT32(s, draw_gdiplus_cache_first->cbTotalSize); /* cbTotalSize (4 bytes) */
3099         return Stream_SafeSeek(s, draw_gdiplus_cache_first->cbSize);  /* emfRecords */
3100 }
3101 static BOOL
3102 update_read_draw_gdiplus_cache_next_order(wStream* s,
3103                                           DRAW_GDIPLUS_CACHE_NEXT_ORDER* draw_gdiplus_cache_next)
3104 {
3105         if (Stream_GetRemainingLength(s) < 7)
3106                 return FALSE;
3107
3108         Stream_Read_UINT8(s, draw_gdiplus_cache_next->flags);       /* flags (1 byte) */
3109         Stream_Read_UINT16(s, draw_gdiplus_cache_next->cacheType);  /* cacheType (2 bytes) */
3110         Stream_Read_UINT16(s, draw_gdiplus_cache_next->cacheIndex); /* cacheIndex (2 bytes) */
3111         FIELD_SKIP_BUFFER16(s, draw_gdiplus_cache_next->cbSize);    /* cbSize(2 bytes) + emfRecords */
3112         return TRUE;
3113 }
3114 static BOOL
3115 update_read_draw_gdiplus_cache_end_order(wStream* s,
3116                                          DRAW_GDIPLUS_CACHE_END_ORDER* draw_gdiplus_cache_end)
3117 {
3118         if (Stream_GetRemainingLength(s) < 11)
3119                 return FALSE;
3120
3121         Stream_Read_UINT8(s, draw_gdiplus_cache_end->flags);        /* flags (1 byte) */
3122         Stream_Read_UINT16(s, draw_gdiplus_cache_end->cacheType);   /* cacheType (2 bytes) */
3123         Stream_Read_UINT16(s, draw_gdiplus_cache_end->cacheIndex);  /* cacheIndex (2 bytes) */
3124         Stream_Read_UINT16(s, draw_gdiplus_cache_end->cbSize);      /* cbSize (2 bytes) */
3125         Stream_Read_UINT32(s, draw_gdiplus_cache_end->cbTotalSize); /* cbTotalSize (4 bytes) */
3126         return Stream_SafeSeek(s, draw_gdiplus_cache_end->cbSize);  /* emfRecords */
3127 }
3128 static BOOL update_read_field_flags(wStream* s, UINT32* fieldFlags, BYTE flags, BYTE fieldBytes)
3129 {
3130         int i;
3131         BYTE byte;
3132
3133         if (flags & ORDER_ZERO_FIELD_BYTE_BIT0)
3134                 fieldBytes--;
3135
3136         if (flags & ORDER_ZERO_FIELD_BYTE_BIT1)
3137         {
3138                 if (fieldBytes > 1)
3139                         fieldBytes -= 2;
3140                 else
3141                         fieldBytes = 0;
3142         }
3143
3144         if (Stream_GetRemainingLength(s) < fieldBytes)
3145                 return FALSE;
3146
3147         *fieldFlags = 0;
3148
3149         for (i = 0; i < fieldBytes; i++)
3150         {
3151                 Stream_Read_UINT8(s, byte);
3152                 *fieldFlags |= byte << (i * 8);
3153         }
3154
3155         return TRUE;
3156 }
3157 BOOL update_write_field_flags(wStream* s, UINT32 fieldFlags, BYTE flags, BYTE fieldBytes)
3158 {
3159         BYTE byte;
3160
3161         if (fieldBytes == 1)
3162         {
3163                 byte = fieldFlags & 0xFF;
3164                 Stream_Write_UINT8(s, byte);
3165         }
3166         else if (fieldBytes == 2)
3167         {
3168                 byte = fieldFlags & 0xFF;
3169                 Stream_Write_UINT8(s, byte);
3170                 byte = (fieldFlags >> 8) & 0xFF;
3171                 Stream_Write_UINT8(s, byte);
3172         }
3173         else if (fieldBytes == 3)
3174         {
3175                 byte = fieldFlags & 0xFF;
3176                 Stream_Write_UINT8(s, byte);
3177                 byte = (fieldFlags >> 8) & 0xFF;
3178                 Stream_Write_UINT8(s, byte);
3179                 byte = (fieldFlags >> 16) & 0xFF;
3180                 Stream_Write_UINT8(s, byte);
3181         }
3182         else
3183         {
3184                 return FALSE;
3185         }
3186
3187         return TRUE;
3188 }
3189 static BOOL update_read_bounds(wStream* s, rdpBounds* bounds)
3190 {
3191         BYTE flags;
3192
3193         if (Stream_GetRemainingLength(s) < 1)
3194                 return FALSE;
3195
3196         Stream_Read_UINT8(s, flags); /* field flags */
3197
3198         if (flags & BOUND_LEFT)
3199         {
3200                 if (!update_read_coord(s, &bounds->left, FALSE))
3201                         return FALSE;
3202         }
3203         else if (flags & BOUND_DELTA_LEFT)
3204         {
3205                 if (!update_read_coord(s, &bounds->left, TRUE))
3206                         return FALSE;
3207         }
3208
3209         if (flags & BOUND_TOP)
3210         {
3211                 if (!update_read_coord(s, &bounds->top, FALSE))
3212                         return FALSE;
3213         }
3214         else if (flags & BOUND_DELTA_TOP)
3215         {
3216                 if (!update_read_coord(s, &bounds->top, TRUE))
3217                         return FALSE;
3218         }
3219
3220         if (flags & BOUND_RIGHT)
3221         {
3222                 if (!update_read_coord(s, &bounds->right, FALSE))
3223                         return FALSE;
3224         }
3225         else if (flags & BOUND_DELTA_RIGHT)
3226         {
3227                 if (!update_read_coord(s, &bounds->right, TRUE))
3228                         return FALSE;
3229         }
3230
3231         if (flags & BOUND_BOTTOM)
3232         {
3233                 if (!update_read_coord(s, &bounds->bottom, FALSE))
3234                         return FALSE;
3235         }
3236         else if (flags & BOUND_DELTA_BOTTOM)
3237         {
3238                 if (!update_read_coord(s, &bounds->bottom, TRUE))
3239                         return FALSE;
3240         }
3241
3242         return TRUE;
3243 }
3244 BOOL update_write_bounds(wStream* s, ORDER_INFO* orderInfo)
3245 {
3246         if (!(orderInfo->controlFlags & ORDER_BOUNDS))
3247                 return TRUE;
3248
3249         if (orderInfo->controlFlags & ORDER_ZERO_BOUNDS_DELTAS)
3250                 return TRUE;
3251
3252         Stream_Write_UINT8(s, orderInfo->boundsFlags); /* field flags */
3253
3254         if (orderInfo->boundsFlags & BOUND_LEFT)
3255         {
3256                 if (!update_write_coord(s, orderInfo->bounds.left))
3257                         return FALSE;
3258         }
3259         else if (orderInfo->boundsFlags & BOUND_DELTA_LEFT)
3260         {
3261         }
3262
3263         if (orderInfo->boundsFlags & BOUND_TOP)
3264         {
3265                 if (!update_write_coord(s, orderInfo->bounds.top))
3266                         return FALSE;
3267         }
3268         else if (orderInfo->boundsFlags & BOUND_DELTA_TOP)
3269         {
3270         }
3271
3272         if (orderInfo->boundsFlags & BOUND_RIGHT)
3273         {
3274                 if (!update_write_coord(s, orderInfo->bounds.right))
3275                         return FALSE;
3276         }
3277         else if (orderInfo->boundsFlags & BOUND_DELTA_RIGHT)
3278         {
3279         }
3280
3281         if (orderInfo->boundsFlags & BOUND_BOTTOM)
3282         {
3283                 if (!update_write_coord(s, orderInfo->bounds.bottom))
3284                         return FALSE;
3285         }
3286         else if (orderInfo->boundsFlags & BOUND_DELTA_BOTTOM)
3287         {
3288         }
3289
3290         return TRUE;
3291 }
3292
3293 static BOOL read_primary_order(wLog* log, const char* orderName, wStream* s,
3294                                const ORDER_INFO* orderInfo, rdpPrimaryUpdate* primary)
3295 {
3296         BOOL rc = FALSE;
3297
3298         if (!s || !orderInfo || !primary || !orderName)
3299                 return FALSE;
3300
3301         switch (orderInfo->orderType)
3302         {
3303                 case ORDER_TYPE_DSTBLT:
3304                         rc = update_read_dstblt_order(s, orderInfo, &(primary->dstblt));
3305                         break;
3306
3307                 case ORDER_TYPE_PATBLT:
3308                         rc = update_read_patblt_order(s, orderInfo, &(primary->patblt));
3309                         break;
3310
3311                 case ORDER_TYPE_SCRBLT:
3312                         rc = update_read_scrblt_order(s, orderInfo, &(primary->scrblt));
3313                         break;
3314
3315                 case ORDER_TYPE_OPAQUE_RECT:
3316                         rc = update_read_opaque_rect_order(s, orderInfo, &(primary->opaque_rect));
3317                         break;
3318
3319                 case ORDER_TYPE_DRAW_NINE_GRID:
3320                         rc = update_read_draw_nine_grid_order(s, orderInfo, &(primary->draw_nine_grid));
3321                         break;
3322
3323                 case ORDER_TYPE_MULTI_DSTBLT:
3324                         rc = update_read_multi_dstblt_order(s, orderInfo, &(primary->multi_dstblt));
3325                         break;
3326
3327                 case ORDER_TYPE_MULTI_PATBLT:
3328                         rc = update_read_multi_patblt_order(s, orderInfo, &(primary->multi_patblt));
3329                         break;
3330
3331                 case ORDER_TYPE_MULTI_SCRBLT:
3332                         rc = update_read_multi_scrblt_order(s, orderInfo, &(primary->multi_scrblt));
3333                         break;
3334
3335                 case ORDER_TYPE_MULTI_OPAQUE_RECT:
3336                         rc = update_read_multi_opaque_rect_order(s, orderInfo, &(primary->multi_opaque_rect));
3337                         break;
3338
3339                 case ORDER_TYPE_MULTI_DRAW_NINE_GRID:
3340                         rc = update_read_multi_draw_nine_grid_order(s, orderInfo,
3341                                                                     &(primary->multi_draw_nine_grid));
3342                         break;
3343
3344                 case ORDER_TYPE_LINE_TO:
3345                         rc = update_read_line_to_order(s, orderInfo, &(primary->line_to));
3346                         break;
3347
3348                 case ORDER_TYPE_POLYLINE:
3349                         rc = update_read_polyline_order(s, orderInfo, &(primary->polyline));
3350                         break;
3351
3352                 case ORDER_TYPE_MEMBLT:
3353                         rc = update_read_memblt_order(s, orderInfo, &(primary->memblt));
3354                         break;
3355
3356                 case ORDER_TYPE_MEM3BLT:
3357                         rc = update_read_mem3blt_order(s, orderInfo, &(primary->mem3blt));
3358                         break;
3359
3360                 case ORDER_TYPE_SAVE_BITMAP:
3361                         rc = update_read_save_bitmap_order(s, orderInfo, &(primary->save_bitmap));
3362                         break;
3363
3364                 case ORDER_TYPE_GLYPH_INDEX:
3365                         rc = update_read_glyph_index_order(s, orderInfo, &(primary->glyph_index));
3366                         break;
3367
3368                 case ORDER_TYPE_FAST_INDEX:
3369                         rc = update_read_fast_index_order(s, orderInfo, &(primary->fast_index));
3370                         break;
3371
3372                 case ORDER_TYPE_FAST_GLYPH:
3373                         rc = update_read_fast_glyph_order(s, orderInfo, &(primary->fast_glyph));
3374                         break;
3375
3376                 case ORDER_TYPE_POLYGON_SC:
3377                         rc = update_read_polygon_sc_order(s, orderInfo, &(primary->polygon_sc));
3378                         break;
3379
3380                 case ORDER_TYPE_POLYGON_CB:
3381                         rc = update_read_polygon_cb_order(s, orderInfo, &(primary->polygon_cb));
3382                         break;
3383
3384                 case ORDER_TYPE_ELLIPSE_SC:
3385                         rc = update_read_ellipse_sc_order(s, orderInfo, &(primary->ellipse_sc));
3386                         break;
3387
3388                 case ORDER_TYPE_ELLIPSE_CB:
3389                         rc = update_read_ellipse_cb_order(s, orderInfo, &(primary->ellipse_cb));
3390                         break;
3391
3392                 default:
3393                         WLog_Print(log, WLOG_WARN, "Primary Drawing Order %s not supported, ignoring",
3394                                    orderName);
3395                         rc = TRUE;
3396                         break;
3397         }
3398
3399         if (!rc)
3400         {
3401                 WLog_Print(log, WLOG_ERROR, "%s - update_read_dstblt_order() failed", orderName);
3402                 return FALSE;
3403         }
3404
3405         return TRUE;
3406 }
3407
3408 static BOOL update_recv_primary_order(rdpUpdate* update, wStream* s, BYTE flags)
3409 {
3410         BYTE field;
3411         BOOL rc = FALSE;
3412         rdpContext* context = update->context;
3413         rdpPrimaryUpdate* primary = update->primary;
3414         ORDER_INFO* orderInfo = &(primary->order_info);
3415         rdpSettings* settings = context->settings;
3416         const char* orderName;
3417
3418         if (flags & ORDER_TYPE_CHANGE)
3419         {
3420                 if (Stream_GetRemainingLength(s) < 1)
3421                 {
3422                         WLog_Print(update->log, WLOG_ERROR, "Stream_GetRemainingLength(s) < 1");
3423                         return FALSE;
3424                 }
3425
3426                 Stream_Read_UINT8(s, orderInfo->orderType); /* orderType (1 byte) */
3427         }
3428
3429         orderName = primary_order_string(orderInfo->orderType);
3430
3431         if (!check_primary_order_supported(update->log, settings, orderInfo->orderType, orderName))
3432                 return FALSE;
3433
3434         field = get_primary_drawing_order_field_bytes(orderInfo->orderType, &rc);
3435         if (!rc)
3436                 return FALSE;
3437
3438         if (!update_read_field_flags(s, &(orderInfo->fieldFlags), flags, field))
3439         {
3440                 WLog_Print(update->log, WLOG_ERROR, "update_read_field_flags() failed");
3441                 return FALSE;
3442         }
3443
3444         if (flags & ORDER_BOUNDS)
3445         {
3446                 if (!(flags & ORDER_ZERO_BOUNDS_DELTAS))
3447                 {
3448                         if (!update_read_bounds(s, &orderInfo->bounds))
3449                         {
3450                                 WLog_Print(update->log, WLOG_ERROR, "update_read_bounds() failed");
3451                                 return FALSE;
3452                         }
3453                 }
3454
3455                 rc = IFCALLRESULT(FALSE, update->SetBounds, context, &orderInfo->bounds);
3456
3457                 if (!rc)
3458                         return FALSE;
3459         }
3460
3461         orderInfo->deltaCoordinates = (flags & ORDER_DELTA_COORDINATES) ? TRUE : FALSE;
3462
3463         if (!read_primary_order(update->log, orderName, s, orderInfo, primary))
3464                 return FALSE;
3465
3466         switch (orderInfo->orderType)
3467         {
3468                 case ORDER_TYPE_DSTBLT:
3469                 {
3470                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s rop=%s [0x%08" PRIx32 "]",
3471                                    orderName, gdi_rop3_code_string(primary->dstblt.bRop),
3472                                    gdi_rop3_code(primary->dstblt.bRop));
3473                         rc = IFCALLRESULT(FALSE, primary->DstBlt, context, &primary->dstblt);
3474                 }
3475                 break;
3476
3477                 case ORDER_TYPE_PATBLT:
3478                 {
3479                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s rop=%s [0x%08" PRIx32 "]",
3480                                    orderName, gdi_rop3_code_string(primary->patblt.bRop),
3481                                    gdi_rop3_code(primary->patblt.bRop));
3482                         rc = IFCALLRESULT(FALSE, primary->PatBlt, context, &primary->patblt);
3483                 }
3484                 break;
3485
3486                 case ORDER_TYPE_SCRBLT:
3487                 {
3488                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s rop=%s [0x%08" PRIx32 "]",
3489                                    orderName, gdi_rop3_code_string(primary->scrblt.bRop),
3490                                    gdi_rop3_code(primary->scrblt.bRop));
3491                         rc = IFCALLRESULT(FALSE, primary->ScrBlt, context, &primary->scrblt);
3492                 }
3493                 break;
3494
3495                 case ORDER_TYPE_OPAQUE_RECT:
3496                 {
3497                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3498                         rc = IFCALLRESULT(FALSE, primary->OpaqueRect, context, &primary->opaque_rect);
3499                 }
3500                 break;
3501
3502                 case ORDER_TYPE_DRAW_NINE_GRID:
3503                 {
3504                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3505                         rc = IFCALLRESULT(FALSE, primary->DrawNineGrid, context, &primary->draw_nine_grid);
3506                 }
3507                 break;
3508
3509                 case ORDER_TYPE_MULTI_DSTBLT:
3510                 {
3511                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s rop=%s [0x%08" PRIx32 "]",
3512                                    orderName, gdi_rop3_code_string(primary->multi_dstblt.bRop),
3513                                    gdi_rop3_code(primary->multi_dstblt.bRop));
3514                         rc = IFCALLRESULT(FALSE, primary->MultiDstBlt, context, &primary->multi_dstblt);
3515                 }
3516                 break;
3517
3518                 case ORDER_TYPE_MULTI_PATBLT:
3519                 {
3520                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s rop=%s [0x%08" PRIx32 "]",
3521                                    orderName, gdi_rop3_code_string(primary->multi_patblt.bRop),
3522                                    gdi_rop3_code(primary->multi_patblt.bRop));
3523                         rc = IFCALLRESULT(FALSE, primary->MultiPatBlt, context, &primary->multi_patblt);
3524                 }
3525                 break;
3526
3527                 case ORDER_TYPE_MULTI_SCRBLT:
3528                 {
3529                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s rop=%s [0x%08" PRIx32 "]",
3530                                    orderName, gdi_rop3_code_string(primary->multi_scrblt.bRop),
3531                                    gdi_rop3_code(primary->multi_scrblt.bRop));
3532                         rc = IFCALLRESULT(FALSE, primary->MultiScrBlt, context, &primary->multi_scrblt);
3533                 }
3534                 break;
3535
3536                 case ORDER_TYPE_MULTI_OPAQUE_RECT:
3537                 {
3538                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3539                         rc =
3540                             IFCALLRESULT(FALSE, primary->MultiOpaqueRect, context, &primary->multi_opaque_rect);
3541                 }
3542                 break;
3543
3544                 case ORDER_TYPE_MULTI_DRAW_NINE_GRID:
3545                 {
3546                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3547                         rc = IFCALLRESULT(FALSE, primary->MultiDrawNineGrid, context,
3548                                           &primary->multi_draw_nine_grid);
3549                 }
3550                 break;
3551
3552                 case ORDER_TYPE_LINE_TO:
3553                 {
3554                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3555                         rc = IFCALLRESULT(FALSE, primary->LineTo, context, &primary->line_to);
3556                 }
3557                 break;
3558
3559                 case ORDER_TYPE_POLYLINE:
3560                 {
3561                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3562                         rc = IFCALLRESULT(FALSE, primary->Polyline, context, &primary->polyline);
3563                 }
3564                 break;
3565
3566                 case ORDER_TYPE_MEMBLT:
3567                 {
3568                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s rop=%s [0x%08" PRIx32 "]",
3569                                    orderName, gdi_rop3_code_string(primary->memblt.bRop),
3570                                    gdi_rop3_code(primary->memblt.bRop));
3571                         rc = IFCALLRESULT(FALSE, primary->MemBlt, context, &primary->memblt);
3572                 }
3573                 break;
3574
3575                 case ORDER_TYPE_MEM3BLT:
3576                 {
3577                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s rop=%s [0x%08" PRIx32 "]",
3578                                    orderName, gdi_rop3_code_string(primary->mem3blt.bRop),
3579                                    gdi_rop3_code(primary->mem3blt.bRop));
3580                         rc = IFCALLRESULT(FALSE, primary->Mem3Blt, context, &primary->mem3blt);
3581                 }
3582                 break;
3583
3584                 case ORDER_TYPE_SAVE_BITMAP:
3585                 {
3586                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3587                         rc = IFCALLRESULT(FALSE, primary->SaveBitmap, context, &primary->save_bitmap);
3588                 }
3589                 break;
3590
3591                 case ORDER_TYPE_GLYPH_INDEX:
3592                 {
3593                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3594                         rc = IFCALLRESULT(FALSE, primary->GlyphIndex, context, &primary->glyph_index);
3595                 }
3596                 break;
3597
3598                 case ORDER_TYPE_FAST_INDEX:
3599                 {
3600                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3601                         rc = IFCALLRESULT(FALSE, primary->FastIndex, context, &primary->fast_index);
3602                 }
3603                 break;
3604
3605                 case ORDER_TYPE_FAST_GLYPH:
3606                 {
3607                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3608                         rc = IFCALLRESULT(FALSE, primary->FastGlyph, context, &primary->fast_glyph);
3609                 }
3610                 break;
3611
3612                 case ORDER_TYPE_POLYGON_SC:
3613                 {
3614                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3615                         rc = IFCALLRESULT(FALSE, primary->PolygonSC, context, &primary->polygon_sc);
3616                 }
3617                 break;
3618
3619                 case ORDER_TYPE_POLYGON_CB:
3620                 {
3621                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3622                         rc = IFCALLRESULT(FALSE, primary->PolygonCB, context, &primary->polygon_cb);
3623                 }
3624                 break;
3625
3626                 case ORDER_TYPE_ELLIPSE_SC:
3627                 {
3628                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3629                         rc = IFCALLRESULT(FALSE, primary->EllipseSC, context, &primary->ellipse_sc);
3630                 }
3631                 break;
3632
3633                 case ORDER_TYPE_ELLIPSE_CB:
3634                 {
3635                         WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName);
3636                         rc = IFCALLRESULT(FALSE, primary->EllipseCB, context, &primary->ellipse_cb);
3637                 }
3638                 break;
3639
3640                 default:
3641                         WLog_Print(update->log, WLOG_WARN, "Primary Drawing Order %s not supported", orderName);
3642                         break;
3643         }
3644
3645         if (!rc)
3646         {
3647                 WLog_Print(update->log, WLOG_WARN, "Primary Drawing Order %s failed", orderName);
3648                 return FALSE;
3649         }
3650
3651         if (flags & ORDER_BOUNDS)
3652         {
3653                 rc = IFCALLRESULT(FALSE, update->SetBounds, context, NULL);
3654         }
3655
3656         return rc;
3657 }
3658
3659 static BOOL update_recv_secondary_order(rdpUpdate* update, wStream* s, BYTE flags)
3660 {
3661         BOOL rc = FALSE;
3662         size_t start, end, pos, diff;
3663         BYTE orderType;
3664         UINT16 extraFlags;
3665         UINT16 orderLength;
3666         rdpContext* context = update->context;
3667         rdpSettings* settings = context->settings;
3668         rdpSecondaryUpdate* secondary = update->secondary;
3669         const char* name;
3670
3671         if (Stream_GetRemainingLength(s) < 5)
3672         {
3673                 WLog_Print(update->log, WLOG_ERROR, "Stream_GetRemainingLength(s) < 5");
3674                 return FALSE;
3675         }
3676
3677         Stream_Read_UINT16(s, orderLength); /* orderLength (2 bytes) */
3678         Stream_Read_UINT16(s, extraFlags);  /* extraFlags (2 bytes) */
3679         Stream_Read_UINT8(s, orderType);    /* orderType (1 byte) */
3680         /*
3681          * According to [MS-RDPEGDI] 2.2.2.2.1.2.1.1 the order length must be increased by 13 bytes
3682          * including the header. As we already read the header 7 left
3683          */
3684         if (Stream_GetRemainingLength(s) < orderLength + 7U)
3685         {
3686                 WLog_Print(update->log, WLOG_ERROR, "Stream_GetRemainingLength(s) %" PRIuz " < %" PRIu16,
3687                            Stream_GetRemainingLength(s), orderLength + 7);
3688                 return FALSE;
3689         }
3690
3691         start = Stream_GetPosition(s);
3692         name = secondary_order_string(orderType);
3693         WLog_Print(update->log, WLOG_DEBUG, "Secondary Drawing Order %s", name);
3694
3695         if (!check_secondary_order_supported(update->log, settings, orderType, name))
3696                 return FALSE;
3697
3698         switch (orderType)
3699         {
3700                 case ORDER_TYPE_BITMAP_UNCOMPRESSED:
3701                 case ORDER_TYPE_CACHE_BITMAP_COMPRESSED:
3702                 {
3703                         const BOOL compressed = (orderType == ORDER_TYPE_CACHE_BITMAP_COMPRESSED);
3704                         CACHE_BITMAP_ORDER* order =
3705                             update_read_cache_bitmap_order(update, s, compressed, extraFlags);
3706
3707                         if (order)
3708                         {
3709                                 rc = IFCALLRESULT(FALSE, secondary->CacheBitmap, context, order);
3710                                 free_cache_bitmap_order(context, order);
3711                         }
3712                 }
3713                 break;
3714
3715                 case ORDER_TYPE_BITMAP_UNCOMPRESSED_V2:
3716                 case ORDER_TYPE_BITMAP_COMPRESSED_V2:
3717                 {
3718                         const BOOL compressed = (orderType == ORDER_TYPE_BITMAP_COMPRESSED_V2);
3719                         CACHE_BITMAP_V2_ORDER* order =
3720                             update_read_cache_bitmap_v2_order(update, s, compressed, extraFlags);
3721
3722                         if (order)
3723                         {
3724                                 rc = IFCALLRESULT(FALSE, secondary->CacheBitmapV2, context, order);
3725                                 free_cache_bitmap_v2_order(context, order);
3726                         }
3727                 }
3728                 break;
3729
3730                 case ORDER_TYPE_BITMAP_COMPRESSED_V3:
3731                 {
3732                         CACHE_BITMAP_V3_ORDER* order = update_read_cache_bitmap_v3_order(update, s, extraFlags);
3733
3734                         if (order)
3735                         {
3736                                 rc = IFCALLRESULT(FALSE, secondary->CacheBitmapV3, context, order);
3737                                 free_cache_bitmap_v3_order(context, order);
3738                         }
3739                 }
3740                 break;
3741
3742                 case ORDER_TYPE_CACHE_COLOR_TABLE:
3743                 {
3744                         CACHE_COLOR_TABLE_ORDER* order =
3745                             update_read_cache_color_table_order(update, s, extraFlags);
3746
3747                         if (order)
3748                         {
3749                                 rc = IFCALLRESULT(FALSE, secondary->CacheColorTable, context, order);
3750                                 free_cache_color_table_order(context, order);
3751                         }
3752                 }
3753                 break;
3754
3755                 case ORDER_TYPE_CACHE_GLYPH:
3756                 {
3757                         switch (settings->GlyphSupportLevel)
3758                         {
3759                                 case GLYPH_SUPPORT_PARTIAL:
3760                                 case GLYPH_SUPPORT_FULL:
3761                                 {
3762                                         CACHE_GLYPH_ORDER* order = update_read_cache_glyph_order(update, s, extraFlags);
3763
3764                                         if (order)
3765                                         {
3766                                                 rc = IFCALLRESULT(FALSE, secondary->CacheGlyph, context, order);
3767                                                 free_cache_glyph_order(context, order);
3768                                         }
3769                                 }
3770                                 break;
3771
3772                                 case GLYPH_SUPPORT_ENCODE:
3773                                 {
3774                                         CACHE_GLYPH_V2_ORDER* order =
3775                                             update_read_cache_glyph_v2_order(update, s, extraFlags);
3776
3777                                         if (order)
3778                                         {
3779                                                 rc = IFCALLRESULT(FALSE, secondary->CacheGlyphV2, context, order);
3780                                                 free_cache_glyph_v2_order(context, order);
3781                                         }
3782                                 }
3783                                 break;
3784
3785                                 case GLYPH_SUPPORT_NONE:
3786                                 default:
3787                                         break;
3788                         }
3789                 }
3790                 break;
3791
3792                 case ORDER_TYPE_CACHE_BRUSH:
3793                         /* [MS-RDPEGDI] 2.2.2.2.1.2.7 Cache Brush (CACHE_BRUSH_ORDER) */
3794                         {
3795                                 CACHE_BRUSH_ORDER* order = update_read_cache_brush_order(update, s, extraFlags);
3796
3797                                 if (order)
3798                                 {
3799                                         rc = IFCALLRESULT(FALSE, secondary->CacheBrush, context, order);
3800                                         free_cache_brush_order(context, order);
3801                                 }
3802                         }
3803                         break;
3804
3805                 default:
3806                         WLog_Print(update->log, WLOG_WARN, "SECONDARY ORDER %s not supported", name);
3807                         break;
3808         }
3809
3810         if (!rc)
3811         {
3812                 WLog_Print(update->log, WLOG_ERROR, "SECONDARY ORDER %s failed", name);
3813         }
3814
3815         end = start + orderLength + 7;
3816         pos = Stream_GetPosition(s);
3817         if (pos > end)
3818         {
3819                 WLog_Print(update->log, WLOG_WARN, "SECONDARY_ORDER %s: read %" PRIuz "bytes too much",
3820                            name, pos - end);
3821                 return FALSE;
3822         }
3823         diff = end - pos;
3824         if (diff > 0)
3825         {
3826                 WLog_Print(update->log, WLOG_DEBUG,
3827                            "SECONDARY_ORDER %s: read %" PRIuz "bytes short, skipping", name, diff);
3828                 if (!Stream_SafeSeek(s, diff))
3829                         return FALSE;
3830         }
3831         return rc;
3832 }
3833
3834 static BOOL read_altsec_order(wStream* s, BYTE orderType, rdpAltSecUpdate* altsec)
3835 {
3836         BOOL rc = FALSE;
3837
3838         switch (orderType)
3839         {
3840                 case ORDER_TYPE_CREATE_OFFSCREEN_BITMAP:
3841                         rc = update_read_create_offscreen_bitmap_order(s, &(altsec->create_offscreen_bitmap));
3842                         break;
3843
3844                 case ORDER_TYPE_SWITCH_SURFACE:
3845                         rc = update_read_switch_surface_order(s, &(altsec->switch_surface));
3846                         break;
3847
3848                 case ORDER_TYPE_CREATE_NINE_GRID_BITMAP:
3849                         rc = update_read_create_nine_grid_bitmap_order(s, &(altsec->create_nine_grid_bitmap));
3850                         break;
3851
3852                 case ORDER_TYPE_FRAME_MARKER:
3853                         rc = update_read_frame_marker_order(s, &(altsec->frame_marker));
3854                         break;
3855
3856                 case ORDER_TYPE_STREAM_BITMAP_FIRST:
3857                         rc = update_read_stream_bitmap_first_order(s, &(altsec->stream_bitmap_first));
3858                         break;
3859
3860                 case ORDER_TYPE_STREAM_BITMAP_NEXT:
3861                         rc = update_read_stream_bitmap_next_order(s, &(altsec->stream_bitmap_next));
3862                         break;
3863
3864                 case ORDER_TYPE_GDIPLUS_FIRST:
3865                         rc = update_read_draw_gdiplus_first_order(s, &(altsec->draw_gdiplus_first));
3866                         break;
3867
3868                 case ORDER_TYPE_GDIPLUS_NEXT:
3869                         rc = update_read_draw_gdiplus_next_order(s, &(altsec->draw_gdiplus_next));
3870                         break;
3871
3872                 case ORDER_TYPE_GDIPLUS_END:
3873                         rc = update_read_draw_gdiplus_end_order(s, &(altsec->draw_gdiplus_end));
3874                         break;
3875
3876                 case ORDER_TYPE_GDIPLUS_CACHE_FIRST:
3877                         rc = update_read_draw_gdiplus_cache_first_order(s, &(altsec->draw_gdiplus_cache_first));
3878                         break;
3879
3880                 case ORDER_TYPE_GDIPLUS_CACHE_NEXT:
3881                         rc = update_read_draw_gdiplus_cache_next_order(s, &(altsec->draw_gdiplus_cache_next));
3882                         break;
3883
3884                 case ORDER_TYPE_GDIPLUS_CACHE_END:
3885                         rc = update_read_draw_gdiplus_cache_end_order(s, &(altsec->draw_gdiplus_cache_end));
3886                         break;
3887
3888                 case ORDER_TYPE_WINDOW:
3889                         /* This order is handled elsewhere. */
3890                         rc = TRUE;
3891                         break;
3892
3893                 case ORDER_TYPE_COMPDESK_FIRST:
3894                         rc = TRUE;
3895                         break;
3896
3897                 default:
3898                         break;
3899         }
3900
3901         return rc;
3902 }
3903
3904 static BOOL update_recv_altsec_order(rdpUpdate* update, wStream* s, BYTE flags)
3905 {
3906         BYTE orderType = flags >>= 2; /* orderType is in higher 6 bits of flags field */
3907         BOOL rc = FALSE;
3908         rdpContext* context = update->context;
3909         rdpSettings* settings = context->settings;
3910         rdpAltSecUpdate* altsec = update->altsec;
3911         const char* orderName = altsec_order_string(orderType);
3912         WLog_Print(update->log, WLOG_DEBUG, "Alternate Secondary Drawing Order %s", orderName);
3913
3914         if (!check_alt_order_supported(update->log, settings, orderType, orderName))
3915                 return FALSE;
3916
3917         if (!read_altsec_order(s, orderType, altsec))
3918                 return FALSE;
3919
3920         switch (orderType)
3921         {
3922                 case ORDER_TYPE_CREATE_OFFSCREEN_BITMAP:
3923                         IFCALLRET(altsec->CreateOffscreenBitmap, rc, context,
3924                                   &(altsec->create_offscreen_bitmap));
3925                         break;
3926
3927                 case ORDER_TYPE_SWITCH_SURFACE:
3928                         IFCALLRET(altsec->SwitchSurface, rc, context, &(altsec->switch_surface));
3929                         break;
3930
3931                 case ORDER_TYPE_CREATE_NINE_GRID_BITMAP:
3932                         IFCALLRET(altsec->CreateNineGridBitmap, rc, context,
3933                                   &(altsec->create_nine_grid_bitmap));
3934                         break;
3935
3936                 case ORDER_TYPE_FRAME_MARKER:
3937                         IFCALLRET(altsec->FrameMarker, rc, context, &(altsec->frame_marker));
3938                         break;
3939
3940                 case ORDER_TYPE_STREAM_BITMAP_FIRST:
3941                         IFCALLRET(altsec->StreamBitmapFirst, rc, context, &(altsec->stream_bitmap_first));
3942                         break;
3943
3944                 case ORDER_TYPE_STREAM_BITMAP_NEXT:
3945                         IFCALLRET(altsec->StreamBitmapNext, rc, context, &(altsec->stream_bitmap_next));
3946                         break;
3947
3948                 case ORDER_TYPE_GDIPLUS_FIRST:
3949                         IFCALLRET(altsec->DrawGdiPlusFirst, rc, context, &(altsec->draw_gdiplus_first));
3950                         break;
3951
3952                 case ORDER_TYPE_GDIPLUS_NEXT:
3953                         IFCALLRET(altsec->DrawGdiPlusNext, rc, context, &(altsec->draw_gdiplus_next));
3954                         break;
3955
3956                 case ORDER_TYPE_GDIPLUS_END:
3957                         IFCALLRET(altsec->DrawGdiPlusEnd, rc, context, &(altsec->draw_gdiplus_end));
3958                         break;
3959
3960                 case ORDER_TYPE_GDIPLUS_CACHE_FIRST:
3961                         IFCALLRET(altsec->DrawGdiPlusCacheFirst, rc, context,
3962                                   &(altsec->draw_gdiplus_cache_first));
3963                         break;
3964
3965                 case ORDER_TYPE_GDIPLUS_CACHE_NEXT:
3966                         IFCALLRET(altsec->DrawGdiPlusCacheNext, rc, context,
3967                                   &(altsec->draw_gdiplus_cache_next));
3968                         break;
3969
3970                 case ORDER_TYPE_GDIPLUS_CACHE_END:
3971                         IFCALLRET(altsec->DrawGdiPlusCacheEnd, rc, context, &(altsec->draw_gdiplus_cache_end));
3972                         break;
3973
3974                 case ORDER_TYPE_WINDOW:
3975                         rc = update_recv_altsec_window_order(update, s);
3976                         break;
3977
3978                 case ORDER_TYPE_COMPDESK_FIRST:
3979                         rc = TRUE;
3980                         break;
3981
3982                 default:
3983                         break;
3984         }
3985
3986         if (!rc)
3987         {
3988                 WLog_Print(update->log, WLOG_WARN, "Alternate Secondary Drawing Order %s failed",
3989                            orderName);
3990         }
3991
3992         return rc;
3993 }
3994 BOOL update_recv_order(rdpUpdate* update, wStream* s)
3995 {
3996         BOOL rc;
3997         BYTE controlFlags;
3998
3999         if (Stream_GetRemainingLength(s) < 1)
4000         {
4001                 WLog_Print(update->log, WLOG_ERROR, "Stream_GetRemainingLength(s) < 1");
4002                 return FALSE;
4003         }
4004
4005         Stream_Read_UINT8(s, controlFlags); /* controlFlags (1 byte) */
4006
4007         if (!(controlFlags & ORDER_STANDARD))
4008                 rc = update_recv_altsec_order(update, s, controlFlags);
4009         else if (controlFlags & ORDER_SECONDARY)
4010                 rc = update_recv_secondary_order(update, s, controlFlags);
4011         else
4012                 rc = update_recv_primary_order(update, s, controlFlags);
4013
4014         if (!rc)
4015                 WLog_Print(update->log, WLOG_ERROR, "order flags %02" PRIx8 " failed", controlFlags);
4016
4017         return rc;
4018 }