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