1 /**
2  * FreeRDP: A Remote Desktop Protocol Server
3  * freerdp wrapper
4  *
5  * Copyright 2011-2013 Jay Sorg
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 
20 #if defined(HAVE_CONFIG_H)
21 #include <config_ac.h>
22 #endif
23 
24 #include "xrdp-neutrinordp.h"
25 #include "xrdp-color.h"
26 #include "xrdp_rail.h"
27 #include "trans.h"
28 #include "log.h"
29 #include "string_calls.h"
30 #include <freerdp/settings.h>
31 
32 #if defined(VERSION_STRUCT_RDP_FREERDP)
33 #if VERSION_STRUCT_RDP_FREERDP > 1
34 #define NEUTRINORDP_HAS_SUPPRESS_OUTPUT
35 #endif
36 #endif
37 
38 /* Max amount of buffered output data before we stop generating more */
39 #define MAX_QUEUED_MODULE_OUTPUT_DATA 50000
40 
41 
42 struct mod_context
43 {
44     rdpContext _p;
45     struct mod *modi;
46 };
47 typedef struct mod_context modContext;
48 
49 /*****************************************************************************/
50 static void
verifyColorMap(struct mod * mod)51 verifyColorMap(struct mod *mod)
52 {
53     int i;
54 
55     for (i = 0; i < 255; i++)
56     {
57         if (mod->colormap[i] != 0)
58         {
59             return ;
60         }
61     }
62 
63     LOG(LOG_LEVEL_WARNING, "The colormap is all NULL");
64 }
65 
66 /*****************************************************************************/
67 static int
get_queued_module_output_data(struct mod * mod)68 get_queued_module_output_data(struct mod *mod)
69 {
70     return (mod->si != NULL) ? mod->si->source[XRDP_SOURCE_MOD] : 0;
71 }
72 
73 /*****************************************************************************/
74 /* return error */
75 static int
lxrdp_start(struct mod * mod,int w,int h,int bpp)76 lxrdp_start(struct mod *mod, int w, int h, int bpp)
77 {
78     rdpSettings *settings;
79 
80     LOG_DEVEL(LOG_LEVEL_DEBUG, "lxrdp_start: w %d h %d bpp %d", w, h, bpp);
81     settings = mod->inst->settings;
82     settings->width = w;
83     settings->height = h;
84     settings->color_depth = bpp;
85     mod->bpp = bpp;
86 
87     settings->encryption = 1;
88     settings->tls_security = 1;
89     settings->nla_security = 0;
90     settings->rdp_security = 1;
91 
92     return 0;
93 }
94 
95 /******************************************************************************/
96 /* return error */
97 static void
set_keyboard_overrides(struct mod * mod)98 set_keyboard_overrides(struct mod *mod)
99 {
100     const struct kbd_overrides *ko = &mod->kbd_overrides;
101     rdpSettings *settings = mod->inst->settings;
102 
103     if (mod->allow_client_kbd_settings)
104     {
105         settings->kbd_type = mod->client_info.keyboard_type;
106         settings->kbd_subtype = mod->client_info.keyboard_subtype;
107         /* Define the most common number of function keys, 12.
108            because we can't get it from client. */
109         settings->kbd_fn_keys = 12;
110         settings->kbd_layout = mod->client_info.keylayout;
111 
112         /* Exception processing for each RDP Keyboard type */
113         if (mod->client_info.keyboard_type == 0x00)
114         {
115             /* 0x00000000 : Set on Server */
116             LOG(LOG_LEVEL_WARNING, "keyboard_type:[0x%02x] ,Set on Server",
117                 mod->client_info.keyboard_type);
118         }
119         else if (mod->client_info.keyboard_type == 0x04)
120         {
121             /* 0x00000004 : IBM enhanced (101- or 102-key) keyboard */
122             /* Nothing to do. */
123         }
124         else if (mod->client_info.keyboard_type == 0x07)
125         {
126             /* 0x00000007 : Japanese keyboard */
127             /* Nothing to do. */
128         }
129     }
130 
131     if (ko->type != 0)
132     {
133         LOG(LOG_LEVEL_INFO, "overrode kbd_type 0x%02X with 0x%02X",
134             settings->kbd_type, ko->type);
135         settings->kbd_type = ko->type;
136     }
137 
138     if (ko->subtype != 0)
139     {
140         LOG(LOG_LEVEL_INFO, "overrode kbd_subtype 0x%02X with 0x%02X",
141             settings->kbd_subtype, ko->subtype);
142         settings->kbd_subtype = ko->subtype;
143     }
144 
145     if (ko->fn_keys != 0)
146     {
147         LOG(LOG_LEVEL_INFO, "overrode kbd_fn_keys %d with %d",
148             settings->kbd_fn_keys, ko->fn_keys);
149         settings->kbd_fn_keys = ko->fn_keys;
150     }
151 
152     if (ko->layout != 0)
153     {
154         LOG(LOG_LEVEL_INFO, "overrode kbd_layout 0x%08X with 0x%08X",
155             settings->kbd_layout, ko->layout);
156         settings->kbd_layout = ko->layout;
157     }
158 
159     if (ko->layout_mask != 0)
160     {
161         LOG(LOG_LEVEL_INFO, "Masked kbd_layout 0x%08X to 0x%08X",
162             settings->kbd_layout, settings->kbd_layout & ko->layout_mask);
163         settings->kbd_layout &= ko->layout_mask;
164     }
165 
166     LOG(LOG_LEVEL_INFO, "NeutrinoRDP proxy remote keyboard settings, "
167         "kbd_type:[0x%02X], kbd_subtype:[0x%02X], "
168         "kbd_fn_keys:[%02d], kbd_layout:[0x%08X]",
169         settings->kbd_type, settings->kbd_subtype,
170         settings->kbd_fn_keys, settings->kbd_layout);
171 }
172 
173 static int
lxrdp_connect(struct mod * mod)174 lxrdp_connect(struct mod *mod)
175 {
176     boolean ok;
177     set_keyboard_overrides(mod);
178 
179     LOG_DEVEL(LOG_LEVEL_TRACE, "lxrdp_connect:");
180 
181     ok = freerdp_connect(mod->inst);
182     LOG_DEVEL(LOG_LEVEL_INFO, "lxrdp_connect: freerdp_connect returned %d", ok);
183 
184     if (!ok)
185     {
186         LOG_DEVEL(LOG_LEVEL_INFO, "Failure to connect");
187 #ifdef ERRORSTART
188 
189         if (connectErrorCode != 0)
190         {
191             char buf[128];
192 
193             if (connectErrorCode < ERRORSTART)
194             {
195                 if (strerror_r(connectErrorCode, buf, 128) != 0)
196                 {
197                     g_snprintf(buf, 128, "Errorcode from connect : %d", connectErrorCode);
198                 }
199             }
200             else
201             {
202                 switch (connectErrorCode)
203                 {
204                     case PREECONNECTERROR:
205                         g_snprintf(buf, 128, "The error code from connect is "
206                                    "PREECONNECTERROR");
207                         break;
208 
209                     case UNDEFINEDCONNECTERROR:
210                         g_snprintf(buf, 128, "The error code from connect is "
211                                    "UNDEFINEDCONNECTERROR");
212                         break;
213 
214                     case POSTCONNECTERROR:
215                         g_snprintf(buf, 128, "The error code from connect is "
216                                    "POSTCONNECTERROR");
217                         break;
218 
219                     case DNSERROR:
220                         g_snprintf(buf, 128, "The DNS system generated an error");
221                         break;
222 
223                     case DNSNAMENOTFOUND:
224                         g_snprintf(buf, 128, "The DNS system could not find the "
225                                    "specified name");
226                         break;
227 
228                     case CONNECTERROR:
229                         g_snprintf(buf, 128, "A general connect error was returned");
230                         break;
231 
232                     case MCSCONNECTINITIALERROR:
233                         g_snprintf(buf, 128, "The error code from connect is "
234                                    "MCSCONNECTINITIALERROR");
235                         break;
236 
237                     case TLSCONNECTERROR:
238                         g_snprintf(buf, 128, "Error in TLS handshake");
239                         break;
240 
241                     case AUTHENTICATIONERROR:
242                         g_snprintf(buf, 128, "Authentication error check your password "
243                                    "and username");
244                         break;
245 
246                     case INSUFFICIENTPRIVILEGESERROR:
247                         g_snprintf(buf, 128, "Insufficent privileges on target server");
248                         break;
249 
250                     default:
251                         g_snprintf(buf, 128, "Unhandled Errorcode from connect : %d",
252                                    connectErrorCode);
253                         break;
254                 }
255             }
256 
257             LOG(LOG_LEVEL_INFO, buf);
258             mod->server_msg(mod, buf, 0);
259         }
260 
261 #endif
262         LOG(LOG_LEVEL_ERROR, "NeutrinoRDP proxy connection: status [Failed],"
263             " RDP client [%s:%s], RDP server [%s:%d], RDP server username [%s],"
264             " xrdp pamusername [%s], xrdp process id [%d]",
265             mod->client_info.client_addr,
266             mod->client_info.client_port,
267             mod->inst->settings->hostname,
268             mod->inst->settings->port,
269             mod->inst->settings->username,
270             mod->pamusername,
271             g_getpid());
272         return 1;
273     }
274     else
275     {
276         LOG(LOG_LEVEL_INFO, "NeutrinoRDP proxy connection: status [Success],"
277             " RDP client [%s:%s], RDP server [%s:%d], RDP server username [%s],"
278             " xrdp pamusername [%s], xrdp process id [%d]",
279             mod->client_info.client_addr,
280             mod->client_info.client_port,
281             mod->inst->settings->hostname,
282             mod->inst->settings->port,
283             mod->inst->settings->username,
284             mod->pamusername,
285             g_getpid());
286     }
287 
288     return 0;
289 }
290 
291 /******************************************************************************/
292 /* return error */
293 static int
lxrdp_event(struct mod * mod,int msg,long param1,long param2,long param3,long param4)294 lxrdp_event(struct mod *mod, int msg, long param1, long param2,
295             long param3, long param4)
296 {
297     int x;
298     int y;
299     int cx;
300     int cy;
301     int flags;
302     int size;
303     int total_size;
304     int chanid;
305     int lchid;
306     char *data;
307 
308     LOG_DEVEL(LOG_LEVEL_DEBUG, "lxrdp_event: msg %d", msg);
309 
310     switch (msg)
311     {
312         case 15: /* key down */
313 
314             /* Before we handle the first character we synchronize
315                capslock and numlock. */
316             /* We collect the state during the first synchronize
317                ( see msg 17) */
318             if (!mod->bool_keyBoardSynced)
319             {
320                 LOG_DEVEL(LOG_LEVEL_DEBUG, "Additional Sync event handled : %d", mod->keyBoardLockInfo);
321                 mod->inst->input->SynchronizeEvent(mod->inst->input, mod->keyBoardLockInfo);
322                 mod->bool_keyBoardSynced = 1;
323             }
324 
325             mod->inst->input->KeyboardEvent(mod->inst->input, param4, param3);
326             break;
327 
328         case 16: /* key up */
329             mod->inst->input->KeyboardEvent(mod->inst->input, param4, param3);
330             break;
331 
332         case 17: /* Synchronize */
333             LOG_DEVEL(LOG_LEVEL_DEBUG, "Synchronized event handled : %ld", param1);
334             /* In some situations the Synchronize event come to early.
335                Therefore we store this information and use it when we
336                receive the first keyboard event
337                Without this fix numlock and capslock can come
338                out of sync. */
339             mod->inst->input->SynchronizeEvent(mod->inst->input, param1);
340 
341             if (!mod->bool_keyBoardSynced)
342             {
343                 mod->keyBoardLockInfo = param1;
344             }
345 
346             break;
347 
348         case 100: /* mouse move */
349             LOG_DEVEL(LOG_LEVEL_DEBUG, "mouse move %ld %ld", param1, param2);
350             x = param1;
351             y = param2;
352             flags = PTR_FLAGS_MOVE;
353             mod->inst->input->MouseEvent(mod->inst->input, flags, x, y);
354             break;
355 
356         case 101: /* left button up */
357             LOG_DEVEL(LOG_LEVEL_DEBUG, "left button up %ld %ld", param1, param2);
358             x = param1;
359             y = param2;
360             flags = PTR_FLAGS_BUTTON1;
361             mod->inst->input->MouseEvent(mod->inst->input, flags, x, y);
362             break;
363 
364         case 102: /* left button down */
365             LOG_DEVEL(LOG_LEVEL_DEBUG, "left button down %ld %ld", param1, param2);
366             x = param1;
367             y = param2;
368             flags = PTR_FLAGS_BUTTON1 | PTR_FLAGS_DOWN;
369             mod->inst->input->MouseEvent(mod->inst->input, flags, x, y);
370             break;
371 
372         case 103: /* right button up */
373             LOG_DEVEL(LOG_LEVEL_DEBUG, "right button up %ld %ld", param1, param2);
374             x = param1;
375             y = param2;
376             flags = PTR_FLAGS_BUTTON2;
377             mod->inst->input->MouseEvent(mod->inst->input, flags, x, y);
378             break;
379 
380         case 104: /* right button down */
381             LOG_DEVEL(LOG_LEVEL_DEBUG, "right button down %ld %ld", param1, param2);
382             x = param1;
383             y = param2;
384             flags = PTR_FLAGS_BUTTON2 | PTR_FLAGS_DOWN;
385             mod->inst->input->MouseEvent(mod->inst->input, flags, x, y);
386             break;
387 
388         case 105: /* middle button up */
389             LOG_DEVEL(LOG_LEVEL_DEBUG, "middle button up %ld %ld", param1, param2);
390             x = param1;
391             y = param2;
392             flags = PTR_FLAGS_BUTTON3;
393             mod->inst->input->MouseEvent(mod->inst->input, flags, x, y);
394             break;
395 
396         case 106: /* middle button down */
397             LOG_DEVEL(LOG_LEVEL_DEBUG, "middle button down %ld %ld", param1, param2);
398             x = param1;
399             y = param2;
400             flags = PTR_FLAGS_BUTTON3 | PTR_FLAGS_DOWN;
401             mod->inst->input->MouseEvent(mod->inst->input, flags, x, y);
402             break;
403 
404         case 107: /* wheel up */
405             flags = PTR_FLAGS_WHEEL | 0x0078;
406             mod->inst->input->MouseEvent(mod->inst->input, flags, 0, 0);
407             break;
408 
409         case 108:
410             break;
411 
412         case 109: /* wheel down */
413             flags = PTR_FLAGS_WHEEL | PTR_FLAGS_WHEEL_NEGATIVE | 0x0088;
414             mod->inst->input->MouseEvent(mod->inst->input, flags, 0, 0);
415             break;
416 
417         case 110:
418             break;
419 
420         case 200:
421             LOG_DEVEL(LOG_LEVEL_DEBUG, "Invalidate request sent from client");
422             x = (param1 >> 16) & 0xffff;
423             y = (param1 >> 0) & 0xffff;
424             cx = (param2 >> 16) & 0xffff;
425             cy = (param2 >> 0) & 0xffff;
426             mod->inst->SendInvalidate(mod->inst, -1, x, y, cx, cy);
427             break;
428 
429         case 0x5555:
430             chanid = LOWORD(param1);
431             flags = HIWORD(param1);
432             size = (int)param2;
433             data = (char *)param3;
434             total_size = (int)param4;
435 
436             LOG_DEVEL(LOG_LEVEL_DEBUG, "lxrdp_event: client to server ,chanid= %d  flags= %d", chanid, flags);
437 
438             if ((chanid < 0) || (chanid >= mod->inst->settings->num_channels))
439             {
440                 LOG(LOG_LEVEL_WARNING, "lxrdp_event: error chanid %d", chanid);
441                 break;
442             }
443 
444             lchid = mod->inst->settings->channels[chanid].channel_id;
445 
446             switch (flags & 3)
447             {
448                 case 3:
449                     mod->inst->SendChannelData(mod->inst, lchid, (tui8 *)data, total_size);
450                     break;
451 
452                 case 2:
453                     /* end */
454                     g_memcpy(mod->chan_buf + mod->chan_buf_valid, data, size);
455                     mod->chan_buf_valid += size;
456                     mod->inst->SendChannelData(mod->inst, lchid, (tui8 *)(mod->chan_buf),
457                                                total_size);
458                     g_free(mod->chan_buf);
459                     mod->chan_buf = 0;
460                     mod->chan_buf_bytes = 0;
461                     mod->chan_buf_valid = 0;
462                     break;
463 
464                 case 1:
465                     /* start */
466                     g_free(mod->chan_buf);
467                     mod->chan_buf = (char *)g_malloc(total_size, 0);
468                     mod->chan_buf_bytes = total_size;
469                     mod->chan_buf_valid = 0;
470                     g_memcpy(mod->chan_buf + mod->chan_buf_valid, data, size);
471                     mod->chan_buf_valid += size;
472                     break;
473 
474                 default:
475                     /* middle */
476                     g_memcpy(mod->chan_buf + mod->chan_buf_valid, data, size);
477                     mod->chan_buf_valid += size;
478                     break;
479             }
480 
481             break;
482 
483         default:
484             LOG(LOG_LEVEL_WARNING, "Unhandled message type in eventhandler %d", msg);
485             break;
486     }
487 
488     return 0;
489 }
490 
491 /******************************************************************************/
492 /* return error */
493 static int
lxrdp_signal(struct mod * mod)494 lxrdp_signal(struct mod *mod)
495 {
496     LOG_DEVEL(LOG_LEVEL_DEBUG, "lxrdp_signal:");
497     return 0;
498 }
499 
500 /******************************************************************************/
501 /* return error */
502 static int
lxrdp_end(struct mod * mod)503 lxrdp_end(struct mod *mod)
504 {
505     int i;
506     int j;
507 
508     for (j = 0; j < 4; j++)
509     {
510         for (i = 0; i < 4096; i++)
511         {
512             g_free(mod->bitmap_cache[j][i].data);
513         }
514     }
515 
516     for (i = 0; i < 64; i++)
517     {
518         if (mod->brush_cache[i].data != mod->brush_cache[i].b8x8)
519         {
520             g_free(mod->brush_cache[i].data);
521         }
522     }
523 
524     LOG_DEVEL(LOG_LEVEL_DEBUG, "lxrdp_end:");
525     LOG(LOG_LEVEL_INFO, "NeutrinoRDP proxy connection: status [Disconnect],"
526         " RDP client [%s:%s], RDP server [%s:%d], RDP server username [%s],"
527         " xrdp pamusername [%s], xrdp process id [%d]",
528         mod->client_info.client_addr,
529         mod->client_info.client_port,
530         mod->inst->settings->hostname,
531         mod->inst->settings->port,
532         mod->inst->settings->username,
533         mod->pamusername,
534         g_getpid());
535     return 0;
536 }
537 
538 /******************************************************************************/
539 /* return error */
540 static int
lxrdp_set_param(struct mod * mod,const char * name,const char * value)541 lxrdp_set_param(struct mod *mod, const char *name, const char *value)
542 {
543     rdpSettings *settings;
544 
545     if (g_strcmp(name, "password") == 0 || g_strcmp(name, "pampassword") == 0)
546     {
547         LOG_DEVEL(LOG_LEVEL_DEBUG, "lxrdp_set_param: name [%s] value [******]", name);
548     }
549     else
550     {
551         LOG_DEVEL(LOG_LEVEL_DEBUG, "lxrdp_set_param: name [%s] value [%s]", name, value);
552     }
553 
554     settings = mod->inst->settings;
555 
556     if (g_strcmp(name, "hostname") == 0)
557     {
558     }
559     else if (g_strcmp(name, "ip") == 0)
560     {
561         settings->hostname = g_strdup(value);
562     }
563     else if (g_strcmp(name, "port") == 0)
564     {
565         settings->port = g_atoi(value);
566     }
567     else if (g_strcmp(name, "keylayout") == 0)
568     {
569         LOG(LOG_LEVEL_DEBUG, "%s:[0x%08X]", name, g_atoi(value));
570     }
571     else if (g_strcmp(name, "name") == 0)
572     {
573     }
574     else if (g_strcmp(name, "lib") == 0)
575     {
576     }
577     else if (g_strcmp(name, "username") == 0)
578     {
579         g_strncpy(mod->username, value, 255);
580     }
581     else if (g_strcmp(name, "domain") == 0)
582     {
583         g_strncpy(mod->domain, value, 255);
584     }
585     else if (g_strcmp(name, "password") == 0)
586     {
587         g_strncpy(mod->password, value, 255);
588     }
589     else if (g_strcmp(name, "client_info") == 0)
590     {
591         g_memcpy(&(mod->client_info), value, sizeof(mod->client_info));
592         /* This is a Struct and cannot be printed in next else*/
593         LOG_DEVEL(LOG_LEVEL_DEBUG, "Client_info struct ignored");
594     }
595     else if (g_strcmp(name, "program") == 0)
596     {
597         settings->shell = g_strdup(value);
598     }
599     else if (g_strcmp(name, "nla") == 0)
600     {
601         settings->nla_security = g_text2bool(value);
602     }
603     else if (g_strcmp(name, "enable_dynamic_resizing") == 0)
604     {
605         settings->desktop_resize = g_text2bool(value);
606     }
607     else if (g_strcmp(name, "pamusername") == 0)
608     {
609         g_strncpy(mod->pamusername, value, 255);
610     }
611     else if (g_strcmp(name, "pampassword") == 0 ||
612              g_strcmp(name, "pamsessionmng") == 0)
613     {
614         /* Valid (but unused) parameters not logged */
615     }
616     else if (g_strcmp(name, "channel.rdpdr") == 0 ||
617              g_strcmp(name, "channel.rdpsnd") == 0 ||
618              g_strcmp(name, "channel.cliprdr") == 0 ||
619              g_strcmp(name, "channel.drdynvc") == 0)
620     {
621         /* Valid (but unused) parameters not logged */
622     }
623     else if (g_strcmp(name, "perf.allow_client_experiencesettings") == 0)
624     {
625         mod->allow_client_experiencesettings = g_text2bool(value);
626     }
627     else if (g_strcmp(name, "perf.wallpaper") == 0)
628     {
629         mod->perf_settings_override_mask |= PERF_DISABLE_WALLPAPER;
630         if (!g_text2bool(value))
631         {
632             mod->perf_settings_values_mask |= PERF_DISABLE_WALLPAPER;
633         }
634     }
635     else if (g_strcmp(name, "perf.font_smoothing") == 0)
636     {
637         mod->perf_settings_override_mask |= PERF_ENABLE_FONT_SMOOTHING;
638         if (g_text2bool(value))
639         {
640             mod->perf_settings_values_mask |= PERF_ENABLE_FONT_SMOOTHING;
641         }
642     }
643     else if (g_strcmp(name, "perf.desktop_composition") == 0)
644     {
645         mod->perf_settings_override_mask |= PERF_ENABLE_DESKTOP_COMPOSITION;
646         if (g_text2bool(value))
647         {
648             mod->perf_settings_values_mask |= PERF_ENABLE_DESKTOP_COMPOSITION;
649         }
650     }
651     else if (g_strcmp(name, "perf.full_window_drag") == 0)
652     {
653         mod->perf_settings_override_mask |= PERF_DISABLE_FULLWINDOWDRAG;
654         if (!g_text2bool(value))
655         {
656             mod->perf_settings_values_mask |= PERF_DISABLE_FULLWINDOWDRAG;
657         }
658     }
659     else if (g_strcmp(name, "perf.menu_anims") == 0)
660     {
661         mod->perf_settings_override_mask |= PERF_DISABLE_MENUANIMATIONS;
662         if (!g_text2bool(value))
663         {
664             mod->perf_settings_values_mask |= PERF_DISABLE_MENUANIMATIONS;
665         }
666     }
667     else if (g_strcmp(name, "perf.themes") == 0)
668     {
669         mod->perf_settings_override_mask |= PERF_DISABLE_THEMING;
670         if (!g_text2bool(value))
671         {
672             mod->perf_settings_values_mask |= PERF_DISABLE_THEMING;
673         }
674     }
675     else if (g_strcmp(name, "perf.cursor_blink") == 0)
676     {
677         mod->perf_settings_override_mask |= PERF_DISABLE_CURSORSETTINGS;
678         if (!g_text2bool(value))
679         {
680             mod->perf_settings_values_mask |= PERF_DISABLE_CURSORSETTINGS;
681         }
682     }
683     else if (g_strcmp(name, "perf.cursor_shadow") == 0)
684     {
685         mod->perf_settings_override_mask |= PERF_DISABLE_CURSOR_SHADOW;
686         if (!g_text2bool(value))
687         {
688             mod->perf_settings_values_mask |= PERF_DISABLE_CURSOR_SHADOW;
689         }
690     }
691     else if (g_strcmp(name, "neutrinordp.allow_client_keyboardLayout") == 0)
692     {
693         mod->allow_client_kbd_settings = g_text2bool(value);
694     }
695     else if (g_strcmp(name, "neutrinordp.override_keyboardLayout_mask") == 0)
696     {
697         /* Keyboard values are stored for later processing */
698         mod->kbd_overrides.layout_mask = g_atoix(value);
699     }
700     else if (g_strcmp(name, "neutrinordp.override_kbd_type") == 0)
701     {
702         mod->kbd_overrides.type = g_atoix(value);
703     }
704     else if (g_strcmp(name, "neutrinordp.override_kbd_subtype") == 0)
705     {
706         mod->kbd_overrides.subtype = g_atoix(value);
707     }
708     else if (g_strcmp(name, "neutrinordp.override_kbd_fn_keys") == 0)
709     {
710         mod->kbd_overrides.fn_keys = g_atoix(value);
711     }
712     else if (g_strcmp(name, "neutrinordp.override_kbd_layout") == 0)
713     {
714         mod->kbd_overrides.layout = g_atoix(value);
715     }
716     else
717     {
718         LOG(LOG_LEVEL_WARNING, "lxrdp_set_param: unknown name [%s] value [%s]", name, value);
719     }
720 
721     return 0;
722 }
723 
724 /******************************************************************************/
725 static int
lxrdp_session_change(struct mod * mod,int a,int b)726 lxrdp_session_change(struct mod *mod, int a, int b)
727 {
728     LOG_DEVEL(LOG_LEVEL_DEBUG, "lxrdp_session_change: - no code here");
729     return 0;
730 }
731 
732 /******************************************************************************/
733 static int
lxrdp_get_wait_objs(struct mod * mod,tbus * read_objs,int * rcount,tbus * write_objs,int * wcount,int * timeout)734 lxrdp_get_wait_objs(struct mod *mod, tbus *read_objs, int *rcount,
735                     tbus *write_objs, int *wcount, int *timeout)
736 {
737     void **rfds;
738     void **wfds;
739     boolean ok;
740 
741     LOG_DEVEL(LOG_LEVEL_TRACE, "lxrdp_get_wait_objs:");
742     /*
743      * Don't check this module for activity if our queued output data
744      * has already reached the limit
745      */
746     if (get_queued_module_output_data(mod) > MAX_QUEUED_MODULE_OUTPUT_DATA)
747     {
748         *rcount = 0;
749         *wcount = 0;
750     }
751     else
752     {
753         rfds = (void **)read_objs;
754         wfds = (void **)write_objs;
755         ok = freerdp_get_fds(mod->inst, rfds, rcount, wfds, wcount);
756 
757         if (!ok)
758         {
759             LOG(LOG_LEVEL_ERROR, "lxrdp_get_wait_objs: freerdp_get_fds failed");
760             return 1;
761         }
762     }
763 
764     return 0;
765 }
766 
767 /******************************************************************************/
768 static int
lxrdp_check_wait_objs(struct mod * mod)769 lxrdp_check_wait_objs(struct mod *mod)
770 {
771     boolean ok;
772 
773     LOG_DEVEL(LOG_LEVEL_TRACE, "lxrdp_check_wait_objs:");
774     /*
775      * Only process the freerdp file descriptors if our queued output data
776      * has not reached the limit
777      */
778     if (get_queued_module_output_data(mod) <= MAX_QUEUED_MODULE_OUTPUT_DATA)
779     {
780         /*
781          * Before checking the file descriptors, set the source info
782          * current source, so any data queued on output trans objects
783          * gets attributed to this module
784          */
785         if (mod->si)
786         {
787             mod->si->cur_source = XRDP_SOURCE_MOD;
788         }
789         ok = freerdp_check_fds(mod->inst);
790         if (mod->si)
791         {
792             mod->si->cur_source = XRDP_SOURCE_NONE;
793         }
794 
795         if (!ok)
796         {
797             LOG(LOG_LEVEL_ERROR, "lxrdp_check_wait_objs: freerdp_check_fds failed");
798             return 1;
799         }
800     }
801 
802     return 0;
803 }
804 
805 /******************************************************************************/
806 static int
lxrdp_frame_ack(struct mod * mod,int flags,int frame_id)807 lxrdp_frame_ack(struct mod *mod, int flags, int frame_id)
808 {
809     return 0;
810 }
811 
812 /******************************************************************************/
813 static int
lxrdp_suppress_output(struct mod * mod,int suppress,int left,int top,int right,int bottom)814 lxrdp_suppress_output(struct mod *mod, int suppress,
815                       int left, int top, int right, int bottom)
816 {
817 #if defined(NEUTRINORDP_HAS_SUPPRESS_OUTPUT)
818     mod->inst->SendSuppressOutput(mod->inst, !suppress, left, top, right, bottom);
819 #endif
820     return 0;
821 }
822 
823 /******************************************************************************/
824 static int
lxrdp_server_version_message(struct mod * mod)825 lxrdp_server_version_message(struct mod *mod)
826 {
827     return 0;
828 }
829 
830 /******************************************************************************/
831 static int
lxrdp_server_monitor_resize(struct mod * mod,int width,int height)832 lxrdp_server_monitor_resize(struct mod *mod, int width, int height)
833 {
834     return 0;
835 }
836 
837 /******************************************************************************/
838 static int
lxrdp_server_monitor_full_invalidate(struct mod * mod,int width,int height)839 lxrdp_server_monitor_full_invalidate(struct mod *mod, int width, int height)
840 {
841     return 0;
842 }
843 
844 /******************************************************************************/
845 static void
lfreerdp_begin_paint(rdpContext * context)846 lfreerdp_begin_paint(rdpContext *context)
847 {
848     struct mod *mod;
849 
850     LOG_DEVEL(LOG_LEVEL_TRACE, "lfreerdp_begin_paint:");
851     mod = ((struct mod_context *)context)->modi;
852     mod->server_begin_update(mod);
853 }
854 
855 /******************************************************************************/
856 static void
lfreerdp_end_paint(rdpContext * context)857 lfreerdp_end_paint(rdpContext *context)
858 {
859     struct mod *mod;
860 
861     LOG_DEVEL(LOG_LEVEL_TRACE, "lfreerdp_end_paint:");
862     mod = ((struct mod_context *)context)->modi;
863     mod->server_end_update(mod);
864 }
865 
866 /******************************************************************************/
867 static void
lfreerdp_set_bounds(rdpContext * context,rdpBounds * bounds)868 lfreerdp_set_bounds(rdpContext *context, rdpBounds *bounds)
869 {
870     struct mod *mod;
871     int x;
872     int y;
873     int cx;
874     int cy;
875 
876     LOG_DEVEL(LOG_LEVEL_DEBUG, "lfreerdp_set_bounds: %p", bounds);
877     mod = ((struct mod_context *)context)->modi;
878 
879     if (bounds != 0)
880     {
881         x = bounds->left;
882         y = bounds->top;
883         cx = (bounds->right - bounds->left) + 1;
884         cy = (bounds->bottom - bounds->top) + 1;
885         mod->server_set_clip(mod, x, y, cx, cy);
886     }
887     else
888     {
889         mod->server_reset_clip(mod);
890     }
891 }
892 
893 /******************************************************************************/
894 static void
lfreerdp_bitmap_update(rdpContext * context,BITMAP_UPDATE * bitmap)895 lfreerdp_bitmap_update(rdpContext *context, BITMAP_UPDATE *bitmap)
896 {
897     struct mod *mod;
898     int index;
899     int cx;
900     int cy;
901     int server_bpp;
902     int server_Bpp;
903     int client_bpp;
904     int j;
905     int line_bytes;
906     BITMAP_DATA *bd;
907     char *dst_data;
908     char *dst_data1;
909     char *src;
910     char *dst;
911 
912     mod = ((struct mod_context *)context)->modi;
913     LOG_DEVEL(LOG_LEVEL_DEBUG, "lfreerdp_bitmap_update: %d %d", bitmap->number, bitmap->count);
914 
915     server_bpp = mod->inst->settings->color_depth;
916     server_Bpp = (server_bpp + 7) / 8;
917     client_bpp = mod->bpp;
918 
919     for (index = 0; index < bitmap->number; index++)
920     {
921         bd = &bitmap->rectangles[index];
922         cx = (bd->destRight - bd->destLeft) + 1;
923         cy = (bd->destBottom - bd->destTop) + 1;
924         line_bytes = server_Bpp * bd->width;
925         dst_data = (char *)g_malloc(bd->height * line_bytes + 16, 0);
926 
927         if (bd->compressed)
928         {
929             LOG_DEVEL(LOG_LEVEL_DEBUG, "decompress size : %d", bd->bitmapLength);
930 
931             if (!bitmap_decompress(bd->bitmapDataStream, (tui8 *)dst_data, bd->width,
932                                    bd->height, bd->bitmapLength, server_bpp, server_bpp))
933             {
934                 LOG(LOG_LEVEL_WARNING, "Failure to decompress the bitmap");
935             }
936         }
937         else
938         {
939             /* bitmap is upside down */
940             LOG_DEVEL(LOG_LEVEL_DEBUG, "bitmap upside down");
941             src = (char *)(bd->bitmapDataStream);
942             dst = dst_data + bd->height * line_bytes;
943 
944             for (j = 0; j < bd->height; j++)
945             {
946                 dst -= line_bytes;
947                 g_memcpy(dst, src, line_bytes);
948                 src += line_bytes;
949             }
950         }
951 
952         dst_data1 = convert_bitmap(server_bpp, client_bpp, dst_data,
953                                    bd->width, bd->height, mod->colormap);
954         mod->server_paint_rect(mod, bd->destLeft, bd->destTop, cx, cy,
955                                dst_data1, bd->width, bd->height, 0, 0);
956 
957         if (dst_data1 != dst_data)
958         {
959             g_free(dst_data1);
960         }
961 
962         g_free(dst_data);
963     }
964 }
965 
966 /******************************************************************************/
967 static void
lfreerdp_dst_blt(rdpContext * context,DSTBLT_ORDER * dstblt)968 lfreerdp_dst_blt(rdpContext *context, DSTBLT_ORDER *dstblt)
969 {
970     struct mod *mod;
971 
972     mod = ((struct mod_context *)context)->modi;
973     LOG_DEVEL(LOG_LEVEL_TRACE, "lfreerdp_dst_blt:");
974     mod->server_set_opcode(mod, dstblt->bRop);
975     mod->server_fill_rect(mod, dstblt->nLeftRect, dstblt->nTopRect,
976                           dstblt->nWidth, dstblt->nHeight);
977     mod->server_set_opcode(mod, 0xcc);
978 }
979 
980 /******************************************************************************/
981 static void
lfreerdp_pat_blt(rdpContext * context,PATBLT_ORDER * patblt)982 lfreerdp_pat_blt(rdpContext *context, PATBLT_ORDER *patblt)
983 {
984     struct mod *mod;
985     int idx;
986     int fgcolor;
987     int bgcolor;
988     int server_bpp;
989     int client_bpp;
990     struct brush_item *bi;
991 
992     mod = ((struct mod_context *)context)->modi;
993     LOG_DEVEL(LOG_LEVEL_TRACE, "lfreerdp_pat_blt:");
994 
995     server_bpp = mod->inst->settings->color_depth;
996     client_bpp = mod->bpp;
997     LOG_DEVEL(LOG_LEVEL_DEBUG, "lfreerdp_pat_blt: bpp %d %d", server_bpp, client_bpp);
998 
999     fgcolor = convert_color(server_bpp, client_bpp,
1000                             patblt->foreColor, mod->colormap);
1001     bgcolor = convert_color(server_bpp, client_bpp,
1002                             patblt->backColor, mod->colormap);
1003 
1004     LOG_DEVEL(LOG_LEVEL_DEBUG, "lfreerdp_pat_blt: nLeftRect %d nTopRect %d "
1005               "nWidth %d nHeight %d fgcolor 0x%8.8x bgcolor 0x%8.8x",
1006               patblt->nLeftRect, patblt->nTopRect,
1007               patblt->nWidth, patblt->nHeight, fgcolor, bgcolor);
1008 
1009     if (fgcolor == bgcolor)
1010     {
1011         LOG(LOG_LEVEL_WARNING, "Warning same color on both bg and fg");
1012     }
1013 
1014     mod->server_set_mixmode(mod, 1);
1015     mod->server_set_opcode(mod, patblt->bRop);
1016     mod->server_set_fgcolor(mod, fgcolor);
1017     mod->server_set_bgcolor(mod, bgcolor);
1018 
1019     if (patblt->brush.style & 0x80)
1020     {
1021         idx = patblt->brush.hatch;
1022 
1023         if ((idx < 0) || (idx >= 64))
1024         {
1025             LOG(LOG_LEVEL_ERROR, "lfreerdp_pat_blt: error patblt->brush.hatch, "
1026                 "Expected min 0, max 63. Actual %d", idx);
1027             return;
1028         }
1029 
1030         bi = mod->brush_cache + idx;
1031         mod->server_set_brush(mod, patblt->brush.x, patblt->brush.y,
1032                               3, bi->b8x8);
1033     }
1034     else
1035     {
1036         mod->server_set_brush(mod, patblt->brush.x, patblt->brush.y,
1037                               patblt->brush.style,
1038                               (char *)(patblt->brush.p8x8));
1039     }
1040 
1041     mod->server_fill_rect(mod, patblt->nLeftRect, patblt->nTopRect,
1042                           patblt->nWidth, patblt->nHeight);
1043     mod->server_set_opcode(mod, 0xcc);
1044     mod->server_set_mixmode(mod, 0);
1045 
1046 }
1047 
1048 /******************************************************************************/
1049 static void
lfreerdp_scr_blt(rdpContext * context,SCRBLT_ORDER * scrblt)1050 lfreerdp_scr_blt(rdpContext *context, SCRBLT_ORDER *scrblt)
1051 {
1052     struct mod *mod;
1053 
1054     mod = ((struct mod_context *)context)->modi;
1055     LOG_DEVEL(LOG_LEVEL_TRACE, "lfreerdp_scr_blt:");
1056     mod->server_set_opcode(mod, scrblt->bRop);
1057     mod->server_screen_blt(mod, scrblt->nLeftRect, scrblt->nTopRect,
1058                            scrblt->nWidth, scrblt->nHeight,
1059                            scrblt->nXSrc, scrblt->nYSrc);
1060     mod->server_set_opcode(mod, 0xcc);
1061 }
1062 
1063 /******************************************************************************/
1064 static void
lfreerdp_opaque_rect(rdpContext * context,OPAQUE_RECT_ORDER * opaque_rect)1065 lfreerdp_opaque_rect(rdpContext *context, OPAQUE_RECT_ORDER *opaque_rect)
1066 {
1067     struct mod *mod;
1068     int server_bpp;
1069     int client_bpp;
1070     int fgcolor;
1071 
1072     mod = ((struct mod_context *)context)->modi;
1073     LOG_DEVEL(LOG_LEVEL_TRACE, "lfreerdp_opaque_rect:");
1074     server_bpp = mod->inst->settings->color_depth;
1075     client_bpp = mod->bpp;
1076     fgcolor = convert_color(server_bpp, client_bpp,
1077                             opaque_rect->color, mod->colormap);
1078     LOG_DEVEL(LOG_LEVEL_DEBUG, "lfreerdp_opaque_rect: nLeftRect %d nTopRect %d "
1079               "nWidth %d nHeight %d fgcolor 0x%8.8x",
1080               opaque_rect->nLeftRect, opaque_rect->nTopRect,
1081               opaque_rect->nWidth, opaque_rect->nHeight, fgcolor);
1082     mod->server_set_fgcolor(mod, fgcolor);
1083     mod->server_fill_rect(mod, opaque_rect->nLeftRect, opaque_rect->nTopRect,
1084                           opaque_rect->nWidth, opaque_rect->nHeight);
1085 }
1086 
1087 /******************************************************************************/
1088 static void
lfreerdp_mem_blt(rdpContext * context,MEMBLT_ORDER * memblt)1089 lfreerdp_mem_blt(rdpContext *context, MEMBLT_ORDER *memblt)
1090 {
1091     int id;
1092     int idx;
1093     struct mod *mod;
1094     struct bitmap_item *bi;
1095 
1096     mod = ((struct mod_context *)context)->modi;
1097     LOG_DEVEL(LOG_LEVEL_DEBUG, "lfreerdp_mem_blt: cacheId %d cacheIndex %d",
1098               memblt->cacheId, memblt->cacheIndex);
1099 
1100     id = memblt->cacheId;
1101     idx = memblt->cacheIndex;
1102 
1103     if (idx == 32767) /* BITMAPCACHE_WAITING_LIST_INDEX */
1104     {
1105         idx = 4096 - 1;
1106     }
1107 
1108     if ((id < 0) || (id >= 4))
1109     {
1110         LOG(LOG_LEVEL_ERROR, "lfreerdp_mem_blt: bad id [%d]", id);
1111         return;
1112     }
1113 
1114     if ((idx < 0) || (idx >= 4096))
1115     {
1116         LOG(LOG_LEVEL_ERROR, "lfreerdp_mem_blt: bad idx [%d]", idx);
1117         return;
1118     }
1119 
1120     bi = &(mod->bitmap_cache[id][idx]);
1121 
1122     mod->server_set_opcode(mod, memblt->bRop);
1123     mod->server_paint_rect(mod, memblt->nLeftRect, memblt->nTopRect,
1124                            memblt->nWidth, memblt->nHeight,
1125                            bi->data, bi->width, bi->height,
1126                            memblt->nXSrc, memblt->nYSrc);
1127     mod->server_set_opcode(mod, 0xcc);
1128 
1129 }
1130 
1131 /******************************************************************************/
1132 static void
lfreerdp_glyph_index(rdpContext * context,GLYPH_INDEX_ORDER * glyph_index)1133 lfreerdp_glyph_index(rdpContext *context, GLYPH_INDEX_ORDER *glyph_index)
1134 {
1135     struct mod *mod;
1136     int server_bpp;
1137     int client_bpp;
1138     int fgcolor;
1139     int bgcolor;
1140     int opLeft;
1141     int opTop;
1142     int opRight;
1143     int opBottom;
1144 
1145     mod = ((struct mod_context *)context)->modi;
1146     LOG_DEVEL(LOG_LEVEL_TRACE, "lfreerdp_glyph_index:");
1147     server_bpp = mod->inst->settings->color_depth;
1148     client_bpp = mod->bpp;
1149     fgcolor = convert_color(server_bpp, client_bpp,
1150                             glyph_index->foreColor, mod->colormap);
1151     bgcolor = convert_color(server_bpp, client_bpp,
1152                             glyph_index->backColor, mod->colormap);
1153     LOG_DEVEL(LOG_LEVEL_DEBUG, "lfreerdp_glyph_index: "
1154               "bkLeft %d bkTop %d width %d height %d "
1155               "opLeft %d opTop %d width %d height %d "
1156               "cbData %d fgcolor 0x%8.8x bgcolor 0x%8.8x fOpRedundant %d",
1157               glyph_index->bkLeft, glyph_index->bkTop,
1158               glyph_index->bkRight - glyph_index->bkLeft,
1159               glyph_index->bkBottom - glyph_index->bkTop,
1160               glyph_index->opLeft, glyph_index->opTop,
1161               glyph_index->opRight - glyph_index->opLeft,
1162               glyph_index->opBottom - glyph_index->opTop,
1163               glyph_index->cbData, fgcolor, bgcolor, glyph_index->fOpRedundant);
1164     mod->server_set_bgcolor(mod, fgcolor);
1165     mod->server_set_fgcolor(mod, bgcolor);
1166     opLeft = glyph_index->opLeft;
1167     opTop = glyph_index->opTop;
1168     opRight = glyph_index->opRight;
1169     opBottom = glyph_index->opBottom;
1170 #if 1
1171 
1172     /* workarounds for freerdp not using fOpRedundant in
1173        glyph.c::update_gdi_glyph_index */
1174     if (glyph_index->fOpRedundant)
1175     {
1176         opLeft = glyph_index->bkLeft;
1177         opTop = glyph_index->bkTop;
1178         opRight = glyph_index->bkRight;
1179         opBottom = glyph_index->bkBottom;
1180     }
1181 
1182 #endif
1183     mod->server_draw_text(mod, glyph_index->cacheId, glyph_index->flAccel,
1184                           glyph_index->fOpRedundant,
1185                           glyph_index->bkLeft, glyph_index->bkTop,
1186                           glyph_index->bkRight, glyph_index->bkBottom,
1187                           opLeft, opTop, opRight, opBottom,
1188                           glyph_index->x, glyph_index->y,
1189                           (char *)(glyph_index->data), glyph_index->cbData);
1190 }
1191 
1192 /******************************************************************************/
1193 static void
lfreerdp_line_to(rdpContext * context,LINE_TO_ORDER * line_to)1194 lfreerdp_line_to(rdpContext *context, LINE_TO_ORDER *line_to)
1195 {
1196     struct mod *mod;
1197     int server_bpp;
1198     int client_bpp;
1199     int fgcolor;
1200     int bgcolor;
1201 
1202     mod = ((struct mod_context *)context)->modi;
1203     LOG_DEVEL(LOG_LEVEL_TRACE, "lfreerdp_line_to:");
1204     mod->server_set_opcode(mod, line_to->bRop2);
1205     server_bpp = mod->inst->settings->color_depth;
1206     client_bpp = mod->bpp;
1207     fgcolor = convert_color(server_bpp, client_bpp,
1208                             line_to->penColor, mod->colormap);
1209     bgcolor = convert_color(server_bpp, client_bpp,
1210                             line_to->backColor, mod->colormap);
1211     mod->server_set_fgcolor(mod, fgcolor);
1212     mod->server_set_bgcolor(mod, bgcolor);
1213     mod->server_set_pen(mod, line_to->penStyle, line_to->penWidth);
1214     mod->server_draw_line(mod, line_to->nXStart, line_to->nYStart,
1215                           line_to->nXEnd, line_to->nYEnd);
1216     mod->server_set_opcode(mod, 0xcc);
1217 }
1218 
1219 /******************************************************************************/
1220 static void
lfreerdp_cache_bitmap(rdpContext * context,CACHE_BITMAP_ORDER * cache_bitmap_order)1221 lfreerdp_cache_bitmap(rdpContext *context, CACHE_BITMAP_ORDER *cache_bitmap_order)
1222 {
1223     LOG_DEVEL(LOG_LEVEL_INFO, "lfreerdp_cache_bitmap: - no code here");
1224 }
1225 
1226 /******************************************************************************/
1227 /* Turn the bitmap upside down*/
1228 static void
lfreerdp_upsidedown(uint8 * destination,CACHE_BITMAP_V2_ORDER * cache_bitmap_v2_order,int server_Bpp)1229 lfreerdp_upsidedown(uint8 *destination, CACHE_BITMAP_V2_ORDER *cache_bitmap_v2_order, int server_Bpp)
1230 {
1231     tui8 *src;
1232     tui8 *dst;
1233     int line_bytes;
1234     int j;
1235 
1236     if (destination == NULL)
1237     {
1238         LOG(LOG_LEVEL_ERROR, "lfreerdp_upsidedown: destination pointer is NULL !!!");
1239         return;
1240     }
1241 
1242     line_bytes = server_Bpp * cache_bitmap_v2_order->bitmapWidth;
1243     src = cache_bitmap_v2_order->bitmapDataStream;
1244     dst = destination + ((cache_bitmap_v2_order->bitmapHeight) * line_bytes);
1245 
1246     for (j = 0; j < cache_bitmap_v2_order->bitmapHeight; j++)
1247     {
1248         dst -= line_bytes;
1249         g_memcpy(dst, src, line_bytes);
1250         src += line_bytes;
1251     }
1252 }
1253 
1254 /******************************************************************************/
1255 static void
lfreerdp_cache_bitmapV2(rdpContext * context,CACHE_BITMAP_V2_ORDER * cache_bitmap_v2_order)1256 lfreerdp_cache_bitmapV2(rdpContext *context,
1257                         CACHE_BITMAP_V2_ORDER *cache_bitmap_v2_order)
1258 {
1259     char *dst_data;
1260     char *dst_data1;
1261     int bytes;
1262     int width;
1263     int height;
1264     int id;
1265     int idx;
1266     int flags;
1267     int server_bpp;
1268     int server_Bpp;
1269     int client_bpp;
1270     struct mod *mod;
1271 
1272     LOG_DEVEL(LOG_LEVEL_DEBUG, "lfreerdp_cache_bitmapV2: %d %d 0x%8.8x compressed %d",
1273               cache_bitmap_v2_order->cacheId,
1274               cache_bitmap_v2_order->cacheIndex,
1275               cache_bitmap_v2_order->flags,
1276               cache_bitmap_v2_order->compressed);
1277 
1278     mod = ((struct mod_context *)context)->modi;
1279     id = cache_bitmap_v2_order->cacheId;
1280     idx = cache_bitmap_v2_order->cacheIndex;
1281     flags = cache_bitmap_v2_order->flags;
1282 
1283     if (flags & 0x10) /* CBR2_DO_NOT_CACHE */
1284     {
1285         LOG_DEVEL(LOG_LEVEL_DEBUG, "lfreerdp_cache_bitmapV2: CBR2_DO_NOT_CACHE");
1286         idx = 4096 - 1;
1287     }
1288 
1289     if ((id < 0) || (id >= 4))
1290     {
1291         LOG(LOG_LEVEL_ERROR, "lfreerdp_cache_bitmapV2: bad id [%d]", id);
1292         return;
1293     }
1294 
1295     if ((idx < 0) || (idx >= 4096))
1296     {
1297         LOG(LOG_LEVEL_ERROR, "lfreerdp_cache_bitmapV2: bad idx [%d]", idx);
1298         return;
1299     }
1300 
1301     server_bpp = mod->inst->settings->color_depth;
1302     server_Bpp = (server_bpp + 7) / 8;
1303     client_bpp = mod->bpp;
1304 
1305     width = cache_bitmap_v2_order->bitmapWidth;
1306     height = cache_bitmap_v2_order->bitmapHeight;
1307     bytes = width * height * server_Bpp + 16;
1308     dst_data = (char *)g_malloc(bytes, 0);
1309 
1310     if (cache_bitmap_v2_order->compressed)
1311     {
1312         bitmap_decompress(cache_bitmap_v2_order->bitmapDataStream,
1313                           (tui8 *)dst_data, width, height,
1314                           cache_bitmap_v2_order->bitmapLength,
1315                           server_bpp, server_bpp);
1316     }
1317     else
1318     {
1319         /* Uncompressed bitmaps are upside down */
1320         lfreerdp_upsidedown((tui8 *)dst_data, cache_bitmap_v2_order, server_Bpp);
1321         LOG_DEVEL(LOG_LEVEL_DEBUG, "lfreerdp_cache_bitmapV2:  upside down progressed");
1322     }
1323 
1324     dst_data1 = convert_bitmap(server_bpp, client_bpp, dst_data,
1325                                width, height, mod->colormap);
1326     g_free(mod->bitmap_cache[id][idx].data);
1327     mod->bitmap_cache[id][idx].width = width;
1328     mod->bitmap_cache[id][idx].height = height;
1329     mod->bitmap_cache[id][idx].data = dst_data1;
1330 
1331     if (dst_data != dst_data1)
1332     {
1333         g_free(dst_data);
1334     }
1335 }
1336 
1337 /******************************************************************************/
1338 static void
lfreerdp_cache_glyph(rdpContext * context,CACHE_GLYPH_ORDER * cache_glyph_order)1339 lfreerdp_cache_glyph(rdpContext *context, CACHE_GLYPH_ORDER *cache_glyph_order)
1340 {
1341     int index;
1342     GLYPH_DATA *gd;
1343     struct mod *mod;
1344 
1345     mod = ((struct mod_context *)context)->modi;
1346     LOG_DEVEL(LOG_LEVEL_DEBUG, "lfreerdp_cache_glyph: %d", cache_glyph_order->cGlyphs);
1347 
1348     for (index = 0; index < cache_glyph_order->cGlyphs; index++)
1349     {
1350         gd = cache_glyph_order->glyphData[index];
1351         LOG_DEVEL(LOG_LEVEL_DEBUG, "  %d %d %d %d %d", gd->cacheIndex, gd->x, gd->y,
1352                   gd->cx, gd->cy);
1353         mod->server_add_char(mod, cache_glyph_order->cacheId, gd->cacheIndex,
1354                              gd->x, gd->y, gd->cx, gd->cy, (char *)(gd->aj));
1355         free(gd->aj);
1356         gd->aj = 0;
1357         free(gd);
1358         cache_glyph_order->glyphData[index] = 0;
1359     }
1360 
1361     free(cache_glyph_order->unicodeCharacters);
1362     cache_glyph_order->unicodeCharacters = 0;
1363 }
1364 
1365 /******************************************************************************/
1366 static void
lfreerdp_cache_brush(rdpContext * context,CACHE_BRUSH_ORDER * cache_brush_order)1367 lfreerdp_cache_brush(rdpContext *context, CACHE_BRUSH_ORDER *cache_brush_order)
1368 {
1369     int idx;
1370     int bytes;
1371     int bpp;
1372     int cx;
1373     int cy;
1374     struct mod *mod;
1375 
1376     mod = ((struct mod_context *)context)->modi;
1377     bpp = cache_brush_order->bpp;
1378     cx = cache_brush_order->cx;
1379     cy = cache_brush_order->cy;
1380     idx = cache_brush_order->index;
1381     bytes = cache_brush_order->length;
1382     LOG_DEVEL(LOG_LEVEL_DEBUG, "lfreerdp_cache_brush: bpp %d cx %d cy %d idx %d bytes %d",
1383               bpp, cx, cy, idx, bytes);
1384 
1385     if ((idx < 0) || (idx >= 64))
1386     {
1387         LOG(LOG_LEVEL_ERROR, "lfreerdp_cache_brush: error idx %d", idx);
1388         return;
1389     }
1390 
1391     if ((bpp != 1) || (cx != 8) || (cy != 8))
1392     {
1393         LOG(LOG_LEVEL_ERROR, "lfreerdp_cache_brush: error unsupported brush "
1394             "bpp %d cx %d cy %d", bpp, cx, cy);
1395         return;
1396     }
1397 
1398     mod->brush_cache[idx].bpp = bpp;
1399     mod->brush_cache[idx].width = cx;
1400     mod->brush_cache[idx].height = cy;
1401     mod->brush_cache[idx].data = mod->brush_cache[idx].b8x8;
1402 
1403     if (bytes > 8)
1404     {
1405         bytes = 8;
1406     }
1407 
1408     g_memset(mod->brush_cache[idx].data, 0, 8);
1409 
1410     if (bytes > 0)
1411     {
1412         if (bytes > 8)
1413         {
1414             LOG_DEVEL(LOG_LEVEL_INFO, "lfreerdp_cache_brush: bytes too big %d", bytes);
1415             bytes = 8;
1416         }
1417 
1418         g_memcpy(mod->brush_cache[idx].data, cache_brush_order->data, bytes);
1419     }
1420 
1421     LOG_DEVEL(LOG_LEVEL_DEBUG, "lfreerdp_cache_brush: out bpp %d cx %d cy %d idx %d bytes %d",
1422               bpp, cx, cy, idx, bytes);
1423 
1424     free(cache_brush_order->data);
1425     cache_brush_order->data = 0;
1426 
1427 }
1428 
1429 /******************************************************************************/
1430 static void
lfreerdp_pointer_position(rdpContext * context,POINTER_POSITION_UPDATE * pointer_position)1431 lfreerdp_pointer_position(rdpContext *context,
1432                           POINTER_POSITION_UPDATE *pointer_position)
1433 {
1434     LOG_DEVEL(LOG_LEVEL_DEBUG, "lfreerdp_pointer_position: - no code here");
1435 }
1436 
1437 /******************************************************************************/
1438 static void
lfreerdp_pointer_system(rdpContext * context,POINTER_SYSTEM_UPDATE * pointer_system)1439 lfreerdp_pointer_system(rdpContext *context,
1440                         POINTER_SYSTEM_UPDATE *pointer_system)
1441 {
1442     LOG_DEVEL(LOG_LEVEL_DEBUG, "lfreerdp_pointer_system: - no code here type value = %d", pointer_system->type);
1443 }
1444 
1445 /******************************************************************************/
1446 static void
lfreerdp_pointer_color(rdpContext * context,POINTER_COLOR_UPDATE * pointer_color)1447 lfreerdp_pointer_color(rdpContext *context,
1448                        POINTER_COLOR_UPDATE *pointer_color)
1449 {
1450     LOG_DEVEL(LOG_LEVEL_DEBUG, "lfreerdp_pointer_color: - no code here");
1451 }
1452 
1453 /******************************************************************************/
1454 static int
lfreerdp_get_pixel(void * bits,int width,int height,int bpp,int delta,int x,int y)1455 lfreerdp_get_pixel(void *bits, int width, int height, int bpp,
1456                    int delta, int x, int y)
1457 {
1458     int start;
1459     int shift;
1460     int pixel;
1461     tui8 *src8;
1462 
1463     if (bpp == 1)
1464     {
1465         src8 = (tui8 *)bits;
1466         start = (y * delta) + x / 8;
1467         shift = x % 8;
1468         pixel = (src8[start] & (0x80 >> shift)) != 0;
1469         return pixel ? 0xffffff : 0;
1470     }
1471     else if (bpp == 32)
1472     {
1473         src8 = (tui8 *)bits;
1474         src8 += y * delta + x * 4;
1475         pixel = ((int *)(src8))[0];
1476         return pixel;
1477     }
1478     else
1479     {
1480         LOG(LOG_LEVEL_WARNING, "lfreerdp_get_pixel: unknown bpp %d", bpp);
1481     }
1482 
1483     return 0;
1484 }
1485 
1486 /******************************************************************************/
1487 static int
lfreerdp_set_pixel(int pixel,void * bits,int width,int height,int bpp,int delta,int x,int y)1488 lfreerdp_set_pixel(int pixel, void *bits, int width, int height, int bpp,
1489                    int delta, int x, int y)
1490 {
1491     tui8 *dst8;
1492     int start;
1493     int shift;
1494 
1495     if (bpp == 1)
1496     {
1497         dst8 = (tui8 *)bits;
1498         start = (y * delta) + x / 8;
1499         shift = x % 8;
1500 
1501         if (pixel)
1502         {
1503             dst8[start] = dst8[start] | (0x80 >> shift);
1504         }
1505         else
1506         {
1507             dst8[start] = dst8[start] & ~(0x80 >> shift);
1508         }
1509     }
1510     else if (bpp == 24)
1511     {
1512         dst8 = (tui8 *)bits;
1513         dst8 += y * delta + x * 3;
1514         dst8[0] = (pixel >> 0) & 0xff;
1515         dst8[1] = (pixel >> 8) & 0xff;
1516         dst8[2] = (pixel >> 16) & 0xff;
1517     }
1518     else if (bpp == 32)
1519     {
1520         dst8 = (tui8 *)bits;
1521         dst8 += y * delta + x * 4;
1522         ((int *)(dst8))[0] = pixel;
1523     }
1524     else
1525     {
1526         LOG(LOG_LEVEL_WARNING, "lfreerdp_set_pixel: unknown bpp %d", bpp);
1527     }
1528 
1529     return 0;
1530 }
1531 
1532 /******************************************************************************/
1533 static int
lfreerdp_convert_color_image(void * dst,int dst_width,int dst_height,int dst_bpp,int dst_delta,void * src,int src_width,int src_height,int src_bpp,int src_delta)1534 lfreerdp_convert_color_image(void *dst, int dst_width, int dst_height,
1535                              int dst_bpp, int dst_delta,
1536                              void *src, int src_width, int src_height,
1537                              int src_bpp, int src_delta)
1538 {
1539     int i;
1540     int j;
1541     int pixel;
1542 
1543     for (j = 0; j < dst_height; j++)
1544     {
1545         for (i = 0; i < dst_width; i++)
1546         {
1547             pixel = lfreerdp_get_pixel(src, src_width, src_height, src_bpp,
1548                                        src_delta, i, j);
1549             lfreerdp_set_pixel(pixel, dst, dst_width, dst_height, dst_bpp,
1550                                dst_delta, i, j);
1551         }
1552     }
1553 
1554     return 0;
1555 }
1556 
1557 /******************************************************************************/
1558 static void
lfreerdp_pointer_new(rdpContext * context,POINTER_NEW_UPDATE * pointer_new)1559 lfreerdp_pointer_new(rdpContext *context,
1560                      POINTER_NEW_UPDATE *pointer_new)
1561 {
1562     struct mod *mod;
1563     int index;
1564     int bytes_per_pixel;
1565     int bits_per_pixel;
1566     tui8 *dst;
1567     tui8 *src;
1568 
1569     mod = ((struct mod_context *)context)->modi;
1570     LOG_DEVEL(LOG_LEVEL_DEBUG, "lfreerdp_pointer_new:");
1571     LOG_DEVEL(LOG_LEVEL_DEBUG, "  bpp %d", pointer_new->xorBpp);
1572     LOG_DEVEL(LOG_LEVEL_DEBUG, "  width %d height %d", pointer_new->colorPtrAttr.width,
1573               pointer_new->colorPtrAttr.height);
1574 
1575     LOG_DEVEL(LOG_LEVEL_DEBUG, "  lengthXorMask %d lengthAndMask %d",
1576               pointer_new->colorPtrAttr.lengthXorMask,
1577               pointer_new->colorPtrAttr.lengthAndMask);
1578 
1579     index = pointer_new->colorPtrAttr.cacheIndex;
1580 
1581     if (index >= 32)
1582     {
1583         LOG(LOG_LEVEL_ERROR, "lfreerdp_pointer_new: pointer index too big");
1584         return ;
1585     }
1586 
1587     if (pointer_new->xorBpp == 1 &&
1588             pointer_new->colorPtrAttr.width == 32 &&
1589             pointer_new->colorPtrAttr.height == 32)
1590     {
1591         LOG_DEVEL(LOG_LEVEL_DEBUG, "lfreerdp_pointer_new:");
1592         mod->pointer_cache[index].hotx = pointer_new->colorPtrAttr.xPos;
1593         mod->pointer_cache[index].hoty = pointer_new->colorPtrAttr.yPos;
1594         mod->pointer_cache[index].bpp = 0;
1595         dst = (tui8 *)(mod->pointer_cache[index].data);
1596         dst += 32 * 32 * 3 - 32 * 3;
1597         src = pointer_new->colorPtrAttr.xorMaskData;
1598         lfreerdp_convert_color_image(dst, 32, 32, 24, 32 * -3,
1599                                      src, 32, 32, 1, 32 / 8);
1600         dst = (tui8 *)(mod->pointer_cache[index].mask);
1601         dst += ( 32 * 32 / 8) - (32 / 8);
1602         src = pointer_new->colorPtrAttr.andMaskData;
1603         lfreerdp_convert_color_image(dst, 32, 32, 1, 32 / -8,
1604                                      src, 32, 32, 1, 32 / 8);
1605     }
1606     else if (pointer_new->xorBpp >= 8 &&
1607              pointer_new->colorPtrAttr.width == 32 &&
1608              pointer_new->colorPtrAttr.height == 32)
1609     {
1610         bytes_per_pixel = (pointer_new->xorBpp + 7) / 8;
1611         bits_per_pixel = pointer_new->xorBpp;
1612         LOG_DEVEL(LOG_LEVEL_DEBUG, "lfreerdp_pointer_new: bpp %d Bpp %d", bits_per_pixel,
1613                   bytes_per_pixel);
1614         mod->pointer_cache[index].hotx = pointer_new->colorPtrAttr.xPos;
1615         mod->pointer_cache[index].hoty = pointer_new->colorPtrAttr.yPos;
1616         mod->pointer_cache[index].bpp = bits_per_pixel;
1617         memcpy(mod->pointer_cache[index].data,
1618                pointer_new->colorPtrAttr.xorMaskData,
1619                32 * 32 * bytes_per_pixel);
1620         memcpy(mod->pointer_cache[index].mask,
1621                pointer_new->colorPtrAttr.andMaskData,
1622                32 * (32 / 8));
1623     }
1624     else
1625     {
1626         LOG(LOG_LEVEL_WARNING, "lfreerdp_pointer_new: error bpp %d width %d height %d index: %d",
1627             pointer_new->xorBpp, pointer_new->colorPtrAttr.width,
1628             pointer_new->colorPtrAttr.height, index);
1629     }
1630 
1631     mod->server_set_pointer_ex(mod, mod->pointer_cache[index].hotx,
1632                                mod->pointer_cache[index].hoty,
1633                                mod->pointer_cache[index].data,
1634                                mod->pointer_cache[index].mask,
1635                                mod->pointer_cache[index].bpp);
1636 
1637     free(pointer_new->colorPtrAttr.xorMaskData);
1638     pointer_new->colorPtrAttr.xorMaskData = 0;
1639     free(pointer_new->colorPtrAttr.andMaskData);
1640     pointer_new->colorPtrAttr.andMaskData = 0;
1641 
1642 }
1643 
1644 /******************************************************************************/
1645 static void
lfreerdp_pointer_cached(rdpContext * context,POINTER_CACHED_UPDATE * pointer_cached)1646 lfreerdp_pointer_cached(rdpContext *context,
1647                         POINTER_CACHED_UPDATE *pointer_cached)
1648 {
1649     struct mod *mod;
1650     int index;
1651 
1652     mod = ((struct mod_context *)context)->modi;
1653     index = pointer_cached->cacheIndex;
1654     LOG_DEVEL(LOG_LEVEL_DEBUG, "lfreerdp_pointer_cached:%d", index);
1655     mod->server_set_pointer_ex(mod, mod->pointer_cache[index].hotx,
1656                                mod->pointer_cache[index].hoty,
1657                                mod->pointer_cache[index].data,
1658                                mod->pointer_cache[index].mask,
1659                                mod->pointer_cache[index].bpp);
1660 }
1661 
1662 /******************************************************************************/
1663 static void
lfreerdp_polygon_cb(rdpContext * context,POLYGON_CB_ORDER * polygon_cb)1664 lfreerdp_polygon_cb(rdpContext *context, POLYGON_CB_ORDER *polygon_cb)
1665 {
1666     LOG_DEVEL(LOG_LEVEL_DEBUG, "lfreerdp_polygon_cb called:- not supported!!!!!!!!!!!!!!!!!!!!");
1667 }
1668 
1669 /******************************************************************************/
1670 static void
lfreerdp_polygon_sc(rdpContext * context,POLYGON_SC_ORDER * polygon_sc)1671 lfreerdp_polygon_sc(rdpContext *context, POLYGON_SC_ORDER *polygon_sc)
1672 {
1673     struct mod *mod;
1674     int i;
1675     struct
1676     {
1677         short x, y;
1678     } points[4];
1679     int fgcolor;
1680     int server_bpp, client_bpp;
1681 
1682     mod = ((struct mod_context *)context)->modi;
1683     LOG_DEVEL(LOG_LEVEL_DEBUG, "lfreerdp_polygon_sc :%d(points) %d(color) %d(fillmode) "
1684               "%d(bRop) %d(cbData) %d(x) %d(y)",
1685               polygon_sc->nDeltaEntries, polygon_sc->brushColor,
1686               polygon_sc->fillMode, polygon_sc->bRop2,
1687               polygon_sc->cbData, polygon_sc->xStart,
1688               polygon_sc->yStart);
1689 
1690     if (polygon_sc->nDeltaEntries == 3)
1691     {
1692         server_bpp = mod->inst->settings->color_depth;
1693         client_bpp = mod->bpp;
1694 
1695         points[0].x = polygon_sc->xStart;
1696         points[0].y = polygon_sc->yStart;
1697 
1698         for (i = 0; i < polygon_sc->nDeltaEntries; i++)
1699         {
1700             points[i + 1].x = 0; // polygon_sc->points[i].x;
1701             points[i + 1].y = 0; // polygon_sc->points[i].y;
1702         }
1703 
1704         fgcolor = convert_color(server_bpp, client_bpp,
1705                                 polygon_sc->brushColor, mod->colormap);
1706 
1707         mod->server_set_opcode(mod, polygon_sc->bRop2);
1708         mod->server_set_bgcolor(mod, 255);
1709         mod->server_set_fgcolor(mod, fgcolor);
1710         mod->server_set_pen(mod, 1, 1); // style, width
1711         // TODO replace with correct brush; this is a workaround
1712         // This workaround handles the text cursor in microsoft word.
1713         mod->server_draw_line(mod, polygon_sc->xStart, polygon_sc->yStart, polygon_sc->xStart, polygon_sc->yStart + points[2].y);
1714         //        mod->server_fill_rect(mod, points[0].x, points[0].y,
1715         //                         points[0].x-points[3].x, points[0].y-points[2].y);
1716         //      mod->server_set_brush(mod,); // howto use this on our indata??
1717         mod->server_set_opcode(mod, 0xcc);
1718     }
1719     else
1720     {
1721         LOG(LOG_LEVEL_WARNING, "Not handled number of points in lfreerdp_polygon_sc");
1722     }
1723 }
1724 
1725 /******************************************************************************/
1726 static void
lfreerdp_synchronize(rdpContext * context)1727 lfreerdp_synchronize(rdpContext *context)
1728 {
1729     /* Uncomment these two lines when needed */
1730 #if 0
1731     struct mod *mod;
1732     mod = ((struct mod_context *)context)->modi;
1733 #endif
1734     LOG_DEVEL(LOG_LEVEL_DEBUG, "lfreerdp_synchronize received - not handled");
1735 }
1736 
1737 /******************************************************************************/
1738 static boolean
lfreerdp_pre_connect(freerdp * instance)1739 lfreerdp_pre_connect(freerdp *instance)
1740 {
1741     struct mod *mod;
1742     int index;
1743     int error;
1744     int num_chans;
1745     int ch_flags;
1746     char ch_name[256];
1747     char *dst_ch_name;
1748 
1749     LOG_DEVEL(LOG_LEVEL_INFO, "lfreerdp_pre_connect:");
1750     mod = ((struct mod_context *)(instance->context))->modi;
1751     verifyColorMap(mod);
1752     num_chans = 0;
1753     index = 0;
1754     error = mod->server_query_channel(mod, index, ch_name, &ch_flags);
1755 
1756     while (error == 0)
1757     {
1758         num_chans++;
1759         LOG_DEVEL(LOG_LEVEL_DEBUG, "lfreerdp_pre_connect: got channel [%s], id [%d], flags [0x%8.8x]",
1760                   ch_name, index, ch_flags);
1761         dst_ch_name = instance->settings->channels[index].name;
1762         g_memset(dst_ch_name, 0, 8);
1763         g_snprintf(dst_ch_name, 8, "%s", ch_name);
1764         instance->settings->channels[index].options = ch_flags;
1765         index++;
1766         error = mod->server_query_channel(mod, index, ch_name, &ch_flags);
1767     }
1768 
1769     instance->settings->num_channels = num_chans;
1770 
1771     instance->settings->offscreen_bitmap_cache = 0;
1772     instance->settings->draw_nine_grid = 0;
1773 
1774     instance->settings->glyph_cache = true;
1775     /* GLYPH_SUPPORT_FULL and GLYPH_SUPPORT_PARTIAL seem to be the same */
1776     /* disabled as workaround for corrupted display like black bars left of cmd with W2K8 */
1777     /* instance->settings->glyphSupportLevel = GLYPH_SUPPORT_FULL; */
1778     instance->settings->glyphSupportLevel = GLYPH_SUPPORT_NONE;
1779 
1780     instance->settings->order_support[NEG_DSTBLT_INDEX] = 1; /* 0x00 */
1781     instance->settings->order_support[NEG_PATBLT_INDEX] = 1;
1782     instance->settings->order_support[NEG_SCRBLT_INDEX] = 1;
1783     instance->settings->order_support[NEG_MEMBLT_INDEX] = 1;
1784     instance->settings->order_support[NEG_MEM3BLT_INDEX] = 0;
1785     instance->settings->order_support[NEG_ATEXTOUT_INDEX] = 0;
1786     instance->settings->order_support[NEG_AEXTTEXTOUT_INDEX] = 0;
1787     instance->settings->order_support[NEG_DRAWNINEGRID_INDEX] = 0;
1788     instance->settings->order_support[NEG_LINETO_INDEX] = 1; /* 0x08 */
1789     instance->settings->order_support[NEG_MULTI_DRAWNINEGRID_INDEX] = 0;
1790     instance->settings->order_support[NEG_OPAQUE_RECT_INDEX] = 1;
1791     instance->settings->order_support[NEG_SAVEBITMAP_INDEX] = 0;
1792     instance->settings->order_support[NEG_WTEXTOUT_INDEX] = 0;
1793     instance->settings->order_support[NEG_MEMBLT_V2_INDEX] = 1;
1794     instance->settings->order_support[NEG_MEM3BLT_V2_INDEX] = 0;
1795     instance->settings->order_support[NEG_MULTIDSTBLT_INDEX] = 0;
1796     instance->settings->order_support[NEG_MULTIPATBLT_INDEX] = 0; /* 0x10 */
1797     instance->settings->order_support[NEG_MULTISCRBLT_INDEX] = 0;
1798     instance->settings->order_support[NEG_MULTIOPAQUERECT_INDEX] = 0;
1799     instance->settings->order_support[NEG_FAST_INDEX_INDEX] = 0;
1800     instance->settings->order_support[NEG_POLYGON_SC_INDEX] = 0;
1801     instance->settings->order_support[NEG_POLYGON_CB_INDEX] = 0;
1802     instance->settings->order_support[NEG_POLYLINE_INDEX] = 0;
1803     /* 0x17 missing */
1804     instance->settings->order_support[NEG_FAST_GLYPH_INDEX] = 0; /* 0x18 */
1805     instance->settings->order_support[NEG_ELLIPSE_SC_INDEX] = 0;
1806     instance->settings->order_support[NEG_ELLIPSE_CB_INDEX] = 0;
1807     /* disabled as workaround for corrupted display like black bars left of cmd with W2K8 */
1808     /* instance->settings->order_support[NEG_GLYPH_INDEX_INDEX] = 1; */
1809     instance->settings->order_support[NEG_GLYPH_INDEX_INDEX] = 0;
1810 
1811     instance->settings->order_support[NEG_GLYPH_WEXTTEXTOUT_INDEX] = 0;
1812     instance->settings->order_support[NEG_GLYPH_WLONGTEXTOUT_INDEX] = 0;
1813     instance->settings->order_support[NEG_GLYPH_WLONGEXTTEXTOUT_INDEX] = 0;
1814     /* 0x1F missing*/
1815 
1816     instance->settings->bitmap_cache = 1;
1817     instance->settings->bitmapCacheV2NumCells = 3; // 5;
1818     instance->settings->bitmapCacheV2CellInfo[0].numEntries = 600; // 0x78;
1819     instance->settings->bitmapCacheV2CellInfo[0].persistent = 0;
1820     instance->settings->bitmapCacheV2CellInfo[1].numEntries = 600; //0x78; // 600;
1821     instance->settings->bitmapCacheV2CellInfo[1].persistent = 0;
1822     instance->settings->bitmapCacheV2CellInfo[2].numEntries = 2048; //0x150; // 2048;
1823     instance->settings->bitmapCacheV2CellInfo[2].persistent = 0;
1824     instance->settings->bitmapCacheV2CellInfo[3].numEntries = 4096; // 4096;
1825     instance->settings->bitmapCacheV2CellInfo[3].persistent = 0;
1826     instance->settings->bitmapCacheV2CellInfo[4].numEntries = 2048; // 2048;
1827     instance->settings->bitmapCacheV2CellInfo[4].persistent = 0;
1828 
1829     instance->settings->bitmap_cache_v3 = 1;
1830 
1831     instance->settings->username = g_strdup(mod->username);
1832     instance->settings->password = g_strdup(mod->password);
1833     instance->settings->domain = g_strdup(mod->domain);
1834 
1835     if (mod->client_info.rail_enable && (mod->client_info.rail_support_level > 0))
1836     {
1837         LOG_DEVEL(LOG_LEVEL_INFO, "Railsupport !!!!!!!!!!!!!!!!!!");
1838         instance->settings->remote_app = 1;
1839         instance->settings->rail_langbar_supported = 1;
1840         instance->settings->workarea = 1;
1841         instance->settings->performance_flags = PERF_DISABLE_WALLPAPER | PERF_DISABLE_FULLWINDOWDRAG;
1842         instance->settings->num_icon_caches = mod->client_info.wnd_num_icon_caches;
1843         instance->settings->num_icon_cache_entries = mod->client_info.wnd_num_icon_cache_entries;
1844 
1845 
1846     }
1847     else
1848     {
1849         LOG_DEVEL(LOG_LEVEL_DEBUG, "Special PerformanceFlags changed");
1850         instance->settings->performance_flags = PERF_DISABLE_WALLPAPER |
1851                                                 PERF_DISABLE_FULLWINDOWDRAG | PERF_DISABLE_MENUANIMATIONS |
1852                                                 PERF_DISABLE_THEMING;
1853         // | PERF_DISABLE_CURSOR_SHADOW | PERF_DISABLE_CURSORSETTINGS;
1854     }
1855 
1856     /* Allow users or administrators to configure the mstsc experience settings. #1903 */
1857 
1858     if ((mod->allow_client_experiencesettings == 1) &&
1859             (mod->client_info.mcs_connection_type == CONNECTION_TYPE_AUTODETECT))
1860     {
1861         /* auto-detect not yet supported - use default performance settings */
1862     }
1863     else if (mod->allow_client_experiencesettings == 1)
1864     {
1865         instance->settings->performance_flags =
1866             (mod->client_info.rdp5_performanceflags &
1867              /* Mask to avoid accepting invalid flags. */
1868              (PERF_DISABLE_WALLPAPER |
1869               PERF_DISABLE_FULLWINDOWDRAG |
1870               PERF_DISABLE_MENUANIMATIONS |
1871               PERF_DISABLE_THEMING |
1872               PERF_DISABLE_CURSOR_SHADOW |
1873               PERF_DISABLE_CURSORSETTINGS |
1874               PERF_ENABLE_FONT_SMOOTHING |
1875               PERF_ENABLE_DESKTOP_COMPOSITION));
1876 
1877         LOG(LOG_LEVEL_DEBUG, "RDP client experience settings, "
1878             "rdp5_performance_flags:[0x%08x], "
1879             "masked performance_flags:[0x%08x]",
1880             mod->client_info.rdp5_performanceflags,
1881             instance->settings->performance_flags);
1882 
1883         if (mod->client_info.rail_enable &&
1884                 (mod->client_info.rail_support_level > 0))
1885         {
1886             instance->settings->performance_flags |= (PERF_DISABLE_WALLPAPER |
1887                     PERF_DISABLE_FULLWINDOWDRAG);
1888             LOG(LOG_LEVEL_DEBUG, "Add in performance setting for Railsupport:"
1889                 "[0x%08x]", PERF_DISABLE_WALLPAPER |
1890                 PERF_DISABLE_FULLWINDOWDRAG);
1891         }
1892     }
1893 
1894     LOG(LOG_LEVEL_DEBUG, "before overriding performance_flags:[0x%08x]",
1895         instance->settings->performance_flags);
1896     LOG(LOG_LEVEL_DEBUG, "perf_settings_override_mask:[0x%08x], "
1897         "perf_settings_values_mask:[0x%08x]",
1898         mod->perf_settings_override_mask,
1899         mod->perf_settings_values_mask);
1900 
1901     /* Clear bits for any overridden performance settings */
1902     instance->settings->performance_flags &= ~mod->perf_settings_override_mask;
1903 
1904     /* Add in overridden performance settings */
1905     instance->settings->performance_flags |= mod->perf_settings_values_mask;
1906 
1907     LOG(LOG_LEVEL_DEBUG, "final performance_flags:[0x%08x]",
1908         instance->settings->performance_flags);
1909 
1910     instance->settings->compression = 0;
1911     instance->settings->ignore_certificate = 1;
1912 
1913     // Multi Monitor Settings
1914     instance->settings->num_monitors = mod->client_info.monitorCount;
1915 
1916     for (index = 0; index < mod->client_info.monitorCount; index++)
1917     {
1918         instance->settings->monitors[index].x = mod->client_info.minfo[index].left;
1919         instance->settings->monitors[index].y = mod->client_info.minfo[index].top;
1920         instance->settings->monitors[index].width = mod->client_info.minfo[index].right;
1921         instance->settings->monitors[index].height = mod->client_info.minfo[index].bottom;
1922         instance->settings->monitors[index].is_primary = mod->client_info.minfo[index].is_primary;
1923     }
1924 
1925     instance->update->BeginPaint = lfreerdp_begin_paint;
1926     instance->update->EndPaint = lfreerdp_end_paint;
1927     instance->update->SetBounds = lfreerdp_set_bounds;
1928     instance->update->BitmapUpdate = lfreerdp_bitmap_update;
1929     instance->update->Synchronize = lfreerdp_synchronize;
1930     instance->update->primary->DstBlt = lfreerdp_dst_blt;
1931     instance->update->primary->PatBlt = lfreerdp_pat_blt;
1932     instance->update->primary->ScrBlt = lfreerdp_scr_blt;
1933     instance->update->primary->OpaqueRect = lfreerdp_opaque_rect;
1934     instance->update->primary->MemBlt = lfreerdp_mem_blt;
1935     instance->update->primary->GlyphIndex = lfreerdp_glyph_index;
1936     instance->update->primary->LineTo = lfreerdp_line_to;
1937     instance->update->primary->PolygonSC = lfreerdp_polygon_sc ;
1938     instance->update->primary->PolygonCB = lfreerdp_polygon_cb;
1939     instance->update->secondary->CacheBitmap = lfreerdp_cache_bitmap;
1940     instance->update->secondary->CacheBitmapV2 = lfreerdp_cache_bitmapV2;
1941     instance->update->secondary->CacheGlyph = lfreerdp_cache_glyph;
1942     instance->update->secondary->CacheBrush = lfreerdp_cache_brush;
1943 
1944     instance->update->pointer->PointerPosition = lfreerdp_pointer_position;
1945     instance->update->pointer->PointerSystem = lfreerdp_pointer_system;
1946     instance->update->pointer->PointerColor = lfreerdp_pointer_color;
1947     instance->update->pointer->PointerNew = lfreerdp_pointer_new;
1948     instance->update->pointer->PointerCached = lfreerdp_pointer_cached;
1949 
1950     if ((mod->username[0] != 0) && (mod->password[0] != 0))
1951     {
1952         /* since we have username and password, we can try nla */
1953         instance->settings->nla_security = 1;
1954     }
1955     else
1956     {
1957         instance->settings->nla_security = 0;
1958     }
1959 
1960     return 1;
1961 }
1962 
1963 /*****************************************************************************/
1964 void
lrail_WindowCreate(rdpContext * context,WINDOW_ORDER_INFO * orderInfo,WINDOW_STATE_ORDER * window_state)1965 lrail_WindowCreate(rdpContext *context, WINDOW_ORDER_INFO *orderInfo,
1966                    WINDOW_STATE_ORDER *window_state)
1967 {
1968     int index;
1969     struct mod *mod;
1970     struct rail_window_state_order wso;
1971     UNICONV *uniconv;
1972 
1973     LOG_DEVEL(LOG_LEVEL_TRACE, "lrail_WindowCreate:");
1974     uniconv = freerdp_uniconv_new();
1975     mod = ((struct mod_context *)context)->modi;
1976     memset(&wso, 0, sizeof(wso));
1977     /* copy the window state order */
1978     wso.owner_window_id = window_state->ownerWindowId;
1979     wso.style = window_state->style;
1980     wso.extended_style = window_state->extendedStyle;
1981     wso.show_state = window_state->showState;
1982 
1983     if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_TITLE)
1984     {
1985         wso.title_info = freerdp_uniconv_in(uniconv,
1986                                             window_state->titleInfo.string, window_state->titleInfo.length);
1987     }
1988 
1989     LOG_DEVEL(LOG_LEVEL_DEBUG, "lrail_WindowCreate: %s", wso.title_info);
1990     wso.client_offset_x = window_state->clientOffsetX;
1991     wso.client_offset_y = window_state->clientOffsetY;
1992     wso.client_area_width = window_state->clientAreaWidth;
1993     wso.client_area_height = window_state->clientAreaHeight;
1994     wso.rp_content = window_state->RPContent;
1995     wso.root_parent_handle = window_state->rootParentHandle;
1996     wso.window_offset_x = window_state->windowOffsetX;
1997     wso.window_offset_y = window_state->windowOffsetY;
1998     wso.window_client_delta_x = window_state->windowClientDeltaX;
1999     wso.window_client_delta_y = window_state->windowClientDeltaY;
2000     wso.window_width = window_state->windowWidth;
2001     wso.window_height = window_state->windowHeight;
2002     wso.num_window_rects = window_state->numWindowRects;
2003 
2004     if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS)
2005     {
2006         wso.window_rects = (struct rail_window_rect *)
2007                            g_malloc(sizeof(struct rail_window_rect) * wso.num_window_rects, 0);
2008 
2009         for (index = 0; index < wso.num_window_rects; index++)
2010         {
2011             wso.window_rects[index].left = window_state->windowRects[index].left;
2012             wso.window_rects[index].top = window_state->windowRects[index].top;
2013             wso.window_rects[index].right = window_state->windowRects[index].right;
2014             wso.window_rects[index].bottom = window_state->windowRects[index].bottom;
2015         }
2016     }
2017 
2018     wso.visible_offset_x = window_state->visibleOffsetX;
2019     wso.visible_offset_y = window_state->visibleOffsetY;
2020     wso.num_visibility_rects = window_state->numVisibilityRects;
2021 
2022     if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY)
2023     {
2024         wso.visibility_rects = (struct rail_window_rect *)
2025                                g_malloc(sizeof(struct rail_window_rect) * wso.num_visibility_rects, 0);
2026 
2027         for (index = 0; index < wso.num_visibility_rects; index++)
2028         {
2029             wso.visibility_rects[index].left = window_state->visibilityRects[index].left;
2030             wso.visibility_rects[index].top = window_state->visibilityRects[index].top;
2031             wso.visibility_rects[index].right = window_state->visibilityRects[index].right;
2032             wso.visibility_rects[index].bottom = window_state->visibilityRects[index].bottom;
2033         }
2034     }
2035 
2036     mod->server_window_new_update(mod, orderInfo->windowId, &wso,
2037                                   orderInfo->fieldFlags);
2038 
2039     free(wso.title_info);
2040     g_free(wso.window_rects);
2041     g_free(wso.visibility_rects);
2042 }
2043 
2044 /*****************************************************************************/
2045 void
lrail_WindowUpdate(rdpContext * context,WINDOW_ORDER_INFO * orderInfo,WINDOW_STATE_ORDER * window_state)2046 lrail_WindowUpdate(rdpContext *context, WINDOW_ORDER_INFO *orderInfo,
2047                    WINDOW_STATE_ORDER *window_state)
2048 {
2049     LOG_DEVEL(LOG_LEVEL_TRACE, "lrail_WindowUpdate:");
2050     lrail_WindowCreate(context, orderInfo, window_state);
2051 }
2052 
2053 /*****************************************************************************/
2054 void
lrail_WindowDelete(rdpContext * context,WINDOW_ORDER_INFO * orderInfo)2055 lrail_WindowDelete(rdpContext *context, WINDOW_ORDER_INFO *orderInfo)
2056 {
2057     struct mod *mod;
2058 
2059     LOG_DEVEL(LOG_LEVEL_TRACE, "lrail_WindowDelete:");
2060     mod = ((struct mod_context *)context)->modi;
2061     mod->server_window_delete(mod, orderInfo->windowId);
2062 }
2063 
2064 /*****************************************************************************/
2065 void
lrail_WindowIcon(rdpContext * context,WINDOW_ORDER_INFO * orderInfo,WINDOW_ICON_ORDER * window_icon)2066 lrail_WindowIcon(rdpContext *context, WINDOW_ORDER_INFO *orderInfo,
2067                  WINDOW_ICON_ORDER *window_icon)
2068 {
2069     struct mod *mod;
2070     struct rail_icon_info rii;
2071 
2072     LOG_DEVEL(LOG_LEVEL_TRACE, "lrail_WindowIcon:");
2073     mod = ((struct mod_context *)context)->modi;
2074     memset(&rii, 0, sizeof(rii));
2075     rii.bpp = window_icon->iconInfo->bpp;
2076     rii.width = window_icon->iconInfo->width;
2077     rii.height = window_icon->iconInfo->height;
2078     rii.cmap_bytes = window_icon->iconInfo->cbColorTable;
2079     rii.mask_bytes = window_icon->iconInfo->cbBitsMask;
2080     rii.data_bytes = window_icon->iconInfo->cbBitsColor;
2081     rii.mask = (char *)(window_icon->iconInfo->bitsMask);
2082     rii.cmap = (char *)(window_icon->iconInfo->colorTable);
2083     rii.data = (char *)(window_icon->iconInfo->bitsColor);
2084     mod->server_window_icon(mod, orderInfo->windowId,
2085                             window_icon->iconInfo->cacheEntry,
2086                             window_icon->iconInfo->cacheId, &rii,
2087                             orderInfo->fieldFlags);
2088 }
2089 
2090 /*****************************************************************************/
2091 void
lrail_WindowCachedIcon(rdpContext * context,WINDOW_ORDER_INFO * orderInfo,WINDOW_CACHED_ICON_ORDER * window_cached_icon)2092 lrail_WindowCachedIcon(rdpContext *context, WINDOW_ORDER_INFO *orderInfo,
2093                        WINDOW_CACHED_ICON_ORDER *window_cached_icon)
2094 {
2095     struct mod *mod;
2096 
2097     LOG_DEVEL(LOG_LEVEL_TRACE, "lrail_WindowCachedIcon:");
2098     mod = ((struct mod_context *)context)->modi;
2099     mod->server_window_cached_icon(mod, orderInfo->windowId,
2100                                    window_cached_icon->cachedIcon.cacheEntry,
2101                                    window_cached_icon->cachedIcon.cacheId,
2102                                    orderInfo->fieldFlags);
2103 }
2104 
2105 /*****************************************************************************/
2106 void
lrail_NotifyIconCreate(rdpContext * context,WINDOW_ORDER_INFO * orderInfo,NOTIFY_ICON_STATE_ORDER * notify_icon_state)2107 lrail_NotifyIconCreate(rdpContext *context, WINDOW_ORDER_INFO *orderInfo,
2108                        NOTIFY_ICON_STATE_ORDER *notify_icon_state)
2109 {
2110     struct mod *mod;
2111     struct rail_notify_state_order rnso;
2112     UNICONV *uniconv;
2113 
2114     LOG_DEVEL(LOG_LEVEL_TRACE, "lrail_NotifyIconCreate:");
2115     uniconv = freerdp_uniconv_new();
2116     mod = ((struct mod_context *)context)->modi;
2117 
2118     memset(&rnso, 0, sizeof(rnso));
2119     rnso.version = notify_icon_state->version;
2120 
2121     if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_TIP)
2122     {
2123         rnso.tool_tip = freerdp_uniconv_in(uniconv,
2124                                            notify_icon_state->toolTip.string, notify_icon_state->toolTip.length);
2125     }
2126 
2127     if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_INFO_TIP)
2128     {
2129         rnso.infotip.timeout = notify_icon_state->infoTip.timeout;
2130         rnso.infotip.flags = notify_icon_state->infoTip.flags;
2131         rnso.infotip.text = freerdp_uniconv_in(uniconv,
2132                                                notify_icon_state->infoTip.text.string,
2133                                                notify_icon_state->infoTip.text.length);
2134         rnso.infotip.title = freerdp_uniconv_in(uniconv,
2135                                                 notify_icon_state->infoTip.title.string,
2136                                                 notify_icon_state->infoTip.title.length);
2137     }
2138 
2139     rnso.state = notify_icon_state->state;
2140     rnso.icon_cache_entry = notify_icon_state->icon.cacheEntry;
2141     rnso.icon_cache_id = notify_icon_state->icon.cacheId;
2142 
2143     rnso.icon_info.bpp = notify_icon_state->icon.bpp;
2144     rnso.icon_info.width = notify_icon_state->icon.width;
2145     rnso.icon_info.height = notify_icon_state->icon.height;
2146     rnso.icon_info.cmap_bytes = notify_icon_state->icon.cbColorTable;
2147     rnso.icon_info.mask_bytes = notify_icon_state->icon.cbBitsMask;
2148     rnso.icon_info.data_bytes = notify_icon_state->icon.cbBitsColor;
2149     rnso.icon_info.mask = (char *)(notify_icon_state->icon.bitsMask);
2150     rnso.icon_info.cmap = (char *)(notify_icon_state->icon.colorTable);
2151     rnso.icon_info.data = (char *)(notify_icon_state->icon.bitsColor);
2152 
2153     mod->server_notify_new_update(mod, orderInfo->windowId,
2154                                   orderInfo->notifyIconId,
2155                                   &rnso, orderInfo->fieldFlags);
2156 
2157     free(rnso.tool_tip);
2158     free(rnso.infotip.text);
2159     free(rnso.infotip.title);
2160 }
2161 
2162 /*****************************************************************************/
2163 void
lrail_NotifyIconUpdate(rdpContext * context,WINDOW_ORDER_INFO * orderInfo,NOTIFY_ICON_STATE_ORDER * notify_icon_state)2164 lrail_NotifyIconUpdate(rdpContext *context, WINDOW_ORDER_INFO *orderInfo,
2165                        NOTIFY_ICON_STATE_ORDER *notify_icon_state)
2166 {
2167     LOG_DEVEL(LOG_LEVEL_TRACE, "lrail_NotifyIconUpdate:");
2168     lrail_NotifyIconCreate(context, orderInfo, notify_icon_state);
2169 }
2170 
2171 /*****************************************************************************/
2172 void
lrail_NotifyIconDelete(rdpContext * context,WINDOW_ORDER_INFO * orderInfo)2173 lrail_NotifyIconDelete(rdpContext *context, WINDOW_ORDER_INFO *orderInfo)
2174 {
2175     struct mod *mod;
2176 
2177     LOG_DEVEL(LOG_LEVEL_TRACE, "lrail_NotifyIconDelete:");
2178     mod = ((struct mod_context *)context)->modi;
2179     mod->server_notify_delete(mod, orderInfo->windowId,
2180                               orderInfo->notifyIconId);
2181 }
2182 
2183 /*****************************************************************************/
2184 void
lrail_MonitoredDesktop(rdpContext * context,WINDOW_ORDER_INFO * orderInfo,MONITORED_DESKTOP_ORDER * monitored_desktop)2185 lrail_MonitoredDesktop(rdpContext *context, WINDOW_ORDER_INFO *orderInfo,
2186                        MONITORED_DESKTOP_ORDER *monitored_desktop)
2187 {
2188     int index;
2189     struct mod *mod;
2190     struct rail_monitored_desktop_order rmdo;
2191 
2192     LOG_DEVEL(LOG_LEVEL_TRACE, "lrail_MonitoredDesktop:");
2193     mod = ((struct mod_context *)context)->modi;
2194     memset(&rmdo, 0, sizeof(rmdo));
2195     rmdo.active_window_id = monitored_desktop->activeWindowId;
2196     rmdo.num_window_ids = monitored_desktop->numWindowIds;
2197 
2198     if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_DESKTOP_ZORDER)
2199     {
2200         if (rmdo.num_window_ids > 0)
2201         {
2202             rmdo.window_ids = (int *)g_malloc(sizeof(int) * rmdo.num_window_ids, 0);
2203 
2204             for (index = 0; index < rmdo.num_window_ids; index++)
2205             {
2206                 rmdo.window_ids[index] = monitored_desktop->windowIds[index];
2207             }
2208         }
2209     }
2210 
2211     mod->server_monitored_desktop(mod, &rmdo, orderInfo->fieldFlags);
2212     g_free(rmdo.window_ids);
2213 }
2214 
2215 /*****************************************************************************/
2216 void
lrail_NonMonitoredDesktop(rdpContext * context,WINDOW_ORDER_INFO * orderInfo)2217 lrail_NonMonitoredDesktop(rdpContext *context, WINDOW_ORDER_INFO *orderInfo)
2218 {
2219     struct mod *mod;
2220     struct rail_monitored_desktop_order rmdo;
2221 
2222     LOG_DEVEL(LOG_LEVEL_TRACE, "lrail_NonMonitoredDesktop:");
2223     mod = ((struct mod_context *)context)->modi;
2224     memset(&rmdo, 0, sizeof(rmdo));
2225     mod->server_monitored_desktop(mod, &rmdo, orderInfo->fieldFlags);
2226 }
2227 
2228 /******************************************************************************/
2229 static boolean
lfreerdp_post_connect(freerdp * instance)2230 lfreerdp_post_connect(freerdp *instance)
2231 {
2232     struct mod *mod;
2233 
2234     LOG_DEVEL(LOG_LEVEL_TRACE, "lfreerdp_post_connect:");
2235     mod = ((struct mod_context *)(instance->context))->modi;
2236     g_memset(mod->password, 0, sizeof(mod->password));
2237 
2238     mod->inst->update->window->WindowCreate = lrail_WindowCreate;
2239     mod->inst->update->window->WindowUpdate = lrail_WindowUpdate;
2240     mod->inst->update->window->WindowDelete = lrail_WindowDelete;
2241     mod->inst->update->window->WindowIcon = lrail_WindowIcon;
2242     mod->inst->update->window->WindowCachedIcon = lrail_WindowCachedIcon;
2243     mod->inst->update->window->NotifyIconCreate = lrail_NotifyIconCreate;
2244     mod->inst->update->window->NotifyIconUpdate = lrail_NotifyIconUpdate;
2245     mod->inst->update->window->NotifyIconDelete = lrail_NotifyIconDelete;
2246     mod->inst->update->window->MonitoredDesktop = lrail_MonitoredDesktop;
2247     mod->inst->update->window->NonMonitoredDesktop = lrail_NonMonitoredDesktop;
2248 
2249     return 1;
2250 }
2251 
2252 /******************************************************************************/
2253 static void
lfreerdp_context_new(freerdp * instance,rdpContext * context)2254 lfreerdp_context_new(freerdp *instance, rdpContext *context)
2255 {
2256     LOG_DEVEL(LOG_LEVEL_INFO, "lfreerdp_context_new: %p", context);
2257 }
2258 
2259 /******************************************************************************/
2260 static void
lfreerdp_context_free(freerdp * instance,rdpContext * context)2261 lfreerdp_context_free(freerdp *instance, rdpContext *context)
2262 {
2263     LOG_DEVEL(LOG_LEVEL_INFO, "lfreerdp_context_free: - no code here");
2264 }
2265 
2266 /******************************************************************************/
2267 static int
lfreerdp_receive_channel_data(freerdp * instance,int channelId,uint8 * data,int size,int flags,int total_size)2268 lfreerdp_receive_channel_data(freerdp *instance, int channelId, uint8 *data,
2269                               int size, int flags, int total_size)
2270 {
2271     struct mod *mod;
2272     int lchid;
2273     int index;
2274     int error;
2275 
2276     mod = ((struct mod_context *)(instance->context))->modi;
2277     lchid = -1;
2278 
2279     for (index = 0; index < instance->settings->num_channels; index++)
2280     {
2281         if (instance->settings->channels[index].channel_id == channelId)
2282         {
2283             lchid = index;
2284             break;
2285         }
2286     }
2287 
2288     if (lchid >= 0)
2289     {
2290         LOG_DEVEL(LOG_LEVEL_DEBUG, "lfreerdp_receive_channel_data: server to client, chanid: %d", lchid);
2291         error = mod->server_send_to_channel(mod, lchid, (char *)data, size,
2292                                             total_size, flags);
2293 
2294         if (error != 0)
2295         {
2296             LOG(LOG_LEVEL_ERROR, "lfreerdp_receive_channel_data: error %d", error);
2297         }
2298     }
2299     else
2300     {
2301         LOG(LOG_LEVEL_ERROR, "lfreerdp_receive_channel_data: bad lchid");
2302     }
2303 
2304     return 0;
2305 }
2306 
2307 /******************************************************************************/
2308 static boolean
lfreerdp_authenticate(freerdp * instance,char ** username,char ** password,char ** domain)2309 lfreerdp_authenticate(freerdp *instance, char **username,
2310                       char **password, char **domain)
2311 {
2312     LOG_DEVEL(LOG_LEVEL_DEBUG, "lfreerdp_authenticate: - no code here");
2313     return 1;
2314 }
2315 
2316 /******************************************************************************/
2317 static boolean
lfreerdp_verify_certificate(freerdp * instance,char * subject,char * issuer,char * fingerprint)2318 lfreerdp_verify_certificate(freerdp *instance, char *subject, char *issuer,
2319                             char *fingerprint)
2320 {
2321     LOG_DEVEL(LOG_LEVEL_DEBUG, "lfreerdp_verify_certificate: - no code here");
2322     return 1;
2323 }
2324 
2325 /******************************************************************************/
2326 static int
lfreerdp_session_info(freerdp * instance,uint8 * data,int data_bytes)2327 lfreerdp_session_info(freerdp *instance, uint8 *data, int data_bytes)
2328 {
2329     struct mod *mod;
2330     int error;
2331 
2332     LOG_DEVEL(LOG_LEVEL_TRACE, "lfreerdp_session_info:");
2333     error = 0;
2334     mod = ((struct mod_context *)(instance->context))->modi;
2335     if (mod != 0)
2336     {
2337         LOG_DEVEL(LOG_LEVEL_DEBUG, "lfreerdp_session_info: mod->server_session_info %p",
2338                   mod->server_session_info);
2339         if (mod->server_session_info != 0)
2340         {
2341             error = mod->server_session_info(mod, (char *)data, data_bytes);
2342         }
2343     }
2344     return error;
2345 }
2346 
2347 /******************************************************************************/
2348 tintptr EXPORT_CC
mod_init(void)2349 mod_init(void)
2350 {
2351     struct mod *mod;
2352     modContext *lcon;
2353 
2354     LOG_DEVEL(LOG_LEVEL_TRACE, "mod_init:");
2355     mod = (struct mod *)g_malloc(sizeof(struct mod), 1);
2356     freerdp_get_version(&(mod->vmaj), &(mod->vmin), &(mod->vrev));
2357     LOG(LOG_LEVEL_INFO, "  FreeRDP version major %d minor %d revision %d",
2358         mod->vmaj, mod->vmin, mod->vrev);
2359     mod->size = sizeof(struct mod);
2360     mod->version = CURRENT_MOD_VER;
2361     mod->handle = (tintptr) mod;
2362     mod->mod_connect = lxrdp_connect;
2363     mod->mod_start = lxrdp_start;
2364     mod->mod_event = lxrdp_event;
2365     mod->mod_signal = lxrdp_signal;
2366     mod->mod_end = lxrdp_end;
2367     mod->mod_set_param = lxrdp_set_param;
2368     mod->mod_session_change = lxrdp_session_change;
2369     mod->mod_get_wait_objs = lxrdp_get_wait_objs;
2370     mod->mod_check_wait_objs = lxrdp_check_wait_objs;
2371     mod->mod_frame_ack = lxrdp_frame_ack;
2372     mod->mod_suppress_output = lxrdp_suppress_output;
2373     mod->mod_server_version_message = lxrdp_server_version_message;
2374     mod->mod_server_monitor_resize = lxrdp_server_monitor_resize;
2375     mod->mod_server_monitor_full_invalidate = lxrdp_server_monitor_full_invalidate;
2376 
2377     mod->inst = freerdp_new();
2378     mod->inst->PreConnect = lfreerdp_pre_connect;
2379     mod->inst->PostConnect = lfreerdp_post_connect;
2380     mod->inst->context_size = sizeof(modContext);
2381     mod->inst->ContextNew = lfreerdp_context_new;
2382     mod->inst->ContextFree = lfreerdp_context_free;
2383     mod->inst->ReceiveChannelData = lfreerdp_receive_channel_data;
2384     mod->inst->Authenticate = lfreerdp_authenticate;
2385     mod->inst->VerifyCertificate = lfreerdp_verify_certificate;
2386 #if defined(VERSION_STRUCT_RDP_FREERDP)
2387 #if VERSION_STRUCT_RDP_FREERDP > 0
2388     mod->inst->SessionInfo = lfreerdp_session_info;
2389 #endif
2390 #endif
2391 
2392     freerdp_context_new(mod->inst);
2393 
2394     lcon = (modContext *)(mod->inst->context);
2395     lcon->modi = mod;
2396     LOG_DEVEL(LOG_LEVEL_DEBUG, "mod_init: mod %p", mod);
2397 
2398     return (tintptr) mod;
2399 }
2400 
2401 /******************************************************************************/
2402 int EXPORT_CC
mod_exit(tintptr handle)2403 mod_exit(tintptr handle)
2404 {
2405     struct mod *mod = (struct mod *) handle;
2406 
2407     LOG_DEVEL(LOG_LEVEL_TRACE, "mod_exit:");
2408 
2409     if (mod == 0)
2410     {
2411         return 0;
2412     }
2413 
2414     if (mod->inst == NULL)
2415     {
2416         LOG(LOG_LEVEL_ERROR, "mod_exit - null pointer for inst:");
2417         g_free(mod);
2418         return 0 ;
2419     }
2420 
2421     freerdp_disconnect(mod->inst);
2422 
2423     if ((mod->vmaj == 1) && (mod->vmin == 0) && (mod->vrev == 1))
2424     {
2425         /* this version has a bug with double free in freerdp_free */
2426     }
2427     else
2428     {
2429         freerdp_context_free(mod->inst);
2430     }
2431 
2432     freerdp_free(mod->inst);
2433     g_free(mod);
2434     return 0;
2435 }
2436