1 /**
2 * FreeRDP: A Remote Desktop Protocol Implementation
3 * Update Data PDUs
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 <winpr/crt.h>
27 #include <winpr/print.h>
28 #include <winpr/synch.h>
29 #include <winpr/thread.h>
30 #include <winpr/collections.h>
31
32 #include "update.h"
33 #include "surface.h"
34 #include "message.h"
35 #include "info.h"
36 #include "window.h"
37
38 #include <freerdp/log.h>
39 #include <freerdp/peer.h>
40 #include <freerdp/codec/bitmap.h>
41
42 #include "../cache/pointer.h"
43 #include "../cache/palette.h"
44 #include "../cache/bitmap.h"
45
46 #define TAG FREERDP_TAG("core.update")
47
48 static const char* const UPDATE_TYPE_STRINGS[] = { "Orders", "Bitmap", "Palette", "Synchronize" };
49
update_type_to_string(UINT16 updateType)50 static const char* update_type_to_string(UINT16 updateType)
51 {
52 if (updateType >= ARRAYSIZE(UPDATE_TYPE_STRINGS))
53 return "UNKNOWN";
54
55 return UPDATE_TYPE_STRINGS[updateType];
56 }
57
update_recv_orders(rdpUpdate * update,wStream * s)58 static BOOL update_recv_orders(rdpUpdate* update, wStream* s)
59 {
60 UINT16 numberOrders;
61
62 if (Stream_GetRemainingLength(s) < 6)
63 {
64 WLog_ERR(TAG, "Stream_GetRemainingLength(s) < 6");
65 return FALSE;
66 }
67
68 Stream_Seek_UINT16(s); /* pad2OctetsA (2 bytes) */
69 Stream_Read_UINT16(s, numberOrders); /* numberOrders (2 bytes) */
70 Stream_Seek_UINT16(s); /* pad2OctetsB (2 bytes) */
71
72 while (numberOrders > 0)
73 {
74 if (!update_recv_order(update, s))
75 {
76 WLog_ERR(TAG, "update_recv_order() failed");
77 return FALSE;
78 }
79
80 numberOrders--;
81 }
82
83 return TRUE;
84 }
85
update_read_bitmap_data(rdpUpdate * update,wStream * s,BITMAP_DATA * bitmapData)86 static BOOL update_read_bitmap_data(rdpUpdate* update, wStream* s, BITMAP_DATA* bitmapData)
87 {
88 WINPR_UNUSED(update);
89 if (Stream_GetRemainingLength(s) < 18)
90 return FALSE;
91
92 Stream_Read_UINT16(s, bitmapData->destLeft);
93 Stream_Read_UINT16(s, bitmapData->destTop);
94 Stream_Read_UINT16(s, bitmapData->destRight);
95 Stream_Read_UINT16(s, bitmapData->destBottom);
96 Stream_Read_UINT16(s, bitmapData->width);
97 Stream_Read_UINT16(s, bitmapData->height);
98 Stream_Read_UINT16(s, bitmapData->bitsPerPixel);
99 Stream_Read_UINT16(s, bitmapData->flags);
100 Stream_Read_UINT16(s, bitmapData->bitmapLength);
101
102 if ((bitmapData->width == 0) || (bitmapData->height == 0))
103 {
104 WLog_ERR(TAG, "Invalid BITMAP_DATA: width=%" PRIu16 ", height=%" PRIu16, bitmapData->width,
105 bitmapData->height);
106 return FALSE;
107 }
108
109 if (bitmapData->flags & BITMAP_COMPRESSION)
110 {
111 if (!(bitmapData->flags & NO_BITMAP_COMPRESSION_HDR))
112 {
113 if (Stream_GetRemainingLength(s) < 8)
114 return FALSE;
115
116 Stream_Read_UINT16(s,
117 bitmapData->cbCompFirstRowSize); /* cbCompFirstRowSize (2 bytes) */
118 Stream_Read_UINT16(s,
119 bitmapData->cbCompMainBodySize); /* cbCompMainBodySize (2 bytes) */
120 Stream_Read_UINT16(s, bitmapData->cbScanWidth); /* cbScanWidth (2 bytes) */
121 Stream_Read_UINT16(s,
122 bitmapData->cbUncompressedSize); /* cbUncompressedSize (2 bytes) */
123 bitmapData->bitmapLength = bitmapData->cbCompMainBodySize;
124 }
125
126 bitmapData->compressed = TRUE;
127 }
128 else
129 bitmapData->compressed = FALSE;
130
131 if (Stream_GetRemainingLength(s) < bitmapData->bitmapLength)
132 return FALSE;
133
134 if (bitmapData->bitmapLength > 0)
135 {
136 bitmapData->bitmapDataStream = malloc(bitmapData->bitmapLength);
137
138 if (!bitmapData->bitmapDataStream)
139 return FALSE;
140
141 memcpy(bitmapData->bitmapDataStream, Stream_Pointer(s), bitmapData->bitmapLength);
142 Stream_Seek(s, bitmapData->bitmapLength);
143 }
144
145 return TRUE;
146 }
147
update_write_bitmap_data(rdpUpdate * update,wStream * s,BITMAP_DATA * bitmapData)148 static BOOL update_write_bitmap_data(rdpUpdate* update, wStream* s, BITMAP_DATA* bitmapData)
149 {
150 if (!Stream_EnsureRemainingCapacity(s, 64 + bitmapData->bitmapLength))
151 return FALSE;
152
153 if (update->autoCalculateBitmapData)
154 {
155 bitmapData->flags = 0;
156 bitmapData->cbCompFirstRowSize = 0;
157
158 if (bitmapData->compressed)
159 bitmapData->flags |= BITMAP_COMPRESSION;
160
161 if (update->context->settings->NoBitmapCompressionHeader)
162 {
163 bitmapData->flags |= NO_BITMAP_COMPRESSION_HDR;
164 bitmapData->cbCompMainBodySize = bitmapData->bitmapLength;
165 }
166 }
167
168 Stream_Write_UINT16(s, bitmapData->destLeft);
169 Stream_Write_UINT16(s, bitmapData->destTop);
170 Stream_Write_UINT16(s, bitmapData->destRight);
171 Stream_Write_UINT16(s, bitmapData->destBottom);
172 Stream_Write_UINT16(s, bitmapData->width);
173 Stream_Write_UINT16(s, bitmapData->height);
174 Stream_Write_UINT16(s, bitmapData->bitsPerPixel);
175 Stream_Write_UINT16(s, bitmapData->flags);
176 Stream_Write_UINT16(s, bitmapData->bitmapLength);
177
178 if (bitmapData->flags & BITMAP_COMPRESSION)
179 {
180 if (!(bitmapData->flags & NO_BITMAP_COMPRESSION_HDR))
181 {
182 Stream_Write_UINT16(s,
183 bitmapData->cbCompFirstRowSize); /* cbCompFirstRowSize (2 bytes) */
184 Stream_Write_UINT16(s,
185 bitmapData->cbCompMainBodySize); /* cbCompMainBodySize (2 bytes) */
186 Stream_Write_UINT16(s, bitmapData->cbScanWidth); /* cbScanWidth (2 bytes) */
187 Stream_Write_UINT16(s,
188 bitmapData->cbUncompressedSize); /* cbUncompressedSize (2 bytes) */
189 }
190
191 Stream_Write(s, bitmapData->bitmapDataStream, bitmapData->bitmapLength);
192 }
193 else
194 {
195 Stream_Write(s, bitmapData->bitmapDataStream, bitmapData->bitmapLength);
196 }
197
198 return TRUE;
199 }
200
update_read_bitmap_update(rdpUpdate * update,wStream * s)201 BITMAP_UPDATE* update_read_bitmap_update(rdpUpdate* update, wStream* s)
202 {
203 UINT32 i;
204 BITMAP_UPDATE* bitmapUpdate = calloc(1, sizeof(BITMAP_UPDATE));
205
206 if (!bitmapUpdate)
207 goto fail;
208
209 if (Stream_GetRemainingLength(s) < 2)
210 goto fail;
211
212 Stream_Read_UINT16(s, bitmapUpdate->number); /* numberRectangles (2 bytes) */
213 WLog_Print(update->log, WLOG_TRACE, "BitmapUpdate: %" PRIu32 "", bitmapUpdate->number);
214
215 if (bitmapUpdate->number > bitmapUpdate->count)
216 {
217 UINT32 count = bitmapUpdate->number * 2;
218 BITMAP_DATA* newdata =
219 (BITMAP_DATA*)realloc(bitmapUpdate->rectangles, sizeof(BITMAP_DATA) * count);
220
221 if (!newdata)
222 goto fail;
223
224 bitmapUpdate->rectangles = newdata;
225 ZeroMemory(&bitmapUpdate->rectangles[bitmapUpdate->count],
226 sizeof(BITMAP_DATA) * (count - bitmapUpdate->count));
227 bitmapUpdate->count = count;
228 }
229
230 /* rectangles */
231 for (i = 0; i < bitmapUpdate->number; i++)
232 {
233 if (!update_read_bitmap_data(update, s, &bitmapUpdate->rectangles[i]))
234 goto fail;
235 }
236
237 return bitmapUpdate;
238 fail:
239 free_bitmap_update(update->context, bitmapUpdate);
240 return NULL;
241 }
242
update_write_bitmap_update(rdpUpdate * update,wStream * s,const BITMAP_UPDATE * bitmapUpdate)243 static BOOL update_write_bitmap_update(rdpUpdate* update, wStream* s,
244 const BITMAP_UPDATE* bitmapUpdate)
245 {
246 int i;
247
248 if (!Stream_EnsureRemainingCapacity(s, 32))
249 return FALSE;
250
251 Stream_Write_UINT16(s, UPDATE_TYPE_BITMAP); /* updateType */
252 Stream_Write_UINT16(s, bitmapUpdate->number); /* numberRectangles (2 bytes) */
253
254 /* rectangles */
255 for (i = 0; i < (int)bitmapUpdate->number; i++)
256 {
257 if (!update_write_bitmap_data(update, s, &bitmapUpdate->rectangles[i]))
258 return FALSE;
259 }
260
261 return TRUE;
262 }
263
update_read_palette(rdpUpdate * update,wStream * s)264 PALETTE_UPDATE* update_read_palette(rdpUpdate* update, wStream* s)
265 {
266 int i;
267 PALETTE_ENTRY* entry;
268 PALETTE_UPDATE* palette_update = calloc(1, sizeof(PALETTE_UPDATE));
269
270 if (!palette_update)
271 goto fail;
272
273 if (Stream_GetRemainingLength(s) < 6)
274 goto fail;
275
276 Stream_Seek_UINT16(s); /* pad2Octets (2 bytes) */
277 Stream_Read_UINT32(s, palette_update->number); /* numberColors (4 bytes), must be set to 256 */
278
279 if (palette_update->number > 256)
280 palette_update->number = 256;
281
282 if (Stream_GetRemainingLength(s) < palette_update->number * 3)
283 goto fail;
284
285 /* paletteEntries */
286 for (i = 0; i < (int)palette_update->number; i++)
287 {
288 entry = &palette_update->entries[i];
289 Stream_Read_UINT8(s, entry->red);
290 Stream_Read_UINT8(s, entry->green);
291 Stream_Read_UINT8(s, entry->blue);
292 }
293
294 return palette_update;
295 fail:
296 free_palette_update(update->context, palette_update);
297 return NULL;
298 }
299
update_read_synchronize(rdpUpdate * update,wStream * s)300 static BOOL update_read_synchronize(rdpUpdate* update, wStream* s)
301 {
302 WINPR_UNUSED(update);
303 return Stream_SafeSeek(s, 2); /* pad2Octets (2 bytes) */
304 /**
305 * The Synchronize Update is an artifact from the
306 * T.128 protocol and should be ignored.
307 */
308 }
309
update_read_play_sound(wStream * s,PLAY_SOUND_UPDATE * play_sound)310 static BOOL update_read_play_sound(wStream* s, PLAY_SOUND_UPDATE* play_sound)
311 {
312 if (Stream_GetRemainingLength(s) < 8)
313 return FALSE;
314
315 Stream_Read_UINT32(s, play_sound->duration); /* duration (4 bytes) */
316 Stream_Read_UINT32(s, play_sound->frequency); /* frequency (4 bytes) */
317 return TRUE;
318 }
319
update_recv_play_sound(rdpUpdate * update,wStream * s)320 BOOL update_recv_play_sound(rdpUpdate* update, wStream* s)
321 {
322 PLAY_SOUND_UPDATE play_sound;
323
324 if (!update_read_play_sound(s, &play_sound))
325 return FALSE;
326
327 return IFCALLRESULT(FALSE, update->PlaySound, update->context, &play_sound);
328 }
329
update_read_pointer_position(rdpUpdate * update,wStream * s)330 POINTER_POSITION_UPDATE* update_read_pointer_position(rdpUpdate* update, wStream* s)
331 {
332 POINTER_POSITION_UPDATE* pointer_position = calloc(1, sizeof(POINTER_POSITION_UPDATE));
333
334 if (!pointer_position)
335 goto fail;
336
337 if (Stream_GetRemainingLength(s) < 4)
338 goto fail;
339
340 Stream_Read_UINT16(s, pointer_position->xPos); /* xPos (2 bytes) */
341 Stream_Read_UINT16(s, pointer_position->yPos); /* yPos (2 bytes) */
342 return pointer_position;
343 fail:
344 free_pointer_position_update(update->context, pointer_position);
345 return NULL;
346 }
347
update_read_pointer_system(rdpUpdate * update,wStream * s)348 POINTER_SYSTEM_UPDATE* update_read_pointer_system(rdpUpdate* update, wStream* s)
349 {
350 POINTER_SYSTEM_UPDATE* pointer_system = calloc(1, sizeof(POINTER_SYSTEM_UPDATE));
351
352 if (!pointer_system)
353 goto fail;
354
355 if (Stream_GetRemainingLength(s) < 4)
356 goto fail;
357
358 Stream_Read_UINT32(s, pointer_system->type); /* systemPointerType (4 bytes) */
359 return pointer_system;
360 fail:
361 free_pointer_system_update(update->context, pointer_system);
362 return NULL;
363 }
364
_update_read_pointer_color(wStream * s,POINTER_COLOR_UPDATE * pointer_color,BYTE xorBpp,UINT32 flags)365 static BOOL _update_read_pointer_color(wStream* s, POINTER_COLOR_UPDATE* pointer_color, BYTE xorBpp,
366 UINT32 flags)
367 {
368 BYTE* newMask;
369 UINT32 scanlineSize;
370 UINT32 max = 32;
371
372 if (flags & LARGE_POINTER_FLAG_96x96)
373 max = 96;
374
375 if (!pointer_color)
376 goto fail;
377
378 if (Stream_GetRemainingLength(s) < 14)
379 goto fail;
380
381 Stream_Read_UINT16(s, pointer_color->cacheIndex); /* cacheIndex (2 bytes) */
382 Stream_Read_UINT16(s, pointer_color->xPos); /* xPos (2 bytes) */
383 Stream_Read_UINT16(s, pointer_color->yPos); /* yPos (2 bytes) */
384 /**
385 * As stated in 2.2.9.1.1.4.4 Color Pointer Update:
386 * The maximum allowed pointer width/height is 96 pixels if the client indicated support
387 * for large pointers by setting the LARGE_POINTER_FLAG (0x00000001) in the Large
388 * Pointer Capability Set (section 2.2.7.2.7). If the LARGE_POINTER_FLAG was not
389 * set, the maximum allowed pointer width/height is 32 pixels.
390 *
391 * So we check for a maximum for CVE-2014-0250.
392 */
393 Stream_Read_UINT16(s, pointer_color->width); /* width (2 bytes) */
394 Stream_Read_UINT16(s, pointer_color->height); /* height (2 bytes) */
395
396 if ((pointer_color->width > max) || (pointer_color->height > max))
397 goto fail;
398
399 Stream_Read_UINT16(s, pointer_color->lengthAndMask); /* lengthAndMask (2 bytes) */
400 Stream_Read_UINT16(s, pointer_color->lengthXorMask); /* lengthXorMask (2 bytes) */
401
402 /**
403 * There does not seem to be any documentation on why
404 * xPos / yPos can be larger than width / height
405 * so it is missing in documentation or a bug in implementation
406 * 2.2.9.1.1.4.4 Color Pointer Update (TS_COLORPOINTERATTRIBUTE)
407 */
408 if (pointer_color->xPos >= pointer_color->width)
409 pointer_color->xPos = 0;
410
411 if (pointer_color->yPos >= pointer_color->height)
412 pointer_color->yPos = 0;
413
414 if (pointer_color->lengthXorMask > 0)
415 {
416 /**
417 * Spec states that:
418 *
419 * xorMaskData (variable): A variable-length array of bytes. Contains the 24-bpp, bottom-up
420 * XOR mask scan-line data. The XOR mask is padded to a 2-byte boundary for each encoded
421 * scan-line. For example, if a 3x3 pixel cursor is being sent, then each scan-line will
422 * consume 10 bytes (3 pixels per scan-line multiplied by 3 bytes per pixel, rounded up to
423 * the next even number of bytes).
424 *
425 * In fact instead of 24-bpp, the bpp parameter is given by the containing packet.
426 */
427 if (Stream_GetRemainingLength(s) < pointer_color->lengthXorMask)
428 goto fail;
429
430 scanlineSize = (7 + xorBpp * pointer_color->width) / 8;
431 scanlineSize = ((scanlineSize + 1) / 2) * 2;
432
433 if (scanlineSize * pointer_color->height != pointer_color->lengthXorMask)
434 {
435 WLog_ERR(TAG,
436 "invalid lengthXorMask: width=%" PRIu32 " height=%" PRIu32 ", %" PRIu32
437 " instead of %" PRIu32 "",
438 pointer_color->width, pointer_color->height, pointer_color->lengthXorMask,
439 scanlineSize * pointer_color->height);
440 goto fail;
441 }
442
443 newMask = realloc(pointer_color->xorMaskData, pointer_color->lengthXorMask);
444
445 if (!newMask)
446 goto fail;
447
448 pointer_color->xorMaskData = newMask;
449 Stream_Read(s, pointer_color->xorMaskData, pointer_color->lengthXorMask);
450 }
451
452 if (pointer_color->lengthAndMask > 0)
453 {
454 /**
455 * andMaskData (variable): A variable-length array of bytes. Contains the 1-bpp, bottom-up
456 * AND mask scan-line data. The AND mask is padded to a 2-byte boundary for each encoded
457 * scan-line. For example, if a 7x7 pixel cursor is being sent, then each scan-line will
458 * consume 2 bytes (7 pixels per scan-line multiplied by 1 bpp, rounded up to the next even
459 * number of bytes).
460 */
461 if (Stream_GetRemainingLength(s) < pointer_color->lengthAndMask)
462 goto fail;
463
464 scanlineSize = ((7 + pointer_color->width) / 8);
465 scanlineSize = ((1 + scanlineSize) / 2) * 2;
466
467 if (scanlineSize * pointer_color->height != pointer_color->lengthAndMask)
468 {
469 WLog_ERR(TAG, "invalid lengthAndMask: %" PRIu32 " instead of %" PRIu32 "",
470 pointer_color->lengthAndMask, scanlineSize * pointer_color->height);
471 goto fail;
472 }
473
474 newMask = realloc(pointer_color->andMaskData, pointer_color->lengthAndMask);
475
476 if (!newMask)
477 goto fail;
478
479 pointer_color->andMaskData = newMask;
480 Stream_Read(s, pointer_color->andMaskData, pointer_color->lengthAndMask);
481 }
482
483 if (Stream_GetRemainingLength(s) > 0)
484 Stream_Seek_UINT8(s); /* pad (1 byte) */
485
486 return TRUE;
487 fail:
488 return FALSE;
489 }
490
update_read_pointer_color(rdpUpdate * update,wStream * s,BYTE xorBpp)491 POINTER_COLOR_UPDATE* update_read_pointer_color(rdpUpdate* update, wStream* s, BYTE xorBpp)
492 {
493 POINTER_COLOR_UPDATE* pointer_color = calloc(1, sizeof(POINTER_COLOR_UPDATE));
494
495 if (!pointer_color)
496 goto fail;
497
498 if (!_update_read_pointer_color(s, pointer_color, xorBpp,
499 update->context->settings->LargePointerFlag))
500 goto fail;
501
502 return pointer_color;
503 fail:
504 free_pointer_color_update(update->context, pointer_color);
505 return NULL;
506 }
507
_update_read_pointer_large(wStream * s,POINTER_LARGE_UPDATE * pointer)508 static BOOL _update_read_pointer_large(wStream* s, POINTER_LARGE_UPDATE* pointer)
509 {
510 BYTE* newMask;
511 UINT32 scanlineSize;
512
513 if (!pointer)
514 goto fail;
515
516 if (Stream_GetRemainingLength(s) < 20)
517 goto fail;
518
519 Stream_Read_UINT16(s, pointer->xorBpp);
520 Stream_Read_UINT16(s, pointer->cacheIndex); /* cacheIndex (2 bytes) */
521 Stream_Read_UINT16(s, pointer->hotSpotX); /* xPos (2 bytes) */
522 Stream_Read_UINT16(s, pointer->hotSpotY); /* yPos (2 bytes) */
523
524 Stream_Read_UINT16(s, pointer->width); /* width (2 bytes) */
525 Stream_Read_UINT16(s, pointer->height); /* height (2 bytes) */
526
527 if ((pointer->width > 384) || (pointer->height > 384))
528 goto fail;
529
530 Stream_Read_UINT32(s, pointer->lengthAndMask); /* lengthAndMask (4 bytes) */
531 Stream_Read_UINT32(s, pointer->lengthXorMask); /* lengthXorMask (4 bytes) */
532
533 if (pointer->hotSpotX >= pointer->width)
534 pointer->hotSpotX = 0;
535
536 if (pointer->hotSpotY >= pointer->height)
537 pointer->hotSpotY = 0;
538
539 if (pointer->lengthXorMask > 0)
540 {
541 /**
542 * Spec states that:
543 *
544 * xorMaskData (variable): A variable-length array of bytes. Contains the 24-bpp, bottom-up
545 * XOR mask scan-line data. The XOR mask is padded to a 2-byte boundary for each encoded
546 * scan-line. For example, if a 3x3 pixel cursor is being sent, then each scan-line will
547 * consume 10 bytes (3 pixels per scan-line multiplied by 3 bytes per pixel, rounded up to
548 * the next even number of bytes).
549 *
550 * In fact instead of 24-bpp, the bpp parameter is given by the containing packet.
551 */
552 if (Stream_GetRemainingLength(s) < pointer->lengthXorMask)
553 goto fail;
554
555 scanlineSize = (7 + pointer->xorBpp * pointer->width) / 8;
556 scanlineSize = ((scanlineSize + 1) / 2) * 2;
557
558 if (scanlineSize * pointer->height != pointer->lengthXorMask)
559 {
560 WLog_ERR(TAG,
561 "invalid lengthXorMask: width=%" PRIu32 " height=%" PRIu32 ", %" PRIu32
562 " instead of %" PRIu32 "",
563 pointer->width, pointer->height, pointer->lengthXorMask,
564 scanlineSize * pointer->height);
565 goto fail;
566 }
567
568 newMask = realloc(pointer->xorMaskData, pointer->lengthXorMask);
569
570 if (!newMask)
571 goto fail;
572
573 pointer->xorMaskData = newMask;
574 Stream_Read(s, pointer->xorMaskData, pointer->lengthXorMask);
575 }
576
577 if (pointer->lengthAndMask > 0)
578 {
579 /**
580 * andMaskData (variable): A variable-length array of bytes. Contains the 1-bpp, bottom-up
581 * AND mask scan-line data. The AND mask is padded to a 2-byte boundary for each encoded
582 * scan-line. For example, if a 7x7 pixel cursor is being sent, then each scan-line will
583 * consume 2 bytes (7 pixels per scan-line multiplied by 1 bpp, rounded up to the next even
584 * number of bytes).
585 */
586 if (Stream_GetRemainingLength(s) < pointer->lengthAndMask)
587 goto fail;
588
589 scanlineSize = ((7 + pointer->width) / 8);
590 scanlineSize = ((1 + scanlineSize) / 2) * 2;
591
592 if (scanlineSize * pointer->height != pointer->lengthAndMask)
593 {
594 WLog_ERR(TAG, "invalid lengthAndMask: %" PRIu32 " instead of %" PRIu32 "",
595 pointer->lengthAndMask, scanlineSize * pointer->height);
596 goto fail;
597 }
598
599 newMask = realloc(pointer->andMaskData, pointer->lengthAndMask);
600
601 if (!newMask)
602 goto fail;
603
604 pointer->andMaskData = newMask;
605 Stream_Read(s, pointer->andMaskData, pointer->lengthAndMask);
606 }
607
608 if (Stream_GetRemainingLength(s) > 0)
609 Stream_Seek_UINT8(s); /* pad (1 byte) */
610
611 return TRUE;
612 fail:
613 return FALSE;
614 }
615
update_read_pointer_large(rdpUpdate * update,wStream * s)616 POINTER_LARGE_UPDATE* update_read_pointer_large(rdpUpdate* update, wStream* s)
617 {
618 POINTER_LARGE_UPDATE* pointer = calloc(1, sizeof(POINTER_LARGE_UPDATE));
619
620 if (!pointer)
621 goto fail;
622
623 if (!_update_read_pointer_large(s, pointer))
624 goto fail;
625
626 return pointer;
627 fail:
628 free_pointer_large_update(update->context, pointer);
629 return NULL;
630 }
631
update_read_pointer_new(rdpUpdate * update,wStream * s)632 POINTER_NEW_UPDATE* update_read_pointer_new(rdpUpdate* update, wStream* s)
633 {
634 POINTER_NEW_UPDATE* pointer_new = calloc(1, sizeof(POINTER_NEW_UPDATE));
635
636 if (!pointer_new)
637 goto fail;
638
639 if (Stream_GetRemainingLength(s) < 2)
640 goto fail;
641
642 Stream_Read_UINT16(s, pointer_new->xorBpp); /* xorBpp (2 bytes) */
643
644 if ((pointer_new->xorBpp < 1) || (pointer_new->xorBpp > 32))
645 {
646 WLog_ERR(TAG, "invalid xorBpp %" PRIu32 "", pointer_new->xorBpp);
647 goto fail;
648 }
649
650 if (!_update_read_pointer_color(s, &pointer_new->colorPtrAttr, pointer_new->xorBpp,
651 update->context->settings->LargePointerFlag)) /* colorPtrAttr */
652 goto fail;
653
654 return pointer_new;
655 fail:
656 free_pointer_new_update(update->context, pointer_new);
657 return NULL;
658 }
659
update_read_pointer_cached(rdpUpdate * update,wStream * s)660 POINTER_CACHED_UPDATE* update_read_pointer_cached(rdpUpdate* update, wStream* s)
661 {
662 POINTER_CACHED_UPDATE* pointer = calloc(1, sizeof(POINTER_CACHED_UPDATE));
663
664 if (!pointer)
665 goto fail;
666
667 if (Stream_GetRemainingLength(s) < 2)
668 goto fail;
669
670 Stream_Read_UINT16(s, pointer->cacheIndex); /* cacheIndex (2 bytes) */
671 return pointer;
672 fail:
673 free_pointer_cached_update(update->context, pointer);
674 return NULL;
675 }
676
update_recv_pointer(rdpUpdate * update,wStream * s)677 BOOL update_recv_pointer(rdpUpdate* update, wStream* s)
678 {
679 BOOL rc = FALSE;
680 UINT16 messageType;
681 rdpContext* context = update->context;
682 rdpPointerUpdate* pointer = update->pointer;
683
684 if (Stream_GetRemainingLength(s) < 2 + 2)
685 return FALSE;
686
687 Stream_Read_UINT16(s, messageType); /* messageType (2 bytes) */
688 Stream_Seek_UINT16(s); /* pad2Octets (2 bytes) */
689
690 switch (messageType)
691 {
692 case PTR_MSG_TYPE_POSITION:
693 {
694 POINTER_POSITION_UPDATE* pointer_position = update_read_pointer_position(update, s);
695
696 if (pointer_position)
697 {
698 rc = IFCALLRESULT(FALSE, pointer->PointerPosition, context, pointer_position);
699 free_pointer_position_update(context, pointer_position);
700 }
701 }
702 break;
703
704 case PTR_MSG_TYPE_SYSTEM:
705 {
706 POINTER_SYSTEM_UPDATE* pointer_system = update_read_pointer_system(update, s);
707
708 if (pointer_system)
709 {
710 rc = IFCALLRESULT(FALSE, pointer->PointerSystem, context, pointer_system);
711 free_pointer_system_update(context, pointer_system);
712 }
713 }
714 break;
715
716 case PTR_MSG_TYPE_COLOR:
717 {
718 POINTER_COLOR_UPDATE* pointer_color = update_read_pointer_color(update, s, 24);
719
720 if (pointer_color)
721 {
722 rc = IFCALLRESULT(FALSE, pointer->PointerColor, context, pointer_color);
723 free_pointer_color_update(context, pointer_color);
724 }
725 }
726 break;
727
728 case PTR_MSG_TYPE_POINTER_LARGE:
729 {
730 POINTER_LARGE_UPDATE* pointer_large = update_read_pointer_large(update, s);
731
732 if (pointer_large)
733 {
734 rc = IFCALLRESULT(FALSE, pointer->PointerLarge, context, pointer_large);
735 free_pointer_large_update(context, pointer_large);
736 }
737 }
738 break;
739
740 case PTR_MSG_TYPE_POINTER:
741 {
742 POINTER_NEW_UPDATE* pointer_new = update_read_pointer_new(update, s);
743
744 if (pointer_new)
745 {
746 rc = IFCALLRESULT(FALSE, pointer->PointerNew, context, pointer_new);
747 free_pointer_new_update(context, pointer_new);
748 }
749 }
750 break;
751
752 case PTR_MSG_TYPE_CACHED:
753 {
754 POINTER_CACHED_UPDATE* pointer_cached = update_read_pointer_cached(update, s);
755
756 if (pointer_cached)
757 {
758 rc = IFCALLRESULT(FALSE, pointer->PointerCached, context, pointer_cached);
759 free_pointer_cached_update(context, pointer_cached);
760 }
761 }
762 break;
763
764 default:
765 break;
766 }
767
768 return rc;
769 }
770
update_recv(rdpUpdate * update,wStream * s)771 BOOL update_recv(rdpUpdate* update, wStream* s)
772 {
773 BOOL rc = FALSE;
774 UINT16 updateType;
775 rdpContext* context = update->context;
776
777 if (Stream_GetRemainingLength(s) < 2)
778 {
779 WLog_ERR(TAG, "Stream_GetRemainingLength(s) < 2");
780 return FALSE;
781 }
782
783 Stream_Read_UINT16(s, updateType); /* updateType (2 bytes) */
784 WLog_Print(update->log, WLOG_TRACE, "%s Update Data PDU", update_type_to_string(updateType));
785
786 if (!update_begin_paint(update))
787 goto fail;
788
789 switch (updateType)
790 {
791 case UPDATE_TYPE_ORDERS:
792 rc = update_recv_orders(update, s);
793 break;
794
795 case UPDATE_TYPE_BITMAP:
796 {
797 BITMAP_UPDATE* bitmap_update = update_read_bitmap_update(update, s);
798
799 if (!bitmap_update)
800 {
801 WLog_ERR(TAG, "UPDATE_TYPE_BITMAP - update_read_bitmap_update() failed");
802 goto fail;
803 }
804
805 rc = IFCALLRESULT(FALSE, update->BitmapUpdate, context, bitmap_update);
806 free_bitmap_update(update->context, bitmap_update);
807 }
808 break;
809
810 case UPDATE_TYPE_PALETTE:
811 {
812 PALETTE_UPDATE* palette_update = update_read_palette(update, s);
813
814 if (!palette_update)
815 {
816 WLog_ERR(TAG, "UPDATE_TYPE_PALETTE - update_read_palette() failed");
817 goto fail;
818 }
819
820 rc = IFCALLRESULT(FALSE, update->Palette, context, palette_update);
821 free_palette_update(context, palette_update);
822 }
823 break;
824
825 case UPDATE_TYPE_SYNCHRONIZE:
826 if (!update_read_synchronize(update, s))
827 goto fail;
828 rc = IFCALLRESULT(TRUE, update->Synchronize, context);
829 break;
830
831 default:
832 break;
833 }
834
835 fail:
836
837 if (!update_end_paint(update))
838 rc = FALSE;
839
840 if (!rc)
841 {
842 WLog_ERR(TAG, "UPDATE_TYPE %s [%" PRIu16 "] failed", update_type_to_string(updateType),
843 updateType);
844 return FALSE;
845 }
846
847 return TRUE;
848 }
849
update_reset_state(rdpUpdate * update)850 void update_reset_state(rdpUpdate* update)
851 {
852 rdpPrimaryUpdate* primary = update->primary;
853 rdpAltSecUpdate* altsec = update->altsec;
854
855 if (primary->fast_glyph.glyphData.aj)
856 {
857 free(primary->fast_glyph.glyphData.aj);
858 primary->fast_glyph.glyphData.aj = NULL;
859 }
860
861 ZeroMemory(&primary->order_info, sizeof(ORDER_INFO));
862 ZeroMemory(&primary->dstblt, sizeof(DSTBLT_ORDER));
863 ZeroMemory(&primary->patblt, sizeof(PATBLT_ORDER));
864 ZeroMemory(&primary->scrblt, sizeof(SCRBLT_ORDER));
865 ZeroMemory(&primary->opaque_rect, sizeof(OPAQUE_RECT_ORDER));
866 ZeroMemory(&primary->draw_nine_grid, sizeof(DRAW_NINE_GRID_ORDER));
867 ZeroMemory(&primary->multi_dstblt, sizeof(MULTI_DSTBLT_ORDER));
868 ZeroMemory(&primary->multi_patblt, sizeof(MULTI_PATBLT_ORDER));
869 ZeroMemory(&primary->multi_scrblt, sizeof(MULTI_SCRBLT_ORDER));
870 ZeroMemory(&primary->multi_opaque_rect, sizeof(MULTI_OPAQUE_RECT_ORDER));
871 ZeroMemory(&primary->multi_draw_nine_grid, sizeof(MULTI_DRAW_NINE_GRID_ORDER));
872 ZeroMemory(&primary->line_to, sizeof(LINE_TO_ORDER));
873 ZeroMemory(&primary->polyline, sizeof(POLYLINE_ORDER));
874 ZeroMemory(&primary->memblt, sizeof(MEMBLT_ORDER));
875 ZeroMemory(&primary->mem3blt, sizeof(MEM3BLT_ORDER));
876 ZeroMemory(&primary->save_bitmap, sizeof(SAVE_BITMAP_ORDER));
877 ZeroMemory(&primary->glyph_index, sizeof(GLYPH_INDEX_ORDER));
878 ZeroMemory(&primary->fast_index, sizeof(FAST_INDEX_ORDER));
879 ZeroMemory(&primary->fast_glyph, sizeof(FAST_GLYPH_ORDER));
880 ZeroMemory(&primary->polygon_sc, sizeof(POLYGON_SC_ORDER));
881 ZeroMemory(&primary->polygon_cb, sizeof(POLYGON_CB_ORDER));
882 ZeroMemory(&primary->ellipse_sc, sizeof(ELLIPSE_SC_ORDER));
883 ZeroMemory(&primary->ellipse_cb, sizeof(ELLIPSE_CB_ORDER));
884 primary->order_info.orderType = ORDER_TYPE_PATBLT;
885
886 if (!update->initialState)
887 {
888 altsec->switch_surface.bitmapId = SCREEN_BITMAP_SURFACE;
889 IFCALL(altsec->SwitchSurface, update->context, &(altsec->switch_surface));
890 }
891 }
892
update_post_connect(rdpUpdate * update)893 BOOL update_post_connect(rdpUpdate* update)
894 {
895 update->asynchronous = update->context->settings->AsyncUpdate;
896
897 if (update->asynchronous)
898 if (!(update->proxy = update_message_proxy_new(update)))
899 return FALSE;
900
901 update->altsec->switch_surface.bitmapId = SCREEN_BITMAP_SURFACE;
902 IFCALL(update->altsec->SwitchSurface, update->context, &(update->altsec->switch_surface));
903 update->initialState = FALSE;
904 return TRUE;
905 }
906
update_post_disconnect(rdpUpdate * update)907 void update_post_disconnect(rdpUpdate* update)
908 {
909 update->asynchronous = update->context->settings->AsyncUpdate;
910
911 if (update->asynchronous)
912 update_message_proxy_free(update->proxy);
913
914 update->initialState = TRUE;
915 }
916
_update_begin_paint(rdpContext * context)917 static BOOL _update_begin_paint(rdpContext* context)
918 {
919 wStream* s;
920 rdpUpdate* update = context->update;
921
922 if (update->us)
923 {
924 if (!update_end_paint(update))
925 return FALSE;
926 }
927
928 s = fastpath_update_pdu_init_new(context->rdp->fastpath);
929
930 if (!s)
931 return FALSE;
932
933 Stream_SealLength(s);
934 Stream_GetLength(s, update->offsetOrders);
935 Stream_Seek(s, 2); /* numberOrders (2 bytes) */
936 update->combineUpdates = TRUE;
937 update->numberOrders = 0;
938 update->us = s;
939 return TRUE;
940 }
941
_update_end_paint(rdpContext * context)942 static BOOL _update_end_paint(rdpContext* context)
943 {
944 wStream* s;
945 rdpUpdate* update = context->update;
946
947 if (!update->us)
948 return FALSE;
949
950 s = update->us;
951 Stream_SealLength(s);
952 Stream_SetPosition(s, update->offsetOrders);
953 Stream_Write_UINT16(s, update->numberOrders); /* numberOrders (2 bytes) */
954 Stream_SetPosition(s, Stream_Length(s));
955
956 if (update->numberOrders > 0)
957 {
958 WLog_DBG(TAG, "sending %" PRIu16 " orders", update->numberOrders);
959 fastpath_send_update_pdu(context->rdp->fastpath, FASTPATH_UPDATETYPE_ORDERS, s, FALSE);
960 }
961
962 update->combineUpdates = FALSE;
963 update->numberOrders = 0;
964 update->offsetOrders = 0;
965 update->us = NULL;
966 Stream_Free(s, TRUE);
967 return TRUE;
968 }
969
update_flush(rdpContext * context)970 static void update_flush(rdpContext* context)
971 {
972 rdpUpdate* update = context->update;
973
974 if (update->numberOrders > 0)
975 {
976 update_end_paint(update);
977 update_begin_paint(update);
978 }
979 }
980
update_force_flush(rdpContext * context)981 static void update_force_flush(rdpContext* context)
982 {
983 update_flush(context);
984 }
985
update_check_flush(rdpContext * context,int size)986 static BOOL update_check_flush(rdpContext* context, int size)
987 {
988 wStream* s;
989 rdpUpdate* update = context->update;
990 s = update->us;
991
992 if (!update->us)
993 {
994 update_begin_paint(update);
995 return FALSE;
996 }
997
998 if (Stream_GetPosition(s) + size + 64 >= 0x3FFF)
999 {
1000 update_flush(context);
1001 return TRUE;
1002 }
1003
1004 return FALSE;
1005 }
1006
update_set_bounds(rdpContext * context,const rdpBounds * bounds)1007 static BOOL update_set_bounds(rdpContext* context, const rdpBounds* bounds)
1008 {
1009 rdpUpdate* update = context->update;
1010 CopyMemory(&update->previousBounds, &update->currentBounds, sizeof(rdpBounds));
1011
1012 if (!bounds)
1013 ZeroMemory(&update->currentBounds, sizeof(rdpBounds));
1014 else
1015 CopyMemory(&update->currentBounds, bounds, sizeof(rdpBounds));
1016
1017 return TRUE;
1018 }
1019
update_bounds_is_null(rdpBounds * bounds)1020 static BOOL update_bounds_is_null(rdpBounds* bounds)
1021 {
1022 if ((bounds->left == 0) && (bounds->top == 0) && (bounds->right == 0) && (bounds->bottom == 0))
1023 return TRUE;
1024
1025 return FALSE;
1026 }
1027
update_bounds_equals(rdpBounds * bounds1,rdpBounds * bounds2)1028 static BOOL update_bounds_equals(rdpBounds* bounds1, rdpBounds* bounds2)
1029 {
1030 if ((bounds1->left == bounds2->left) && (bounds1->top == bounds2->top) &&
1031 (bounds1->right == bounds2->right) && (bounds1->bottom == bounds2->bottom))
1032 return TRUE;
1033
1034 return FALSE;
1035 }
1036
update_prepare_bounds(rdpContext * context,ORDER_INFO * orderInfo)1037 static int update_prepare_bounds(rdpContext* context, ORDER_INFO* orderInfo)
1038 {
1039 int length = 0;
1040 rdpUpdate* update = context->update;
1041 orderInfo->boundsFlags = 0;
1042
1043 if (update_bounds_is_null(&update->currentBounds))
1044 return 0;
1045
1046 orderInfo->controlFlags |= ORDER_BOUNDS;
1047
1048 if (update_bounds_equals(&update->previousBounds, &update->currentBounds))
1049 {
1050 orderInfo->controlFlags |= ORDER_ZERO_BOUNDS_DELTAS;
1051 return 0;
1052 }
1053 else
1054 {
1055 length += 1;
1056
1057 if (update->previousBounds.left != update->currentBounds.left)
1058 {
1059 orderInfo->bounds.left = update->currentBounds.left;
1060 orderInfo->boundsFlags |= BOUND_LEFT;
1061 length += 2;
1062 }
1063
1064 if (update->previousBounds.top != update->currentBounds.top)
1065 {
1066 orderInfo->bounds.top = update->currentBounds.top;
1067 orderInfo->boundsFlags |= BOUND_TOP;
1068 length += 2;
1069 }
1070
1071 if (update->previousBounds.right != update->currentBounds.right)
1072 {
1073 orderInfo->bounds.right = update->currentBounds.right;
1074 orderInfo->boundsFlags |= BOUND_RIGHT;
1075 length += 2;
1076 }
1077
1078 if (update->previousBounds.bottom != update->currentBounds.bottom)
1079 {
1080 orderInfo->bounds.bottom = update->currentBounds.bottom;
1081 orderInfo->boundsFlags |= BOUND_BOTTOM;
1082 length += 2;
1083 }
1084 }
1085
1086 return length;
1087 }
1088
update_prepare_order_info(rdpContext * context,ORDER_INFO * orderInfo,UINT32 orderType)1089 static int update_prepare_order_info(rdpContext* context, ORDER_INFO* orderInfo, UINT32 orderType)
1090 {
1091 int length = 1;
1092 orderInfo->fieldFlags = 0;
1093 orderInfo->orderType = orderType;
1094 orderInfo->controlFlags = ORDER_STANDARD;
1095 orderInfo->controlFlags |= ORDER_TYPE_CHANGE;
1096 length += 1;
1097 length += get_primary_drawing_order_field_bytes(orderInfo->orderType, NULL);
1098 length += update_prepare_bounds(context, orderInfo);
1099 return length;
1100 }
1101
update_write_order_info(rdpContext * context,wStream * s,ORDER_INFO * orderInfo,size_t offset)1102 static int update_write_order_info(rdpContext* context, wStream* s, ORDER_INFO* orderInfo,
1103 size_t offset)
1104 {
1105 size_t position;
1106 WINPR_UNUSED(context);
1107 position = Stream_GetPosition(s);
1108 Stream_SetPosition(s, offset);
1109 Stream_Write_UINT8(s, orderInfo->controlFlags); /* controlFlags (1 byte) */
1110
1111 if (orderInfo->controlFlags & ORDER_TYPE_CHANGE)
1112 Stream_Write_UINT8(s, orderInfo->orderType); /* orderType (1 byte) */
1113
1114 update_write_field_flags(s, orderInfo->fieldFlags, orderInfo->controlFlags,
1115 get_primary_drawing_order_field_bytes(orderInfo->orderType, NULL));
1116 update_write_bounds(s, orderInfo);
1117 Stream_SetPosition(s, position);
1118 return 0;
1119 }
1120
update_write_refresh_rect(wStream * s,BYTE count,const RECTANGLE_16 * areas)1121 static void update_write_refresh_rect(wStream* s, BYTE count, const RECTANGLE_16* areas)
1122 {
1123 int i;
1124 Stream_Write_UINT8(s, count); /* numberOfAreas (1 byte) */
1125 Stream_Seek(s, 3); /* pad3Octets (3 bytes) */
1126
1127 for (i = 0; i < count; i++)
1128 {
1129 Stream_Write_UINT16(s, areas[i].left); /* left (2 bytes) */
1130 Stream_Write_UINT16(s, areas[i].top); /* top (2 bytes) */
1131 Stream_Write_UINT16(s, areas[i].right); /* right (2 bytes) */
1132 Stream_Write_UINT16(s, areas[i].bottom); /* bottom (2 bytes) */
1133 }
1134 }
1135
update_send_refresh_rect(rdpContext * context,BYTE count,const RECTANGLE_16 * areas)1136 static BOOL update_send_refresh_rect(rdpContext* context, BYTE count, const RECTANGLE_16* areas)
1137 {
1138 rdpRdp* rdp = context->rdp;
1139
1140 if (rdp->settings->RefreshRect)
1141 {
1142 wStream* s = rdp_data_pdu_init(rdp);
1143
1144 if (!s)
1145 return FALSE;
1146
1147 update_write_refresh_rect(s, count, areas);
1148 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_REFRESH_RECT, rdp->mcs->userId);
1149 }
1150
1151 return TRUE;
1152 }
1153
update_write_suppress_output(wStream * s,BYTE allow,const RECTANGLE_16 * area)1154 static void update_write_suppress_output(wStream* s, BYTE allow, const RECTANGLE_16* area)
1155 {
1156 Stream_Write_UINT8(s, allow); /* allowDisplayUpdates (1 byte) */
1157 /* Use zeros for padding (like mstsc) for compatibility with legacy servers */
1158 Stream_Zero(s, 3); /* pad3Octets (3 bytes) */
1159
1160 if (allow > 0)
1161 {
1162 Stream_Write_UINT16(s, area->left); /* left (2 bytes) */
1163 Stream_Write_UINT16(s, area->top); /* top (2 bytes) */
1164 Stream_Write_UINT16(s, area->right); /* right (2 bytes) */
1165 Stream_Write_UINT16(s, area->bottom); /* bottom (2 bytes) */
1166 }
1167 }
1168
update_send_suppress_output(rdpContext * context,BYTE allow,const RECTANGLE_16 * area)1169 static BOOL update_send_suppress_output(rdpContext* context, BYTE allow, const RECTANGLE_16* area)
1170 {
1171 rdpRdp* rdp = context->rdp;
1172
1173 if (rdp->settings->SuppressOutput)
1174 {
1175 wStream* s = rdp_data_pdu_init(rdp);
1176
1177 if (!s)
1178 return FALSE;
1179
1180 update_write_suppress_output(s, allow, area);
1181 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SUPPRESS_OUTPUT, rdp->mcs->userId);
1182 }
1183
1184 return TRUE;
1185 }
1186
update_send_surface_command(rdpContext * context,wStream * s)1187 static BOOL update_send_surface_command(rdpContext* context, wStream* s)
1188 {
1189 wStream* update;
1190 rdpRdp* rdp = context->rdp;
1191 BOOL ret;
1192 update = fastpath_update_pdu_init(rdp->fastpath);
1193
1194 if (!update)
1195 return FALSE;
1196
1197 if (!Stream_EnsureRemainingCapacity(update, Stream_GetPosition(s)))
1198 {
1199 ret = FALSE;
1200 goto out;
1201 }
1202
1203 Stream_Write(update, Stream_Buffer(s), Stream_GetPosition(s));
1204 ret = fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, update, FALSE);
1205 out:
1206 Stream_Release(update);
1207 return ret;
1208 }
1209
update_send_surface_bits(rdpContext * context,const SURFACE_BITS_COMMAND * surfaceBitsCommand)1210 static BOOL update_send_surface_bits(rdpContext* context,
1211 const SURFACE_BITS_COMMAND* surfaceBitsCommand)
1212 {
1213 wStream* s;
1214 rdpRdp* rdp = context->rdp;
1215 BOOL ret = FALSE;
1216 update_force_flush(context);
1217 s = fastpath_update_pdu_init(rdp->fastpath);
1218
1219 if (!s)
1220 return FALSE;
1221
1222 if (!update_write_surfcmd_surface_bits(s, surfaceBitsCommand))
1223 goto out_fail;
1224
1225 if (!fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, s,
1226 surfaceBitsCommand->skipCompression))
1227 goto out_fail;
1228
1229 update_force_flush(context);
1230 ret = TRUE;
1231 out_fail:
1232 Stream_Release(s);
1233 return ret;
1234 }
1235
update_send_surface_frame_marker(rdpContext * context,const SURFACE_FRAME_MARKER * surfaceFrameMarker)1236 static BOOL update_send_surface_frame_marker(rdpContext* context,
1237 const SURFACE_FRAME_MARKER* surfaceFrameMarker)
1238 {
1239 wStream* s;
1240 rdpRdp* rdp = context->rdp;
1241 BOOL ret = FALSE;
1242 update_force_flush(context);
1243 s = fastpath_update_pdu_init(rdp->fastpath);
1244
1245 if (!s)
1246 return FALSE;
1247
1248 if (!update_write_surfcmd_frame_marker(s, surfaceFrameMarker->frameAction,
1249 surfaceFrameMarker->frameId) ||
1250 !fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, s, FALSE))
1251 goto out_fail;
1252
1253 update_force_flush(context);
1254 ret = TRUE;
1255 out_fail:
1256 Stream_Release(s);
1257 return ret;
1258 }
1259
update_send_surface_frame_bits(rdpContext * context,const SURFACE_BITS_COMMAND * cmd,BOOL first,BOOL last,UINT32 frameId)1260 static BOOL update_send_surface_frame_bits(rdpContext* context, const SURFACE_BITS_COMMAND* cmd,
1261 BOOL first, BOOL last, UINT32 frameId)
1262 {
1263 wStream* s;
1264 rdpRdp* rdp = context->rdp;
1265 BOOL ret = FALSE;
1266 update_force_flush(context);
1267 s = fastpath_update_pdu_init(rdp->fastpath);
1268
1269 if (!s)
1270 return FALSE;
1271
1272 if (first)
1273 {
1274 if (!update_write_surfcmd_frame_marker(s, SURFACECMD_FRAMEACTION_BEGIN, frameId))
1275 goto out_fail;
1276 }
1277
1278 if (!update_write_surfcmd_surface_bits(s, cmd))
1279 goto out_fail;
1280
1281 if (last)
1282 {
1283 if (!update_write_surfcmd_frame_marker(s, SURFACECMD_FRAMEACTION_END, frameId))
1284 goto out_fail;
1285 }
1286
1287 ret = fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, s,
1288 cmd->skipCompression);
1289 update_force_flush(context);
1290 out_fail:
1291 Stream_Release(s);
1292 return ret;
1293 }
1294
update_send_frame_acknowledge(rdpContext * context,UINT32 frameId)1295 static BOOL update_send_frame_acknowledge(rdpContext* context, UINT32 frameId)
1296 {
1297 rdpRdp* rdp = context->rdp;
1298
1299 if (rdp->settings->ReceivedCapabilities[CAPSET_TYPE_FRAME_ACKNOWLEDGE])
1300 {
1301 wStream* s = rdp_data_pdu_init(rdp);
1302
1303 if (!s)
1304 return FALSE;
1305
1306 Stream_Write_UINT32(s, frameId);
1307 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_FRAME_ACKNOWLEDGE, rdp->mcs->userId);
1308 }
1309
1310 return TRUE;
1311 }
1312
update_send_synchronize(rdpContext * context)1313 static BOOL update_send_synchronize(rdpContext* context)
1314 {
1315 wStream* s;
1316 rdpRdp* rdp = context->rdp;
1317 BOOL ret;
1318 s = fastpath_update_pdu_init(rdp->fastpath);
1319
1320 if (!s)
1321 return FALSE;
1322
1323 Stream_Zero(s, 2); /* pad2Octets (2 bytes) */
1324 ret = fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SYNCHRONIZE, s, FALSE);
1325 Stream_Release(s);
1326 return ret;
1327 }
1328
update_send_desktop_resize(rdpContext * context)1329 static BOOL update_send_desktop_resize(rdpContext* context)
1330 {
1331 return rdp_server_reactivate(context->rdp);
1332 }
1333
update_send_bitmap_update(rdpContext * context,const BITMAP_UPDATE * bitmapUpdate)1334 static BOOL update_send_bitmap_update(rdpContext* context, const BITMAP_UPDATE* bitmapUpdate)
1335 {
1336 wStream* s;
1337 rdpRdp* rdp = context->rdp;
1338 rdpUpdate* update = context->update;
1339 BOOL ret = TRUE;
1340 update_force_flush(context);
1341 s = fastpath_update_pdu_init(rdp->fastpath);
1342
1343 if (!s)
1344 return FALSE;
1345
1346 if (!update_write_bitmap_update(update, s, bitmapUpdate) ||
1347 !fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_BITMAP, s,
1348 bitmapUpdate->skipCompression))
1349 {
1350 ret = FALSE;
1351 goto out_fail;
1352 }
1353
1354 update_force_flush(context);
1355 out_fail:
1356 Stream_Release(s);
1357 return ret;
1358 }
1359
update_send_play_sound(rdpContext * context,const PLAY_SOUND_UPDATE * play_sound)1360 static BOOL update_send_play_sound(rdpContext* context, const PLAY_SOUND_UPDATE* play_sound)
1361 {
1362 wStream* s;
1363 rdpRdp* rdp = context->rdp;
1364
1365 if (!rdp->settings->ReceivedCapabilities[CAPSET_TYPE_SOUND])
1366 {
1367 return TRUE;
1368 }
1369
1370 s = rdp_data_pdu_init(rdp);
1371
1372 if (!s)
1373 return FALSE;
1374
1375 Stream_Write_UINT32(s, play_sound->duration);
1376 Stream_Write_UINT32(s, play_sound->frequency);
1377 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_PLAY_SOUND, rdp->mcs->userId);
1378 }
1379
1380 /**
1381 * Primary Drawing Orders
1382 */
1383
update_send_dstblt(rdpContext * context,const DSTBLT_ORDER * dstblt)1384 static BOOL update_send_dstblt(rdpContext* context, const DSTBLT_ORDER* dstblt)
1385 {
1386 wStream* s;
1387 UINT32 offset;
1388 UINT32 headerLength;
1389 ORDER_INFO orderInfo;
1390 int inf;
1391 rdpUpdate* update = context->update;
1392 headerLength = update_prepare_order_info(context, &orderInfo, ORDER_TYPE_DSTBLT);
1393 inf = update_approximate_dstblt_order(&orderInfo, dstblt);
1394 update_check_flush(context, headerLength + inf);
1395 s = update->us;
1396
1397 if (!s)
1398 return FALSE;
1399
1400 offset = Stream_GetPosition(s);
1401
1402 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1403 return FALSE;
1404
1405 Stream_Seek(s, headerLength);
1406
1407 if (!update_write_dstblt_order(s, &orderInfo, dstblt))
1408 return FALSE;
1409
1410 update_write_order_info(context, s, &orderInfo, offset);
1411 update->numberOrders++;
1412 return TRUE;
1413 }
1414
update_send_patblt(rdpContext * context,PATBLT_ORDER * patblt)1415 static BOOL update_send_patblt(rdpContext* context, PATBLT_ORDER* patblt)
1416 {
1417 wStream* s;
1418 size_t offset;
1419 int headerLength;
1420 ORDER_INFO orderInfo;
1421 rdpUpdate* update = context->update;
1422 headerLength = update_prepare_order_info(context, &orderInfo, ORDER_TYPE_PATBLT);
1423 update_check_flush(context, headerLength + update_approximate_patblt_order(&orderInfo, patblt));
1424 s = update->us;
1425
1426 if (!s)
1427 return FALSE;
1428
1429 offset = Stream_GetPosition(s);
1430
1431 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1432 return FALSE;
1433
1434 Stream_Seek(s, headerLength);
1435 update_write_patblt_order(s, &orderInfo, patblt);
1436 update_write_order_info(context, s, &orderInfo, offset);
1437 update->numberOrders++;
1438 return TRUE;
1439 }
1440
update_send_scrblt(rdpContext * context,const SCRBLT_ORDER * scrblt)1441 static BOOL update_send_scrblt(rdpContext* context, const SCRBLT_ORDER* scrblt)
1442 {
1443 wStream* s;
1444 UINT32 offset;
1445 UINT32 headerLength;
1446 ORDER_INFO orderInfo;
1447 int inf;
1448 rdpUpdate* update = context->update;
1449 headerLength = update_prepare_order_info(context, &orderInfo, ORDER_TYPE_SCRBLT);
1450 inf = update_approximate_scrblt_order(&orderInfo, scrblt);
1451 update_check_flush(context, headerLength + inf);
1452 s = update->us;
1453
1454 if (!s)
1455 return TRUE;
1456
1457 offset = Stream_GetPosition(s);
1458
1459 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1460 return FALSE;
1461
1462 Stream_Seek(s, headerLength);
1463 update_write_scrblt_order(s, &orderInfo, scrblt);
1464 update_write_order_info(context, s, &orderInfo, offset);
1465 update->numberOrders++;
1466 return TRUE;
1467 }
1468
update_send_opaque_rect(rdpContext * context,const OPAQUE_RECT_ORDER * opaque_rect)1469 static BOOL update_send_opaque_rect(rdpContext* context, const OPAQUE_RECT_ORDER* opaque_rect)
1470 {
1471 wStream* s;
1472 size_t offset;
1473 int headerLength;
1474 ORDER_INFO orderInfo;
1475 rdpUpdate* update = context->update;
1476 headerLength = update_prepare_order_info(context, &orderInfo, ORDER_TYPE_OPAQUE_RECT);
1477 update_check_flush(context, headerLength +
1478 update_approximate_opaque_rect_order(&orderInfo, opaque_rect));
1479 s = update->us;
1480
1481 if (!s)
1482 return FALSE;
1483
1484 offset = Stream_GetPosition(s);
1485
1486 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1487 return FALSE;
1488
1489 Stream_Seek(s, headerLength);
1490 update_write_opaque_rect_order(s, &orderInfo, opaque_rect);
1491 update_write_order_info(context, s, &orderInfo, offset);
1492 update->numberOrders++;
1493 return TRUE;
1494 }
1495
update_send_line_to(rdpContext * context,const LINE_TO_ORDER * line_to)1496 static BOOL update_send_line_to(rdpContext* context, const LINE_TO_ORDER* line_to)
1497 {
1498 wStream* s;
1499 int offset;
1500 int headerLength;
1501 ORDER_INFO orderInfo;
1502 int inf;
1503 rdpUpdate* update = context->update;
1504 headerLength = update_prepare_order_info(context, &orderInfo, ORDER_TYPE_LINE_TO);
1505 inf = update_approximate_line_to_order(&orderInfo, line_to);
1506 update_check_flush(context, headerLength + inf);
1507 s = update->us;
1508
1509 if (!s)
1510 return FALSE;
1511
1512 offset = Stream_GetPosition(s);
1513
1514 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1515 return FALSE;
1516
1517 Stream_Seek(s, headerLength);
1518 update_write_line_to_order(s, &orderInfo, line_to);
1519 update_write_order_info(context, s, &orderInfo, offset);
1520 update->numberOrders++;
1521 return TRUE;
1522 }
1523
update_send_memblt(rdpContext * context,MEMBLT_ORDER * memblt)1524 static BOOL update_send_memblt(rdpContext* context, MEMBLT_ORDER* memblt)
1525 {
1526 wStream* s;
1527 size_t offset;
1528 int headerLength;
1529 ORDER_INFO orderInfo;
1530 rdpUpdate* update = context->update;
1531 headerLength = update_prepare_order_info(context, &orderInfo, ORDER_TYPE_MEMBLT);
1532 update_check_flush(context, headerLength + update_approximate_memblt_order(&orderInfo, memblt));
1533 s = update->us;
1534
1535 if (!s)
1536 return FALSE;
1537
1538 offset = Stream_GetPosition(s);
1539
1540 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1541 return FALSE;
1542
1543 Stream_Seek(s, headerLength);
1544 update_write_memblt_order(s, &orderInfo, memblt);
1545 update_write_order_info(context, s, &orderInfo, offset);
1546 update->numberOrders++;
1547 return TRUE;
1548 }
1549
update_send_glyph_index(rdpContext * context,GLYPH_INDEX_ORDER * glyph_index)1550 static BOOL update_send_glyph_index(rdpContext* context, GLYPH_INDEX_ORDER* glyph_index)
1551 {
1552 wStream* s;
1553 size_t offset;
1554 int headerLength;
1555 int inf;
1556 ORDER_INFO orderInfo;
1557 rdpUpdate* update = context->update;
1558 headerLength = update_prepare_order_info(context, &orderInfo, ORDER_TYPE_GLYPH_INDEX);
1559 inf = update_approximate_glyph_index_order(&orderInfo, glyph_index);
1560 update_check_flush(context, headerLength + inf);
1561 s = update->us;
1562
1563 if (!s)
1564 return FALSE;
1565
1566 offset = Stream_GetPosition(s);
1567
1568 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1569 return FALSE;
1570
1571 Stream_Seek(s, headerLength);
1572 update_write_glyph_index_order(s, &orderInfo, glyph_index);
1573 update_write_order_info(context, s, &orderInfo, offset);
1574 update->numberOrders++;
1575 return TRUE;
1576 }
1577
1578 /*
1579 * Secondary Drawing Orders
1580 */
1581
update_send_cache_bitmap(rdpContext * context,const CACHE_BITMAP_ORDER * cache_bitmap)1582 static BOOL update_send_cache_bitmap(rdpContext* context, const CACHE_BITMAP_ORDER* cache_bitmap)
1583 {
1584 wStream* s;
1585 size_t bm, em;
1586 BYTE orderType;
1587 int headerLength;
1588 int inf;
1589 UINT16 extraFlags;
1590 INT16 orderLength;
1591 rdpUpdate* update = context->update;
1592 extraFlags = 0;
1593 headerLength = 6;
1594 orderType = cache_bitmap->compressed ? ORDER_TYPE_CACHE_BITMAP_COMPRESSED
1595 : ORDER_TYPE_BITMAP_UNCOMPRESSED;
1596 inf =
1597 update_approximate_cache_bitmap_order(cache_bitmap, cache_bitmap->compressed, &extraFlags);
1598 update_check_flush(context, headerLength + inf);
1599 s = update->us;
1600
1601 if (!s)
1602 return FALSE;
1603
1604 bm = Stream_GetPosition(s);
1605
1606 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1607 return FALSE;
1608
1609 Stream_Seek(s, headerLength);
1610
1611 if (!update_write_cache_bitmap_order(s, cache_bitmap, cache_bitmap->compressed, &extraFlags))
1612 return FALSE;
1613
1614 em = Stream_GetPosition(s);
1615 orderLength = (em - bm) - 13;
1616 Stream_SetPosition(s, bm);
1617 Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY); /* controlFlags (1 byte) */
1618 Stream_Write_UINT16(s, orderLength); /* orderLength (2 bytes) */
1619 Stream_Write_UINT16(s, extraFlags); /* extraFlags (2 bytes) */
1620 Stream_Write_UINT8(s, orderType); /* orderType (1 byte) */
1621 Stream_SetPosition(s, em);
1622 update->numberOrders++;
1623 return TRUE;
1624 }
1625
update_send_cache_bitmap_v2(rdpContext * context,CACHE_BITMAP_V2_ORDER * cache_bitmap_v2)1626 static BOOL update_send_cache_bitmap_v2(rdpContext* context, CACHE_BITMAP_V2_ORDER* cache_bitmap_v2)
1627 {
1628 wStream* s;
1629 size_t bm, em;
1630 BYTE orderType;
1631 int headerLength;
1632 UINT16 extraFlags;
1633 INT16 orderLength;
1634 rdpUpdate* update = context->update;
1635 extraFlags = 0;
1636 headerLength = 6;
1637 orderType = cache_bitmap_v2->compressed ? ORDER_TYPE_BITMAP_COMPRESSED_V2
1638 : ORDER_TYPE_BITMAP_UNCOMPRESSED_V2;
1639
1640 if (context->settings->NoBitmapCompressionHeader)
1641 cache_bitmap_v2->flags |= CBR2_NO_BITMAP_COMPRESSION_HDR;
1642
1643 update_check_flush(context, headerLength +
1644 update_approximate_cache_bitmap_v2_order(
1645 cache_bitmap_v2, cache_bitmap_v2->compressed, &extraFlags));
1646 s = update->us;
1647
1648 if (!s)
1649 return FALSE;
1650
1651 bm = Stream_GetPosition(s);
1652
1653 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1654 return FALSE;
1655
1656 Stream_Seek(s, headerLength);
1657
1658 if (!update_write_cache_bitmap_v2_order(s, cache_bitmap_v2, cache_bitmap_v2->compressed,
1659 &extraFlags))
1660 return FALSE;
1661
1662 em = Stream_GetPosition(s);
1663 orderLength = (em - bm) - 13;
1664 Stream_SetPosition(s, bm);
1665 Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY); /* controlFlags (1 byte) */
1666 Stream_Write_UINT16(s, orderLength); /* orderLength (2 bytes) */
1667 Stream_Write_UINT16(s, extraFlags); /* extraFlags (2 bytes) */
1668 Stream_Write_UINT8(s, orderType); /* orderType (1 byte) */
1669 Stream_SetPosition(s, em);
1670 update->numberOrders++;
1671 return TRUE;
1672 }
1673
update_send_cache_bitmap_v3(rdpContext * context,CACHE_BITMAP_V3_ORDER * cache_bitmap_v3)1674 static BOOL update_send_cache_bitmap_v3(rdpContext* context, CACHE_BITMAP_V3_ORDER* cache_bitmap_v3)
1675 {
1676 wStream* s;
1677 size_t bm, em;
1678 BYTE orderType;
1679 int headerLength;
1680 UINT16 extraFlags;
1681 INT16 orderLength;
1682 rdpUpdate* update = context->update;
1683 extraFlags = 0;
1684 headerLength = 6;
1685 orderType = ORDER_TYPE_BITMAP_COMPRESSED_V3;
1686 update_check_flush(context, headerLength + update_approximate_cache_bitmap_v3_order(
1687 cache_bitmap_v3, &extraFlags));
1688 s = update->us;
1689
1690 if (!s)
1691 return FALSE;
1692
1693 bm = Stream_GetPosition(s);
1694
1695 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1696 return FALSE;
1697
1698 Stream_Seek(s, headerLength);
1699
1700 if (!update_write_cache_bitmap_v3_order(s, cache_bitmap_v3, &extraFlags))
1701 return FALSE;
1702
1703 em = Stream_GetPosition(s);
1704 orderLength = (em - bm) - 13;
1705 Stream_SetPosition(s, bm);
1706 Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY); /* controlFlags (1 byte) */
1707 Stream_Write_UINT16(s, orderLength); /* orderLength (2 bytes) */
1708 Stream_Write_UINT16(s, extraFlags); /* extraFlags (2 bytes) */
1709 Stream_Write_UINT8(s, orderType); /* orderType (1 byte) */
1710 Stream_SetPosition(s, em);
1711 update->numberOrders++;
1712 return TRUE;
1713 }
1714
update_send_cache_color_table(rdpContext * context,const CACHE_COLOR_TABLE_ORDER * cache_color_table)1715 static BOOL update_send_cache_color_table(rdpContext* context,
1716 const CACHE_COLOR_TABLE_ORDER* cache_color_table)
1717 {
1718 wStream* s;
1719 UINT16 flags;
1720 size_t bm, em, inf;
1721 int headerLength;
1722 INT16 orderLength;
1723 rdpUpdate* update = context->update;
1724 flags = 0;
1725 headerLength = 6;
1726 inf = update_approximate_cache_color_table_order(cache_color_table, &flags);
1727 update_check_flush(context, headerLength + inf);
1728 s = update->us;
1729
1730 if (!s)
1731 return FALSE;
1732
1733 bm = Stream_GetPosition(s);
1734
1735 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1736 return FALSE;
1737
1738 Stream_Seek(s, headerLength);
1739
1740 if (!update_write_cache_color_table_order(s, cache_color_table, &flags))
1741 return FALSE;
1742
1743 em = Stream_GetPosition(s);
1744 orderLength = (em - bm) - 13;
1745 Stream_SetPosition(s, bm);
1746 Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY); /* controlFlags (1 byte) */
1747 Stream_Write_UINT16(s, orderLength); /* orderLength (2 bytes) */
1748 Stream_Write_UINT16(s, flags); /* extraFlags (2 bytes) */
1749 Stream_Write_UINT8(s, ORDER_TYPE_CACHE_COLOR_TABLE); /* orderType (1 byte) */
1750 Stream_SetPosition(s, em);
1751 update->numberOrders++;
1752 return TRUE;
1753 }
1754
update_send_cache_glyph(rdpContext * context,const CACHE_GLYPH_ORDER * cache_glyph)1755 static BOOL update_send_cache_glyph(rdpContext* context, const CACHE_GLYPH_ORDER* cache_glyph)
1756 {
1757 wStream* s;
1758 UINT16 flags;
1759 size_t bm, em, inf;
1760 int headerLength;
1761 INT16 orderLength;
1762 rdpUpdate* update = context->update;
1763 flags = 0;
1764 headerLength = 6;
1765 inf = update_approximate_cache_glyph_order(cache_glyph, &flags);
1766 update_check_flush(context, headerLength + inf);
1767 s = update->us;
1768
1769 if (!s)
1770 return FALSE;
1771
1772 bm = Stream_GetPosition(s);
1773
1774 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1775 return FALSE;
1776
1777 Stream_Seek(s, headerLength);
1778
1779 if (!update_write_cache_glyph_order(s, cache_glyph, &flags))
1780 return FALSE;
1781
1782 em = Stream_GetPosition(s);
1783 orderLength = (em - bm) - 13;
1784 Stream_SetPosition(s, bm);
1785 Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY); /* controlFlags (1 byte) */
1786 Stream_Write_UINT16(s, orderLength); /* orderLength (2 bytes) */
1787 Stream_Write_UINT16(s, flags); /* extraFlags (2 bytes) */
1788 Stream_Write_UINT8(s, ORDER_TYPE_CACHE_GLYPH); /* orderType (1 byte) */
1789 Stream_SetPosition(s, em);
1790 update->numberOrders++;
1791 return TRUE;
1792 }
1793
update_send_cache_glyph_v2(rdpContext * context,const CACHE_GLYPH_V2_ORDER * cache_glyph_v2)1794 static BOOL update_send_cache_glyph_v2(rdpContext* context,
1795 const CACHE_GLYPH_V2_ORDER* cache_glyph_v2)
1796 {
1797 wStream* s;
1798 UINT16 flags;
1799 size_t bm, em, inf;
1800 int headerLength;
1801 INT16 orderLength;
1802 rdpUpdate* update = context->update;
1803 flags = 0;
1804 headerLength = 6;
1805 inf = update_approximate_cache_glyph_v2_order(cache_glyph_v2, &flags);
1806 update_check_flush(context, headerLength + inf);
1807 s = update->us;
1808
1809 if (!s)
1810 return FALSE;
1811
1812 bm = Stream_GetPosition(s);
1813
1814 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1815 return FALSE;
1816
1817 Stream_Seek(s, headerLength);
1818
1819 if (!update_write_cache_glyph_v2_order(s, cache_glyph_v2, &flags))
1820 return FALSE;
1821
1822 em = Stream_GetPosition(s);
1823 orderLength = (em - bm) - 13;
1824 Stream_SetPosition(s, bm);
1825 Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY); /* controlFlags (1 byte) */
1826 Stream_Write_UINT16(s, orderLength); /* orderLength (2 bytes) */
1827 Stream_Write_UINT16(s, flags); /* extraFlags (2 bytes) */
1828 Stream_Write_UINT8(s, ORDER_TYPE_CACHE_GLYPH); /* orderType (1 byte) */
1829 Stream_SetPosition(s, em);
1830 update->numberOrders++;
1831 return TRUE;
1832 }
1833
update_send_cache_brush(rdpContext * context,const CACHE_BRUSH_ORDER * cache_brush)1834 static BOOL update_send_cache_brush(rdpContext* context, const CACHE_BRUSH_ORDER* cache_brush)
1835 {
1836 wStream* s;
1837 UINT16 flags;
1838 size_t bm, em, inf;
1839 int headerLength;
1840 INT16 orderLength;
1841 rdpUpdate* update = context->update;
1842 flags = 0;
1843 headerLength = 6;
1844 inf = update_approximate_cache_brush_order(cache_brush, &flags);
1845 update_check_flush(context, headerLength + inf);
1846 s = update->us;
1847
1848 if (!s)
1849 return FALSE;
1850
1851 bm = Stream_GetPosition(s);
1852
1853 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1854 return FALSE;
1855
1856 Stream_Seek(s, headerLength);
1857
1858 if (!update_write_cache_brush_order(s, cache_brush, &flags))
1859 return FALSE;
1860
1861 em = Stream_GetPosition(s);
1862 orderLength = (em - bm) - 13;
1863 Stream_SetPosition(s, bm);
1864 Stream_Write_UINT8(s, ORDER_STANDARD | ORDER_SECONDARY); /* controlFlags (1 byte) */
1865 Stream_Write_UINT16(s, orderLength); /* orderLength (2 bytes) */
1866 Stream_Write_UINT16(s, flags); /* extraFlags (2 bytes) */
1867 Stream_Write_UINT8(s, ORDER_TYPE_CACHE_BRUSH); /* orderType (1 byte) */
1868 Stream_SetPosition(s, em);
1869 update->numberOrders++;
1870 return TRUE;
1871 }
1872
1873 /**
1874 * Alternate Secondary Drawing Orders
1875 */
1876
update_send_create_offscreen_bitmap_order(rdpContext * context,const CREATE_OFFSCREEN_BITMAP_ORDER * create_offscreen_bitmap)1877 static BOOL update_send_create_offscreen_bitmap_order(
1878 rdpContext* context, const CREATE_OFFSCREEN_BITMAP_ORDER* create_offscreen_bitmap)
1879 {
1880 wStream* s;
1881 size_t bm, em, inf;
1882 BYTE orderType;
1883 BYTE controlFlags;
1884 int headerLength;
1885 rdpUpdate* update = context->update;
1886 headerLength = 1;
1887 orderType = ORDER_TYPE_CREATE_OFFSCREEN_BITMAP;
1888 controlFlags = ORDER_SECONDARY | (orderType << 2);
1889 inf = update_approximate_create_offscreen_bitmap_order(create_offscreen_bitmap);
1890 update_check_flush(context, headerLength + inf);
1891 s = update->us;
1892
1893 if (!s)
1894 return FALSE;
1895
1896 bm = Stream_GetPosition(s);
1897
1898 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1899 return FALSE;
1900
1901 Stream_Seek(s, headerLength);
1902
1903 if (!update_write_create_offscreen_bitmap_order(s, create_offscreen_bitmap))
1904 return FALSE;
1905
1906 em = Stream_GetPosition(s);
1907 Stream_SetPosition(s, bm);
1908 Stream_Write_UINT8(s, controlFlags); /* controlFlags (1 byte) */
1909 Stream_SetPosition(s, em);
1910 update->numberOrders++;
1911 return TRUE;
1912 }
1913
update_send_switch_surface_order(rdpContext * context,const SWITCH_SURFACE_ORDER * switch_surface)1914 static BOOL update_send_switch_surface_order(rdpContext* context,
1915 const SWITCH_SURFACE_ORDER* switch_surface)
1916 {
1917 wStream* s;
1918 size_t bm, em, inf;
1919 BYTE orderType;
1920 BYTE controlFlags;
1921 int headerLength;
1922 rdpUpdate* update;
1923
1924 if (!context || !switch_surface || !context->update)
1925 return FALSE;
1926
1927 update = context->update;
1928 headerLength = 1;
1929 orderType = ORDER_TYPE_SWITCH_SURFACE;
1930 controlFlags = ORDER_SECONDARY | (orderType << 2);
1931 inf = update_approximate_switch_surface_order(switch_surface);
1932 update_check_flush(context, headerLength + inf);
1933 s = update->us;
1934
1935 if (!s)
1936 return FALSE;
1937
1938 bm = Stream_GetPosition(s);
1939
1940 if (!Stream_EnsureRemainingCapacity(s, headerLength))
1941 return FALSE;
1942
1943 Stream_Seek(s, headerLength);
1944
1945 if (!update_write_switch_surface_order(s, switch_surface))
1946 return FALSE;
1947
1948 em = Stream_GetPosition(s);
1949 Stream_SetPosition(s, bm);
1950 Stream_Write_UINT8(s, controlFlags); /* controlFlags (1 byte) */
1951 Stream_SetPosition(s, em);
1952 update->numberOrders++;
1953 return TRUE;
1954 }
1955
update_send_pointer_system(rdpContext * context,const POINTER_SYSTEM_UPDATE * pointer_system)1956 static BOOL update_send_pointer_system(rdpContext* context,
1957 const POINTER_SYSTEM_UPDATE* pointer_system)
1958 {
1959 wStream* s;
1960 BYTE updateCode;
1961 rdpRdp* rdp = context->rdp;
1962 BOOL ret;
1963 s = fastpath_update_pdu_init(rdp->fastpath);
1964
1965 if (!s)
1966 return FALSE;
1967
1968 if (pointer_system->type == SYSPTR_NULL)
1969 updateCode = FASTPATH_UPDATETYPE_PTR_NULL;
1970 else
1971 updateCode = FASTPATH_UPDATETYPE_PTR_DEFAULT;
1972
1973 ret = fastpath_send_update_pdu(rdp->fastpath, updateCode, s, FALSE);
1974 Stream_Release(s);
1975 return ret;
1976 }
1977
update_send_pointer_position(rdpContext * context,const POINTER_POSITION_UPDATE * pointerPosition)1978 static BOOL update_send_pointer_position(rdpContext* context,
1979 const POINTER_POSITION_UPDATE* pointerPosition)
1980 {
1981 wStream* s;
1982 rdpRdp* rdp = context->rdp;
1983 BOOL ret = FALSE;
1984 s = fastpath_update_pdu_init(rdp->fastpath);
1985
1986 if (!s)
1987 return FALSE;
1988
1989 if (!Stream_EnsureRemainingCapacity(s, 16))
1990 goto out_fail;
1991
1992 Stream_Write_UINT16(s, pointerPosition->xPos); /* xPos (2 bytes) */
1993 Stream_Write_UINT16(s, pointerPosition->yPos); /* yPos (2 bytes) */
1994 ret = fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_PTR_POSITION, s, FALSE);
1995 out_fail:
1996 Stream_Release(s);
1997 return ret;
1998 }
1999
update_write_pointer_color(wStream * s,const POINTER_COLOR_UPDATE * pointer_color)2000 static BOOL update_write_pointer_color(wStream* s, const POINTER_COLOR_UPDATE* pointer_color)
2001 {
2002 if (!Stream_EnsureRemainingCapacity(s, 32 + pointer_color->lengthAndMask +
2003 pointer_color->lengthXorMask))
2004 return FALSE;
2005
2006 Stream_Write_UINT16(s, pointer_color->cacheIndex);
2007 Stream_Write_UINT16(s, pointer_color->xPos);
2008 Stream_Write_UINT16(s, pointer_color->yPos);
2009 Stream_Write_UINT16(s, pointer_color->width);
2010 Stream_Write_UINT16(s, pointer_color->height);
2011 Stream_Write_UINT16(s, pointer_color->lengthAndMask);
2012 Stream_Write_UINT16(s, pointer_color->lengthXorMask);
2013
2014 if (pointer_color->lengthXorMask > 0)
2015 Stream_Write(s, pointer_color->xorMaskData, pointer_color->lengthXorMask);
2016
2017 if (pointer_color->lengthAndMask > 0)
2018 Stream_Write(s, pointer_color->andMaskData, pointer_color->lengthAndMask);
2019
2020 Stream_Write_UINT8(s, 0); /* pad (1 byte) */
2021 return TRUE;
2022 }
2023
update_send_pointer_color(rdpContext * context,const POINTER_COLOR_UPDATE * pointer_color)2024 static BOOL update_send_pointer_color(rdpContext* context,
2025 const POINTER_COLOR_UPDATE* pointer_color)
2026 {
2027 wStream* s;
2028 rdpRdp* rdp = context->rdp;
2029 BOOL ret = FALSE;
2030 s = fastpath_update_pdu_init(rdp->fastpath);
2031
2032 if (!s)
2033 return FALSE;
2034
2035 if (!update_write_pointer_color(s, pointer_color))
2036 goto out_fail;
2037
2038 ret = fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_COLOR, s, FALSE);
2039 out_fail:
2040 Stream_Release(s);
2041 return ret;
2042 }
2043
update_write_pointer_large(wStream * s,const POINTER_LARGE_UPDATE * pointer)2044 static BOOL update_write_pointer_large(wStream* s, const POINTER_LARGE_UPDATE* pointer)
2045 {
2046 if (!Stream_EnsureRemainingCapacity(s, 32 + pointer->lengthAndMask + pointer->lengthXorMask))
2047 return FALSE;
2048
2049 Stream_Write_UINT16(s, pointer->xorBpp);
2050 Stream_Write_UINT16(s, pointer->cacheIndex);
2051 Stream_Write_UINT16(s, pointer->hotSpotX);
2052 Stream_Write_UINT16(s, pointer->hotSpotY);
2053 Stream_Write_UINT16(s, pointer->width);
2054 Stream_Write_UINT16(s, pointer->height);
2055 Stream_Write_UINT32(s, pointer->lengthAndMask);
2056 Stream_Write_UINT32(s, pointer->lengthXorMask);
2057 Stream_Write(s, pointer->xorMaskData, pointer->lengthXorMask);
2058 Stream_Write(s, pointer->andMaskData, pointer->lengthAndMask);
2059 Stream_Write_UINT8(s, 0); /* pad (1 byte) */
2060 return TRUE;
2061 }
2062
update_send_pointer_large(rdpContext * context,const POINTER_LARGE_UPDATE * pointer)2063 static BOOL update_send_pointer_large(rdpContext* context, const POINTER_LARGE_UPDATE* pointer)
2064 {
2065 wStream* s;
2066 rdpRdp* rdp = context->rdp;
2067 BOOL ret = FALSE;
2068 s = fastpath_update_pdu_init(rdp->fastpath);
2069
2070 if (!s)
2071 return FALSE;
2072
2073 if (!update_write_pointer_large(s, pointer))
2074 goto out_fail;
2075
2076 ret = fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_LARGE_POINTER, s, FALSE);
2077 out_fail:
2078 Stream_Release(s);
2079 return ret;
2080 }
2081
update_send_pointer_new(rdpContext * context,const POINTER_NEW_UPDATE * pointer_new)2082 static BOOL update_send_pointer_new(rdpContext* context, const POINTER_NEW_UPDATE* pointer_new)
2083 {
2084 wStream* s;
2085 rdpRdp* rdp = context->rdp;
2086 BOOL ret = FALSE;
2087 s = fastpath_update_pdu_init(rdp->fastpath);
2088
2089 if (!s)
2090 return FALSE;
2091
2092 if (!Stream_EnsureRemainingCapacity(s, 16))
2093 goto out_fail;
2094
2095 Stream_Write_UINT16(s, pointer_new->xorBpp); /* xorBpp (2 bytes) */
2096 update_write_pointer_color(s, &pointer_new->colorPtrAttr);
2097 ret = fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_POINTER, s, FALSE);
2098 out_fail:
2099 Stream_Release(s);
2100 return ret;
2101 }
2102
update_send_pointer_cached(rdpContext * context,const POINTER_CACHED_UPDATE * pointer_cached)2103 static BOOL update_send_pointer_cached(rdpContext* context,
2104 const POINTER_CACHED_UPDATE* pointer_cached)
2105 {
2106 wStream* s;
2107 rdpRdp* rdp = context->rdp;
2108 BOOL ret;
2109 s = fastpath_update_pdu_init(rdp->fastpath);
2110
2111 if (!s)
2112 return FALSE;
2113
2114 Stream_Write_UINT16(s, pointer_cached->cacheIndex); /* cacheIndex (2 bytes) */
2115 ret = fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_CACHED, s, FALSE);
2116 Stream_Release(s);
2117 return ret;
2118 }
2119
update_read_refresh_rect(rdpUpdate * update,wStream * s)2120 BOOL update_read_refresh_rect(rdpUpdate* update, wStream* s)
2121 {
2122 int index;
2123 BYTE numberOfAreas;
2124 RECTANGLE_16* areas;
2125
2126 if (Stream_GetRemainingLength(s) < 4)
2127 return FALSE;
2128
2129 Stream_Read_UINT8(s, numberOfAreas);
2130 Stream_Seek(s, 3); /* pad3Octects */
2131
2132 if (Stream_GetRemainingLength(s) < ((size_t)numberOfAreas * 4 * 2))
2133 return FALSE;
2134
2135 areas = (RECTANGLE_16*)calloc(numberOfAreas, sizeof(RECTANGLE_16));
2136
2137 if (!areas)
2138 return FALSE;
2139
2140 for (index = 0; index < numberOfAreas; index++)
2141 {
2142 Stream_Read_UINT16(s, areas[index].left);
2143 Stream_Read_UINT16(s, areas[index].top);
2144 Stream_Read_UINT16(s, areas[index].right);
2145 Stream_Read_UINT16(s, areas[index].bottom);
2146 }
2147
2148 if (update->context->settings->RefreshRect)
2149 IFCALL(update->RefreshRect, update->context, numberOfAreas, areas);
2150 else
2151 WLog_Print(update->log, WLOG_WARN, "ignoring refresh rect request from client");
2152
2153 free(areas);
2154 return TRUE;
2155 }
2156
update_read_suppress_output(rdpUpdate * update,wStream * s)2157 BOOL update_read_suppress_output(rdpUpdate* update, wStream* s)
2158 {
2159 RECTANGLE_16* prect = NULL;
2160 RECTANGLE_16 rect = { 0 };
2161 BYTE allowDisplayUpdates;
2162
2163 if (Stream_GetRemainingLength(s) < 4)
2164 return FALSE;
2165
2166 Stream_Read_UINT8(s, allowDisplayUpdates);
2167 Stream_Seek(s, 3); /* pad3Octects */
2168
2169 if (allowDisplayUpdates > 0)
2170 {
2171 if (Stream_GetRemainingLength(s) < sizeof(RECTANGLE_16))
2172 return FALSE;
2173 Stream_Read_UINT16(s, rect.left);
2174 Stream_Read_UINT16(s, rect.top);
2175 Stream_Read_UINT16(s, rect.right);
2176 Stream_Read_UINT16(s, rect.bottom);
2177
2178 prect = ▭
2179 }
2180
2181 if (update->context->settings->SuppressOutput)
2182 IFCALL(update->SuppressOutput, update->context, allowDisplayUpdates, prect);
2183 else
2184 WLog_Print(update->log, WLOG_WARN, "ignoring suppress output request from client");
2185
2186 return TRUE;
2187 }
2188
update_send_set_keyboard_indicators(rdpContext * context,UINT16 led_flags)2189 static BOOL update_send_set_keyboard_indicators(rdpContext* context, UINT16 led_flags)
2190 {
2191 wStream* s;
2192 rdpRdp* rdp = context->rdp;
2193 s = rdp_data_pdu_init(rdp);
2194
2195 if (!s)
2196 return FALSE;
2197
2198 Stream_Write_UINT16(s, 0); /* unitId should be 0 according to MS-RDPBCGR 2.2.8.2.1.1 */
2199 Stream_Write_UINT16(s, led_flags); /* ledFlags (2 bytes) */
2200 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SET_KEYBOARD_INDICATORS, rdp->mcs->userId);
2201 }
2202
update_send_set_keyboard_ime_status(rdpContext * context,UINT16 imeId,UINT32 imeState,UINT32 imeConvMode)2203 static BOOL update_send_set_keyboard_ime_status(rdpContext* context, UINT16 imeId, UINT32 imeState,
2204 UINT32 imeConvMode)
2205 {
2206 wStream* s;
2207 rdpRdp* rdp = context->rdp;
2208 s = rdp_data_pdu_init(rdp);
2209
2210 if (!s)
2211 return FALSE;
2212
2213 /* unitId should be 0 according to MS-RDPBCGR 2.2.8.2.2.1 */
2214 Stream_Write_UINT16(s, imeId);
2215 Stream_Write_UINT32(s, imeState);
2216 Stream_Write_UINT32(s, imeConvMode);
2217 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SET_KEYBOARD_IME_STATUS, rdp->mcs->userId);
2218 }
2219
update_calculate_new_or_existing_window(const WINDOW_ORDER_INFO * orderInfo,const WINDOW_STATE_ORDER * stateOrder)2220 static UINT16 update_calculate_new_or_existing_window(const WINDOW_ORDER_INFO* orderInfo,
2221 const WINDOW_STATE_ORDER* stateOrder)
2222 {
2223 UINT16 orderSize = 11;
2224
2225 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_OWNER) != 0)
2226 orderSize += 4;
2227
2228 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_STYLE) != 0)
2229 orderSize += 8;
2230
2231 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_SHOW) != 0)
2232 orderSize += 1;
2233
2234 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_TITLE) != 0)
2235 orderSize += 2 + stateOrder->titleInfo.length;
2236
2237 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET) != 0)
2238 orderSize += 8;
2239
2240 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE) != 0)
2241 orderSize += 8;
2242
2243 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_RESIZE_MARGIN_X) != 0)
2244 orderSize += 8;
2245
2246 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_RESIZE_MARGIN_Y) != 0)
2247 orderSize += 8;
2248
2249 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_RP_CONTENT) != 0)
2250 orderSize += 1;
2251
2252 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_ROOT_PARENT) != 0)
2253 orderSize += 4;
2254
2255 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET) != 0)
2256 orderSize += 8;
2257
2258 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA) != 0)
2259 orderSize += 8;
2260
2261 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE) != 0)
2262 orderSize += 8;
2263
2264 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS) != 0)
2265 orderSize += 2 + stateOrder->numWindowRects * sizeof(RECTANGLE_16);
2266
2267 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_VIS_OFFSET) != 0)
2268 orderSize += 8;
2269
2270 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY) != 0)
2271 orderSize += 2 + stateOrder->numVisibilityRects * sizeof(RECTANGLE_16);
2272
2273 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_OVERLAY_DESCRIPTION) != 0)
2274 orderSize += 2 + stateOrder->OverlayDescription.length;
2275
2276 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_TASKBAR_BUTTON) != 0)
2277 orderSize += 1;
2278
2279 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_ENFORCE_SERVER_ZORDER) != 0)
2280 orderSize += 1;
2281
2282 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_APPBAR_STATE) != 0)
2283 orderSize += 1;
2284
2285 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_APPBAR_EDGE) != 0)
2286 orderSize += 1;
2287
2288 return orderSize;
2289 }
2290
update_send_new_or_existing_window(rdpContext * context,const WINDOW_ORDER_INFO * orderInfo,const WINDOW_STATE_ORDER * stateOrder)2291 static BOOL update_send_new_or_existing_window(rdpContext* context,
2292 const WINDOW_ORDER_INFO* orderInfo,
2293 const WINDOW_STATE_ORDER* stateOrder)
2294 {
2295 wStream* s;
2296 rdpUpdate* update = context->update;
2297 BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2);
2298 UINT16 orderSize = update_calculate_new_or_existing_window(orderInfo, stateOrder);
2299
2300 update_check_flush(context, orderSize);
2301
2302 s = update->us;
2303
2304 if (!s)
2305 return FALSE;
2306
2307 if (!Stream_EnsureRemainingCapacity(s, orderSize))
2308 return FALSE;
2309
2310 Stream_Write_UINT8(s, controlFlags); /* Header (1 byte) */
2311 Stream_Write_UINT16(s, orderSize); /* OrderSize (2 bytes) */
2312 Stream_Write_UINT32(s, orderInfo->fieldFlags); /* FieldsPresentFlags (4 bytes) */
2313 Stream_Write_UINT32(s, orderInfo->windowId); /* WindowID (4 bytes) */
2314
2315 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_OWNER) != 0)
2316 Stream_Write_UINT32(s, stateOrder->ownerWindowId);
2317
2318 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_STYLE) != 0)
2319 {
2320 Stream_Write_UINT32(s, stateOrder->style);
2321 Stream_Write_UINT32(s, stateOrder->extendedStyle);
2322 }
2323
2324 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_SHOW) != 0)
2325 {
2326 Stream_Write_UINT8(s, stateOrder->showState);
2327 }
2328
2329 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_TITLE) != 0)
2330 {
2331 Stream_Write_UINT16(s, stateOrder->titleInfo.length);
2332 Stream_Write(s, stateOrder->titleInfo.string, stateOrder->titleInfo.length);
2333 }
2334
2335 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET) != 0)
2336 {
2337 Stream_Write_INT32(s, stateOrder->clientOffsetX);
2338 Stream_Write_INT32(s, stateOrder->clientOffsetY);
2339 }
2340
2341 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE) != 0)
2342 {
2343 Stream_Write_UINT32(s, stateOrder->clientAreaWidth);
2344 Stream_Write_UINT32(s, stateOrder->clientAreaHeight);
2345 }
2346
2347 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_RESIZE_MARGIN_X) != 0)
2348 {
2349 Stream_Write_UINT32(s, stateOrder->resizeMarginLeft);
2350 Stream_Write_UINT32(s, stateOrder->resizeMarginRight);
2351 }
2352
2353 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_RESIZE_MARGIN_Y) != 0)
2354 {
2355 Stream_Write_UINT32(s, stateOrder->resizeMarginTop);
2356 Stream_Write_UINT32(s, stateOrder->resizeMarginBottom);
2357 }
2358
2359 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_RP_CONTENT) != 0)
2360 {
2361 Stream_Write_UINT8(s, stateOrder->RPContent);
2362 }
2363
2364 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_ROOT_PARENT) != 0)
2365 {
2366 Stream_Write_UINT32(s, stateOrder->rootParentHandle);
2367 }
2368
2369 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET) != 0)
2370 {
2371 Stream_Write_INT32(s, stateOrder->windowOffsetX);
2372 Stream_Write_INT32(s, stateOrder->windowOffsetY);
2373 }
2374
2375 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA) != 0)
2376 {
2377 Stream_Write_INT32(s, stateOrder->windowClientDeltaX);
2378 Stream_Write_INT32(s, stateOrder->windowClientDeltaY);
2379 }
2380
2381 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE) != 0)
2382 {
2383 Stream_Write_UINT32(s, stateOrder->windowWidth);
2384 Stream_Write_UINT32(s, stateOrder->windowHeight);
2385 }
2386
2387 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS) != 0)
2388 {
2389 Stream_Write_UINT16(s, stateOrder->numWindowRects);
2390 Stream_Write(s, stateOrder->windowRects, stateOrder->numWindowRects * sizeof(RECTANGLE_16));
2391 }
2392
2393 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_VIS_OFFSET) != 0)
2394 {
2395 Stream_Write_UINT32(s, stateOrder->visibleOffsetX);
2396 Stream_Write_UINT32(s, stateOrder->visibleOffsetY);
2397 }
2398
2399 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY) != 0)
2400 {
2401 Stream_Write_UINT16(s, stateOrder->numVisibilityRects);
2402 Stream_Write(s, stateOrder->visibilityRects,
2403 stateOrder->numVisibilityRects * sizeof(RECTANGLE_16));
2404 }
2405
2406 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_OVERLAY_DESCRIPTION) != 0)
2407 {
2408 Stream_Write_UINT16(s, stateOrder->OverlayDescription.length);
2409 Stream_Write(s, stateOrder->OverlayDescription.string,
2410 stateOrder->OverlayDescription.length);
2411 }
2412
2413 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_TASKBAR_BUTTON) != 0)
2414 {
2415 Stream_Write_UINT8(s, stateOrder->TaskbarButton);
2416 }
2417
2418 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_ENFORCE_SERVER_ZORDER) != 0)
2419 {
2420 Stream_Write_UINT8(s, stateOrder->EnforceServerZOrder);
2421 }
2422
2423 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_APPBAR_STATE) != 0)
2424 {
2425 Stream_Write_UINT8(s, stateOrder->AppBarState);
2426 }
2427
2428 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_APPBAR_EDGE) != 0)
2429 {
2430 Stream_Write_UINT8(s, stateOrder->AppBarEdge);
2431 }
2432
2433 update->numberOrders++;
2434 return TRUE;
2435 }
2436
update_send_window_create(rdpContext * context,const WINDOW_ORDER_INFO * orderInfo,const WINDOW_STATE_ORDER * stateOrder)2437 static BOOL update_send_window_create(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo,
2438 const WINDOW_STATE_ORDER* stateOrder)
2439 {
2440 return update_send_new_or_existing_window(context, orderInfo, stateOrder);
2441 }
2442
update_send_window_update(rdpContext * context,const WINDOW_ORDER_INFO * orderInfo,const WINDOW_STATE_ORDER * stateOrder)2443 static BOOL update_send_window_update(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo,
2444 const WINDOW_STATE_ORDER* stateOrder)
2445 {
2446 return update_send_new_or_existing_window(context, orderInfo, stateOrder);
2447 }
2448
update_calculate_window_icon_order(const WINDOW_ORDER_INFO * orderInfo,const WINDOW_ICON_ORDER * iconOrder)2449 static UINT16 update_calculate_window_icon_order(const WINDOW_ORDER_INFO* orderInfo,
2450 const WINDOW_ICON_ORDER* iconOrder)
2451 {
2452 UINT16 orderSize = 23;
2453 ICON_INFO* iconInfo = iconOrder->iconInfo;
2454
2455 orderSize += iconInfo->cbBitsColor + iconInfo->cbBitsMask;
2456
2457 if (iconInfo->bpp <= 8)
2458 orderSize += 2 + iconInfo->cbColorTable;
2459
2460 return orderSize;
2461 }
2462
update_send_window_icon(rdpContext * context,const WINDOW_ORDER_INFO * orderInfo,const WINDOW_ICON_ORDER * iconOrder)2463 static BOOL update_send_window_icon(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo,
2464 const WINDOW_ICON_ORDER* iconOrder)
2465 {
2466 wStream* s;
2467 rdpUpdate* update = context->update;
2468 BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2);
2469 ICON_INFO* iconInfo = iconOrder->iconInfo;
2470 UINT16 orderSize = update_calculate_window_icon_order(orderInfo, iconOrder);
2471
2472 update_check_flush(context, orderSize);
2473
2474 s = update->us;
2475
2476 if (!s || !iconInfo)
2477 return FALSE;
2478
2479 if (!Stream_EnsureRemainingCapacity(s, orderSize))
2480 return FALSE;
2481
2482 /* Write Hdr */
2483 Stream_Write_UINT8(s, controlFlags); /* Header (1 byte) */
2484 Stream_Write_UINT16(s, orderSize); /* OrderSize (2 bytes) */
2485 Stream_Write_UINT32(s, orderInfo->fieldFlags); /* FieldsPresentFlags (4 bytes) */
2486 Stream_Write_UINT32(s, orderInfo->windowId); /* WindowID (4 bytes) */
2487 /* Write body */
2488 Stream_Write_UINT16(s, iconInfo->cacheEntry); /* CacheEntry (2 bytes) */
2489 Stream_Write_UINT8(s, iconInfo->cacheId); /* CacheId (1 byte) */
2490 Stream_Write_UINT8(s, iconInfo->bpp); /* Bpp (1 byte) */
2491 Stream_Write_UINT16(s, iconInfo->width); /* Width (2 bytes) */
2492 Stream_Write_UINT16(s, iconInfo->height); /* Height (2 bytes) */
2493
2494 if (iconInfo->bpp <= 8)
2495 {
2496 Stream_Write_UINT16(s, iconInfo->cbColorTable); /* CbColorTable (2 bytes) */
2497 }
2498
2499 Stream_Write_UINT16(s, iconInfo->cbBitsMask); /* CbBitsMask (2 bytes) */
2500 Stream_Write_UINT16(s, iconInfo->cbBitsColor); /* CbBitsColor (2 bytes) */
2501 Stream_Write(s, iconInfo->bitsMask, iconInfo->cbBitsMask); /* BitsMask (variable) */
2502
2503 if (iconInfo->bpp <= 8)
2504 {
2505 Stream_Write(s, iconInfo->colorTable, iconInfo->cbColorTable); /* ColorTable (variable) */
2506 }
2507
2508 Stream_Write(s, iconInfo->bitsColor, iconInfo->cbBitsColor); /* BitsColor (variable) */
2509
2510 update->numberOrders++;
2511 return TRUE;
2512 }
2513
update_send_window_cached_icon(rdpContext * context,const WINDOW_ORDER_INFO * orderInfo,const WINDOW_CACHED_ICON_ORDER * cachedIconOrder)2514 static BOOL update_send_window_cached_icon(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo,
2515 const WINDOW_CACHED_ICON_ORDER* cachedIconOrder)
2516 {
2517 wStream* s;
2518 rdpUpdate* update = context->update;
2519 BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2);
2520 UINT16 orderSize = 14;
2521 CACHED_ICON_INFO cachedIcon = cachedIconOrder->cachedIcon;
2522
2523 update_check_flush(context, orderSize);
2524
2525 s = update->us;
2526 if (!s)
2527 return FALSE;
2528
2529 if (!Stream_EnsureRemainingCapacity(s, orderSize))
2530 return FALSE;
2531
2532 /* Write Hdr */
2533 Stream_Write_UINT8(s, controlFlags); /* Header (1 byte) */
2534 Stream_Write_UINT16(s, orderSize); /* OrderSize (2 bytes) */
2535 Stream_Write_UINT32(s, orderInfo->fieldFlags); /* FieldsPresentFlags (4 bytes) */
2536 Stream_Write_UINT32(s, orderInfo->windowId); /* WindowID (4 bytes) */
2537 /* Write body */
2538 Stream_Write_UINT16(s, cachedIcon.cacheEntry); /* CacheEntry (2 bytes) */
2539 Stream_Write_UINT8(s, cachedIcon.cacheId); /* CacheId (1 byte) */
2540 update->numberOrders++;
2541 return TRUE;
2542 }
2543
update_send_window_delete(rdpContext * context,const WINDOW_ORDER_INFO * orderInfo)2544 static BOOL update_send_window_delete(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo)
2545 {
2546 wStream* s;
2547 rdpUpdate* update = context->update;
2548 BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2);
2549 UINT16 orderSize = 11;
2550 update_check_flush(context, orderSize);
2551
2552 s = update->us;
2553
2554 if (!s)
2555 return FALSE;
2556
2557 if (!Stream_EnsureRemainingCapacity(s, orderSize))
2558 return FALSE;
2559
2560 /* Write Hdr */
2561 Stream_Write_UINT8(s, controlFlags); /* Header (1 byte) */
2562 Stream_Write_UINT16(s, orderSize); /* OrderSize (2 bytes) */
2563 Stream_Write_UINT32(s, orderInfo->fieldFlags); /* FieldsPresentFlags (4 bytes) */
2564 Stream_Write_UINT32(s, orderInfo->windowId); /* WindowID (4 bytes) */
2565 update->numberOrders++;
2566 return TRUE;
2567 }
2568
update_calculate_new_or_existing_notification_icons_order(const WINDOW_ORDER_INFO * orderInfo,const NOTIFY_ICON_STATE_ORDER * iconStateOrder)2569 static UINT16 update_calculate_new_or_existing_notification_icons_order(
2570 const WINDOW_ORDER_INFO* orderInfo, const NOTIFY_ICON_STATE_ORDER* iconStateOrder)
2571 {
2572 UINT16 orderSize = 15;
2573
2574 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_VERSION) != 0)
2575 orderSize += 4;
2576
2577 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_TIP) != 0)
2578 {
2579 orderSize += 2 + iconStateOrder->toolTip.length;
2580 }
2581
2582 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_INFO_TIP) != 0)
2583 {
2584 NOTIFY_ICON_INFOTIP infoTip = iconStateOrder->infoTip;
2585 orderSize += 12 + infoTip.text.length + infoTip.title.length;
2586 }
2587
2588 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_STATE) != 0)
2589 {
2590 orderSize += 4;
2591 }
2592
2593 if ((orderInfo->fieldFlags & WINDOW_ORDER_ICON) != 0)
2594 {
2595 ICON_INFO iconInfo = iconStateOrder->icon;
2596 orderSize += 12;
2597
2598 if (iconInfo.bpp <= 8)
2599 orderSize += 2 + iconInfo.cbColorTable;
2600
2601 orderSize += iconInfo.cbBitsMask + iconInfo.cbBitsColor;
2602 }
2603 else if ((orderInfo->fieldFlags & WINDOW_ORDER_CACHED_ICON) != 0)
2604 {
2605 orderSize += 3;
2606 }
2607
2608 return orderSize;
2609 }
2610
2611 static BOOL
update_send_new_or_existing_notification_icons(rdpContext * context,const WINDOW_ORDER_INFO * orderInfo,const NOTIFY_ICON_STATE_ORDER * iconStateOrder)2612 update_send_new_or_existing_notification_icons(rdpContext* context,
2613 const WINDOW_ORDER_INFO* orderInfo,
2614 const NOTIFY_ICON_STATE_ORDER* iconStateOrder)
2615 {
2616 wStream* s;
2617 rdpUpdate* update = context->update;
2618 BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2);
2619 BOOL versionFieldPresent = FALSE;
2620 UINT16 orderSize =
2621 update_calculate_new_or_existing_notification_icons_order(orderInfo, iconStateOrder);
2622
2623 update_check_flush(context, orderSize);
2624
2625 s = update->us;
2626 if (!s)
2627 return FALSE;
2628
2629 if (!Stream_EnsureRemainingCapacity(s, orderSize))
2630 return FALSE;
2631
2632 /* Write Hdr */
2633 Stream_Write_UINT8(s, controlFlags); /* Header (1 byte) */
2634 Stream_Write_INT16(s, orderSize); /* OrderSize (2 bytes) */
2635 Stream_Write_UINT32(s, orderInfo->fieldFlags); /* FieldsPresentFlags (4 bytes) */
2636 Stream_Write_UINT32(s, orderInfo->windowId); /* WindowID (4 bytes) */
2637 Stream_Write_UINT32(s, orderInfo->notifyIconId); /* NotifyIconId (4 bytes) */
2638
2639 /* Write body */
2640 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_VERSION) != 0)
2641 {
2642 versionFieldPresent = TRUE;
2643 Stream_Write_UINT32(s, iconStateOrder->version);
2644 }
2645
2646 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_TIP) != 0)
2647 {
2648 Stream_Write_UINT16(s, iconStateOrder->toolTip.length);
2649 Stream_Write(s, iconStateOrder->toolTip.string, iconStateOrder->toolTip.length);
2650 }
2651
2652 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_INFO_TIP) != 0)
2653 {
2654 NOTIFY_ICON_INFOTIP infoTip = iconStateOrder->infoTip;
2655
2656 /* info tip should not be sent when version is 0 */
2657 if (versionFieldPresent && iconStateOrder->version == 0)
2658 return FALSE;
2659
2660 Stream_Write_UINT32(s, infoTip.timeout); /* Timeout (4 bytes) */
2661 Stream_Write_UINT32(s, infoTip.flags); /* InfoFlags (4 bytes) */
2662 Stream_Write_UINT16(s, infoTip.text.length); /* InfoTipText (variable) */
2663 Stream_Write(s, infoTip.text.string, infoTip.text.length);
2664 Stream_Write_UINT16(s, infoTip.title.length); /* Title (variable) */
2665 Stream_Write(s, infoTip.title.string, infoTip.title.length);
2666 }
2667
2668 if ((orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_STATE) != 0)
2669 {
2670 /* notify state should not be sent when version is 0 */
2671 if (versionFieldPresent && iconStateOrder->version == 0)
2672 return FALSE;
2673
2674 Stream_Write_UINT32(s, iconStateOrder->state);
2675 }
2676
2677 if ((orderInfo->fieldFlags & WINDOW_ORDER_ICON) != 0)
2678 {
2679 ICON_INFO iconInfo = iconStateOrder->icon;
2680 Stream_Write_UINT16(s, iconInfo.cacheEntry); /* CacheEntry (2 bytes) */
2681 Stream_Write_UINT8(s, iconInfo.cacheId); /* CacheId (1 byte) */
2682 Stream_Write_UINT8(s, iconInfo.bpp); /* Bpp (1 byte) */
2683 Stream_Write_UINT16(s, iconInfo.width); /* Width (2 bytes) */
2684 Stream_Write_UINT16(s, iconInfo.height); /* Height (2 bytes) */
2685
2686 if (iconInfo.bpp <= 8)
2687 {
2688 Stream_Write_UINT16(s, iconInfo.cbColorTable); /* CbColorTable (2 bytes) */
2689 }
2690
2691 Stream_Write_UINT16(s, iconInfo.cbBitsMask); /* CbBitsMask (2 bytes) */
2692 Stream_Write_UINT16(s, iconInfo.cbBitsColor); /* CbBitsColor (2 bytes) */
2693 Stream_Write(s, iconInfo.bitsMask, iconInfo.cbBitsMask); /* BitsMask (variable) */
2694 orderSize += iconInfo.cbBitsMask;
2695
2696 if (iconInfo.bpp <= 8)
2697 {
2698 Stream_Write(s, iconInfo.colorTable, iconInfo.cbColorTable); /* ColorTable (variable) */
2699 }
2700
2701 Stream_Write(s, iconInfo.bitsColor, iconInfo.cbBitsColor); /* BitsColor (variable) */
2702 }
2703 else if ((orderInfo->fieldFlags & WINDOW_ORDER_CACHED_ICON) != 0)
2704 {
2705 CACHED_ICON_INFO cachedIcon = iconStateOrder->cachedIcon;
2706 Stream_Write_UINT16(s, cachedIcon.cacheEntry); /* CacheEntry (2 bytes) */
2707 Stream_Write_UINT8(s, cachedIcon.cacheId); /* CacheId (1 byte) */
2708 }
2709
2710 update->numberOrders++;
2711 return TRUE;
2712 }
2713
update_send_notify_icon_create(rdpContext * context,const WINDOW_ORDER_INFO * orderInfo,const NOTIFY_ICON_STATE_ORDER * iconStateOrder)2714 static BOOL update_send_notify_icon_create(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo,
2715 const NOTIFY_ICON_STATE_ORDER* iconStateOrder)
2716 {
2717 return update_send_new_or_existing_notification_icons(context, orderInfo, iconStateOrder);
2718 }
2719
update_send_notify_icon_update(rdpContext * context,const WINDOW_ORDER_INFO * orderInfo,const NOTIFY_ICON_STATE_ORDER * iconStateOrder)2720 static BOOL update_send_notify_icon_update(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo,
2721 const NOTIFY_ICON_STATE_ORDER* iconStateOrder)
2722 {
2723 return update_send_new_or_existing_notification_icons(context, orderInfo, iconStateOrder);
2724 }
2725
update_send_notify_icon_delete(rdpContext * context,const WINDOW_ORDER_INFO * orderInfo)2726 static BOOL update_send_notify_icon_delete(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo)
2727 {
2728 wStream* s;
2729 rdpUpdate* update = context->update;
2730 BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2);
2731 UINT16 orderSize = 15;
2732 update_check_flush(context, orderSize);
2733
2734 s = update->us;
2735
2736 if (!s)
2737 return FALSE;
2738
2739 /* Write Hdr */
2740 Stream_Write_UINT8(s, controlFlags); /* Header (1 byte) */
2741 Stream_Write_UINT16(s, orderSize); /* OrderSize (2 bytes) */
2742 Stream_Write_UINT32(s, orderInfo->fieldFlags); /* FieldsPresentFlags (4 bytes) */
2743 Stream_Write_UINT32(s, orderInfo->windowId); /* WindowID (4 bytes) */
2744 Stream_Write_UINT32(s, orderInfo->notifyIconId); /* NotifyIconId (4 bytes) */
2745 update->numberOrders++;
2746 return TRUE;
2747 }
2748
update_calculate_monitored_desktop(const WINDOW_ORDER_INFO * orderInfo,const MONITORED_DESKTOP_ORDER * monitoredDesktop)2749 static UINT16 update_calculate_monitored_desktop(const WINDOW_ORDER_INFO* orderInfo,
2750 const MONITORED_DESKTOP_ORDER* monitoredDesktop)
2751 {
2752 UINT16 orderSize = 7;
2753
2754 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_DESKTOP_ACTIVE_WND)
2755 {
2756 orderSize += 4;
2757 }
2758
2759 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_DESKTOP_ZORDER)
2760 {
2761 orderSize += 1 + (4 * monitoredDesktop->numWindowIds);
2762 }
2763
2764 return orderSize;
2765 }
2766
update_send_monitored_desktop(rdpContext * context,const WINDOW_ORDER_INFO * orderInfo,const MONITORED_DESKTOP_ORDER * monitoredDesktop)2767 static BOOL update_send_monitored_desktop(rdpContext* context, const WINDOW_ORDER_INFO* orderInfo,
2768 const MONITORED_DESKTOP_ORDER* monitoredDesktop)
2769 {
2770 UINT32 i;
2771 wStream* s;
2772 rdpUpdate* update = context->update;
2773 BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2);
2774 UINT16 orderSize = update_calculate_monitored_desktop(orderInfo, monitoredDesktop);
2775 update_check_flush(context, orderSize);
2776
2777 s = update->us;
2778
2779 if (!s)
2780 return FALSE;
2781
2782 Stream_Write_UINT8(s, controlFlags); /* Header (1 byte) */
2783 Stream_Write_UINT16(s, orderSize); /* OrderSize (2 bytes) */
2784 Stream_Write_UINT32(s, orderInfo->fieldFlags); /* FieldsPresentFlags (4 bytes) */
2785
2786 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_DESKTOP_ACTIVE_WND)
2787 {
2788 Stream_Write_UINT32(s, monitoredDesktop->activeWindowId); /* activeWindowId (4 bytes) */
2789 }
2790
2791 if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_DESKTOP_ZORDER)
2792 {
2793 Stream_Write_UINT8(s, monitoredDesktop->numWindowIds); /* numWindowIds (1 byte) */
2794
2795 /* windowIds */
2796 for (i = 0; i < monitoredDesktop->numWindowIds; i++)
2797 {
2798 Stream_Write_UINT32(s, monitoredDesktop->windowIds[i]);
2799 }
2800 }
2801
2802 update->numberOrders++;
2803 return TRUE;
2804 }
2805
update_send_non_monitored_desktop(rdpContext * context,const WINDOW_ORDER_INFO * orderInfo)2806 static BOOL update_send_non_monitored_desktop(rdpContext* context,
2807 const WINDOW_ORDER_INFO* orderInfo)
2808 {
2809 wStream* s;
2810 rdpUpdate* update = context->update;
2811 BYTE controlFlags = ORDER_SECONDARY | (ORDER_TYPE_WINDOW << 2);
2812 UINT16 orderSize = 7;
2813 update_check_flush(context, orderSize);
2814
2815 s = update->us;
2816
2817 if (!s)
2818 return FALSE;
2819
2820 Stream_Write_UINT8(s, controlFlags); /* Header (1 byte) */
2821 Stream_Write_UINT16(s, orderSize); /* OrderSize (2 bytes) */
2822 Stream_Write_UINT32(s, orderInfo->fieldFlags); /* FieldsPresentFlags (4 bytes) */
2823 update->numberOrders++;
2824 return TRUE;
2825 }
2826
update_register_server_callbacks(rdpUpdate * update)2827 void update_register_server_callbacks(rdpUpdate* update)
2828 {
2829 update->BeginPaint = _update_begin_paint;
2830 update->EndPaint = _update_end_paint;
2831 update->SetBounds = update_set_bounds;
2832 update->Synchronize = update_send_synchronize;
2833 update->DesktopResize = update_send_desktop_resize;
2834 update->BitmapUpdate = update_send_bitmap_update;
2835 update->SurfaceBits = update_send_surface_bits;
2836 update->SurfaceFrameMarker = update_send_surface_frame_marker;
2837 update->SurfaceCommand = update_send_surface_command;
2838 update->SurfaceFrameBits = update_send_surface_frame_bits;
2839 update->PlaySound = update_send_play_sound;
2840 update->SetKeyboardIndicators = update_send_set_keyboard_indicators;
2841 update->SetKeyboardImeStatus = update_send_set_keyboard_ime_status;
2842 update->SaveSessionInfo = rdp_send_save_session_info;
2843 update->ServerStatusInfo = rdp_send_server_status_info;
2844 update->primary->DstBlt = update_send_dstblt;
2845 update->primary->PatBlt = update_send_patblt;
2846 update->primary->ScrBlt = update_send_scrblt;
2847 update->primary->OpaqueRect = update_send_opaque_rect;
2848 update->primary->LineTo = update_send_line_to;
2849 update->primary->MemBlt = update_send_memblt;
2850 update->primary->GlyphIndex = update_send_glyph_index;
2851 update->secondary->CacheBitmap = update_send_cache_bitmap;
2852 update->secondary->CacheBitmapV2 = update_send_cache_bitmap_v2;
2853 update->secondary->CacheBitmapV3 = update_send_cache_bitmap_v3;
2854 update->secondary->CacheColorTable = update_send_cache_color_table;
2855 update->secondary->CacheGlyph = update_send_cache_glyph;
2856 update->secondary->CacheGlyphV2 = update_send_cache_glyph_v2;
2857 update->secondary->CacheBrush = update_send_cache_brush;
2858 update->altsec->CreateOffscreenBitmap = update_send_create_offscreen_bitmap_order;
2859 update->altsec->SwitchSurface = update_send_switch_surface_order;
2860 update->pointer->PointerSystem = update_send_pointer_system;
2861 update->pointer->PointerPosition = update_send_pointer_position;
2862 update->pointer->PointerColor = update_send_pointer_color;
2863 update->pointer->PointerLarge = update_send_pointer_large;
2864 update->pointer->PointerNew = update_send_pointer_new;
2865 update->pointer->PointerCached = update_send_pointer_cached;
2866 update->window->WindowCreate = update_send_window_create;
2867 update->window->WindowUpdate = update_send_window_update;
2868 update->window->WindowIcon = update_send_window_icon;
2869 update->window->WindowCachedIcon = update_send_window_cached_icon;
2870 update->window->WindowDelete = update_send_window_delete;
2871 update->window->NotifyIconCreate = update_send_notify_icon_create;
2872 update->window->NotifyIconUpdate = update_send_notify_icon_update;
2873 update->window->NotifyIconDelete = update_send_notify_icon_delete;
2874 update->window->MonitoredDesktop = update_send_monitored_desktop;
2875 update->window->NonMonitoredDesktop = update_send_non_monitored_desktop;
2876 }
2877
update_register_client_callbacks(rdpUpdate * update)2878 void update_register_client_callbacks(rdpUpdate* update)
2879 {
2880 update->RefreshRect = update_send_refresh_rect;
2881 update->SuppressOutput = update_send_suppress_output;
2882 update->SurfaceFrameAcknowledge = update_send_frame_acknowledge;
2883 }
2884
update_process_messages(rdpUpdate * update)2885 int update_process_messages(rdpUpdate* update)
2886 {
2887 return update_message_queue_process_pending_messages(update);
2888 }
2889
update_free_queued_message(void * obj)2890 static void update_free_queued_message(void* obj)
2891 {
2892 wMessage* msg = (wMessage*)obj;
2893 update_message_queue_free_message(msg);
2894 }
2895
update_free_window_state(WINDOW_STATE_ORDER * window_state)2896 void update_free_window_state(WINDOW_STATE_ORDER* window_state)
2897 {
2898 if (!window_state)
2899 return;
2900
2901 free(window_state->OverlayDescription.string);
2902 free(window_state->titleInfo.string);
2903 free(window_state->windowRects);
2904 free(window_state->visibilityRects);
2905 memset(window_state, 0, sizeof(WINDOW_STATE_ORDER));
2906 }
2907
update_new(rdpRdp * rdp)2908 rdpUpdate* update_new(rdpRdp* rdp)
2909 {
2910 const wObject cb = { NULL, NULL, NULL, update_free_queued_message, NULL };
2911 rdpUpdate* update;
2912 OFFSCREEN_DELETE_LIST* deleteList;
2913 WINPR_UNUSED(rdp);
2914 update = (rdpUpdate*)calloc(1, sizeof(rdpUpdate));
2915
2916 if (!update)
2917 return NULL;
2918
2919 update->log = WLog_Get("com.freerdp.core.update");
2920 InitializeCriticalSection(&(update->mux));
2921 update->pointer = (rdpPointerUpdate*)calloc(1, sizeof(rdpPointerUpdate));
2922
2923 if (!update->pointer)
2924 goto fail;
2925
2926 update->primary = (rdpPrimaryUpdate*)calloc(1, sizeof(rdpPrimaryUpdate));
2927
2928 if (!update->primary)
2929 goto fail;
2930
2931 update->secondary = (rdpSecondaryUpdate*)calloc(1, sizeof(rdpSecondaryUpdate));
2932
2933 if (!update->secondary)
2934 goto fail;
2935
2936 update->altsec = (rdpAltSecUpdate*)calloc(1, sizeof(rdpAltSecUpdate));
2937
2938 if (!update->altsec)
2939 goto fail;
2940
2941 update->window = (rdpWindowUpdate*)calloc(1, sizeof(rdpWindowUpdate));
2942
2943 if (!update->window)
2944 goto fail;
2945
2946 deleteList = &(update->altsec->create_offscreen_bitmap.deleteList);
2947 deleteList->sIndices = 64;
2948 deleteList->indices = calloc(deleteList->sIndices, 2);
2949
2950 if (!deleteList->indices)
2951 goto fail;
2952
2953 deleteList->cIndices = 0;
2954 update->SuppressOutput = update_send_suppress_output;
2955 update->initialState = TRUE;
2956 update->autoCalculateBitmapData = TRUE;
2957 update->queue = MessageQueue_New(&cb);
2958
2959 if (!update->queue)
2960 goto fail;
2961
2962 return update;
2963 fail:
2964 update_free(update);
2965 return NULL;
2966 }
2967
update_free(rdpUpdate * update)2968 void update_free(rdpUpdate* update)
2969 {
2970 if (update != NULL)
2971 {
2972 OFFSCREEN_DELETE_LIST* deleteList = &(update->altsec->create_offscreen_bitmap.deleteList);
2973
2974 if (deleteList)
2975 free(deleteList->indices);
2976
2977 free(update->pointer);
2978
2979 if (update->primary)
2980 {
2981 free(update->primary->polyline.points);
2982 free(update->primary->polygon_sc.points);
2983 free(update->primary->fast_glyph.glyphData.aj);
2984 free(update->primary);
2985 }
2986
2987 free(update->secondary);
2988 free(update->altsec);
2989
2990 if (update->window)
2991 {
2992 free(update->window);
2993 }
2994
2995 MessageQueue_Free(update->queue);
2996 DeleteCriticalSection(&update->mux);
2997 free(update);
2998 }
2999 }
3000
update_begin_paint(rdpUpdate * update)3001 BOOL update_begin_paint(rdpUpdate* update)
3002 {
3003 if (!update)
3004 return FALSE;
3005
3006 EnterCriticalSection(&update->mux);
3007
3008 if (!update->BeginPaint)
3009 return TRUE;
3010
3011 return update->BeginPaint(update->context);
3012 }
3013
update_end_paint(rdpUpdate * update)3014 BOOL update_end_paint(rdpUpdate* update)
3015 {
3016 BOOL rc = FALSE;
3017
3018 if (!update)
3019 return FALSE;
3020
3021 if (update->EndPaint)
3022 rc = update->EndPaint(update->context);
3023
3024 LeaveCriticalSection(&update->mux);
3025 return rc;
3026 }
3027