static BOOL xf_event_ClientMessage(xfInfo* xfi, XEvent* event, BOOL app) { if ((event->xclient.message_type == xfi->WM_PROTOCOLS) && ((Atom) event->xclient.data.l[0] == xfi->WM_DELETE_WINDOW)) { if (app) { DEBUG_X11("RAIL window closed"); rdpWindow* window; rdpRail* rail = ((rdpContext*) xfi->context)->rail; window = window_list_get_by_extra_id(rail->list, (void*) event->xclient.window); if (window != NULL) { xf_rail_send_client_system_command(xfi, window->windowId, SC_CLOSE); } return TRUE; } else { DEBUG_X11("Main window closed"); return FALSE; } } return TRUE; }
static void xf_cliprdr_process_html(clipboardContext* cb, uint8* data, int size) { char* start_str; char* end_str; int start; int end; start_str = strstr((char*) data, "StartHTML:"); end_str = strstr((char*) data, "EndHTML:"); if (start_str == NULL || end_str == NULL) { DEBUG_X11("invalid HTML clipboard format"); return; } start = atoi(start_str + 10); end = atoi(end_str + 8); if (start > size || end > size || start >= end) { DEBUG_X11("invalid HTML offset"); return; } cb->data = (uint8*) xmalloc(size - start + 1); memcpy(cb->data, data + start, end - start); cb->data_length = end - start; crlf2lf(cb->data, &cb->data_length); }
static void xf_cliprdr_get_requested_targets(xfInfo* xfi) { int num; int i, j; Atom atom; int format; BYTE* data = NULL; unsigned long length, bytes_left; RDP_CB_FORMAT_LIST_EVENT* event; clipboardContext* cb = (clipboardContext*) xfi->clipboard_context; XGetWindowProperty(xfi->display, xfi->drawable, cb->property_atom, 0, 200, 0, XA_ATOM, &atom, &format, &length, &bytes_left, &data); DEBUG_X11_CLIPRDR("type=%d format=%d length=%d bytes_left=%d", (int) atom, format, (int) length, (int) bytes_left); if (length > 0) { event = (RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_FormatList, NULL, NULL); event->formats = (UINT32*) malloc(sizeof(UINT32) * cb->num_format_mappings); num = 0; for (i = 0; i < length; i++) { atom = ((Atom*) data)[i]; DEBUG_X11("atom %d", (int) atom); for (j = 0; j < cb->num_format_mappings; j++) { if (cb->format_mappings[j].target_format == atom) { DEBUG_X11("found format %d for atom %d", cb->format_mappings[j].format_id, (int)atom); event->formats[num++] = cb->format_mappings[j].format_id; break; } } } event->num_formats = num; XFree(data); freerdp_channels_send_event(cb->channels, (wMessage*) event); } else { if (data) XFree(data); xf_cliprdr_send_null_format_list(xfi); } }
static void xf_cliprdr_get_requested_targets(xfInfo* xfi) { int num; int i, j; Atom atom; int format; uint8* data = NULL; unsigned long len, bytes_left; RDP_CB_FORMAT_LIST_EVENT* event; clipboardContext* cb = (clipboardContext*) xfi->clipboard_context; XGetWindowProperty(xfi->display, xfi->window->handle, cb->property_atom, 0, 200, 0, XA_ATOM, &atom, &format, &len, &bytes_left, &data); DEBUG_X11("type=%d format=%d len=%d bytes_left=%d", (int)atom, format, (int)len, (int)bytes_left); if (len > 0) { event = (RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new(RDP_EVENT_CLASS_CLIPRDR, RDP_EVENT_TYPE_CB_FORMAT_LIST, NULL, NULL); event->formats = (uint32*) xmalloc(sizeof(uint32) * cb->num_format_mappings); num = 0; for (i = 0; i < len; i++) { atom = ((Atom*)data)[i]; DEBUG_X11("atom %d", (int)atom); for (j = 0; j < cb->num_format_mappings; j++) { if (cb->format_mappings[j].target_format == atom) { DEBUG_X11("found format %d for atom %d", cb->format_mappings[j].format_id, (int)atom); event->formats[num++] = cb->format_mappings[j].format_id; break; } } } event->num_formats = num; XFree(data); freerdp_chanman_send_event(cb->chanman, (RDP_EVENT*) event); } else { if (data) { XFree(data); } xf_cliprdr_send_null_format_list(xfi); } }
static BOOL xf_event_ClientMessage(xfContext* xfc, XEvent* event, BOOL app) { if ((event->xclient.message_type == xfc->WM_PROTOCOLS) && ((Atom) event->xclient.data.l[0] == xfc->WM_DELETE_WINDOW)) { if (app) { xfAppWindow* appWindow; appWindow = xf_AppWindowFromX11Window(xfc, event->xany.window); if (appWindow) { xf_rail_send_client_system_command(xfc, appWindow->windowId, SC_CLOSE); } return TRUE; } else { DEBUG_X11("Main window closed"); return FALSE; } } return TRUE; }
static void xf_cliprdr_send_raw_format_list(xfInfo* xfi) { Atom type; uint8* format_data; int format, result; unsigned long len, bytes_left; RDP_CB_FORMAT_LIST_EVENT* event; clipboardContext* cb = (clipboardContext*) xfi->clipboard_context; result = XGetWindowProperty(xfi->display, cb->root_window, cb->property_atom, 0, 3600, 0, XA_STRING, &type, &format, &len, &bytes_left, (unsigned char**) &format_data); if (result != Success) { DEBUG_WARN("XGetWindowProperty failed"); return; } DEBUG_X11("format=%d len=%d bytes_left=%d", format, (int)len, (int)bytes_left); event = (RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new(RDP_EVENT_CLASS_CLIPRDR, RDP_EVENT_TYPE_CB_FORMAT_LIST, NULL, NULL); event->raw_format_data = (uint8*) xmalloc(len); memcpy(event->raw_format_data, format_data, len); event->raw_format_data_size = len; XFree(format_data); freerdp_chanman_send_event(cb->chanman, (RDP_EVENT*) event); }
void xf_process_cliprdr_event(xfInfo* xfi, RDP_EVENT* event) { switch (event->event_type) { case RDP_EVENT_TYPE_CB_SYNC: xf_cliprdr_process_cb_sync_event(xfi); break; case RDP_EVENT_TYPE_CB_FORMAT_LIST: xf_cliprdr_process_cb_format_list_event(xfi, (RDP_CB_FORMAT_LIST_EVENT*) event); break; case RDP_EVENT_TYPE_CB_DATA_REQUEST: xf_cliprdr_process_cb_data_request_event(xfi, (RDP_CB_DATA_REQUEST_EVENT*) event); break; case RDP_EVENT_TYPE_CB_DATA_RESPONSE: xf_cliprdr_process_cb_data_response_event(xfi, (RDP_CB_DATA_RESPONSE_EVENT*) event); break; default: DEBUG_X11("unknown event type %d", event->event_type); break; } }
/** * Post an event from the client to the X server */ void xf_SendClientEvent(xfContext* xfc, Window window, Atom atom, unsigned int numArgs, ...) { XEvent xevent; unsigned int i; va_list argp; va_start(argp, numArgs); ZeroMemory(&xevent, sizeof(XEvent)); xevent.xclient.type = ClientMessage; xevent.xclient.serial = 0; xevent.xclient.send_event = False; xevent.xclient.display = xfc->display; xevent.xclient.window = window; xevent.xclient.message_type = atom; xevent.xclient.format = 32; for (i = 0; i < numArgs; i++) { xevent.xclient.data.l[i] = va_arg(argp, int); } DEBUG_X11("Send ClientMessage Event: wnd=0x%04lX", (unsigned long) xevent.xclient.window); XSendEvent(xfc->display, RootWindowOfScreen(xfc->screen), False, SubstructureRedirectMask | SubstructureNotifyMask, &xevent); XSync(xfc->display, False); va_end(argp); }
static void xf_cliprdr_process_dib(clipboardContext* cb, uint8* data, int size) { STREAM* s; uint16 bpp; uint32 offset; uint32 ncolors; /* size should be at least sizeof(BITMAPINFOHEADER) */ if (size < 40) { DEBUG_X11("dib size %d too short", size); return; } s = stream_new(0); stream_attach(s, data, size); stream_seek(s, 14); stream_read_uint16(s, bpp); stream_read_uint32(s, ncolors); offset = 14 + 40 + (bpp <= 8 ? (ncolors == 0 ? (1 << bpp) : ncolors) * 4 : 0); stream_detach(s); stream_free(s); DEBUG_X11("offset=%d bpp=%d ncolors=%d", offset, bpp, ncolors); s = stream_new(14 + size); stream_write_uint8(s, 'B'); stream_write_uint8(s, 'M'); stream_write_uint32(s, 14 + size); stream_write_uint32(s, 0); stream_write_uint32(s, offset); stream_write(s, data, size); cb->data = stream_get_head(s); cb->data_length = stream_get_length(s); stream_detach(s); stream_free(s); }
static void xf_cliprdr_process_cb_data_request_event(xfInfo* xfi, RDP_CB_DATA_REQUEST_EVENT* event) { int i; clipboardContext* cb = (clipboardContext*) xfi->clipboard_context; DEBUG_X11("format %d", event->format); if (xf_cliprdr_is_self_owned(xfi)) { /* CB_FORMAT_RAW */ i = 0; XChangeProperty(xfi->display, xfi->window->handle, cb->property_atom, XA_INTEGER, 32, PropModeReplace, (unsigned char*) &event->format, 1); } else { i = xf_cliprdr_select_format_by_id(cb, event->format); } if (i < 0) { DEBUG_X11("unsupported format requested"); xf_cliprdr_send_null_data_response(xfi); } else { cb->request_index = i; DEBUG_X11("target=%d", (int)cb->format_mappings[i].target_format); XConvertSelection(xfi->display, cb->clipboard_atom, cb->format_mappings[i].target_format, cb->property_atom, xfi->window->handle, CurrentTime); XFlush(xfi->display); /* After this point, we expect a SelectionNotify event from the clipboard owner. */ } }
boolean xf_cliprdr_process_property_notify(xfInfo* xfi, XEvent* xevent) { clipboardContext* cb = (clipboardContext*) xfi->clipboard_context; if (xevent->xproperty.atom != cb->property_atom) return False; /* Not cliprdr-related */ if (xevent->xproperty.window == cb->root_window) { DEBUG_X11("root window PropertyNotify"); xf_cliprdr_send_format_list(xfi); } else if (xevent->xproperty.window == xfi->window->handle && xevent->xproperty.state == PropertyNewValue && cb->incr_starts && cb->request_index >= 0) { DEBUG_X11("cliprdr window PropertyNotify"); xf_cliprdr_get_requested_data(xfi, cb->format_mappings[cb->request_index].target_format); } return True; }
static uint8* xf_cliprdr_process_requested_dib(uint8* data, int* size) { uint8* outbuf; /* length should be at least BMP header (14) + sizeof(BITMAPINFOHEADER) */ if (*size < 54) { DEBUG_X11("bmp length %d too short", *size); return NULL; } *size -= 14; outbuf = (uint8*) xzalloc(*size); memcpy(outbuf, data + 14, *size); return outbuf; }
static void xf_cliprdr_process_cb_format_list_event(xfInfo* xfi, RDP_CB_FORMAT_LIST_EVENT* event) { int i, j; clipboardContext* cb = (clipboardContext*) xfi->clipboard_context; if (cb->data) { free(cb->data); cb->data = NULL; } if (cb->formats) free(cb->formats); cb->formats = event->formats; cb->num_formats = event->num_formats; event->formats = NULL; event->num_formats = 0; cb->num_targets = 2; for (i = 0; i < cb->num_formats; i++) { for (j = 0; j < cb->num_format_mappings; j++) { if (cb->formats[i] == cb->format_mappings[j].format_id) { DEBUG_X11("announce format#%d : %d", i, cb->formats[i]); xf_cliprdr_append_target(cb, cb->format_mappings[j].target_format); } } } XSetSelectionOwner(xfi->display, cb->clipboard_atom, xfi->drawable, CurrentTime); if (event->raw_format_data) { XChangeProperty(xfi->display, cb->root_window, cb->property_atom, XA_STRING, 8, PropModeReplace, event->raw_format_data, event->raw_format_data_size); } XFlush(xfi->display); }
static void xf_cliprdr_send_supported_format_list(xfInfo* xfi) { int i; RDP_CB_FORMAT_LIST_EVENT* event; clipboardContext* cb = (clipboardContext*) xfi->clipboard_context; DEBUG_X11(""); event = (RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new(RDP_EVENT_CLASS_CLIPRDR, RDP_EVENT_TYPE_CB_FORMAT_LIST, NULL, NULL); event->formats = (uint32*) xmalloc(sizeof(uint32) * cb->num_format_mappings); event->num_formats = cb->num_format_mappings; for (i = 0; i < cb->num_format_mappings; i++) { event->formats[i] = cb->format_mappings[i].format_id; } freerdp_chanman_send_event(cb->chanman, (RDP_EVENT*) event); }
boolean xf_cliprdr_process_selection_notify(xfInfo* xfi, XEvent* xevent) { clipboardContext* cb = (clipboardContext*) xfi->clipboard_context; if (xevent->xselection.target == cb->targets[1]) { if (xevent->xselection.property == None) { DEBUG_X11("owner not support TARGETS. sending all format."); xf_cliprdr_send_supported_format_list(xfi); } else { xf_cliprdr_get_requested_targets(xfi); } return True; } else { return xf_cliprdr_get_requested_data(xfi, xevent->xselection.target); } }
BOOL xf_event_process(freerdp* instance, XEvent* event) { BOOL status = TRUE; xfInfo* xfi = ((xfContext*) instance->context)->xfi; rdpRail* rail = ((rdpContext*) xfi->context)->rail; rdpWindow* window; if (xfi->remote_app) { window = window_list_get_by_extra_id(rail->list, (void*) event->xexpose.window); if (window) { /* Update "current" window for cursor change orders */ xfi->window = (xfWindow*) window->extra; if (xf_event_suppress_events(xfi, window, event)) return TRUE; } } if (event->type != MotionNotify) DEBUG_X11("%s Event(%d): wnd=0x%04X", X11_EVENT_STRINGS[event->type], event->type, (UINT32) event->xany.window); switch (event->type) { case Expose: status = xf_event_Expose(xfi, event, xfi->remote_app); break; case VisibilityNotify: status = xf_event_VisibilityNotify(xfi, event, xfi->remote_app); break; case MotionNotify: status = xf_event_MotionNotify(xfi, event, xfi->remote_app); break; case ButtonPress: status = xf_event_ButtonPress(xfi, event, xfi->remote_app); break; case ButtonRelease: status = xf_event_ButtonRelease(xfi, event, xfi->remote_app); break; case KeyPress: status = xf_event_KeyPress(xfi, event, xfi->remote_app); break; case KeyRelease: status = xf_event_KeyRelease(xfi, event, xfi->remote_app); break; case FocusIn: status = xf_event_FocusIn(xfi, event, xfi->remote_app); break; case FocusOut: status = xf_event_FocusOut(xfi, event, xfi->remote_app); break; case EnterNotify: status = xf_event_EnterNotify(xfi, event, xfi->remote_app); break; case LeaveNotify: status = xf_event_LeaveNotify(xfi, event, xfi->remote_app); break; case NoExpose: break; case GraphicsExpose: break; case ConfigureNotify: status = xf_event_ConfigureNotify(xfi, event, xfi->remote_app); break; case MapNotify: status = xf_event_MapNotify(xfi, event, xfi->remote_app); break; case UnmapNotify: status = xf_event_UnmapNotify(xfi, event, xfi->remote_app); break; case ReparentNotify: break; case MappingNotify: status = xf_event_MappingNotify(xfi, event, xfi->remote_app); break; case ClientMessage: status = xf_event_ClientMessage(xfi, event, xfi->remote_app); break; case SelectionNotify: status = xf_event_SelectionNotify(xfi, event, xfi->remote_app); break; case SelectionRequest: status = xf_event_SelectionRequest(xfi, event, xfi->remote_app); break; case SelectionClear: status = xf_event_SelectionClear(xfi, event, xfi->remote_app); break; case PropertyNotify: status = xf_event_PropertyNotify(xfi, event, xfi->remote_app); break; } xf_input_handle_event(xfi, event); XSync(xfi->display, FALSE); return status; }
int main(int argc, char ** argv) { int rv; xfInfo * xfi; pthread_t thread; int index = 1; char reason_msg[ERRINFO_BUFFER_SIZE]; setlocale(LC_CTYPE, ""); if (argc == 1) { out_args(); return 0; } if (!freerdp_global_init()) { printf("Error initializing freerdp\n"); return 1; } freerdp_chanman_init(); freerdp_sem_create(&g_sem, 0); while (1) { xfi = (xfInfo *) malloc(sizeof(xfInfo)); memset(xfi, 0, sizeof(xfInfo)); xfi->settings = (rdpSet *) malloc(sizeof(rdpSet)); xfi->chan_man = freerdp_chanman_new(); xfi->clrconv = (HCLRCONV) malloc(sizeof(CLRCONV)); memset(xfi->clrconv, 0, sizeof(CLRCONV)); xfi->clrconv->alpha = 1; xfi->clrconv->palette = NULL; rv = process_params(xfi, argc, argv, &index); if (rv) { free(xfi->settings); freerdp_chanman_free(xfi->chan_man); free(xfi); break; } DEBUG_X11("starting thread %d to %s:%d", g_thread_count, xfi->settings->server, xfi->settings->tcp_port_rdp); if (pthread_create(&thread, 0, thread_func, xfi) == 0) { g_thread_count++; } } if (g_thread_count > 0) { DEBUG_X11("main thread, waiting for all threads to exit"); freerdp_sem_wait(&g_sem); DEBUG_X11("main thread, all threads did exit"); } freerdp_chanman_uninit(); freerdp_global_finish(); if (g_error_code) return g_error_code; else if (g_disconnect_reason) { printf("disconnect: %s\n", freerdp_str_disconnect_reason(g_disconnect_reason, reason_msg, ERRINFO_BUFFER_SIZE)); } return exit_code_from_disconnect_reason(g_disconnect_reason); }
void xf_SetWindowFullscreen(xfContext* xfc, xfWindow* window, BOOL fullscreen) { UINT32 i; rdpSettings* settings = xfc->context.settings; int startX, startY; UINT32 width = window->width; UINT32 height = window->height; /* xfc->decorations is set by caller depending on settings and whether it is fullscreen or not */ window->decorations = xfc->decorations; /* show/hide decorations (e.g. title bar) as guided by xfc->decorations */ xf_SetWindowDecorations(xfc, window->handle, window->decorations); DEBUG_X11(TAG, "X window decoration set to %d", (int)window->decorations); xf_floatbar_toggle_fullscreen(xfc->window->floatbar, fullscreen); if (fullscreen) { xfc->savedWidth = xfc->window->width; xfc->savedHeight = xfc->window->height; xfc->savedPosX = xfc->window->left; xfc->savedPosY = xfc->window->top; startX = (settings->DesktopPosX != UINT32_MAX) ? settings->DesktopPosX : 0; startY = (settings->DesktopPosY != UINT32_MAX) ? settings->DesktopPosY : 0; } else { width = xfc->savedWidth; height = xfc->savedHeight; startX = xfc->savedPosX; startY = xfc->savedPosY; } /* Determine the x,y starting location for the fullscreen window */ if (fullscreen) { /* Initialize startX and startY with reasonable values */ startX = xfc->context.settings->MonitorDefArray[0].x; startY = xfc->context.settings->MonitorDefArray[0].y; /* Search all monitors to find the lowest startX and startY values */ for (i = 0; i < xfc->context.settings->MonitorCount; i++) { startX = MIN(startX, xfc->context.settings->MonitorDefArray[i].x); startY = MIN(startY, xfc->context.settings->MonitorDefArray[i].y); } /* Lastly apply any monitor shift(translation from remote to local coordinate system) * to startX and startY values */ startX += xfc->context.settings->MonitorLocalShiftX; startY += xfc->context.settings->MonitorLocalShiftY; } /* It is safe to proceed with simply toogling _NET_WM_STATE_FULLSCREEN window state on the following conditions: - The window manager supports multiple monitor full screen - The user requested to use a single monitor to render the remote desktop */ if (xfc->_NET_WM_FULLSCREEN_MONITORS != None || settings->MonitorCount == 1) { xf_ResizeDesktopWindow(xfc, window, width, height); if (fullscreen) { /* enter full screen: move the window before adding NET_WM_STATE_FULLSCREEN */ XMoveWindow(xfc->display, window->handle, startX, startY); } /* Set the fullscreen state */ xf_SendClientEvent(xfc, window->handle, xfc->_NET_WM_STATE, 4, fullscreen ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE, xfc->_NET_WM_STATE_FULLSCREEN, 0, 0); if (!fullscreen) { /* leave full screen: move the window after removing NET_WM_STATE_FULLSCREEN */ XMoveWindow(xfc->display, window->handle, startX, startY); } /* Set monitor bounds */ if (settings->MonitorCount > 1) { xf_SendClientEvent(xfc, window->handle, xfc->_NET_WM_FULLSCREEN_MONITORS, 5, xfc->fullscreenMonitors.top, xfc->fullscreenMonitors.bottom, xfc->fullscreenMonitors.left, xfc->fullscreenMonitors.right, 1); } } else { if (fullscreen) { xf_SetWindowDecorations(xfc, window->handle, FALSE); if (xfc->fullscreenMonitors.top) { xf_SendClientEvent(xfc, window->handle, xfc->_NET_WM_STATE, 4, _NET_WM_STATE_ADD, xfc->fullscreenMonitors.top, 0, 0); } else { XSetWindowAttributes xswa; xswa.override_redirect = True; XChangeWindowAttributes(xfc->display, window->handle, CWOverrideRedirect, &xswa); XRaiseWindow(xfc->display, window->handle); xswa.override_redirect = False; XChangeWindowAttributes(xfc->display, window->handle, CWOverrideRedirect, &xswa); } /* if window is in maximized state, save and remove */ if (xfc->_NET_WM_STATE_MAXIMIZED_VERT != None) { BYTE state; unsigned long nitems; unsigned long bytes; BYTE* prop; if (xf_GetWindowProperty(xfc, window->handle, xfc->_NET_WM_STATE, 255, &nitems, &bytes, &prop)) { state = 0; while (nitems-- > 0) { if (((Atom*) prop)[nitems] == xfc->_NET_WM_STATE_MAXIMIZED_VERT) state |= 0x01; if (((Atom*) prop)[nitems] == xfc->_NET_WM_STATE_MAXIMIZED_HORZ) state |= 0x02; } if (state) { xf_SendClientEvent(xfc, window->handle, xfc->_NET_WM_STATE, 4, _NET_WM_STATE_REMOVE, xfc->_NET_WM_STATE_MAXIMIZED_VERT, 0, 0); xf_SendClientEvent(xfc, window->handle, xfc->_NET_WM_STATE, 4, _NET_WM_STATE_REMOVE, xfc->_NET_WM_STATE_MAXIMIZED_HORZ, 0, 0); xfc->savedMaximizedState = state; } XFree(prop); } } width = xfc->vscreen.area.right - xfc->vscreen.area.left + 1; height = xfc->vscreen.area.bottom - xfc->vscreen.area.top + 1; DEBUG_X11("X window move and resize %dx%d@%dx%d", startX, startY, width, height); xf_ResizeDesktopWindow(xfc, window, width, height); XMoveWindow(xfc->display, window->handle, startX, startY); } else { xf_SetWindowDecorations(xfc, window->handle, window->decorations); xf_ResizeDesktopWindow(xfc, window, width, height); XMoveWindow(xfc->display, window->handle, startX, startY); if (xfc->fullscreenMonitors.top) { xf_SendClientEvent(xfc, window->handle, xfc->_NET_WM_STATE, 4, _NET_WM_STATE_REMOVE, xfc->fullscreenMonitors.top, 0, 0); } /* restore maximized state, if the window was maximized before setting fullscreen */ if (xfc->savedMaximizedState & 0x01) { xf_SendClientEvent(xfc, window->handle, xfc->_NET_WM_STATE, 4, _NET_WM_STATE_ADD, xfc->_NET_WM_STATE_MAXIMIZED_VERT, 0, 0); } if (xfc->savedMaximizedState & 0x02) { xf_SendClientEvent(xfc, window->handle, xfc->_NET_WM_STATE, 4, _NET_WM_STATE_ADD, xfc->_NET_WM_STATE_MAXIMIZED_HORZ, 0, 0); } xfc->savedMaximizedState = 0; } } }
static BOOL xf_cliprdr_get_requested_data(xfInfo* xfi, Atom target) { Atom type; int format; BYTE* data = NULL; BOOL has_data = FALSE; unsigned long length, bytes_left, dummy; clipboardContext* cb = (clipboardContext*) xfi->clipboard_context; if ((cb->request_index < 0) || (cb->format_mappings[cb->request_index].target_format != target)) { DEBUG_X11_CLIPRDR("invalid target"); xf_cliprdr_send_null_data_response(xfi); return FALSE; } XGetWindowProperty(xfi->display, xfi->drawable, cb->property_atom, 0, 0, 0, target, &type, &format, &length, &bytes_left, &data); DEBUG_X11_CLIPRDR("type=%d format=%d bytes=%d request_index=%d", (int) type, format, (int) bytes_left, cb->request_index); if (data) { XFree(data); data = NULL; } if (bytes_left <= 0 && !cb->incr_starts) { DEBUG_X11("no data"); } else if (type == cb->incr_atom) { DEBUG_X11("INCR started"); cb->incr_starts = TRUE; if (cb->incr_data) { free(cb->incr_data); cb->incr_data = NULL; } cb->incr_data_length = 0; /* Data will be followed in PropertyNotify event */ has_data = TRUE; } else { if (bytes_left <= 0) { /* INCR finish */ data = cb->incr_data; cb->incr_data = NULL; bytes_left = cb->incr_data_length; cb->incr_data_length = 0; cb->incr_starts = 0; DEBUG_X11("INCR finished"); has_data = TRUE; } else if (XGetWindowProperty(xfi->display, xfi->drawable, cb->property_atom, 0, bytes_left, 0, target, &type, &format, &length, &dummy, &data) == Success) { if (cb->incr_starts) { bytes_left = length * format / 8; DEBUG_X11("%d bytes", (int)bytes_left); cb->incr_data = (BYTE*) realloc(cb->incr_data, cb->incr_data_length + bytes_left); CopyMemory(cb->incr_data + cb->incr_data_length, data, bytes_left); cb->incr_data_length += bytes_left; XFree(data); data = NULL; } has_data = TRUE; } else { DEBUG_X11_CLIPRDR("XGetWindowProperty failed"); } } XDeleteProperty(xfi->display, xfi->drawable, cb->property_atom); xf_cliprdr_process_requested_data(xfi, has_data, data, (int) bytes_left); if (data) XFree(data); return TRUE; }
xfWindow* xf_CreateDesktopWindow(xfContext* xfc, char* name, int width, int height) { XEvent xevent; int input_mask; xfWindow* window; Window parentWindow; XClassHint* classHints; rdpSettings* settings; window = (xfWindow*) calloc(1, sizeof(xfWindow)); if (!window) return NULL; settings = xfc->context.settings; parentWindow = (Window) xfc->context.settings->ParentWindowId; window->width = width; window->height = height; window->decorations = xfc->decorations; window->is_mapped = FALSE; window->is_transient = FALSE; window->handle = XCreateWindow(xfc->display, RootWindowOfScreen(xfc->screen), xfc->workArea.x, xfc->workArea.y, xfc->workArea.width, xfc->workArea.height, 0, xfc->depth, InputOutput, xfc->visual, CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap | CWBorderPixel | CWWinGravity | CWBitGravity, &xfc->attribs); window->shmid = shm_open(get_shm_id(), (O_CREAT | O_RDWR), (S_IREAD | S_IWRITE)); if (window->shmid < 0) { DEBUG_X11("xf_CreateDesktopWindow: failed to get access to shared memory - shmget()\n"); } else { void* mem; ftruncate(window->shmid, sizeof(window->handle)); mem = mmap(0, sizeof(window->handle), PROT_READ | PROT_WRITE, MAP_SHARED, window->shmid, 0); if (mem == MAP_FAILED) { DEBUG_X11("xf_CreateDesktopWindow: failed to assign pointer to the memory address - shmat()\n"); } else { window->xfwin = mem; *window->xfwin = window->handle; } } classHints = XAllocClassHint(); if (classHints) { classHints->res_name = "xfreerdp"; if (xfc->context.settings->WmClass) classHints->res_class = xfc->context.settings->WmClass; else classHints->res_class = "xfreerdp"; XSetClassHint(xfc->display, window->handle, classHints); XFree(classHints); } xf_ResizeDesktopWindow(xfc, window, width, height); xf_SetWindowDecorations(xfc, window->handle, window->decorations); xf_SetWindowPID(xfc, window->handle, 0); input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | VisibilityChangeMask | FocusChangeMask | StructureNotifyMask | PointerMotionMask | ExposureMask | PropertyChangeMask; if (xfc->grab_keyboard) input_mask |= EnterWindowMask | LeaveWindowMask; XChangeProperty(xfc->display, window->handle, xfc->_NET_WM_ICON, XA_CARDINAL, 32, PropModeReplace, (BYTE*) xf_icon_prop, ARRAYSIZE(xf_icon_prop)); if (parentWindow) XReparentWindow(xfc->display, window->handle, parentWindow, 0, 0); XSelectInput(xfc->display, window->handle, input_mask); XClearWindow(xfc->display, window->handle); xf_SetWindowTitleText(xfc, window->handle, name); XMapWindow(xfc->display, window->handle); xf_input_init(xfc, window->handle); /* * NOTE: This must be done here to handle reparenting the window, * so that we don't miss the event and hang waiting for the next one */ do { XMaskEvent(xfc->display, VisibilityChangeMask, &xevent); } while (xevent.type != VisibilityNotify); /* * The XCreateWindow call will start the window in the upper-left corner of our current * monitor instead of the upper-left monitor for remote app mode (which uses all monitors). * This extra call after the window is mapped will position the login window correctly */ if (xfc->context.settings->RemoteApplicationMode) { XMoveWindow(xfc->display, window->handle, 0, 0); } else if (settings->DesktopPosX != UINT32_MAX && settings->DesktopPosY != UINT32_MAX) { XMoveWindow(xfc->display, window->handle, settings->DesktopPosX, settings->DesktopPosY); } window->floatbar = xf_floatbar_new(xfc, window->handle, name, settings->Floatbar); return window; }
static void xf_cliprdr_process_cb_data_response_event(xfInfo* xfi, RDP_CB_DATA_RESPONSE_EVENT* event) { clipboardContext* cb = (clipboardContext*) xfi->clipboard_context; DEBUG_X11("size=%d", event->size); if (cb->respond == NULL) { DEBUG_X11("unexpected data"); return; } if (event->size == 0) { cb->respond->xselection.property = None; } else { if (cb->data) { xfree(cb->data); cb->data = NULL; } switch (cb->data_format) { case CB_FORMAT_RAW: case CB_FORMAT_PNG: case CB_FORMAT_JPEG: case CB_FORMAT_GIF: cb->data = event->data; cb->data_length = event->size; event->data = NULL; event->size = 0; break; case CB_FORMAT_TEXT: xf_cliprdr_process_text(cb, event->data, event->size); break; case CB_FORMAT_UNICODETEXT: xf_cliprdr_process_unicodetext(cb, event->data, event->size); break; case CB_FORMAT_DIB: xf_cliprdr_process_dib(cb, event->data, event->size); break; case CB_FORMAT_HTML: xf_cliprdr_process_html(cb, event->data, event->size); break; default: cb->respond->xselection.property = None; break; } xf_cliprdr_provide_data(xfi, cb->respond); } XSendEvent(xfi->display, cb->respond->xselection.requestor, 0, 0, cb->respond); XFlush(xfi->display); xfree(cb->respond); cb->respond = NULL; }
boolean xf_event_process(freerdp* instance, XEvent* event) { boolean app = False; boolean status = True; xfInfo* xfi = GET_XFI(instance); if (xfi->remote_app == True) { app = True; } else { if (event->xany.window != xfi->window->handle) app = True; } if (event->type != MotionNotify) DEBUG_X11("%s Event: wnd=0x%04X", X11_EVENT_STRINGS[event->type], (uint32) event->xany.window); switch (event->type) { case Expose: status = xf_event_Expose(xfi, event, app); break; case VisibilityNotify: status = xf_event_VisibilityNotify(xfi, event, app); break; case MotionNotify: status = xf_event_MotionNotify(xfi, event, app); break; case ButtonPress: status = xf_event_ButtonPress(xfi, event, app); break; case ButtonRelease: status = xf_event_ButtonRelease(xfi, event, app); break; case KeyPress: status = xf_event_KeyPress(xfi, event, app); break; case KeyRelease: status = xf_event_KeyRelease(xfi, event, app); break; case FocusIn: status = xf_event_FocusIn(xfi, event, app); break; case FocusOut: status = xf_event_FocusOut(xfi, event, app); break; case EnterNotify: status = xf_event_EnterNotify(xfi, event, app); break; case LeaveNotify: status = xf_event_LeaveNotify(xfi, event, app); break; case NoExpose: break; case GraphicsExpose: break; case ConfigureNotify: status = xf_event_ConfigureNotify(xfi, event, app); break; case MapNotify: status = xf_event_MapNotify(xfi, event, app); break; case ReparentNotify: break; case MappingNotify: status = xf_event_MappingNotify(xfi, event, app); break; case ClientMessage: status = xf_event_ClientMessage(xfi, event, app); break; default: DEBUG_X11("xf_event_process unknown event %d", event->type); break; } return status; }
boolean xf_cliprdr_process_selection_request(xfInfo* xfi, XEvent* xevent) { int i; int fmt; Atom type; uint32 format; XEvent* respond; uint32 alt_format; uint8* data = NULL; boolean delay_respond; unsigned long len, bytes_left; clipboardContext* cb = (clipboardContext*) xfi->clipboard_context; DEBUG_X11("target=%d", (int)xevent->xselectionrequest.target); if (xevent->xselectionrequest.owner != xfi->window->handle) { DEBUG_X11("not owner"); return False; } delay_respond = False; respond = xnew(XEvent); respond->xselection.property = None; respond->xselection.type = SelectionNotify; respond->xselection.display = xevent->xselectionrequest.display; respond->xselection.requestor = xevent->xselectionrequest.requestor; respond->xselection.selection = xevent->xselectionrequest.selection; respond->xselection.target = xevent->xselectionrequest.target; respond->xselection.time = xevent->xselectionrequest.time; if (xevent->xselectionrequest.target == cb->targets[0]) /* TIMESTAMP */ { /* TODO */ } else if (xevent->xselectionrequest.target == cb->targets[1]) /* TARGETS */ { /* Someone else requests our available formats */ respond->xselection.property = xevent->xselectionrequest.property; xf_cliprdr_provide_targets(xfi, respond); } else { i = xf_cliprdr_select_format_by_atom(cb, xevent->xselectionrequest.target); if (i >= 0 && xevent->xselectionrequest.requestor != xfi->window->handle) { format = cb->format_mappings[i].format_id; alt_format = format; if (format == CB_FORMAT_RAW) { if (XGetWindowProperty(xfi->display, xevent->xselectionrequest.requestor, cb->property_atom, 0, 4, 0, XA_INTEGER, &type, &fmt, &len, &bytes_left, &data) != Success) { DEBUG_X11("XGetWindowProperty failed"); } if (data) { memcpy(&alt_format, data, 4); XFree(data); } } DEBUG_X11("provide format 0x%04x alt_format 0x%04x", format, alt_format); if (cb->data != 0 && format == cb->data_format && alt_format == cb->data_alt_format) { /* Cached clipboard data available. Send it now */ respond->xselection.property = xevent->xselectionrequest.property; xf_cliprdr_provide_data(xfi, respond); } else if (cb->respond) { DEBUG_X11("duplicated request"); } else { /** * Send clipboard data request to the server. * Response will be postponed after receiving the data */ if (cb->data) { xfree(cb->data); cb->data = NULL; } respond->xselection.property = xevent->xselectionrequest.property; cb->respond = respond; cb->data_format = format; cb->data_alt_format = alt_format; delay_respond = True; xf_cliprdr_send_data_request(xfi, alt_format); } } } if (!delay_respond) { XSendEvent(xfi->display, xevent->xselectionrequest.requestor, 0, 0, respond); XFlush(xfi->display); xfree(respond); } return True; }
static int run_xfreerdp(xfInfo * xfi) { rdpInst * inst; void * read_fds[32]; void * write_fds[32]; int read_count; int write_count; int index; int sck; int max_sck; fd_set rfds; fd_set wfds; RD_EVENT * event; /* create an instance of the library */ inst = freerdp_new(xfi->settings); if (inst == NULL) { printf("run_xfreerdp: freerdp_new failed\n"); return XF_EXIT_MEMORY; } if ((inst->version != FREERDP_INTERFACE_VERSION) || (inst->size != sizeof(rdpInst))) { printf("run_xfreerdp: freerdp_new size, version / size do not " "match expecting v %d s %d got v %d s %d\n", FREERDP_INTERFACE_VERSION, (int)sizeof(rdpInst), inst->version, inst->size); return XF_EXIT_PROTOCOL; } xfi->inst = inst; SET_XFI(inst, xfi); if (xf_pre_connect(xfi) != 0) { printf("run_xfreerdp: xf_pre_connect failed\n"); return XF_EXIT_CONN_FAILED; } if (freerdp_chanman_pre_connect(xfi->chan_man, inst) != 0) { printf("run_xfreerdp: freerdp_chanman_pre_connect failed\n"); return XF_EXIT_CONN_FAILED; } xf_kb_init(xfi->display, xfi->keyboard_layout_id); xf_kb_inst_init(xfi); printf("keyboard_layout: 0x%X\n", inst->settings->keyboard_layout); /* call connect */ if (inst->rdp_connect(inst) != 0) { printf("run_xfreerdp: inst->rdp_connect failed\n"); return XF_EXIT_CONN_FAILED; } if (freerdp_chanman_post_connect(xfi->chan_man, inst) != 0) { printf("run_xfreerdp: freerdp_chanman_post_connect failed\n"); return XF_EXIT_CONN_FAILED; } if (xf_post_connect(xfi) != 0) { printf("run_xfreerdp: xf_post_connect failed\n"); return XF_EXIT_CONN_FAILED; } xf_video_init(xfi); xf_decode_init(xfi); /* program main loop */ while (1) { read_count = 0; write_count = 0; /* get libfreerdp fds */ if (inst->rdp_get_fds(inst, read_fds, &read_count, write_fds, &write_count) != 0) { printf("run_xfreerdp: inst->rdp_get_fds failed\n"); break; } /* get x fds */ if (xf_get_fds(xfi, read_fds, &read_count, write_fds, &write_count) != 0) { printf("run_xfreerdp: xf_get_fds failed\n"); break; } /* get channel fds */ if (freerdp_chanman_get_fds(xfi->chan_man, inst, read_fds, &read_count, write_fds, &write_count) != 0) { printf("run_xfreerdp: freerdp_chanman_get_fds failed\n"); break; } max_sck = 0; /* setup read fds */ FD_ZERO(&rfds); for (index = 0; index < read_count; index++) { sck = (int)(long) (read_fds[index]); if (sck > max_sck) max_sck = sck; FD_SET(sck, &rfds); } /* setup write fds */ FD_ZERO(&wfds); for (index = 0; index < write_count; index++) { sck = (int)(long) (write_fds[index]); if (sck > max_sck) max_sck = sck; FD_SET(sck, &wfds); } /* exit if nothing to do */ if (max_sck == 0) { printf("run_xfreerdp: max_sck is zero\n"); break; } /* do the wait */ if (select(max_sck + 1, &rfds, &wfds, NULL, NULL) == -1) { /* these are not really errors */ if (!((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINPROGRESS) || (errno == EINTR))) /* signal occurred */ { printf("run_xfreerdp: select failed\n"); break; } } /* check the libfreerdp fds */ if (inst->rdp_check_fds(inst) != 0) { printf("run_xfreerdp: inst->rdp_check_fds failed\n"); break; } /* check x fds */ if (xf_check_fds(xfi) != 0) { /* xfreerdp is usually terminated by this failing because the X windows has been closed */ DEBUG_X11("xf_check_fds failed"); break; } /* check channel fds */ if (freerdp_chanman_check_fds(xfi->chan_man, inst) != 0) { printf("run_xfreerdp: freerdp_chanman_check_fds failed\n"); break; } /* check channel event */ event = freerdp_chanman_pop_event(xfi->chan_man); if (event) { switch (event->event_type) { case RD_EVENT_TYPE_VIDEO_FRAME: xf_video_process_frame(xfi, (RD_VIDEO_FRAME_EVENT *) event); break; case RD_EVENT_TYPE_REDRAW: xf_handle_redraw_event(xfi, (RD_REDRAW_EVENT *) event); break; default: printf("run_xfreerdp: unknown event type %d\n", event->event_type); break; } freerdp_chanman_free_event(xfi->chan_man, event); } } g_disconnect_reason = inst->disc_reason; /* cleanup */ xf_decode_uninit(xfi); xf_video_uninit(xfi); freerdp_chanman_close(xfi->chan_man, inst); inst->rdp_disconnect(inst); freerdp_free(inst); xf_uninit(xfi); return 0; }
BOOL xf_event_process(freerdp* instance, XEvent* event) { BOOL status = TRUE; xfAppWindow* appWindow; xfContext* xfc = (xfContext*) instance->context; if (xfc->remote_app) { appWindow = xf_AppWindowFromX11Window(xfc, event->xany.window); if (appWindow) { /* Update "current" window for cursor change orders */ xfc->appWindow = appWindow; if (xf_event_suppress_events(xfc, appWindow, event)) return TRUE; } } xf_event_execute_action_script(xfc, event); if (event->type != MotionNotify) DEBUG_X11("%s Event(%d): wnd=0x%08lX", X11_EVENT_STRINGS[event->type], event->type, (unsigned long) event->xany.window); switch (event->type) { case Expose: status = xf_event_Expose(xfc, event, xfc->remote_app); break; case VisibilityNotify: status = xf_event_VisibilityNotify(xfc, event, xfc->remote_app); break; case MotionNotify: status = xf_event_MotionNotify(xfc, event, xfc->remote_app); break; case ButtonPress: status = xf_event_ButtonPress(xfc, event, xfc->remote_app); break; case ButtonRelease: status = xf_event_ButtonRelease(xfc, event, xfc->remote_app); break; case KeyPress: status = xf_event_KeyPress(xfc, event, xfc->remote_app); break; case KeyRelease: status = xf_event_KeyRelease(xfc, event, xfc->remote_app); break; case FocusIn: status = xf_event_FocusIn(xfc, event, xfc->remote_app); break; case FocusOut: status = xf_event_FocusOut(xfc, event, xfc->remote_app); break; case EnterNotify: status = xf_event_EnterNotify(xfc, event, xfc->remote_app); break; case LeaveNotify: status = xf_event_LeaveNotify(xfc, event, xfc->remote_app); break; case NoExpose: break; case GraphicsExpose: break; case ConfigureNotify: status = xf_event_ConfigureNotify(xfc, event, xfc->remote_app); break; case MapNotify: status = xf_event_MapNotify(xfc, event, xfc->remote_app); break; case UnmapNotify: status = xf_event_UnmapNotify(xfc, event, xfc->remote_app); break; case ReparentNotify: break; case MappingNotify: status = xf_event_MappingNotify(xfc, event, xfc->remote_app); break; case ClientMessage: status = xf_event_ClientMessage(xfc, event, xfc->remote_app); break; case PropertyNotify: status = xf_event_PropertyNotify(xfc, event, xfc->remote_app); break; } if (!xfc->remote_app) { xf_cliprdr_handle_xevent(xfc, event); } xf_input_handle_event(xfc, event); XSync(xfc->display, FALSE); return status; }
/* Returns "true" on errors or other reasons to not continue normal operation */ static int process_params(xfInfo * xfi, int argc, char ** argv, int * pindex) { rdpSet * settings; rdpKeyboardLayout * layouts; char * p; RD_PLUGIN_DATA plugin_data[MAX_PLUGIN_DATA + 1]; int index; int i, j; struct passwd * pw; int num_extensions; int rv; set_default_params(xfi); settings = xfi->settings; num_extensions = 0; p = getlogin(); i = sizeof(settings->username) - 1; if (p != 0) { strncpy(settings->username, p, i); } else { pw = getpwuid(getuid()); if (pw != 0) { if (pw->pw_name != 0) { strncpy(settings->username, pw->pw_name, i); } } } if (argc < *pindex + 1) { if (*pindex == 1) printf("no parameters specified\n"); return 1; } while (*pindex < argc) { if (strcmp("-a", argv[*pindex]) == 0) { *pindex = *pindex + 1; if (*pindex == argc) { printf("missing server depth\n"); exit(XF_EXIT_WRONG_PARAM); } settings->server_depth = atoi(argv[*pindex]); } else if (strcmp("-u", argv[*pindex]) == 0) { *pindex = *pindex + 1; if (*pindex == argc) { printf("missing username\n"); exit(XF_EXIT_WRONG_PARAM); } strncpy(settings->username, argv[*pindex], sizeof(settings->username) - 1); settings->username[sizeof(settings->username) - 1] = 0; } else if (strcmp("-p", argv[*pindex]) == 0) { *pindex = *pindex + 1; if (*pindex == argc) { printf("missing password\n"); exit(XF_EXIT_WRONG_PARAM); } strncpy(settings->password, argv[*pindex], sizeof(settings->password) - 1); settings->password[sizeof(settings->password) - 1] = 0; settings->autologin = 1; /* * Overwrite original password which could be revealed by a simple "ps aux" command. * This approach won't hide the password length, but it is better than nothing. */ memset(argv[*pindex], '*', strlen(argv[*pindex])); } else if (strcmp("-d", argv[*pindex]) == 0) { *pindex = *pindex + 1; if (*pindex == argc) { printf("missing domain\n"); exit(XF_EXIT_WRONG_PARAM); } strncpy(settings->domain, argv[*pindex], sizeof(settings->domain) - 1); settings->domain[sizeof(settings->domain) - 1] = 0; } else if (strcmp("-k", argv[*pindex]) == 0) { *pindex = *pindex + 1; if (*pindex == argc) { printf("missing keyboard layout ID\n"); exit(XF_EXIT_WRONG_PARAM); } sscanf(argv[*pindex], "%X", &(xfi->keyboard_layout_id)); DEBUG_X11("keyboard layout ID: %X", xfi->keyboard_layout_id); } else if (strcmp("-K", argv[*pindex]) == 0) { xfi->grab_keyboard = 0; } else if (strcmp("--kbd-list", argv[*pindex]) == 0) { layouts = freerdp_kbd_get_layouts(RDP_KEYBOARD_LAYOUT_TYPE_STANDARD); printf("\nKeyboard Layouts\n"); for (i = 0; layouts[i].code; i++) printf("0x%08X\t%s\n", layouts[i].code, layouts[i].name); free(layouts); layouts = freerdp_kbd_get_layouts(RDP_KEYBOARD_LAYOUT_TYPE_VARIANT); printf("\nKeyboard Layout Variants\n"); for (i = 0; layouts[i].code; i++) printf("0x%08X\t%s\n", layouts[i].code, layouts[i].name); free(layouts); layouts = freerdp_kbd_get_layouts(RDP_KEYBOARD_LAYOUT_TYPE_IME); printf("\nKeyboard Input Method Editors (IMEs)\n"); for (i = 0; layouts[i].code; i++) printf("0x%08X\t%s\n", layouts[i].code, layouts[i].name); free(layouts); return 1; } else if (strcmp("-s", argv[*pindex]) == 0) { *pindex = *pindex + 1; if (*pindex == argc) { printf("missing shell\n"); exit(XF_EXIT_WRONG_PARAM); } strncpy(settings->shell, argv[*pindex], sizeof(settings->shell) - 1); settings->shell[sizeof(settings->shell) - 1] = 0; } else if (strcmp("-c", argv[*pindex]) == 0) { *pindex = *pindex + 1; if (*pindex == argc) { printf("missing directory\n"); exit(XF_EXIT_WRONG_PARAM); } strncpy(settings->directory, argv[*pindex], sizeof(settings->directory) - 1); settings->directory[sizeof(settings->directory) - 1] = 0; } else if (strcmp("-g", argv[*pindex]) == 0) { *pindex = *pindex + 1; if (*pindex == argc) { printf("missing width\n"); exit(XF_EXIT_WRONG_PARAM); } settings->width = strtol(argv[*pindex], &p, 10); if (*p == 'x') { settings->height = strtol(p + 1, &p, 10); } if (*p == '%') { xfi->percentscreen = settings->width; } } else if (strcmp("-t", argv[*pindex]) == 0) { *pindex = *pindex + 1; if (*pindex == argc) { printf("missing port number\n"); exit(XF_EXIT_WRONG_PARAM); } settings->tcp_port_rdp = atoi(argv[*pindex]); } else if (strcmp("-T", argv[*pindex]) == 0) { *pindex = *pindex + 1; if (*pindex == argc) { printf("missing window title\n"); exit(XF_EXIT_WRONG_PARAM); } strncpy(xfi->window_title, argv[*pindex], sizeof(xfi->window_title) - 1); xfi->window_title[sizeof(xfi->window_title) - 1] = 0; } else if (strcmp("-n", argv[*pindex]) == 0) { *pindex = *pindex + 1; if (*pindex == argc) { printf("missing hostname\n"); exit(XF_EXIT_WRONG_PARAM); } strncpy(settings->hostname, argv[*pindex], sizeof(settings->hostname) - 1); settings->hostname[sizeof(settings->hostname) - 1] = 0; } else if (strcmp("-o", argv[*pindex]) == 0) { settings->console_audio = 1; } else if (strcmp("-0", argv[*pindex]) == 0) { settings->console_session = 1; } else if (strcmp("-z", argv[*pindex]) == 0) { settings->bulk_compression = 1; } else if (strcmp("--gdi", argv[*pindex]) == 0) { *pindex = *pindex + 1; if (*pindex == argc) { printf("missing GDI rendering\n"); return 1; } if (strncmp("sw", argv[*pindex], 1) == 0) /* Software */ { settings->software_gdi = 1; } else if (strncmp("hw", argv[*pindex], 1) == 0) /* Hardware */ { settings->software_gdi = 0; } else { printf("unknown GDI rendering\n"); return 1; } } else if (strcmp("--no-osb", argv[*pindex]) == 0) { settings->off_screen_bitmaps = 0; } else if (strcmp("--rfx", argv[*pindex]) == 0) { settings->rfx_flags = 1; settings->ui_decode_flags = 1; settings->use_frame_ack = 0; settings->server_depth = 32; settings->performanceflags = PERF_FLAG_NONE; xfi->codec = XF_CODEC_REMOTEFX; } else if (strcmp("--app", argv[*pindex]) == 0) { *pindex = *pindex + 1; if (*pindex == argc) { printf("missing application name\n"); exit(XF_EXIT_WRONG_PARAM); } strncpy(settings->app_name, argv[*pindex], sizeof(settings->app_name) - 1); settings->app_name[sizeof(settings->app_name) - 1] = 0; settings->remote_app = 1; } #ifdef HAVE_XV else if (strcmp("--xv-port", argv[*pindex]) == 0) { *pindex = *pindex + 1; xfi->xv_port = atoi(argv[*pindex]); } #endif else if (strcmp("-f", argv[*pindex]) == 0) { xfi->fullscreen = xfi->fs_toggle = 1; printf("full screen option\n"); } else if (strcmp("-D", argv[*pindex]) == 0) { xfi->decoration = 0; } else if (strcmp("-x", argv[*pindex]) == 0) { *pindex = *pindex + 1; if (*pindex == argc) { printf("missing performance flag\n"); exit(XF_EXIT_WRONG_PARAM); } if (strncmp("m", argv[*pindex], 1) == 0) /* modem */ { settings->performanceflags = PERF_DISABLE_WALLPAPER | PERF_DISABLE_FULLWINDOWDRAG | PERF_DISABLE_MENUANIMATIONS | PERF_DISABLE_THEMING; } else if (strncmp("b", argv[*pindex], 1) == 0) /* broadband */ { settings->performanceflags = PERF_DISABLE_WALLPAPER; } else if (strncmp("l", argv[*pindex], 1) == 0) /* lan */ { settings->performanceflags = PERF_FLAG_NONE; } else { settings->performanceflags = strtol(argv[*pindex], 0, 16); } } else if (strcmp("-X", argv[*pindex]) == 0) { *pindex = *pindex + 1; if (*pindex == argc) { printf("missing XID\n"); exit(XF_EXIT_WRONG_PARAM); } xfi->embed = strtoul(argv[*pindex], NULL, 16); if (!xfi->embed) { printf("bad XID\n"); exit(XF_EXIT_WRONG_PARAM); } } #ifndef DISABLE_TLS else if (strcmp("--no-rdp", argv[*pindex]) == 0) { settings->rdp_security = 0; } else if (strcmp("--no-tls", argv[*pindex]) == 0) { settings->tls_security = 0; } else if (strcmp("--no-nla", argv[*pindex]) == 0) { settings->nla_security = 0; } else if (strcmp("--sec", argv[*pindex]) == 0) { *pindex = *pindex + 1; if (*pindex == argc) { printf("missing protocol security\n"); exit(XF_EXIT_WRONG_PARAM); } if (strncmp("rdp", argv[*pindex], 1) == 0) /* Standard RDP */ { settings->rdp_security = 1; settings->tls_security = 0; settings->nla_security = 0; } else if (strncmp("tls", argv[*pindex], 1) == 0) /* TLS */ { settings->rdp_security = 0; settings->tls_security = 1; settings->nla_security = 0; } else if (strncmp("nla", argv[*pindex], 1) == 0) /* NLA */ { settings->rdp_security = 0; settings->tls_security = 0; settings->nla_security = 1; } else { printf("unknown protocol security\n"); exit(XF_EXIT_WRONG_PARAM); } } #endif else if (strcmp("--plugin", argv[*pindex]) == 0) { *pindex = *pindex + 1; if (*pindex == argc) { printf("missing plugin name\n"); exit(XF_EXIT_WRONG_PARAM); } index = *pindex; memset(plugin_data, 0, sizeof(plugin_data)); if (*pindex < argc - 1 && strcmp("--data", argv[*pindex + 1]) == 0) { *pindex = *pindex + 2; i = 0; while (*pindex < argc && strcmp("--", argv[*pindex]) != 0 && i < MAX_PLUGIN_DATA) { plugin_data[i].size = sizeof(RD_PLUGIN_DATA); for (j = 0, p = argv[*pindex]; j < 4 && p != NULL; j++) { plugin_data[i].data[j] = p; if (j < 3) { p = strchr(plugin_data[i].data[j], ':'); if (p != NULL) *p++ = 0; } } *pindex = *pindex + 1; i++; } } rv = freerdp_chanman_load_plugin(xfi->chan_man, settings, argv[index], plugin_data); if (rv) exit(XF_EXIT_WRONG_PARAM); } else if (strcmp("--ext", argv[*pindex]) == 0) { *pindex = *pindex + 1; if (*pindex == argc) { printf("missing extension name\n"); exit(XF_EXIT_WRONG_PARAM); } if (num_extensions >= sizeof(settings->extensions) / sizeof(struct rdp_ext_set)) { printf("maximum extensions reached\n"); exit(XF_EXIT_WRONG_PARAM); } index = *pindex; snprintf(settings->extensions[num_extensions].name, sizeof(settings->extensions[num_extensions].name), "%s", argv[index]); settings->extensions[num_extensions].data = NULL; if (*pindex < argc - 1 && strcmp("--data", argv[*pindex + 1]) == 0) { *pindex = *pindex + 2; settings->extensions[num_extensions].data = argv[*pindex]; i = 0; while (*pindex < argc && strcmp("--", argv[*pindex]) != 0) { *pindex = *pindex + 1; i++; } } num_extensions++; } else if ((strcmp("-h", argv[*pindex]) == 0) || strcmp("--help", argv[*pindex]) == 0) { out_args(); return 1; } else if (strcmp("--version", argv[*pindex]) == 0) { printf("This is FreeRDP version %s\n", PACKAGE_VERSION); return 1; } else if (argv[*pindex][0] != '-') { settings->server[sizeof(settings->server) - 1] = 0; if (argv[*pindex][0] == '[' && (p = strchr(argv[*pindex], ']')) && (p[1] == 0 || (p[1] == ':' && !strchr(p + 2, ':')))) { /* Either "[...]" or "[...]:..." with at most one : after the brackets */ strncpy(settings->server, argv[*pindex] + 1, sizeof(settings->server) - 1); if ((p = strchr(settings->server, ']'))) { *p = 0; if (p[1] == ':') settings->tcp_port_rdp = atoi(p + 2); } } else { /* Port number is cut off and used if exactly one : in the string */ strncpy(settings->server, argv[*pindex], sizeof(settings->server) - 1); if ((p = strchr(settings->server, ':')) && !strchr(p + 1, ':')) { *p = 0; settings->tcp_port_rdp = atoi(p + 1); } } /* server is the last argument for the current session. arguments followed will be parsed for the next session. */ *pindex = *pindex + 1; return 0; } else { printf("invalid option: %s\n", argv[*pindex]); exit(XF_EXIT_WRONG_PARAM); } *pindex = *pindex + 1; } printf("missing server name\n"); exit(XF_EXIT_WRONG_PARAM); }