1 /**
2 * xrdp: A Remote Desktop Protocol server.
3 *
4 * Copyright (C) Jay Sorg 2004-2014
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * cache
19 */
20
21 #if defined(HAVE_CONFIG_H)
22 #include <config_ac.h>
23 #endif
24
25 #include "xrdp.h"
26 #include "log.h"
27
28
29
30 /*****************************************************************************/
31 static int
xrdp_cache_reset_lru(struct xrdp_cache * self)32 xrdp_cache_reset_lru(struct xrdp_cache *self)
33 {
34 int index;
35 int jndex;
36 struct xrdp_lru_item *lru;
37
38 for (index = 0; index < XRDP_MAX_BITMAP_CACHE_ID; index++)
39 {
40 /* fist item */
41 lru = &(self->bitmap_lrus[index][0]);
42 lru->next = 1;
43 lru->prev = -1;
44 /* middle items */
45 for (jndex = 1; jndex < XRDP_MAX_BITMAP_CACHE_IDX - 1; jndex++)
46 {
47 lru = &(self->bitmap_lrus[index][jndex]);
48 lru->next = jndex + 1;
49 lru->prev = jndex - 1;
50 }
51 /* last item */
52 lru = &(self->bitmap_lrus[index][XRDP_MAX_BITMAP_CACHE_IDX - 1]);
53 lru->next = -1;
54 lru->prev = XRDP_MAX_BITMAP_CACHE_IDX - 2;
55
56 self->lru_head[index] = 0;
57 self->lru_tail[index] = XRDP_MAX_BITMAP_CACHE_IDX - 1;
58
59 self->lru_reset[index] = 1;
60 }
61 return 0;
62 }
63
64 /*****************************************************************************/
65 static int
xrdp_cache_reset_crc(struct xrdp_cache * self)66 xrdp_cache_reset_crc(struct xrdp_cache *self)
67 {
68 int index;
69 int jndex;
70
71 for (index = 0; index < XRDP_MAX_BITMAP_CACHE_ID; index++)
72 {
73 for (jndex = 0; jndex < 64 * 1024; jndex++)
74 {
75 /* it's ok to deinit a zeroed out struct list16 */
76 list16_deinit(&(self->crc16[index][jndex]));
77 list16_init(&(self->crc16[index][jndex]));
78 }
79 }
80 return 0;
81 }
82
83 /*****************************************************************************/
84 struct xrdp_cache *
xrdp_cache_create(struct xrdp_wm * owner,struct xrdp_session * session,struct xrdp_client_info * client_info)85 xrdp_cache_create(struct xrdp_wm *owner,
86 struct xrdp_session *session,
87 struct xrdp_client_info *client_info)
88 {
89 struct xrdp_cache *self;
90
91 self = (struct xrdp_cache *)g_malloc(sizeof(struct xrdp_cache), 1);
92 self->wm = owner;
93 self->session = session;
94 self->use_bitmap_comp = client_info->use_bitmap_comp;
95
96 self->cache1_entries = MIN(XRDP_MAX_BITMAP_CACHE_IDX,
97 client_info->cache1_entries);
98 self->cache1_entries = MAX(self->cache1_entries, 0);
99 self->cache1_size = client_info->cache1_size;
100
101 self->cache2_entries = MIN(XRDP_MAX_BITMAP_CACHE_IDX,
102 client_info->cache2_entries);
103 self->cache2_entries = MAX(self->cache2_entries, 0);
104 self->cache2_size = client_info->cache2_size;
105
106 self->cache3_entries = MIN(XRDP_MAX_BITMAP_CACHE_IDX,
107 client_info->cache3_entries);
108 self->cache3_entries = MAX(self->cache3_entries, 0);
109 self->cache3_size = client_info->cache3_size;
110
111 self->bitmap_cache_persist_enable = client_info->bitmap_cache_persist_enable;
112 self->bitmap_cache_version = client_info->bitmap_cache_version;
113 self->pointer_cache_entries = client_info->pointer_cache_entries;
114 self->xrdp_os_del_list = list_create();
115 xrdp_cache_reset_lru(self);
116 xrdp_cache_reset_crc(self);
117 LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_cache_create: 0 %d 1 %d 2 %d",
118 self->cache1_entries, self->cache2_entries, self->cache3_entries);
119 return self;
120 }
121
122 /*****************************************************************************/
123 void
xrdp_cache_delete(struct xrdp_cache * self)124 xrdp_cache_delete(struct xrdp_cache *self)
125 {
126 int i;
127 int j;
128
129 if (self == 0)
130 {
131 return;
132 }
133
134 /* free all the cached bitmaps */
135 for (i = 0; i < XRDP_MAX_BITMAP_CACHE_ID; i++)
136 {
137 for (j = 0; j < XRDP_MAX_BITMAP_CACHE_IDX; j++)
138 {
139 xrdp_bitmap_delete(self->bitmap_items[i][j].bitmap);
140 }
141 }
142
143 /* free all the cached font items */
144 for (i = 0; i < 12; i++)
145 {
146 for (j = 0; j < 256; j++)
147 {
148 g_free(self->char_items[i][j].font_item.data);
149 }
150 }
151
152 /* free all the off screen bitmaps */
153 for (i = 0; i < 2000; i++)
154 {
155 xrdp_bitmap_delete(self->os_bitmap_items[i].bitmap);
156 }
157
158 list_delete(self->xrdp_os_del_list);
159
160 /* free all crc lists */
161 for (i = 0; i < XRDP_MAX_BITMAP_CACHE_ID; i++)
162 {
163 for (j = 0; j < 64 * 1024; j++)
164 {
165 list16_deinit(&(self->crc16[i][j]));
166 }
167 }
168
169 g_free(self);
170 }
171
172 /*****************************************************************************/
173 int
xrdp_cache_reset(struct xrdp_cache * self,struct xrdp_client_info * client_info)174 xrdp_cache_reset(struct xrdp_cache *self,
175 struct xrdp_client_info *client_info)
176 {
177 struct xrdp_wm *wm;
178 struct xrdp_session *session;
179 int i;
180 int j;
181
182 /* free all the cached bitmaps */
183 for (i = 0; i < XRDP_MAX_BITMAP_CACHE_ID; i++)
184 {
185 for (j = 0; j < XRDP_MAX_BITMAP_CACHE_IDX; j++)
186 {
187 xrdp_bitmap_delete(self->bitmap_items[i][j].bitmap);
188 }
189 }
190
191 /* free all the cached font items */
192 for (i = 0; i < 12; i++)
193 {
194 for (j = 0; j < 256; j++)
195 {
196 g_free(self->char_items[i][j].font_item.data);
197 }
198 }
199
200 /* save these */
201 wm = self->wm;
202 session = self->session;
203 /* set whole struct to zero */
204 g_memset(self, 0, sizeof(struct xrdp_cache));
205 /* set some stuff back */
206 self->wm = wm;
207 self->session = session;
208 self->use_bitmap_comp = client_info->use_bitmap_comp;
209 self->cache1_entries = client_info->cache1_entries;
210 self->cache1_size = client_info->cache1_size;
211 self->cache2_entries = client_info->cache2_entries;
212 self->cache2_size = client_info->cache2_size;
213 self->cache3_entries = client_info->cache3_entries;
214 self->cache3_size = client_info->cache3_size;
215 self->bitmap_cache_persist_enable = client_info->bitmap_cache_persist_enable;
216 self->bitmap_cache_version = client_info->bitmap_cache_version;
217 self->pointer_cache_entries = client_info->pointer_cache_entries;
218 xrdp_cache_reset_lru(self);
219 xrdp_cache_reset_crc(self);
220 return 0;
221 }
222
223 #define COMPARE_WITH_CRC32(_b1, _b2) \
224 ((_b1->crc32 == _b2->crc32) && \
225 (_b1->bpp == _b2->bpp) && \
226 (_b1->width == _b2->width) && (_b1->height == _b2->height))
227
228 /*****************************************************************************/
229 static int
xrdp_cache_update_lru(struct xrdp_cache * self,int cache_id,int lru_index)230 xrdp_cache_update_lru(struct xrdp_cache *self, int cache_id, int lru_index)
231 {
232 int tail_index;
233 struct xrdp_lru_item *nextlru;
234 struct xrdp_lru_item *prevlru;
235 struct xrdp_lru_item *thislru;
236 struct xrdp_lru_item *taillru;
237
238 LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_cache_update_lru: lru_index %d", lru_index);
239 if ((lru_index < 0) || (lru_index >= XRDP_MAX_BITMAP_CACHE_IDX))
240 {
241 LOG(LOG_LEVEL_ERROR, "xrdp_cache_update_lru: error");
242 return 1;
243 }
244 if (self->lru_tail[cache_id] == lru_index)
245 {
246 /* nothing to do */
247 return 0;
248 }
249 else if (self->lru_head[cache_id] == lru_index)
250 {
251 /* moving head item to tail */
252
253 thislru = &(self->bitmap_lrus[cache_id][lru_index]);
254 nextlru = &(self->bitmap_lrus[cache_id][thislru->next]);
255 tail_index = self->lru_tail[cache_id];
256 taillru = &(self->bitmap_lrus[cache_id][tail_index]);
257
258 /* unhook old */
259 nextlru->prev = -1;
260
261 /* set head to next */
262 self->lru_head[cache_id] = thislru->next;
263
264 /* move to tail and hook up */
265 taillru->next = lru_index;
266 thislru->prev = tail_index;
267 thislru->next = -1;
268
269 /* update tail */
270 self->lru_tail[cache_id] = lru_index;
271
272 }
273 else
274 {
275 /* move middle item */
276
277 thislru = &(self->bitmap_lrus[cache_id][lru_index]);
278 prevlru = &(self->bitmap_lrus[cache_id][thislru->prev]);
279 nextlru = &(self->bitmap_lrus[cache_id][thislru->next]);
280 tail_index = self->lru_tail[cache_id];
281 taillru = &(self->bitmap_lrus[cache_id][tail_index]);
282
283 /* unhook old */
284 prevlru->next = thislru->next;
285 nextlru->prev = thislru->prev;
286
287 /* move to tail and hook up */
288 taillru->next = lru_index;
289 thislru->prev = tail_index;
290 thislru->next = -1;
291
292 /* update tail */
293 self->lru_tail[cache_id] = lru_index;
294 }
295 return 0;
296 }
297
298 /*****************************************************************************/
299 /* returns cache id */
300 int
xrdp_cache_add_bitmap(struct xrdp_cache * self,struct xrdp_bitmap * bitmap,int hints)301 xrdp_cache_add_bitmap(struct xrdp_cache *self, struct xrdp_bitmap *bitmap,
302 int hints)
303 {
304 int index;
305 int jndex;
306 int cache_id;
307 int cache_idx;
308 int bmp_size;
309 int e;
310 int Bpp;
311 int crc16;
312 int iig;
313 int found;
314 int cache_entries;
315 int lru_index;
316 struct list16 *ll;
317 struct xrdp_bitmap *lbm;
318 struct xrdp_lru_item *llru;
319
320 LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_cache_add_bitmap:");
321 LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_cache_add_bitmap: crc16 0x%4.4x",
322 bitmap->crc16);
323
324 e = (4 - (bitmap->width % 4)) & 3;
325 found = 0;
326 cache_id = 0;
327 cache_entries = 0;
328
329 /* client Bpp, bmp_size */
330 Bpp = (bitmap->bpp + 7) / 8;
331 bmp_size = (bitmap->width + e) * bitmap->height * Bpp;
332 self->bitmap_stamp++;
333
334 if (bmp_size <= self->cache1_size)
335 {
336 cache_id = 0;
337 cache_entries = self->cache1_entries;
338 }
339 else if (bmp_size <= self->cache2_size)
340 {
341 cache_id = 1;
342 cache_entries = self->cache2_entries;
343 }
344 else if (bmp_size <= self->cache3_size)
345 {
346 cache_id = 2;
347 cache_entries = self->cache3_entries;
348 }
349 else
350 {
351 LOG(LOG_LEVEL_ERROR, "error in xrdp_cache_add_bitmap, "
352 "too big(%d) bpp %d", bmp_size, bitmap->bpp);
353 return 0;
354 }
355
356 crc16 = bitmap->crc16;
357 ll = &(self->crc16[cache_id][crc16]);
358 for (jndex = 0; jndex < ll->count; jndex++)
359 {
360 cache_idx = list16_get_item(ll, jndex);
361 lbm = self->bitmap_items[cache_id][cache_idx].bitmap;
362 if ((lbm != NULL) && COMPARE_WITH_CRC32(lbm, bitmap))
363 {
364 LOG_DEVEL(LOG_LEVEL_DEBUG, "found bitmap at %d %d", cache_idx, jndex);
365 found = 1;
366 break;
367 }
368 }
369 if (found)
370 {
371 lru_index = self->bitmap_items[cache_id][cache_idx].lru_index;
372 self->bitmap_items[cache_id][cache_idx].stamp = self->bitmap_stamp;
373 xrdp_bitmap_delete(bitmap);
374
375 /* update lru to end */
376 xrdp_cache_update_lru(self, cache_id, lru_index);
377
378 return MAKELONG(cache_idx, cache_id);
379 }
380
381 /* find lru */
382
383 /* check for reset */
384 if (self->lru_reset[cache_id])
385 {
386 self->lru_reset[cache_id] = 0;
387 LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_cache_add_bitmap: reset detected cache_id %d",
388 cache_id);
389 self->lru_tail[cache_id] = cache_entries - 1;
390 index = self->lru_tail[cache_id];
391 llru = &(self->bitmap_lrus[cache_id][index]);
392 llru->next = -1;
393 }
394
395 /* lru is item at head */
396 lru_index = self->lru_head[cache_id];
397 cache_idx = lru_index;
398
399 /* update lru to end */
400 xrdp_cache_update_lru(self, cache_id, lru_index);
401
402 LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_cache_add_bitmap: oldest %d %d", cache_id, cache_idx);
403
404 LOG_DEVEL(LOG_LEVEL_DEBUG, "adding bitmap at %d %d old ptr %p new ptr %p",
405 cache_id, cache_idx,
406 self->bitmap_items[cache_id][cache_idx].bitmap,
407 bitmap);
408
409 /* remove old, about to be deleted, from crc16 list */
410 lbm = self->bitmap_items[cache_id][cache_idx].bitmap;
411 if (lbm != 0)
412 {
413 crc16 = lbm->crc16;
414 ll = &(self->crc16[cache_id][crc16]);
415 iig = list16_index_of(ll, cache_idx);
416 if (iig == -1)
417 {
418 LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_cache_add_bitmap: error removing cache_idx");
419 }
420 LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_cache_add_bitmap: removing index %d from crc16 %d",
421 iig, crc16);
422 list16_remove_item(ll, iig);
423 xrdp_bitmap_delete(lbm);
424 }
425
426 /* set, send bitmap and return */
427
428 self->bitmap_items[cache_id][cache_idx].bitmap = bitmap;
429 self->bitmap_items[cache_id][cache_idx].stamp = self->bitmap_stamp;
430 self->bitmap_items[cache_id][cache_idx].lru_index = lru_index;
431
432 /* add to crc16 list */
433 crc16 = bitmap->crc16;
434 ll = &(self->crc16[cache_id][crc16]);
435 list16_add_item(ll, cache_idx);
436 if (ll->count > 1)
437 {
438 LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_cache_add_bitmap: count %d", ll->count);
439 }
440
441 if (self->use_bitmap_comp)
442 {
443 if (self->bitmap_cache_version & 4)
444 {
445 if (libxrdp_orders_send_bitmap3(self->session, bitmap->width,
446 bitmap->height, bitmap->bpp,
447 bitmap->data, cache_id, cache_idx,
448 hints) == 0)
449 {
450 return MAKELONG(cache_idx, cache_id);
451 }
452 }
453
454 if (self->bitmap_cache_version & 2)
455 {
456 libxrdp_orders_send_bitmap2(self->session, bitmap->width,
457 bitmap->height, bitmap->bpp,
458 bitmap->data, cache_id, cache_idx,
459 hints);
460 }
461 else if (self->bitmap_cache_version & 1)
462 {
463 libxrdp_orders_send_bitmap(self->session, bitmap->width,
464 bitmap->height, bitmap->bpp,
465 bitmap->data, cache_id, cache_idx);
466 }
467 }
468 else
469 {
470 if (self->bitmap_cache_version & 2)
471 {
472 libxrdp_orders_send_raw_bitmap2(self->session, bitmap->width,
473 bitmap->height, bitmap->bpp,
474 bitmap->data, cache_id, cache_idx);
475 }
476 else if (self->bitmap_cache_version & 1)
477 {
478 libxrdp_orders_send_raw_bitmap(self->session, bitmap->width,
479 bitmap->height, bitmap->bpp,
480 bitmap->data, cache_id, cache_idx);
481 }
482 }
483
484 return MAKELONG(cache_idx, cache_id);
485 }
486
487 /*****************************************************************************/
488 /* not used */
489 /* not sure how to use a palette in rdp */
490 int
xrdp_cache_add_palette(struct xrdp_cache * self,int * palette)491 xrdp_cache_add_palette(struct xrdp_cache *self, int *palette)
492 {
493 int i;
494 int oldest;
495 int index;
496
497 if (self == 0)
498 {
499 return 0;
500 }
501
502 if (palette == 0)
503 {
504 return 0;
505 }
506
507 if (self->wm->screen->bpp > 8)
508 {
509 return 0;
510 }
511
512 self->palette_stamp++;
513
514 /* look for match */
515 for (i = 0; i < 6; i++)
516 {
517 if (g_memcmp(palette, self->palette_items[i].palette,
518 256 * sizeof(int)) == 0)
519 {
520 self->palette_items[i].stamp = self->palette_stamp;
521 return i;
522 }
523 }
524
525 /* look for oldest */
526 index = 0;
527 oldest = 0x7fffffff;
528
529 for (i = 0; i < 6; i++)
530 {
531 if (self->palette_items[i].stamp < oldest)
532 {
533 oldest = self->palette_items[i].stamp;
534 index = i;
535 }
536 }
537
538 /* set, send palette and return */
539 g_memcpy(self->palette_items[index].palette, palette, 256 * sizeof(int));
540 self->palette_items[index].stamp = self->palette_stamp;
541 libxrdp_orders_send_palette(self->session, palette, index);
542 return index;
543 }
544
545 /*****************************************************************************/
546 int
xrdp_cache_add_char(struct xrdp_cache * self,struct xrdp_font_char * font_item)547 xrdp_cache_add_char(struct xrdp_cache *self,
548 struct xrdp_font_char *font_item)
549 {
550 int i;
551 int j;
552 int oldest;
553 int f;
554 int c;
555 int datasize;
556 struct xrdp_font_char *fi;
557
558 self->char_stamp++;
559
560 /* look for match */
561 for (i = 7; i < 12; i++)
562 {
563 for (j = 0; j < 250; j++)
564 {
565 if (xrdp_font_item_compare(&self->char_items[i][j].font_item, font_item))
566 {
567 self->char_items[i][j].stamp = self->char_stamp;
568 LOG_DEVEL(LOG_LEVEL_TRACE, "found font at %d %d", i, j);
569 return MAKELONG(j, i);
570 }
571 }
572 }
573
574 /* look for oldest */
575 f = 0;
576 c = 0;
577 oldest = 0x7fffffff;
578
579 for (i = 7; i < 12; i++)
580 {
581 for (j = 0; j < 250; j++)
582 {
583 if (self->char_items[i][j].stamp < oldest)
584 {
585 oldest = self->char_items[i][j].stamp;
586 f = i;
587 c = j;
588 }
589 }
590 }
591
592 LOG_DEVEL(LOG_LEVEL_TRACE, "adding char at %d %d", f, c);
593 /* set, send char and return */
594 fi = &self->char_items[f][c].font_item;
595 g_free(fi->data);
596 datasize = FONT_DATASIZE(font_item);
597 fi->data = (char *)g_malloc(datasize, 1);
598 g_memcpy(fi->data, font_item->data, datasize);
599 fi->offset = font_item->offset;
600 fi->baseline = font_item->baseline;
601 fi->width = font_item->width;
602 fi->height = font_item->height;
603 self->char_items[f][c].stamp = self->char_stamp;
604 libxrdp_orders_send_font(self->session, fi, f, c);
605 return MAKELONG(c, f);
606 }
607
608 /*****************************************************************************/
609 /* added the pointer to the cache and send it to client, it also sets the
610 client if it finds it
611 returns the index in the cache
612 does not take ownership of pointer_item */
613 int
xrdp_cache_add_pointer(struct xrdp_cache * self,struct xrdp_pointer_item * pointer_item)614 xrdp_cache_add_pointer(struct xrdp_cache *self,
615 struct xrdp_pointer_item *pointer_item)
616 {
617 int i;
618 int oldest;
619 int index;
620
621 if (self == 0)
622 {
623 return 0;
624 }
625
626 self->pointer_stamp++;
627
628 /* look for match */
629 for (i = 2; i < self->pointer_cache_entries; i++)
630 {
631 if (self->pointer_items[i].x == pointer_item->x &&
632 self->pointer_items[i].y == pointer_item->y &&
633 g_memcmp(self->pointer_items[i].data,
634 pointer_item->data, 32 * 32 * 4) == 0 &&
635 g_memcmp(self->pointer_items[i].mask,
636 pointer_item->mask, 32 * 32 / 8) == 0 &&
637 self->pointer_items[i].bpp == pointer_item->bpp)
638 {
639 self->pointer_items[i].stamp = self->pointer_stamp;
640 xrdp_wm_set_pointer(self->wm, i);
641 self->wm->current_pointer = i;
642 LOG_DEVEL(LOG_LEVEL_TRACE, "found pointer at %d", i);
643 return i;
644 }
645 }
646
647 /* look for oldest */
648 index = 2;
649 oldest = 0x7fffffff;
650
651 for (i = 2; i < self->pointer_cache_entries; i++)
652 {
653 if (self->pointer_items[i].stamp < oldest)
654 {
655 oldest = self->pointer_items[i].stamp;
656 index = i;
657 }
658 }
659
660 self->pointer_items[index].x = pointer_item->x;
661 self->pointer_items[index].y = pointer_item->y;
662 g_memcpy(self->pointer_items[index].data,
663 pointer_item->data, 32 * 32 * 4);
664 g_memcpy(self->pointer_items[index].mask,
665 pointer_item->mask, 32 * 32 / 8);
666 self->pointer_items[index].stamp = self->pointer_stamp;
667 self->pointer_items[index].bpp = pointer_item->bpp;
668 xrdp_wm_send_pointer(self->wm, index,
669 self->pointer_items[index].data,
670 self->pointer_items[index].mask,
671 self->pointer_items[index].x,
672 self->pointer_items[index].y,
673 self->pointer_items[index].bpp);
674 self->wm->current_pointer = index;
675 LOG_DEVEL(LOG_LEVEL_TRACE, "adding pointer at %d", index);
676 return index;
677 }
678
679 /*****************************************************************************/
680 /* this does not take ownership of pointer_item, it makes a copy */
681 int
xrdp_cache_add_pointer_static(struct xrdp_cache * self,struct xrdp_pointer_item * pointer_item,int index)682 xrdp_cache_add_pointer_static(struct xrdp_cache *self,
683 struct xrdp_pointer_item *pointer_item,
684 int index)
685 {
686
687 if (self == 0)
688 {
689 return 0;
690 }
691
692 self->pointer_items[index].x = pointer_item->x;
693 self->pointer_items[index].y = pointer_item->y;
694 g_memcpy(self->pointer_items[index].data,
695 pointer_item->data, 32 * 32 * 4);
696 g_memcpy(self->pointer_items[index].mask,
697 pointer_item->mask, 32 * 32 / 8);
698 self->pointer_items[index].stamp = self->pointer_stamp;
699 self->pointer_items[index].bpp = pointer_item->bpp;
700 xrdp_wm_send_pointer(self->wm, index,
701 self->pointer_items[index].data,
702 self->pointer_items[index].mask,
703 self->pointer_items[index].x,
704 self->pointer_items[index].y,
705 self->pointer_items[index].bpp);
706 self->wm->current_pointer = index;
707 LOG_DEVEL(LOG_LEVEL_TRACE, "adding pointer at %d", index);
708 return index;
709 }
710
711 /*****************************************************************************/
712 /* this does not take ownership of brush_item_data, it makes a copy */
713 int
xrdp_cache_add_brush(struct xrdp_cache * self,char * brush_item_data)714 xrdp_cache_add_brush(struct xrdp_cache *self,
715 char *brush_item_data)
716 {
717 int i;
718 int oldest;
719 int index;
720
721 if (self == 0)
722 {
723 return 0;
724 }
725
726 self->brush_stamp++;
727
728 /* look for match */
729 for (i = 0; i < 64; i++)
730 {
731 if (g_memcmp(self->brush_items[i].pattern,
732 brush_item_data, 8) == 0)
733 {
734 self->brush_items[i].stamp = self->brush_stamp;
735 LOG_DEVEL(LOG_LEVEL_TRACE, "found brush at %d", i);
736 return i;
737 }
738 }
739
740 /* look for oldest */
741 index = 0;
742 oldest = 0x7fffffff;
743
744 for (i = 0; i < 64; i++)
745 {
746 if (self->brush_items[i].stamp < oldest)
747 {
748 oldest = self->brush_items[i].stamp;
749 index = i;
750 }
751 }
752
753 g_memcpy(self->brush_items[index].pattern,
754 brush_item_data, 8);
755 self->brush_items[index].stamp = self->brush_stamp;
756 libxrdp_orders_send_brush(self->session, 8, 8, 1, 0x81, 8,
757 self->brush_items[index].pattern, index);
758 LOG_DEVEL(LOG_LEVEL_TRACE, "adding brush at %d", index);
759 return index;
760 }
761
762 /*****************************************************************************/
763 /* returns error */
764 int
xrdp_cache_add_os_bitmap(struct xrdp_cache * self,struct xrdp_bitmap * bitmap,int rdpindex)765 xrdp_cache_add_os_bitmap(struct xrdp_cache *self, struct xrdp_bitmap *bitmap,
766 int rdpindex)
767 {
768 struct xrdp_os_bitmap_item *bi;
769
770 if ((rdpindex < 0) || (rdpindex >= 2000))
771 {
772 return 1;
773 }
774
775 bi = self->os_bitmap_items + rdpindex;
776 bi->bitmap = bitmap;
777 return 0;
778 }
779
780 /*****************************************************************************/
781 /* returns error */
782 int
xrdp_cache_remove_os_bitmap(struct xrdp_cache * self,int rdpindex)783 xrdp_cache_remove_os_bitmap(struct xrdp_cache *self, int rdpindex)
784 {
785 struct xrdp_os_bitmap_item *bi;
786 int index;
787
788 if ((rdpindex < 0) || (rdpindex >= 2000))
789 {
790 return 1;
791 }
792
793 bi = self->os_bitmap_items + rdpindex;
794
795 if (bi->bitmap->tab_stop)
796 {
797 index = list_index_of(self->xrdp_os_del_list, rdpindex);
798
799 if (index == -1)
800 {
801 list_add_item(self->xrdp_os_del_list, rdpindex);
802 }
803 }
804
805 xrdp_bitmap_delete(bi->bitmap);
806 g_memset(bi, 0, sizeof(struct xrdp_os_bitmap_item));
807 return 0;
808 }
809
810 /*****************************************************************************/
811 struct xrdp_os_bitmap_item *
xrdp_cache_get_os_bitmap(struct xrdp_cache * self,int rdpindex)812 xrdp_cache_get_os_bitmap(struct xrdp_cache *self, int rdpindex)
813 {
814 struct xrdp_os_bitmap_item *bi;
815
816 if ((rdpindex < 0) || (rdpindex >= 2000))
817 {
818 return 0;
819 }
820
821 bi = self->os_bitmap_items + rdpindex;
822 return bi;
823 }
824