2 * FreeRDP: A Remote Desktop Protocol Client
5 * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 #include <X11/Xutil.h>
24 #include <X11/Xcursor/Xcursor.h>
28 #include <X11/extensions/Xinerama.h>
40 #include <sys/types.h>
41 #include <sys/select.h>
42 #include <freerdp/constants.h>
43 #include <freerdp/codec/nsc.h>
44 #include <freerdp/codec/rfx.h>
45 #include <freerdp/codec/color.h>
46 #include <freerdp/codec/bitmap.h>
47 #include <freerdp/utils/args.h>
48 #include <freerdp/utils/memory.h>
49 #include <freerdp/utils/semaphore.h>
50 #include <freerdp/utils/memory.h>
51 #include <freerdp/utils/event.h>
52 #include <freerdp/utils/signal.h>
53 #include <freerdp/utils/passphrase.h>
54 #include <freerdp/plugins/cliprdr.h>
55 #include <freerdp/rail.h>
61 #include "xf_cliprdr.h"
62 #include "xf_monitor.h"
63 #include "xf_graphics.h"
64 #include "xf_keyboard.h"
68 static freerdp_sem g_sem;
69 static int g_thread_count = 0;
70 static uint8 g_disconnect_reason = 0;
72 static long xv_port = 0;
73 static const size_t password_size = 512;
80 int xf_process_client_args(rdpSettings* settings, const char* opt, const char* val, void* user_data);
81 int xf_process_plugin_args(rdpSettings* settings, const char* name, RDP_PLUGIN_DATA* plugin_data, void* user_data);
83 void xf_context_new(freerdp* instance, rdpContext* context)
85 context->channels = freerdp_channels_new();
88 void xf_context_free(freerdp* instance, rdpContext* context)
93 void xf_sw_begin_paint(rdpContext* context)
95 rdpGdi* gdi = context->gdi;
96 gdi->primary->hdc->hwnd->invalid->null = 1;
97 gdi->primary->hdc->hwnd->ninvalid = 0;
100 void xf_sw_end_paint(rdpContext* context)
107 xfi = ((xfContext*) context)->xfi;
110 if (xfi->remote_app != true)
112 if (xfi->complex_regions != true)
114 if (gdi->primary->hdc->hwnd->invalid->null)
117 x = gdi->primary->hdc->hwnd->invalid->x;
118 y = gdi->primary->hdc->hwnd->invalid->y;
119 w = gdi->primary->hdc->hwnd->invalid->w;
120 h = gdi->primary->hdc->hwnd->invalid->h;
122 XPutImage(xfi->display, xfi->primary, xfi->gc, xfi->image, x, y, x, y, w, h);
123 XCopyArea(xfi->display, xfi->primary, xfi->window->handle, xfi->gc, x, y, w, h, x, y);
131 if (gdi->primary->hdc->hwnd->ninvalid < 1)
134 ninvalid = gdi->primary->hdc->hwnd->ninvalid;
135 cinvalid = gdi->primary->hdc->hwnd->cinvalid;
137 for (i = 0; i < ninvalid; i++)
144 XPutImage(xfi->display, xfi->primary, xfi->gc, xfi->image, x, y, x, y, w, h);
145 XCopyArea(xfi->display, xfi->primary, xfi->window->handle, xfi->gc, x, y, w, h, x, y);
148 XFlush(xfi->display);
153 if (gdi->primary->hdc->hwnd->invalid->null)
156 x = gdi->primary->hdc->hwnd->invalid->x;
157 y = gdi->primary->hdc->hwnd->invalid->y;
158 w = gdi->primary->hdc->hwnd->invalid->w;
159 h = gdi->primary->hdc->hwnd->invalid->h;
161 xf_rail_paint(xfi, context->rail, x, y, x + w - 1, y + h - 1);
165 void xf_sw_desktop_resize(rdpContext* context)
168 rdpSettings* settings;
170 xfi = ((xfContext*) context)->xfi;
171 settings = xfi->instance->settings;
173 if (xfi->fullscreen != true)
175 rdpGdi* gdi = context->gdi;
176 gdi_resize(gdi, xfi->width, xfi->height);
180 xfi->image->data = NULL;
181 XDestroyImage(xfi->image);
182 xfi->image = XCreateImage(xfi->display, xfi->visual, xfi->depth, ZPixmap, 0,
183 (char*) gdi->primary_buffer, gdi->width, gdi->height, xfi->scanline_pad, 0);
188 void xf_hw_begin_paint(rdpContext* context)
191 xfi = ((xfContext*) context)->xfi;
192 xfi->hdc->hwnd->invalid->null = 1;
193 xfi->hdc->hwnd->ninvalid = 0;
196 void xf_hw_end_paint(rdpContext* context)
202 xfi = ((xfContext*) context)->xfi;
206 if (xfi->hdc->hwnd->invalid->null)
209 x = xfi->hdc->hwnd->invalid->x;
210 y = xfi->hdc->hwnd->invalid->y;
211 w = xfi->hdc->hwnd->invalid->w;
212 h = xfi->hdc->hwnd->invalid->h;
214 xf_rail_paint(xfi, context->rail, x, y, x + w - 1, y + h - 1);
218 void xf_hw_desktop_resize(rdpContext* context)
222 rdpSettings* settings;
224 xfi = ((xfContext*) context)->xfi;
225 settings = xfi->instance->settings;
227 if (xfi->fullscreen != true)
229 xfi->width = settings->width;
230 xfi->height = settings->height;
233 xf_ResizeDesktopWindow(xfi, xfi->window, settings->width, settings->height);
237 same = (xfi->primary == xfi->drawing) ? true : false;
239 XFreePixmap(xfi->display, xfi->primary);
241 xfi->primary = XCreatePixmap(xfi->display, xfi->drawable,
242 xfi->width, xfi->height, xfi->depth);
245 xfi->drawing = xfi->primary;
250 boolean xf_get_fds(freerdp* instance, void** rfds, int* rcount, void** wfds, int* wcount)
252 xfInfo* xfi = ((xfContext*) instance->context)->xfi;
254 rfds[*rcount] = (void*)(long)(xfi->xfds);
260 boolean xf_check_fds(freerdp* instance, fd_set* set)
263 xfInfo* xfi = ((xfContext*) instance->context)->xfi;
265 while (XPending(xfi->display))
267 memset(&xevent, 0, sizeof(xevent));
268 XNextEvent(xfi->display, &xevent);
270 if (xf_event_process(instance, &xevent) != true)
277 void xf_create_window(xfInfo* xfi)
284 height = xfi->height;
286 xfi->attribs.background_pixel = BlackPixelOfScreen(xfi->screen);
287 xfi->attribs.border_pixel = WhitePixelOfScreen(xfi->screen);
288 xfi->attribs.backing_store = xfi->primary ? NotUseful : Always;
289 xfi->attribs.override_redirect = xfi->fullscreen;
290 xfi->attribs.colormap = xfi->colormap;
291 xfi->attribs.bit_gravity = ForgetGravity;
292 xfi->attribs.win_gravity = StaticGravity;
294 if (xfi->instance->settings->window_title != NULL)
296 win_title = xstrdup(xfi->instance->settings->window_title);
298 else if (xfi->instance->settings->port == 3389)
300 win_title = xmalloc(1 + sizeof("FreeRDP: ") + strlen(xfi->instance->settings->hostname));
301 sprintf(win_title, "FreeRDP: %s", xfi->instance->settings->hostname);
305 win_title = xmalloc(1 + sizeof("FreeRDP: ") + strlen(xfi->instance->settings->hostname) + sizeof(":00000"));
306 sprintf(win_title, "FreeRDP: %s:%i", xfi->instance->settings->hostname, xfi->instance->settings->port);
309 xfi->window = xf_CreateDesktopWindow(xfi, win_title, width, height, xfi->decorations);
312 if (xfi->parent_window)
313 XReparentWindow(xfi->display, xfi->window->handle, xfi->parent_window, 0, 0);
316 xf_SetWindowFullscreen(xfi, xfi->window, xfi->fullscreen);
318 /* wait for VisibilityNotify */
321 XMaskEvent(xfi->display, VisibilityChangeMask, &xevent);
323 while (xevent.type != VisibilityNotify);
325 xfi->unobscured = (xevent.xvisibility.state == VisibilityUnobscured);
327 XSetWMProtocols(xfi->display, xfi->window->handle, &(xfi->WM_DELETE_WINDOW), 1);
328 xfi->drawable = xfi->window->handle;
331 void xf_toggle_fullscreen(xfInfo* xfi)
335 contents = XCreatePixmap(xfi->display, xfi->window->handle, xfi->width, xfi->height, xfi->depth);
336 XCopyArea(xfi->display, xfi->primary, contents, xfi->gc, 0, 0, xfi->width, xfi->height, 0, 0);
338 XDestroyWindow(xfi->display, xfi->window->handle);
339 xfi->fullscreen = (xfi->fullscreen) ? false : true;
340 xf_create_window(xfi);
342 XCopyArea(xfi->display, contents, xfi->primary, xfi->gc, 0, 0, xfi->width, xfi->height, 0, 0);
343 XFreePixmap(xfi->display, contents);
346 boolean xf_get_pixmap_info(xfInfo* xfi)
353 XVisualInfo template;
354 XPixmapFormatValues* pf;
355 XPixmapFormatValues* pfs;
357 pfs = XListPixmapFormats(xfi->display, &pf_count);
361 printf("xf_get_pixmap_info: XListPixmapFormats failed\n");
365 for (i = 0; i < pf_count; i++)
369 if (pf->depth == xfi->depth)
371 xfi->bpp = pf->bits_per_pixel;
372 xfi->scanline_pad = pf->scanline_pad;
378 memset(&template, 0, sizeof(template));
379 template.class = TrueColor;
380 template.screen = xfi->screen_number;
382 vis = XGetVisualInfo(xfi->display, VisualClassMask | VisualScreenMask, &template, &vi_count);
386 printf("xf_get_pixmap_info: XGetVisualInfo failed\n");
391 for (i = 0; i < vi_count; i++)
395 if (vi->depth == xfi->depth)
397 xfi->visual = vi->visual;
405 * Detect if the server visual has an inverted colormap
406 * (BGR vs RGB, or red being the least significant byte)
409 if (vi->red_mask & 0xFF)
411 xfi->clrconv->invert = true;
417 if ((xfi->visual == NULL) || (xfi->scanline_pad == 0))
425 static int (*_def_error_handler)(Display*, XErrorEvent*);
426 int xf_error_handler(Display* d, XErrorEvent* ev)
431 XGetErrorText(d, ev->error_code, buf, sizeof(buf));
437 _def_error_handler(d, ev);
442 int _xf_error_handler(Display* d, XErrorEvent* ev)
445 * ungrab the keyboard, in case a debugger is running in
446 * another window. This make xf_error_handler() a potential
447 * debugger breakpoint.
449 XUngrabKeyboard(d, CurrentTime);
450 return xf_error_handler(d, ev);
453 boolean xf_pre_connect(freerdp* instance)
456 boolean bitmap_cache;
457 rdpSettings* settings;
458 int arg_parse_result;
460 xfi = (xfInfo*) xzalloc(sizeof(xfInfo));
461 ((xfContext*) instance->context)->xfi = xfi;
463 xfi->_context = instance->context;
464 xfi->context = (xfContext*) instance->context;
465 xfi->context->settings = instance->settings;
466 xfi->instance = instance;
468 arg_parse_result = freerdp_parse_args(instance->settings, instance->context->argc,instance->context->argv,
469 xf_process_plugin_args, instance->context->channels, xf_process_client_args, xfi);
471 if (arg_parse_result < 0)
473 if (arg_parse_result == FREERDP_ARGS_PARSE_FAILURE)
474 printf("failed to parse arguments.\n");
476 exit(XF_EXIT_PARSE_ARGUMENTS);
479 settings = instance->settings;
480 bitmap_cache = settings->bitmap_cache;
482 settings->os_major_type = OSMAJORTYPE_UNIX;
483 settings->os_minor_type = OSMINORTYPE_NATIVE_XSERVER;
484 settings->order_support[NEG_DSTBLT_INDEX] = true;
485 settings->order_support[NEG_PATBLT_INDEX] = true;
486 settings->order_support[NEG_SCRBLT_INDEX] = true;
487 settings->order_support[NEG_OPAQUE_RECT_INDEX] = true;
488 settings->order_support[NEG_DRAWNINEGRID_INDEX] = false;
489 settings->order_support[NEG_MULTIDSTBLT_INDEX] = false;
490 settings->order_support[NEG_MULTIPATBLT_INDEX] = false;
491 settings->order_support[NEG_MULTISCRBLT_INDEX] = false;
492 settings->order_support[NEG_MULTIOPAQUERECT_INDEX] = true;
493 settings->order_support[NEG_MULTI_DRAWNINEGRID_INDEX] = false;
494 settings->order_support[NEG_LINETO_INDEX] = true;
495 settings->order_support[NEG_POLYLINE_INDEX] = true;
496 settings->order_support[NEG_MEMBLT_INDEX] = bitmap_cache;
497 settings->order_support[NEG_MEM3BLT_INDEX] = false;
498 settings->order_support[NEG_MEMBLT_V2_INDEX] = bitmap_cache;
499 settings->order_support[NEG_MEM3BLT_V2_INDEX] = false;
500 settings->order_support[NEG_SAVEBITMAP_INDEX] = false;
501 settings->order_support[NEG_GLYPH_INDEX_INDEX] = true;
502 settings->order_support[NEG_FAST_INDEX_INDEX] = true;
503 settings->order_support[NEG_FAST_GLYPH_INDEX] = true;
504 settings->order_support[NEG_POLYGON_SC_INDEX] = false;
505 settings->order_support[NEG_POLYGON_CB_INDEX] = false;
506 settings->order_support[NEG_ELLIPSE_SC_INDEX] = false;
507 settings->order_support[NEG_ELLIPSE_CB_INDEX] = false;
509 freerdp_channels_pre_connect(xfi->_context->channels, instance);
511 xfi->display = XOpenDisplay(NULL);
513 if (xfi->display == NULL)
515 printf("xf_pre_connect: failed to open display: %s\n", XDisplayName(NULL));
516 printf("Please check that the $DISPLAY environment variable is properly set.\n");
522 printf("Enabling X11 debug mode.\n");
523 XSynchronize(xfi->display, true);
524 _def_error_handler = XSetErrorHandler(_xf_error_handler);
527 xfi->_NET_WM_ICON = XInternAtom(xfi->display, "_NET_WM_ICON", False);
528 xfi->_MOTIF_WM_HINTS = XInternAtom(xfi->display, "_MOTIF_WM_HINTS", False);
529 xfi->_NET_CURRENT_DESKTOP = XInternAtom(xfi->display, "_NET_CURRENT_DESKTOP", False);
530 xfi->_NET_WORKAREA = XInternAtom(xfi->display, "_NET_WORKAREA", False);
531 xfi->_NET_WM_STATE = XInternAtom(xfi->display, "_NET_WM_STATE", False);
532 xfi->_NET_WM_STATE_FULLSCREEN = XInternAtom(xfi->display, "_NET_WM_STATE_FULLSCREEN", False);
533 xfi->_NET_WM_WINDOW_TYPE = XInternAtom(xfi->display, "_NET_WM_WINDOW_TYPE", False);
535 xfi->_NET_WM_WINDOW_TYPE_NORMAL = XInternAtom(xfi->display, "_NET_WM_WINDOW_TYPE_NORMAL", False);
536 xfi->_NET_WM_WINDOW_TYPE_DIALOG = XInternAtom(xfi->display, "_NET_WM_WINDOW_TYPE_DIALOG", False);
537 xfi->_NET_WM_WINDOW_TYPE_POPUP= XInternAtom(xfi->display, "_NET_WM_WINDOW_TYPE_POPUP", False);
538 xfi->_NET_WM_WINDOW_TYPE_UTILITY = XInternAtom(xfi->display, "_NET_WM_WINDOW_TYPE_UTILITY", False);
539 xfi->_NET_WM_WINDOW_TYPE_DROPDOWN_MENU = XInternAtom(xfi->display, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU", False);
540 xfi->_NET_WM_STATE_SKIP_TASKBAR = XInternAtom(xfi->display, "_NET_WM_STATE_SKIP_TASKBAR", False);
541 xfi->_NET_WM_STATE_SKIP_PAGER = XInternAtom(xfi->display, "_NET_WM_STATE_SKIP_PAGER", False);
542 xfi->_NET_WM_MOVERESIZE = XInternAtom(xfi->display, "_NET_WM_MOVERESIZE", False);
543 xfi->_NET_MOVERESIZE_WINDOW = XInternAtom(xfi->display, "_NET_MOVERESIZE_WINDOW", False);
545 xfi->WM_PROTOCOLS = XInternAtom(xfi->display, "WM_PROTOCOLS", False);
546 xfi->WM_DELETE_WINDOW = XInternAtom(xfi->display, "WM_DELETE_WINDOW", False);
550 xfi->clrconv = freerdp_clrconv_new(CLRCONV_ALPHA);
552 instance->context->cache = cache_new(instance->settings);
554 xfi->xfds = ConnectionNumber(xfi->display);
555 xfi->screen_number = DefaultScreen(xfi->display);
556 xfi->screen = ScreenOfDisplay(xfi->display, xfi->screen_number);
557 xfi->depth = DefaultDepthOfScreen(xfi->screen);
558 xfi->big_endian = (ImageByteOrder(xfi->display) == MSBFirst);
560 xfi->mouse_motion = settings->mouse_motion;
561 xfi->complex_regions = true;
562 xfi->decorations = settings->decorations;
563 xfi->fullscreen = settings->fullscreen;
564 xfi->grab_keyboard = settings->grab_keyboard;
565 xfi->fullscreen_toggle = true;
566 xfi->sw_gdi = settings->sw_gdi;
567 xfi->parent_window = (Window) settings->parent_window_xid;
569 xf_detect_monitors(xfi, settings);
574 void cpuid(unsigned info, unsigned *eax, unsigned *ebx, unsigned *ecx, unsigned *edx)
577 #if defined(__i386__) || defined(__x86_64__)
580 ("mov %%ebx, %%edi;" /* 32bit PIC: don't clobber ebx */
584 :"+a" (*eax), "=S" (*ebx), "=c" (*ecx), "=d" (*edx)
590 uint32 xf_detect_cpu()
592 unsigned int eax, ebx, ecx, edx = 0;
595 cpuid(1, &eax, &ebx, &ecx, &edx);
599 DEBUG("SSE2 detected");
606 boolean xf_post_connect(freerdp* instance)
611 rdpChannels* channels;
612 RFX_CONTEXT* rfx_context = NULL;
614 xfi = ((xfContext*) instance->context)->xfi;
615 cache = instance->context->cache;
616 channels = xfi->_context->channels;
618 if (xf_get_pixmap_info(xfi) != true)
621 xf_register_graphics(instance->context->graphics);
628 flags = CLRCONV_ALPHA;
631 flags |= CLRBUF_32BPP;
633 flags |= CLRBUF_16BPP;
635 gdi_init(instance, flags, NULL);
636 gdi = instance->context->gdi;
637 xfi->primary_buffer = gdi->primary_buffer;
639 rfx_context = gdi->rfx_context;
643 xfi->srcBpp = instance->settings->color_depth;
644 xf_gdi_register_update_callbacks(instance->update);
646 xfi->hdc = gdi_CreateDC(xfi->clrconv, xfi->bpp);
648 if (instance->settings->rfx_codec)
650 rfx_context = (void*) rfx_context_new();
651 xfi->rfx_context = rfx_context;
654 if (instance->settings->ns_codec)
655 xfi->nsc_context = (void*) nsc_context_new();
661 /* detect only if needed */
662 rfx_context_set_cpu_opt(rfx_context, xf_detect_cpu());
666 xfi->width = instance->settings->width;
667 xfi->height = instance->settings->height;
669 xf_create_window(xfi);
671 memset(&gcv, 0, sizeof(gcv));
672 xfi->modifier_map = XGetModifierMapping(xfi->display);
674 xfi->gc = XCreateGC(xfi->display, xfi->drawable, GCGraphicsExposures, &gcv);
675 xfi->primary = XCreatePixmap(xfi->display, xfi->drawable, xfi->width, xfi->height, xfi->depth);
676 xfi->drawing = xfi->primary;
678 xfi->bitmap_mono = XCreatePixmap(xfi->display, xfi->drawable, 8, 8, 1);
679 xfi->gc_mono = XCreateGC(xfi->display, xfi->bitmap_mono, GCGraphicsExposures, &gcv);
681 XSetForeground(xfi->display, xfi->gc, BlackPixelOfScreen(xfi->screen));
682 XFillRectangle(xfi->display, xfi->primary, xfi->gc, 0, 0, xfi->width, xfi->height);
684 xfi->image = XCreateImage(xfi->display, xfi->visual, xfi->depth, ZPixmap, 0,
685 (char*) xfi->primary_buffer, xfi->width, xfi->height, xfi->scanline_pad, 0);
687 xfi->bmp_codec_none = (uint8*) xmalloc(64 * 64 * 4);
691 instance->update->BeginPaint = xf_sw_begin_paint;
692 instance->update->EndPaint = xf_sw_end_paint;
693 instance->update->DesktopResize = xf_sw_desktop_resize;
697 instance->update->BeginPaint = xf_hw_begin_paint;
698 instance->update->EndPaint = xf_hw_end_paint;
699 instance->update->DesktopResize = xf_hw_desktop_resize;
702 pointer_cache_register_callbacks(instance->update);
704 if (xfi->sw_gdi != true)
706 glyph_cache_register_callbacks(instance->update);
707 brush_cache_register_callbacks(instance->update);
708 bitmap_cache_register_callbacks(instance->update);
709 offscreen_cache_register_callbacks(instance->update);
710 palette_cache_register_callbacks(instance->update);
713 instance->context->rail = rail_new(instance->settings);
714 rail_register_update_callbacks(instance->context->rail, instance->update);
715 xf_rail_register_callbacks(xfi, instance->context->rail);
717 freerdp_channels_post_connect(channels, instance);
719 xf_tsmf_init(xfi, xv_port);
721 xf_cliprdr_init(xfi, channels);
726 boolean xf_authenticate(freerdp* instance, char** username, char** password, char** domain)
728 *password = xmalloc(password_size * sizeof(char));
730 if (freerdp_passphrase_read("Password: ", *password, password_size) == NULL)
736 boolean xf_verify_certificate(freerdp* instance, char* subject, char* issuer, char* fingerprint)
740 printf("Certificate details:\n");
741 printf("\tSubject: %s\n", subject);
742 printf("\tIssuer: %s\n", issuer);
743 printf("\tThumbprint: %s\n", fingerprint);
744 printf("The above X.509 certificate could not be verified, possibly because you do not have "
745 "the CA certificate in your certificate store, or the certificate has expired. "
746 "Please look at the documentation on how to create local certificate store for a private CA.\n");
750 printf("Do you trust the above certificate? (Y/N) ");
751 answer = fgetc(stdin);
753 if (answer == 'y' || answer == 'Y')
757 else if (answer == 'n' || answer == 'N')
767 int xf_process_client_args(rdpSettings* settings, const char* opt, const char* val, void* user_data)
770 xfInfo* xfi = (xfInfo*) user_data;
772 if (strcmp("--kbd-list", opt) == 0)
775 rdpKeyboardLayout* layouts;
777 layouts = freerdp_kbd_get_layouts(RDP_KEYBOARD_LAYOUT_TYPE_STANDARD);
778 printf("\nKeyboard Layouts\n");
779 for (i = 0; layouts[i].code; i++)
780 printf("0x%08X\t%s\n", layouts[i].code, layouts[i].name);
783 layouts = freerdp_kbd_get_layouts(RDP_KEYBOARD_LAYOUT_TYPE_VARIANT);
784 printf("\nKeyboard Layout Variants\n");
785 for (i = 0; layouts[i].code; i++)
786 printf("0x%08X\t%s\n", layouts[i].code, layouts[i].name);
789 layouts = freerdp_kbd_get_layouts(RDP_KEYBOARD_LAYOUT_TYPE_IME);
790 printf("\nKeyboard Input Method Editors (IMEs)\n");
791 for (i = 0; layouts[i].code; i++)
792 printf("0x%08X\t%s\n", layouts[i].code, layouts[i].name);
797 else if (strcmp("--xv-port", opt) == 0)
802 else if (strcmp("--dbg-x11", opt) == 0)
811 int xf_process_plugin_args(rdpSettings* settings, const char* name, RDP_PLUGIN_DATA* plugin_data, void* user_data)
813 rdpChannels* channels = (rdpChannels*) user_data;
815 printf("loading plugin %s\n", name);
816 freerdp_channels_load_plugin(channels, settings, name, plugin_data);
821 int xf_receive_channel_data(freerdp* instance, int channelId, uint8* data, int size, int flags, int total_size)
823 return freerdp_channels_data(instance, channelId, data, size, flags, total_size);
826 void xf_process_channel_event(rdpChannels* chanman, freerdp* instance)
831 xfi = ((xfContext*) instance->context)->xfi;
833 event = freerdp_channels_pop_event(chanman);
837 switch (event->event_class)
839 case RDP_EVENT_CLASS_RAIL:
840 xf_process_rail_event(xfi, chanman, event);
843 case RDP_EVENT_CLASS_TSMF:
844 xf_process_tsmf_event(xfi, event);
847 case RDP_EVENT_CLASS_CLIPRDR:
848 xf_process_cliprdr_event(xfi, event);
855 freerdp_event_free(event);
859 void xf_window_free(xfInfo* xfi)
861 rdpContext* context = xfi->instance->context;
863 XFreeModifiermap(xfi->modifier_map);
864 xfi->modifier_map = 0;
866 XFreeGC(xfi->display, xfi->gc);
869 XFreeGC(xfi->display, xfi->gc_mono);
872 if (xfi->window != NULL)
874 xf_DestroyWindow(xfi, xfi->window);
880 XFreePixmap(xfi->display, xfi->primary);
886 xfi->image->data = NULL;
887 XDestroyImage(xfi->image);
893 cache_free(context->cache);
894 context->cache = NULL;
896 rail_free(context->rail);
897 context->rail = NULL;
900 if (xfi->rfx_context)
902 rfx_context_free(xfi->rfx_context);
903 xfi->rfx_context = NULL;
906 freerdp_clrconv_free(xfi->clrconv);
909 gdi_DeleteDC(xfi->hdc);
912 xf_cliprdr_uninit(xfi);
915 void xf_free(xfInfo* xfi)
919 xfree(xfi->bmp_codec_none);
921 XCloseDisplay(xfi->display);
926 int xfreerdp_run(freerdp* instance)
940 rdpChannels* channels;
941 struct timeval timeout;
943 memset(rfds, 0, sizeof(rfds));
944 memset(wfds, 0, sizeof(wfds));
945 memset(&timeout, 0, sizeof(struct timeval));
947 if (!freerdp_connect(instance))
948 return XF_EXIT_CONN_FAILED;
950 xfi = ((xfContext*) instance->context)->xfi;
951 channels = instance->context->channels;
953 while (!xfi->disconnect && !freerdp_shall_disconnect(instance))
958 if (freerdp_get_fds(instance, rfds, &rcount, wfds, &wcount) != true)
960 printf("Failed to get FreeRDP file descriptor\n");
961 ret = XF_EXIT_CONN_FAILED;
964 if (freerdp_channels_get_fds(channels, instance, rfds, &rcount, wfds, &wcount) != true)
966 printf("Failed to get channel manager file descriptor\n");
967 ret = XF_EXIT_CONN_FAILED;
970 if (xf_get_fds(instance, rfds, &rcount, wfds, &wcount) != true)
972 printf("Failed to get xfreerdp file descriptor\n");
973 ret = XF_EXIT_CONN_FAILED;
981 for (i = 0; i < rcount; i++)
983 fds = (int)(long)(rfds[i]);
988 FD_SET(fds, &rfds_set);
995 select_status = select(max_fds + 1, &rfds_set, &wfds_set, NULL, &timeout);
997 if (select_status == 0)
999 //freerdp_send_keep_alive(instance);
1002 else if (select_status == -1)
1004 /* these are not really errors */
1005 if (!((errno == EAGAIN) ||
1006 (errno == EWOULDBLOCK) ||
1007 (errno == EINPROGRESS) ||
1008 (errno == EINTR))) /* signal occurred */
1010 printf("xfreerdp_run: select failed\n");
1015 if (freerdp_check_fds(instance) != true)
1017 printf("Failed to check FreeRDP file descriptor\n");
1020 if (xf_check_fds(instance, &rfds_set) != true)
1022 printf("Failed to check xfreerdp file descriptor\n");
1025 if (freerdp_channels_check_fds(channels, instance) != true)
1027 printf("Failed to check channel manager file descriptor\n");
1030 xf_process_channel_event(channels, instance);
1034 ret = freerdp_error_info(instance);
1036 freerdp_channels_close(channels, instance);
1037 freerdp_channels_free(channels);
1038 freerdp_disconnect(instance);
1042 freerdp_free(instance);
1047 void* thread_func(void* param)
1049 struct thread_data* data;
1050 data = (struct thread_data*) param;
1052 g_disconnect_reason = xfreerdp_run(data->instance);
1056 pthread_detach(pthread_self());
1060 if (g_thread_count < 1)
1061 freerdp_sem_signal(g_sem);
1066 static uint8 exit_code_from_disconnect_reason(uint32 reason)
1069 (reason >= XF_EXIT_PARSE_ARGUMENTS && reason <= XF_EXIT_CONN_FAILED))
1072 /* Licence error set */
1073 else if (reason >= 0x100 && reason <= 0x10A)
1074 reason -= 0x100 + XF_EXIT_LICENSE_INTERNAL;
1076 /* RDP protocol error set */
1077 else if (reason >= 0x10c9 && reason <= 0x1193)
1078 reason = XF_EXIT_RDP;
1080 /* There's no need to test protocol-independent codes: they match */
1081 else if (!(reason <= 0xB))
1082 reason = XF_EXIT_UNKNOWN;
1087 int main(int argc, char* argv[])
1091 struct thread_data* data;
1093 freerdp_handle_signals();
1095 setlocale(LC_ALL, "");
1097 freerdp_channels_global_init();
1099 g_sem = freerdp_sem_new(1);
1101 instance = freerdp_new();
1102 instance->PreConnect = xf_pre_connect;
1103 instance->PostConnect = xf_post_connect;
1104 instance->Authenticate = xf_authenticate;
1105 instance->VerifyCertificate = xf_verify_certificate;
1106 instance->ReceiveChannelData = xf_receive_channel_data;
1108 instance->context_size = sizeof(xfContext);
1109 instance->ContextNew = (pContextNew) xf_context_new;
1110 instance->ContextFree = (pContextFree) xf_context_free;
1111 freerdp_context_new(instance);
1113 instance->context->argc = argc;
1114 instance->context->argv = argv;
1115 instance->settings->sw_gdi = false;
1117 data = (struct thread_data*) xzalloc(sizeof(struct thread_data));
1118 data->instance = instance;
1121 pthread_create(&thread, 0, thread_func, data);
1123 while (g_thread_count > 0)
1125 freerdp_sem_wait(g_sem);
1128 freerdp_channels_global_uninit();
1130 return exit_code_from_disconnect_reason(g_disconnect_reason);