Merge pull request #1754 from awakecoding/master
Multimon Fix, xfreerdp extensibility, context-specific error handling, Gateway LAN auto-detect
This commit is contained in:
commit
caecf1823b
@ -1091,8 +1091,6 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
||||
|
||||
rdpsnd->log = WLog_Get("com.freerdp.channels.rdpsnd.client");
|
||||
|
||||
WLog_SetLogLevel(rdpsnd->log, WLOG_TRACE);
|
||||
|
||||
rdpsnd->channelEntryPoints.pVirtualChannelInit(&rdpsnd->InitHandle,
|
||||
&rdpsnd->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, rdpsnd_virtual_channel_init_event);
|
||||
|
||||
|
@ -868,7 +868,7 @@ BOOL xf_pre_connect(freerdp* instance)
|
||||
xfc->WM_DELETE_WINDOW = XInternAtom(xfc->display, "WM_DELETE_WINDOW", False);
|
||||
xfc->WM_STATE = XInternAtom(xfc->display, "WM_STATE", False);
|
||||
|
||||
xf_kbd_init(xfc);
|
||||
xf_keyboard_init(xfc);
|
||||
|
||||
xfc->clrconv = freerdp_clrconv_new(CLRCONV_ALPHA);
|
||||
|
||||
@ -972,10 +972,10 @@ BOOL xf_post_connect(freerdp* instance)
|
||||
|
||||
ZeroMemory(&gcv, sizeof(gcv));
|
||||
|
||||
if (xfc->modifier_map)
|
||||
XFreeModifiermap(xfc->modifier_map);
|
||||
if (xfc->modifierMap)
|
||||
XFreeModifiermap(xfc->modifierMap);
|
||||
|
||||
xfc->modifier_map = XGetModifierMapping(xfc->display);
|
||||
xfc->modifierMap = XGetModifierMapping(xfc->display);
|
||||
|
||||
xfc->gc = XCreateGC(xfc->display, xfc->drawable, GCGraphicsExposures, &gcv);
|
||||
xfc->primary = XCreatePixmap(xfc->display, xfc->drawable, xfc->width, xfc->height, xfc->depth);
|
||||
@ -1161,11 +1161,7 @@ void xf_window_free(xfContext* xfc)
|
||||
{
|
||||
rdpContext* context = (rdpContext*) xfc;
|
||||
|
||||
if (xfc->modifier_map)
|
||||
{
|
||||
XFreeModifiermap(xfc->modifier_map);
|
||||
xfc->modifier_map = NULL;
|
||||
}
|
||||
xf_keyboard_free(xfc);
|
||||
|
||||
if (xfc->gc)
|
||||
{
|
||||
@ -1515,8 +1511,8 @@ void* xf_thread(void* param)
|
||||
*/
|
||||
if (freerdp_focus_required(instance))
|
||||
{
|
||||
xf_kbd_focus_in(xfc);
|
||||
xf_kbd_focus_in(xfc);
|
||||
xf_keyboard_focus_in(xfc);
|
||||
xf_keyboard_focus_in(xfc);
|
||||
}
|
||||
|
||||
if (!async_transport)
|
||||
|
@ -87,6 +87,99 @@ const char* const X11_EVENT_STRINGS[] =
|
||||
#define DEBUG_X11_LMS(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
int xf_event_action_script_init(xfContext* xfc)
|
||||
{
|
||||
int exitCode;
|
||||
char* xevent;
|
||||
FILE* actionScript;
|
||||
char buffer[1024] = { 0 };
|
||||
char command[1024] = { 0 };
|
||||
|
||||
xfc->xevents = ArrayList_New(TRUE);
|
||||
ArrayList_Object(xfc->xevents)->fnObjectFree = free;
|
||||
|
||||
sprintf_s(command, sizeof(command), "%s xevent", xfc->actionScript);
|
||||
|
||||
actionScript = popen(command, "r");
|
||||
|
||||
if (actionScript < 0)
|
||||
return -1;
|
||||
|
||||
while (fgets(buffer, sizeof(buffer), actionScript) != NULL)
|
||||
{
|
||||
strtok(buffer, "\n");
|
||||
xevent = _strdup(buffer);
|
||||
ArrayList_Add(xfc->xevents, xevent);
|
||||
}
|
||||
|
||||
exitCode = pclose(actionScript);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void xf_event_action_script_free(xfContext* xfc)
|
||||
{
|
||||
if (xfc->xevents)
|
||||
{
|
||||
ArrayList_Free(xfc->xevents);
|
||||
xfc->xevents = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int xf_event_execute_action_script(xfContext* xfc, XEvent* event)
|
||||
{
|
||||
int index;
|
||||
int count;
|
||||
char* name;
|
||||
int exitCode;
|
||||
FILE* actionScript;
|
||||
BOOL match = FALSE;
|
||||
const char* xeventName;
|
||||
char buffer[1024] = { 0 };
|
||||
char command[1024] = { 0 };
|
||||
|
||||
if (!xfc->actionScript)
|
||||
return 1;
|
||||
|
||||
if (event->type > (sizeof(X11_EVENT_STRINGS) / sizeof(const char*)))
|
||||
return 1;
|
||||
|
||||
xeventName = X11_EVENT_STRINGS[event->type];
|
||||
|
||||
count = ArrayList_Count(xfc->xevents);
|
||||
|
||||
for (index = 0; index < count; index++)
|
||||
{
|
||||
name = (char*) ArrayList_GetItem(xfc->xevents, index);
|
||||
|
||||
if (_stricmp(name, xeventName) == 0)
|
||||
{
|
||||
match = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!match)
|
||||
return 1;
|
||||
|
||||
sprintf_s(command, sizeof(command), "%s xevent %s %d",
|
||||
xfc->actionScript, xeventName, (int) xfc->window->handle);
|
||||
|
||||
actionScript = popen(command, "r");
|
||||
|
||||
if (actionScript < 0)
|
||||
return -1;
|
||||
|
||||
while (fgets(buffer, sizeof(buffer), actionScript) != NULL)
|
||||
{
|
||||
strtok(buffer, "\n");
|
||||
}
|
||||
|
||||
exitCode = pclose(actionScript);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static BOOL xf_event_Expose(xfContext* xfc, XEvent* event, BOOL app)
|
||||
{
|
||||
int x, y;
|
||||
@ -395,34 +488,28 @@ static BOOL xf_event_KeyPress(xfContext* xfc, XEvent* event, BOOL app)
|
||||
|
||||
XLookupString((XKeyEvent*) event, str, sizeof(str), &keysym, NULL);
|
||||
|
||||
xf_kbd_set_keypress(xfc, event->xkey.keycode, keysym);
|
||||
|
||||
if (xfc->fullscreen_toggle && xf_kbd_handle_special_keys(xfc, keysym))
|
||||
return TRUE;
|
||||
|
||||
xf_kbd_send_key(xfc, TRUE, event->xkey.keycode);
|
||||
xf_keyboard_key_press(xfc, event->xkey.keycode, keysym);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL xf_event_KeyRelease(xfContext* xfc, XEvent* event, BOOL app)
|
||||
{
|
||||
XEvent next_event;
|
||||
XEvent nextEvent;
|
||||
|
||||
if (XPending(xfc->display))
|
||||
{
|
||||
ZeroMemory(&next_event, sizeof(next_event));
|
||||
XPeekEvent(xfc->display, &next_event);
|
||||
ZeroMemory(&nextEvent, sizeof(nextEvent));
|
||||
XPeekEvent(xfc->display, &nextEvent);
|
||||
|
||||
if (next_event.type == KeyPress)
|
||||
if (nextEvent.type == KeyPress)
|
||||
{
|
||||
if (next_event.xkey.keycode == event->xkey.keycode)
|
||||
if (nextEvent.xkey.keycode == event->xkey.keycode)
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
xf_kbd_unset_keypress(xfc, event->xkey.keycode);
|
||||
xf_kbd_send_key(xfc, FALSE, event->xkey.keycode);
|
||||
xf_keyboard_key_release(xfc, event->xkey.keycode);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -451,7 +538,7 @@ static BOOL xf_event_FocusIn(xfContext* xfc, XEvent* event, BOOL app)
|
||||
xf_rail_adjust_position(xfc, window);
|
||||
}
|
||||
|
||||
xf_kbd_focus_in(xfc);
|
||||
xf_keyboard_focus_in(xfc);
|
||||
|
||||
if (!app)
|
||||
xf_cliprdr_check_owner(xfc);
|
||||
@ -469,7 +556,7 @@ static BOOL xf_event_FocusOut(xfContext* xfc, XEvent* event, BOOL app)
|
||||
if (event->xfocus.mode == NotifyWhileGrabbed)
|
||||
XUngrabKeyboard(xfc->display, CurrentTime);
|
||||
|
||||
xf_kbd_clear(xfc);
|
||||
xf_keyboard_clear(xfc);
|
||||
|
||||
if (app)
|
||||
xf_rail_send_activate(xfc, event->xany.window, FALSE);
|
||||
@ -481,10 +568,10 @@ static BOOL xf_event_MappingNotify(xfContext* xfc, XEvent* event, BOOL app)
|
||||
{
|
||||
if (event->xmapping.request == MappingModifier)
|
||||
{
|
||||
if (xfc->modifier_map)
|
||||
XFreeModifiermap(xfc->modifier_map);
|
||||
if (xfc->modifierMap)
|
||||
XFreeModifiermap(xfc->modifierMap);
|
||||
|
||||
xfc->modifier_map = XGetModifierMapping(xfc->display);
|
||||
xfc->modifierMap = XGetModifierMapping(xfc->display);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
@ -681,7 +768,7 @@ static BOOL xf_event_UnmapNotify(xfContext* xfc, XEvent* event, BOOL app)
|
||||
rdpUpdate* update = xfc->instance->update;
|
||||
rdpRail* rail = ((rdpContext*) xfc)->rail;
|
||||
|
||||
xf_kbd_release_all_keypress(xfc);
|
||||
xf_keyboard_release_all_keypress(xfc);
|
||||
|
||||
if (!app)
|
||||
{
|
||||
@ -941,6 +1028,8 @@ BOOL xf_event_process(freerdp* instance, XEvent* event)
|
||||
}
|
||||
}
|
||||
|
||||
xf_event_execute_action_script(xfc, event);
|
||||
|
||||
if (event->type != MotionNotify)
|
||||
DEBUG_X11("%s Event(%d): wnd=0x%04X", X11_EVENT_STRINGS[event->type], event->type, (UINT32) event->xany.window);
|
||||
|
||||
|
@ -25,6 +25,9 @@
|
||||
#include "xf_client.h"
|
||||
#include "xfreerdp.h"
|
||||
|
||||
int xf_event_action_script_init(xfContext* xfc);
|
||||
void xf_event_action_script_free(xfContext* xfc);
|
||||
|
||||
BOOL xf_event_process(freerdp* instance, XEvent* event);
|
||||
void xf_event_SendClientEvent(xfContext* xfc, xfWindow* window, Atom atom, unsigned int numArgs, ...);
|
||||
|
||||
|
@ -236,7 +236,6 @@ void xf_input_save_last_event(XGenericEventCookie* cookie)
|
||||
lastEvent.detail = event->detail;
|
||||
lastEvent.event_x = event->event_x;
|
||||
lastEvent.event_y = event->event_y;
|
||||
|
||||
}
|
||||
|
||||
void xf_input_detect_pan(xfContext* xfc)
|
||||
@ -269,13 +268,10 @@ void xf_input_detect_pan(xfContext* xfc)
|
||||
|
||||
dist_x = fabs(contacts[0].pos_x - contacts[1].pos_x);
|
||||
dist_y = fabs(contacts[0].pos_y - contacts[1].pos_y);
|
||||
|
||||
|
||||
//only pan in x if dist_y is greater than something
|
||||
if(dist_y > MIN_FINGER_DIST)
|
||||
|
||||
if (dist_y > MIN_FINGER_DIST)
|
||||
{
|
||||
|
||||
if(px_vector > PAN_THRESHOLD)
|
||||
if (px_vector > PAN_THRESHOLD)
|
||||
{
|
||||
|
||||
{
|
||||
@ -293,7 +289,7 @@ void xf_input_detect_pan(xfContext* xfc)
|
||||
py_vector = 0;
|
||||
z_vector = 0;
|
||||
}
|
||||
else if(px_vector < -PAN_THRESHOLD)
|
||||
else if (px_vector < -PAN_THRESHOLD)
|
||||
{
|
||||
{
|
||||
PanningChangeEventArgs e;
|
||||
@ -313,10 +309,10 @@ void xf_input_detect_pan(xfContext* xfc)
|
||||
|
||||
}
|
||||
|
||||
if(dist_x > MIN_FINGER_DIST)
|
||||
if (dist_x > MIN_FINGER_DIST)
|
||||
{
|
||||
|
||||
if(py_vector > PAN_THRESHOLD)
|
||||
if (py_vector > PAN_THRESHOLD)
|
||||
{
|
||||
{
|
||||
PanningChangeEventArgs e;
|
||||
@ -333,7 +329,7 @@ void xf_input_detect_pan(xfContext* xfc)
|
||||
py_vector = 0;
|
||||
z_vector = 0;
|
||||
}
|
||||
else if(py_vector < -PAN_THRESHOLD)
|
||||
else if (py_vector < -PAN_THRESHOLD)
|
||||
{
|
||||
{
|
||||
PanningChangeEventArgs e;
|
||||
@ -351,7 +347,6 @@ void xf_input_detect_pan(xfContext* xfc)
|
||||
z_vector = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void xf_input_detect_pinch(xfContext* xfc)
|
||||
@ -368,7 +363,6 @@ void xf_input_detect_pinch(xfContext* xfc)
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* first calculate the distance */
|
||||
dist = sqrt(pow(contacts[1].pos_x - contacts[0].last_x, 2.0) +
|
||||
pow(contacts[1].pos_y - contacts[0].last_y, 2.0));
|
||||
@ -399,7 +393,6 @@ void xf_input_detect_pinch(xfContext* xfc)
|
||||
|
||||
z_vector += delta;
|
||||
|
||||
|
||||
lastDist = dist;
|
||||
|
||||
if (z_vector > ZOOM_THRESHOLD)
|
||||
@ -451,8 +444,6 @@ void xf_input_detect_pinch(xfContext* xfc)
|
||||
void xf_input_touch_begin(xfContext* xfc, XIDeviceEvent* event)
|
||||
{
|
||||
int i;
|
||||
if(active_contacts == MAX_CONTACTS)
|
||||
printf("Houston, we have a problem!\n\n");
|
||||
|
||||
for (i = 0; i < MAX_CONTACTS; i++)
|
||||
{
|
||||
@ -472,6 +463,7 @@ void xf_input_touch_begin(xfContext* xfc, XIDeviceEvent* event)
|
||||
void xf_input_touch_update(xfContext* xfc, XIDeviceEvent* event)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_CONTACTS; i++)
|
||||
{
|
||||
if (contacts[i].id == event->detail)
|
||||
@ -493,14 +485,13 @@ void xf_input_touch_update(xfContext* xfc, XIDeviceEvent* event)
|
||||
void xf_input_touch_end(xfContext* xfc, XIDeviceEvent* event)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_CONTACTS; i++)
|
||||
{
|
||||
if (contacts[i].id == event->detail)
|
||||
{
|
||||
contacts[i].id = 0;
|
||||
contacts[i].count = 0;
|
||||
//contacts[i].pos_x = (int)event->event_x;
|
||||
//contacts[i].pos_y = (int)event->event_y;
|
||||
|
||||
active_contacts--;
|
||||
break;printf("TouchBegin\n");
|
||||
@ -733,15 +724,15 @@ void xf_process_rdpei_event(xfContext* xfc, wMessage* event)
|
||||
int xf_input_handle_event(xfContext* xfc, XEvent* event)
|
||||
{
|
||||
#ifdef WITH_XI
|
||||
//printf("m:%d g:%d\n", (xfc->settings->MultiTouchInput), (xfc->settings->MultiTouchGestures) );
|
||||
if (xfc->settings->MultiTouchInput)
|
||||
{
|
||||
return xf_input_handle_event_remote(xfc, event);
|
||||
}
|
||||
|
||||
if (xfc->settings->MultiTouchGestures)
|
||||
{
|
||||
return xf_input_handle_event_local(xfc, event);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
@ -26,6 +26,8 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/path.h>
|
||||
#include <winpr/collections.h>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
@ -33,66 +35,153 @@
|
||||
|
||||
#include <freerdp/locale/keyboard.h>
|
||||
|
||||
#include "xf_event.h"
|
||||
|
||||
#include "xf_keyboard.h"
|
||||
|
||||
void xf_kbd_init(xfContext* xfc)
|
||||
int xf_keyboard_action_script_init(xfContext* xfc)
|
||||
{
|
||||
xf_kbd_clear(xfc);
|
||||
int exitCode;
|
||||
FILE* keyScript;
|
||||
char* keyCombination;
|
||||
char buffer[1024] = { 0 };
|
||||
char command[1024] = { 0 };
|
||||
|
||||
xfc->keyboard_layout_id = xfc->instance->settings->KeyboardLayout;
|
||||
xfc->keyboard_layout_id = freerdp_keyboard_init(xfc->keyboard_layout_id);
|
||||
xfc->instance->settings->KeyboardLayout = xfc->keyboard_layout_id;
|
||||
if (xfc->actionScript)
|
||||
{
|
||||
free(xfc->actionScript);
|
||||
xfc->actionScript = NULL;
|
||||
}
|
||||
|
||||
if (xfc->modifier_map)
|
||||
XFreeModifiermap(xfc->modifier_map);
|
||||
if (PathFileExistsA("/usr/share/freerdp/action.sh"))
|
||||
xfc->actionScript = _strdup("/usr/share/freerdp/action.sh");
|
||||
|
||||
xfc->modifier_map = XGetModifierMapping(xfc->display);
|
||||
if (!xfc->actionScript)
|
||||
return 0;
|
||||
|
||||
xfc->keyCombinations = ArrayList_New(TRUE);
|
||||
ArrayList_Object(xfc->keyCombinations)->fnObjectFree = free;
|
||||
|
||||
sprintf_s(command, sizeof(command), "%s key", xfc->actionScript);
|
||||
|
||||
keyScript = popen(command, "r");
|
||||
|
||||
if (keyScript < 0)
|
||||
{
|
||||
free(xfc->actionScript);
|
||||
xfc->actionScript = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (fgets(buffer, sizeof(buffer), keyScript) != NULL)
|
||||
{
|
||||
strtok(buffer, "\n");
|
||||
keyCombination = _strdup(buffer);
|
||||
ArrayList_Add(xfc->keyCombinations, keyCombination);
|
||||
}
|
||||
|
||||
exitCode = pclose(keyScript);
|
||||
|
||||
xf_event_action_script_init(xfc);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void xf_kbd_clear(xfContext* xfc)
|
||||
void xf_keyboard_action_script_free(xfContext* xfc)
|
||||
{
|
||||
ZeroMemory(xfc->pressed_keys, 256 * sizeof(BOOL));
|
||||
xf_event_action_script_free(xfc);
|
||||
|
||||
if (xfc->keyCombinations)
|
||||
{
|
||||
ArrayList_Free(xfc->keyCombinations);
|
||||
xfc->keyCombinations = NULL;
|
||||
}
|
||||
|
||||
if (xfc->actionScript)
|
||||
{
|
||||
free(xfc->actionScript);
|
||||
xfc->actionScript = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void xf_kbd_set_keypress(xfContext* xfc, BYTE keycode, KeySym keysym)
|
||||
void xf_keyboard_init(xfContext* xfc)
|
||||
{
|
||||
if (keycode >= 8)
|
||||
xfc->pressed_keys[keycode] = keysym;
|
||||
else
|
||||
xf_keyboard_clear(xfc);
|
||||
|
||||
xfc->KeyboardLayout = xfc->instance->settings->KeyboardLayout;
|
||||
xfc->KeyboardLayout = freerdp_keyboard_init(xfc->KeyboardLayout);
|
||||
xfc->instance->settings->KeyboardLayout = xfc->KeyboardLayout;
|
||||
|
||||
if (xfc->modifierMap)
|
||||
XFreeModifiermap(xfc->modifierMap);
|
||||
|
||||
xfc->modifierMap = XGetModifierMapping(xfc->display);
|
||||
|
||||
xf_keyboard_action_script_init(xfc);
|
||||
}
|
||||
|
||||
void xf_keyboard_free(xfContext* xfc)
|
||||
{
|
||||
if (xfc->modifierMap)
|
||||
{
|
||||
XFreeModifiermap(xfc->modifierMap);
|
||||
xfc->modifierMap = NULL;
|
||||
}
|
||||
|
||||
xf_keyboard_action_script_free(xfc);
|
||||
}
|
||||
|
||||
void xf_keyboard_clear(xfContext* xfc)
|
||||
{
|
||||
ZeroMemory(xfc->KeyboardState, 256 * sizeof(BOOL));
|
||||
}
|
||||
|
||||
void xf_keyboard_key_press(xfContext* xfc, BYTE keycode, KeySym keysym)
|
||||
{
|
||||
if (keycode < 8)
|
||||
return;
|
||||
}
|
||||
|
||||
void xf_kbd_unset_keypress(xfContext* xfc, BYTE keycode)
|
||||
{
|
||||
if (keycode >= 8)
|
||||
xfc->pressed_keys[keycode] = NoSymbol;
|
||||
else
|
||||
xfc->KeyboardState[keycode] = keysym;
|
||||
|
||||
if (xf_keyboard_handle_special_keys(xfc, keysym))
|
||||
return;
|
||||
|
||||
xf_keyboard_send_key(xfc, TRUE, keycode);
|
||||
}
|
||||
|
||||
void xf_kbd_release_all_keypress(xfContext* xfc)
|
||||
void xf_keyboard_key_release(xfContext* xfc, BYTE keycode)
|
||||
{
|
||||
if (keycode < 8)
|
||||
return;
|
||||
|
||||
xfc->KeyboardState[keycode] = NoSymbol;
|
||||
|
||||
xf_keyboard_send_key(xfc, FALSE, keycode);
|
||||
}
|
||||
|
||||
void xf_keyboard_release_all_keypress(xfContext* xfc)
|
||||
{
|
||||
int keycode;
|
||||
DWORD rdp_scancode;
|
||||
|
||||
for (keycode = 0; keycode < ARRAYSIZE(xfc->pressed_keys); keycode++)
|
||||
for (keycode = 0; keycode < ARRAYSIZE(xfc->KeyboardState); keycode++)
|
||||
{
|
||||
if (xfc->pressed_keys[keycode] != NoSymbol)
|
||||
if (xfc->KeyboardState[keycode] != NoSymbol)
|
||||
{
|
||||
rdp_scancode = freerdp_keyboard_get_rdp_scancode_from_x11_keycode(keycode);
|
||||
freerdp_input_send_keyboard_event_ex(xfc->instance->input, FALSE, rdp_scancode);
|
||||
xfc->pressed_keys[keycode] = NoSymbol;
|
||||
xfc->KeyboardState[keycode] = NoSymbol;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOL xf_kbd_key_pressed(xfContext* xfc, KeySym keysym)
|
||||
BOOL xf_keyboard_key_pressed(xfContext* xfc, KeySym keysym)
|
||||
{
|
||||
KeyCode keycode = XKeysymToKeycode(xfc->display, keysym);
|
||||
return (xfc->pressed_keys[keycode] == keysym);
|
||||
return (xfc->KeyboardState[keycode] == keysym);
|
||||
}
|
||||
|
||||
void xf_kbd_send_key(xfContext* xfc, BOOL down, BYTE keycode)
|
||||
void xf_keyboard_send_key(xfContext* xfc, BOOL down, BYTE keycode)
|
||||
{
|
||||
DWORD rdp_scancode;
|
||||
rdpInput* input;
|
||||
@ -105,7 +194,7 @@ void xf_kbd_send_key(xfContext* xfc, BOOL down, BYTE keycode)
|
||||
fprintf(stderr, "Unknown key with X keycode 0x%02x\n", keycode);
|
||||
}
|
||||
else if (rdp_scancode == RDP_SCANCODE_PAUSE &&
|
||||
!xf_kbd_key_pressed(xfc, XK_Control_L) && !xf_kbd_key_pressed(xfc, XK_Control_R))
|
||||
!xf_keyboard_key_pressed(xfc, XK_Control_L) && !xf_keyboard_key_pressed(xfc, XK_Control_R))
|
||||
{
|
||||
/* Pause without Ctrl has to be sent as Ctrl + NumLock. */
|
||||
if (down)
|
||||
@ -123,13 +212,13 @@ void xf_kbd_send_key(xfContext* xfc, BOOL down, BYTE keycode)
|
||||
if ((rdp_scancode == RDP_SCANCODE_CAPSLOCK) && (down == FALSE))
|
||||
{
|
||||
UINT32 syncFlags;
|
||||
syncFlags = xf_kbd_get_toggle_keys_state(xfc);
|
||||
syncFlags = xf_keyboard_get_toggle_keys_state(xfc);
|
||||
input->SynchronizeEvent(input, syncFlags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int xf_kbd_read_keyboard_state(xfContext* xfc)
|
||||
int xf_keyboard_read_keyboard_state(xfContext* xfc)
|
||||
{
|
||||
int dummy;
|
||||
Window wdummy;
|
||||
@ -145,10 +234,11 @@ int xf_kbd_read_keyboard_state(xfContext* xfc)
|
||||
XQueryPointer(xfc->display, DefaultRootWindow(xfc->display),
|
||||
&wdummy, &wdummy, &dummy, &dummy, &dummy, &dummy, &state);
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
BOOL xf_kbd_get_key_state(xfContext* xfc, int state, int keysym)
|
||||
BOOL xf_keyboard_get_key_state(xfContext* xfc, int state, int keysym)
|
||||
{
|
||||
int offset;
|
||||
int modifierpos, key, keysymMask = 0;
|
||||
@ -159,11 +249,11 @@ BOOL xf_kbd_get_key_state(xfContext* xfc, int state, int keysym)
|
||||
|
||||
for (modifierpos = 0; modifierpos < 8; modifierpos++)
|
||||
{
|
||||
offset = xfc->modifier_map->max_keypermod * modifierpos;
|
||||
offset = xfc->modifierMap->max_keypermod * modifierpos;
|
||||
|
||||
for (key = 0; key < xfc->modifier_map->max_keypermod; key++)
|
||||
for (key = 0; key < xfc->modifierMap->max_keypermod; key++)
|
||||
{
|
||||
if (xfc->modifier_map->modifiermap[offset + key] == keycode)
|
||||
if (xfc->modifierMap->modifiermap[offset + key] == keycode)
|
||||
{
|
||||
keysymMask |= 1 << modifierpos;
|
||||
}
|
||||
@ -173,26 +263,26 @@ BOOL xf_kbd_get_key_state(xfContext* xfc, int state, int keysym)
|
||||
return (state & keysymMask) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
int xf_kbd_get_toggle_keys_state(xfContext* xfc)
|
||||
UINT32 xf_keyboard_get_toggle_keys_state(xfContext* xfc)
|
||||
{
|
||||
int state;
|
||||
int toggle_keys_state = 0;
|
||||
UINT32 toggleKeysState = 0;
|
||||
|
||||
state = xf_kbd_read_keyboard_state(xfc);
|
||||
state = xf_keyboard_read_keyboard_state(xfc);
|
||||
|
||||
if (xf_kbd_get_key_state(xfc, state, XK_Scroll_Lock))
|
||||
toggle_keys_state |= KBD_SYNC_SCROLL_LOCK;
|
||||
if (xf_kbd_get_key_state(xfc, state, XK_Num_Lock))
|
||||
toggle_keys_state |= KBD_SYNC_NUM_LOCK;
|
||||
if (xf_kbd_get_key_state(xfc, state, XK_Caps_Lock))
|
||||
toggle_keys_state |= KBD_SYNC_CAPS_LOCK;
|
||||
if (xf_kbd_get_key_state(xfc, state, XK_Kana_Lock))
|
||||
toggle_keys_state |= KBD_SYNC_KANA_LOCK;
|
||||
if (xf_keyboard_get_key_state(xfc, state, XK_Scroll_Lock))
|
||||
toggleKeysState |= KBD_SYNC_SCROLL_LOCK;
|
||||
if (xf_keyboard_get_key_state(xfc, state, XK_Num_Lock))
|
||||
toggleKeysState |= KBD_SYNC_NUM_LOCK;
|
||||
if (xf_keyboard_get_key_state(xfc, state, XK_Caps_Lock))
|
||||
toggleKeysState |= KBD_SYNC_CAPS_LOCK;
|
||||
if (xf_keyboard_get_key_state(xfc, state, XK_Kana_Lock))
|
||||
toggleKeysState |= KBD_SYNC_KANA_LOCK;
|
||||
|
||||
return toggle_keys_state;
|
||||
return toggleKeysState;
|
||||
}
|
||||
|
||||
void xf_kbd_focus_in(xfContext* xfc)
|
||||
void xf_keyboard_focus_in(xfContext* xfc)
|
||||
{
|
||||
rdpInput* input;
|
||||
UINT32 syncFlags;
|
||||
@ -200,39 +290,141 @@ void xf_kbd_focus_in(xfContext* xfc)
|
||||
Window wdummy;
|
||||
UINT32 state = 0;
|
||||
|
||||
if (xfc->display && xfc->window)
|
||||
{
|
||||
input = xfc->instance->input;
|
||||
syncFlags = xf_kbd_get_toggle_keys_state(xfc);
|
||||
XQueryPointer(xfc->display, xfc->window->handle, &wdummy, &wdummy, &mouseX, &mouseY, &dummy, &dummy, &state);
|
||||
input->FocusInEvent(input, syncFlags, mouseX, mouseY);
|
||||
if (xfc->display && xfc->window)
|
||||
{
|
||||
input = xfc->instance->input;
|
||||
syncFlags = xf_keyboard_get_toggle_keys_state(xfc);
|
||||
XQueryPointer(xfc->display, xfc->window->handle, &wdummy, &wdummy, &mouseX, &mouseY, &dummy, &dummy, &state);
|
||||
input->FocusInEvent(input, syncFlags, mouseX, mouseY);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL xf_kbd_handle_special_keys(xfContext* xfc, KeySym keysym)
|
||||
int xf_keyboard_execute_action_script(xfContext* xfc, XF_MODIFIER_KEYS* mod, KeySym keysym)
|
||||
{
|
||||
int index;
|
||||
int count;
|
||||
int exitCode;
|
||||
int status = 1;
|
||||
FILE* keyScript;
|
||||
const char* keyStr;
|
||||
BOOL match = FALSE;
|
||||
char* keyCombination;
|
||||
char buffer[1024] = { 0 };
|
||||
char command[1024] = { 0 };
|
||||
char combination[1024] = { 0 };
|
||||
|
||||
if (!xfc->actionScript)
|
||||
return 1;
|
||||
|
||||
if ((keysym == XK_Shift_L) || (keysym == XK_Shift_R) ||
|
||||
(keysym == XK_Alt_L) || (keysym == XK_Alt_R) ||
|
||||
(keysym == XK_Control_L) || (keysym == XK_Control_R))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
keyStr = XKeysymToString(keysym);
|
||||
|
||||
if (mod->Shift)
|
||||
strcat(combination, "Shift+");
|
||||
|
||||
if (mod->Ctrl)
|
||||
strcat(combination, "Ctrl+");
|
||||
|
||||
if (mod->Alt)
|
||||
strcat(combination, "Alt+");
|
||||
|
||||
strcat(combination, keyStr);
|
||||
|
||||
count = ArrayList_Count(xfc->keyCombinations);
|
||||
|
||||
for (index = 0; index < count; index++)
|
||||
{
|
||||
keyCombination = (char*) ArrayList_GetItem(xfc->keyCombinations, index);
|
||||
|
||||
if (_stricmp(keyCombination, combination) == 0)
|
||||
{
|
||||
match = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!match)
|
||||
return 1;
|
||||
|
||||
sprintf_s(command, sizeof(command), "%s key %s",
|
||||
xfc->actionScript, combination);
|
||||
|
||||
keyScript = popen(command, "r");
|
||||
|
||||
if (keyScript < 0)
|
||||
return -1;
|
||||
|
||||
while (fgets(buffer, sizeof(buffer), keyScript) != NULL)
|
||||
{
|
||||
strtok(buffer, "\n");
|
||||
|
||||
if (strcmp(buffer, "key-local") == 0)
|
||||
status = 0;
|
||||
}
|
||||
|
||||
exitCode = pclose(keyScript);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int xk_keyboard_get_modifier_keys(xfContext* xfc, XF_MODIFIER_KEYS* mod)
|
||||
{
|
||||
mod->LeftShift = xf_keyboard_key_pressed(xfc, XK_Shift_L);
|
||||
mod->RightShift = xf_keyboard_key_pressed(xfc, XK_Shift_R);
|
||||
mod->Shift = mod->LeftShift || mod->RightShift;
|
||||
|
||||
mod->LeftAlt = xf_keyboard_key_pressed(xfc, XK_Alt_L);
|
||||
mod->RightAlt = xf_keyboard_key_pressed(xfc, XK_Alt_R);
|
||||
mod->Alt = mod->LeftAlt || mod->RightAlt;
|
||||
|
||||
mod->LeftCtrl = xf_keyboard_key_pressed(xfc, XK_Control_L);
|
||||
mod->RightCtrl = xf_keyboard_key_pressed(xfc, XK_Control_R);
|
||||
mod->Ctrl = mod->LeftCtrl || mod->RightCtrl;
|
||||
|
||||
mod->LeftSuper = xf_keyboard_key_pressed(xfc, XK_Super_L);
|
||||
mod->RightSuper = xf_keyboard_key_pressed(xfc, XK_Super_R);
|
||||
mod->Super = mod->LeftSuper || mod->RightSuper;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL xf_keyboard_handle_special_keys(xfContext* xfc, KeySym keysym)
|
||||
{
|
||||
XF_MODIFIER_KEYS mod = { 0 };
|
||||
|
||||
xk_keyboard_get_modifier_keys(xfc, &mod);
|
||||
|
||||
if (!xf_keyboard_execute_action_script(xfc, &mod, keysym))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (keysym == XK_Return)
|
||||
{
|
||||
if ((xf_kbd_key_pressed(xfc, XK_Alt_L) || xf_kbd_key_pressed(xfc, XK_Alt_R))
|
||||
&& (xf_kbd_key_pressed(xfc, XK_Control_L) || xf_kbd_key_pressed(xfc, XK_Control_R)))
|
||||
if (mod.Ctrl && mod.Alt)
|
||||
{
|
||||
/* Ctrl-Alt-Enter: toggle full screen */
|
||||
xf_toggle_fullscreen(xfc);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (keysym == XK_period)
|
||||
{
|
||||
if ((xf_kbd_key_pressed(xfc, XK_Alt_L)
|
||||
|| xf_kbd_key_pressed(xfc, XK_Alt_R))
|
||||
&& (xf_kbd_key_pressed(xfc, XK_Control_L)
|
||||
|| xf_kbd_key_pressed(xfc,
|
||||
XK_Control_R)))
|
||||
if (mod.Ctrl && mod.Alt)
|
||||
{
|
||||
//Zoom in (scale larger)
|
||||
/* Zoom In (scale larger) */
|
||||
|
||||
double s = xfc->settings->ScalingFactor;
|
||||
|
||||
s += 0.1;
|
||||
|
||||
if (s > 2.0)
|
||||
s = 2.0;
|
||||
|
||||
@ -258,15 +450,14 @@ BOOL xf_kbd_handle_special_keys(xfContext* xfc, KeySym keysym)
|
||||
|
||||
if (keysym == XK_comma)
|
||||
{
|
||||
if ((xf_kbd_key_pressed(xfc, XK_Alt_L)
|
||||
|| xf_kbd_key_pressed(xfc, XK_Alt_R))
|
||||
&& (xf_kbd_key_pressed(xfc, XK_Control_L)
|
||||
|| xf_kbd_key_pressed(xfc,
|
||||
XK_Control_R)))
|
||||
if (mod.Ctrl && mod.Alt)
|
||||
{
|
||||
//Zoom out (scale smaller)
|
||||
/* Zoom Out (scale smaller) */
|
||||
|
||||
double s = xfc->settings->ScalingFactor;
|
||||
|
||||
s -= 0.1;
|
||||
|
||||
if (s < 0.5)
|
||||
s = 0.5;
|
||||
|
||||
@ -293,11 +484,7 @@ BOOL xf_kbd_handle_special_keys(xfContext* xfc, KeySym keysym)
|
||||
|
||||
if (keysym == XK_KP_4)
|
||||
{
|
||||
if ((xf_kbd_key_pressed(xfc, XK_Alt_L)
|
||||
|| xf_kbd_key_pressed(xfc, XK_Alt_R))
|
||||
&& (xf_kbd_key_pressed(xfc, XK_Control_L)
|
||||
|| xf_kbd_key_pressed(xfc,
|
||||
XK_Control_R)))
|
||||
if (mod.Ctrl && mod.Alt)
|
||||
{
|
||||
|
||||
{
|
||||
@ -315,11 +502,7 @@ BOOL xf_kbd_handle_special_keys(xfContext* xfc, KeySym keysym)
|
||||
|
||||
if (keysym == XK_KP_6)
|
||||
{
|
||||
if ((xf_kbd_key_pressed(xfc, XK_Alt_L)
|
||||
|| xf_kbd_key_pressed(xfc, XK_Alt_R))
|
||||
&& (xf_kbd_key_pressed(xfc, XK_Control_L)
|
||||
|| xf_kbd_key_pressed(xfc,
|
||||
XK_Control_R)))
|
||||
if (mod.Ctrl && mod.Alt)
|
||||
{
|
||||
|
||||
{
|
||||
@ -336,11 +519,7 @@ BOOL xf_kbd_handle_special_keys(xfContext* xfc, KeySym keysym)
|
||||
|
||||
if (keysym == XK_KP_8)
|
||||
{
|
||||
if ((xf_kbd_key_pressed(xfc, XK_Alt_L)
|
||||
|| xf_kbd_key_pressed(xfc, XK_Alt_R))
|
||||
&& (xf_kbd_key_pressed(xfc, XK_Control_L)
|
||||
|| xf_kbd_key_pressed(xfc,
|
||||
XK_Control_R)))
|
||||
if (mod.Ctrl && mod.Alt)
|
||||
{
|
||||
{
|
||||
PanningChangeEventArgs e;
|
||||
@ -356,11 +535,7 @@ BOOL xf_kbd_handle_special_keys(xfContext* xfc, KeySym keysym)
|
||||
|
||||
if (keysym == XK_KP_2)
|
||||
{
|
||||
if ((xf_kbd_key_pressed(xfc, XK_Alt_L)
|
||||
|| xf_kbd_key_pressed(xfc, XK_Alt_R))
|
||||
&& (xf_kbd_key_pressed(xfc, XK_Control_L)
|
||||
|| xf_kbd_key_pressed(xfc,
|
||||
XK_Control_R)))
|
||||
if (mod.Ctrl && mod.Alt)
|
||||
{
|
||||
{
|
||||
PanningChangeEventArgs e;
|
||||
@ -374,7 +549,6 @@ BOOL xf_kbd_handle_special_keys(xfContext* xfc, KeySym keysym)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -25,17 +25,37 @@
|
||||
#include "xf_client.h"
|
||||
#include "xfreerdp.h"
|
||||
|
||||
void xf_kbd_init(xfContext* xfc);
|
||||
void xf_kbd_clear(xfContext* xfc);
|
||||
void xf_kbd_set_keypress(xfContext* xfc, BYTE keycode, KeySym keysym);
|
||||
void xf_kbd_unset_keypress(xfContext* xfc, BYTE keycode);
|
||||
void xf_kbd_release_all_keypress(xfContext* xfc);
|
||||
BOOL xf_kbd_key_pressed(xfContext* xfc, KeySym keysym);
|
||||
void xf_kbd_send_key(xfContext* xfc, BOOL down, BYTE keycode);
|
||||
int xf_kbd_read_keyboard_state(xfContext* xfc);
|
||||
BOOL xf_kbd_get_key_state(xfContext* xfc, int state, int keysym);
|
||||
int xf_kbd_get_toggle_keys_state(xfContext* xfc);
|
||||
void xf_kbd_focus_in(xfContext* xfc);
|
||||
BOOL xf_kbd_handle_special_keys(xfContext* xfc, KeySym keysym);
|
||||
#define XF_ACTION_SCRIPT "~/.config/freerdp/action.sh"
|
||||
|
||||
struct _XF_MODIFIER_KEYS
|
||||
{
|
||||
BOOL Shift;
|
||||
BOOL LeftShift;
|
||||
BOOL RightShift;
|
||||
BOOL Alt;
|
||||
BOOL LeftAlt;
|
||||
BOOL RightAlt;
|
||||
BOOL Ctrl;
|
||||
BOOL LeftCtrl;
|
||||
BOOL RightCtrl;
|
||||
BOOL Super;
|
||||
BOOL LeftSuper;
|
||||
BOOL RightSuper;
|
||||
};
|
||||
typedef struct _XF_MODIFIER_KEYS XF_MODIFIER_KEYS;
|
||||
|
||||
void xf_keyboard_init(xfContext* xfc);
|
||||
void xf_keyboard_free(xfContext* xfc);
|
||||
void xf_keyboard_clear(xfContext* xfc);
|
||||
void xf_keyboard_key_press(xfContext* xfc, BYTE keycode, KeySym keysym);
|
||||
void xf_keyboard_key_release(xfContext* xfc, BYTE keycode);
|
||||
void xf_keyboard_release_all_keypress(xfContext* xfc);
|
||||
BOOL xf_keyboard_key_pressed(xfContext* xfc, KeySym keysym);
|
||||
void xf_keyboard_send_key(xfContext* xfc, BOOL down, BYTE keycode);
|
||||
int xf_keyboard_read_keyboard_state(xfContext* xfc);
|
||||
BOOL xf_keyboard_get_key_state(xfContext* xfc, int state, int keysym);
|
||||
UINT32 xf_keyboard_get_toggle_keys_state(xfContext* xfc);
|
||||
void xf_keyboard_focus_in(xfContext* xfc);
|
||||
BOOL xf_keyboard_handle_special_keys(xfContext* xfc, KeySym keysym);
|
||||
|
||||
#endif /* __XF_KEYBOARD_H */
|
||||
|
@ -125,9 +125,13 @@ struct xf_context
|
||||
BOOL mouse_active;
|
||||
BOOL suppress_output;
|
||||
BOOL fullscreen_toggle;
|
||||
UINT32 keyboard_layout_id;
|
||||
BOOL pressed_keys[256];
|
||||
XModifierKeymap* modifier_map;
|
||||
UINT32 KeyboardLayout;
|
||||
BOOL KeyboardState[256];
|
||||
XModifierKeymap* modifierMap;
|
||||
wArrayList* keyCombinations;
|
||||
wArrayList* xevents;
|
||||
char* actionScript;
|
||||
|
||||
XSetWindowAttributes attribs;
|
||||
BOOL complex_regions;
|
||||
VIRTUAL_SCREEN vscreen;
|
||||
|
@ -56,6 +56,7 @@ COMMAND_LINE_ARGUMENT_A args[] =
|
||||
{ "pth", COMMAND_LINE_VALUE_REQUIRED, "<password hash>", NULL, NULL, -1, "pass-the-hash", "Pass the hash (restricted admin mode)" },
|
||||
{ "client-hostname", COMMAND_LINE_VALUE_REQUIRED, "<name>", NULL, NULL, -1, NULL, "Client Hostname to send to server" },
|
||||
{ "multimon", COMMAND_LINE_VALUE_OPTIONAL, NULL, NULL, NULL, -1, NULL, "Use multiple monitors" },
|
||||
{ "span", COMMAND_LINE_VALUE_OPTIONAL, NULL, NULL, NULL, -1, NULL, "Span screen over multiple monitors" },
|
||||
{ "workarea", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Use available work area" },
|
||||
{ "monitors", COMMAND_LINE_VALUE_REQUIRED, "<0,1,2...>", NULL, NULL, -1, NULL, "Select monitors to use" },
|
||||
{ "monitor-list", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT, NULL, NULL, NULL, -1, NULL, "List detected monitors" },
|
||||
@ -1188,13 +1189,10 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
|
||||
{
|
||||
settings->Fullscreen = TRUE;
|
||||
}
|
||||
CommandLineSwitchCase(arg, "span")
|
||||
{
|
||||
settings->SpanMonitors = TRUE;
|
||||
}
|
||||
CommandLineSwitchCase(arg, "multimon")
|
||||
{
|
||||
settings->UseMultimon = TRUE;
|
||||
settings->SpanMonitors = FALSE;
|
||||
settings->Fullscreen = TRUE;
|
||||
|
||||
if (arg->Flags & COMMAND_LINE_VALUE_PRESENT)
|
||||
@ -1205,6 +1203,12 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
|
||||
}
|
||||
}
|
||||
}
|
||||
CommandLineSwitchCase(arg, "span")
|
||||
{
|
||||
settings->UseMultimon = TRUE;
|
||||
settings->SpanMonitors = TRUE;
|
||||
settings->Fullscreen = TRUE;
|
||||
}
|
||||
CommandLineSwitchCase(arg, "workarea")
|
||||
{
|
||||
settings->Workarea = TRUE;
|
||||
@ -1345,9 +1349,11 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
|
||||
settings->GatewayHostname = _strdup(settings->ServerHostname);
|
||||
}
|
||||
|
||||
settings->GatewayUsageMethod = TSC_PROXY_MODE_DIRECT;
|
||||
settings->GatewayUseSameCredentials = TRUE;
|
||||
|
||||
settings->GatewayUsageMethod = TSC_PROXY_MODE_DETECT;
|
||||
settings->GatewayEnabled = TRUE;
|
||||
settings->GatewayBypassLocal = TRUE;
|
||||
}
|
||||
CommandLineSwitchCase(arg, "gu")
|
||||
{
|
||||
|
@ -866,14 +866,36 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings*
|
||||
{
|
||||
freerdp_set_param_uint32(settings, FreeRDP_GatewayUsageMethod, file->GatewayUsageMethod);
|
||||
|
||||
if (file->GatewayUsageMethod == TSC_PROXY_MODE_DIRECT)
|
||||
freerdp_set_param_bool(settings, FreeRDP_GatewayEnabled, TRUE);
|
||||
else if (file->GatewayUsageMethod == TSC_PROXY_MODE_DETECT)
|
||||
freerdp_set_param_bool(settings, FreeRDP_GatewayEnabled, TRUE);
|
||||
else if (file->GatewayUsageMethod == TSC_PROXY_MODE_DEFAULT)
|
||||
freerdp_set_param_bool(settings, FreeRDP_GatewayEnabled, TRUE);
|
||||
else if (file->GatewayUsageMethod == TSC_PROXY_MODE_NONE_DETECT)
|
||||
if (file->GatewayUsageMethod == TSC_PROXY_MODE_NONE_DIRECT)
|
||||
{
|
||||
freerdp_set_param_bool(settings, FreeRDP_GatewayEnabled, FALSE);
|
||||
freerdp_set_param_bool(settings, FreeRDP_GatewayBypassLocal, FALSE);
|
||||
}
|
||||
else if (file->GatewayUsageMethod == TSC_PROXY_MODE_DIRECT)
|
||||
{
|
||||
freerdp_set_param_bool(settings, FreeRDP_GatewayEnabled, TRUE);
|
||||
freerdp_set_param_bool(settings, FreeRDP_GatewayBypassLocal, FALSE);
|
||||
}
|
||||
else if (file->GatewayUsageMethod == TSC_PROXY_MODE_DETECT)
|
||||
{
|
||||
freerdp_set_param_bool(settings, FreeRDP_GatewayEnabled, TRUE);
|
||||
freerdp_set_param_bool(settings, FreeRDP_GatewayBypassLocal, TRUE);
|
||||
}
|
||||
else if (file->GatewayUsageMethod == TSC_PROXY_MODE_DEFAULT)
|
||||
{
|
||||
/**
|
||||
* This corresponds to "Automatically detect RD Gateway server settings",
|
||||
* which means the client attempts to use gateway group policy settings
|
||||
* http://technet.microsoft.com/en-us/library/cc770601.aspx
|
||||
*/
|
||||
freerdp_set_param_bool(settings, FreeRDP_GatewayEnabled, FALSE);
|
||||
freerdp_set_param_bool(settings, FreeRDP_GatewayBypassLocal, FALSE);
|
||||
}
|
||||
else if (file->GatewayUsageMethod == TSC_PROXY_MODE_NONE_DETECT)
|
||||
{
|
||||
freerdp_set_param_bool(settings, FreeRDP_GatewayEnabled, FALSE);
|
||||
freerdp_set_param_bool(settings, FreeRDP_GatewayBypassLocal, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
if (~file->PromptCredentialOnce)
|
||||
|
@ -176,6 +176,60 @@ FREERDP_API extern int connectErrorCode;
|
||||
#define INSUFFICIENTPRIVILEGESERROR ERRORSTART + 10
|
||||
#define CANCELEDBYUSER ERRORSTART + 11
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* FreeRDP Context Error Codes
|
||||
*/
|
||||
|
||||
#define MAKE_FREERDP_ERROR(_class, _type) \
|
||||
(((FREERDP_ERROR_ ## _class ## _CLASS) << 16) | (_type))
|
||||
|
||||
#define GET_FREERDP_ERROR_CLASS(_errorCode) \
|
||||
((_errorCode >> 16) & 0xFFFF)
|
||||
|
||||
#define GET_FREERDP_ERROR_TYPE(_errorCode) \
|
||||
(_errorCode & 0xFFFF)
|
||||
|
||||
#define GET_FREERDP_ERROR_SUBCODE
|
||||
|
||||
#define FREERDP_ERROR_BASE 0
|
||||
|
||||
#define FREERDP_ERROR_SUCCESS ERRINFO_SUCCESS
|
||||
#define FREERDP_ERROR_NONE ERRINFO_NONE
|
||||
|
||||
/* Error Info Codes */
|
||||
|
||||
#define FREERDP_ERROR_ERRINFO_CLASS (FREERDP_ERROR_BASE + 1)
|
||||
|
||||
#define FREERDP_ERROR_RPC_INITIATED_DISCONNECT MAKE_FREERDP_ERROR(ERRINFO, ERRINFO_RPC_INITIATED_DISCONNECT)
|
||||
#define FREERDP_ERROR_RPC_INITIATED_LOGOFF MAKE_FREERDP_ERROR(ERRINFO, ERRINFO_RPC_INITIATED_LOGOFF)
|
||||
#define FREERDP_ERROR_IDLE_TIMEOUT MAKE_FREERDP_ERROR(ERRINFO, ERRINFO_IDLE_TIMEOUT)
|
||||
#define FREERDP_ERROR_LOGON_TIMEOUT MAKE_FREERDP_ERROR(ERRINFO, ERRINFO_LOGON_TIMEOUT)
|
||||
#define FREERDP_ERROR_DISCONNECTED_BY_OTHER_CONNECTION MAKE_FREERDP_ERROR(ERRINFO, ERRINFO_DISCONNECTED_BY_OTHER_CONNECTION)
|
||||
#define FREERDP_ERROR_OUT_OF_MEMORY MAKE_FREERDP_ERROR(ERRINFO, ERRINFO_OUT_OF_MEMORY)
|
||||
#define FREERDP_ERROR_SERVER_DENIED_CONNECTION MAKE_FREERDP_ERROR(ERRINFO, ERRINFO_SERVER_DENIED_CONNECTION)
|
||||
#define FREERDP_ERROR_SERVER_INSUFFICIENT_PRIVILEGES MAKE_FREERDP_ERROR(ERRINFO, ERRINFO_SERVER_INSUFFICIENT_PRIVILEGES)
|
||||
#define FREERDP_ERROR_SERVER_FRESH_CREDENTIALS_REQUIRED MAKE_FREERDP_ERROR(ERRINFO, ERRINFO_SERVER_FRESH_CREDENTIALS_REQUIRED)
|
||||
#define FREERDP_ERROR_RPC_INITIATED_DISCONNECT_BY_USER MAKE_FREERDP_ERROR(ERRINFO, ERRINFO_RPC_INITIATED_DISCONNECT_BY_USER)
|
||||
#define FREERDP_ERROR_LOGOFF_BY_USER MAKE_FREERDP_ERROR(ERRINFO, ERRINFO_LOGOFF_BY_USER)
|
||||
|
||||
/* Connection Error Codes */
|
||||
|
||||
#define FREERDP_ERROR_CONNECT_CLASS (FREERDP_ERROR_BASE + 2)
|
||||
|
||||
#define FREERDP_ERROR_PRE_CONNECT_FAILED MAKE_FREERDP_ERROR(CONNECT, 1)
|
||||
#define FREERDP_ERROR_CONNECT_UNDEFINED MAKE_FREERDP_ERROR(CONNECT, 2)
|
||||
#define FREERDP_ERROR_POST_CONNECT_FAILED MAKE_FREERDP_ERROR(CONNECT, 3)
|
||||
#define FREERDP_ERROR_DNS_ERROR MAKE_FREERDP_ERROR(CONNECT, 4)
|
||||
#define FREERDP_ERROR_DNS_NAME_NOT_FOUND MAKE_FREERDP_ERROR(CONNECT, 5)
|
||||
#define FREERDP_ERROR_CONNECT_FAILED MAKE_FREERDP_ERROR(CONNECT, 6)
|
||||
#define FREERDP_ERROR_MCS_CONNECT_INITIAL_ERROR MAKE_FREERDP_ERROR(CONNECT, 7)
|
||||
#define FREERDP_ERROR_TLS_CONNECT_FAILED MAKE_FREERDP_ERROR(CONNECT, 8)
|
||||
#define FREERDP_ERROR_AUTHENTICATION_FAILED MAKE_FREERDP_ERROR(CONNECT, 9)
|
||||
#define FREERDP_ERROR_INSUFFICIENT_PRIVILEGES MAKE_FREERDP_ERROR(CONNECT, 10)
|
||||
#define FREERDP_ERROR_CONNECT_CANCELLED MAKE_FREERDP_ERROR(CONNECT, 11)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -85,7 +85,9 @@ struct rdp_context
|
||||
This field is used only on the server side. */
|
||||
ALIGN64 BOOL ServerMode; /**< (offset 2) true when context is in server mode */
|
||||
|
||||
UINT64 paddingA[16 - 3]; /* 3 */
|
||||
ALIGN64 UINT32 LastError; /* 3 */
|
||||
|
||||
UINT64 paddingA[16 - 4]; /* 4 */
|
||||
|
||||
ALIGN64 int argc; /**< (offset 16)
|
||||
Number of arguments given to the program at launch time.
|
||||
@ -247,6 +249,9 @@ FREERDP_API void freerdp_free(freerdp* instance);
|
||||
|
||||
FREERDP_API BOOL freerdp_focus_required(freerdp* instance);
|
||||
|
||||
FREERDP_API UINT32 freerdp_get_last_error(rdpContext* context);
|
||||
FREERDP_API void freerdp_set_last_error(rdpContext* context, UINT32 lastError);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -669,6 +669,7 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL;
|
||||
#define FreeRDP_GatewayCredentialsSource 1990
|
||||
#define FreeRDP_GatewayUseSameCredentials 1991
|
||||
#define FreeRDP_GatewayEnabled 1992
|
||||
#define FreeRDP_GatewayBypassLocal 1993
|
||||
#define FreeRDP_RemoteApplicationMode 2112
|
||||
#define FreeRDP_RemoteApplicationName 2113
|
||||
#define FreeRDP_RemoteApplicationIcon 2114
|
||||
@ -1073,7 +1074,8 @@ struct rdp_settings
|
||||
ALIGN64 UINT32 GatewayCredentialsSource; /* 1990 */
|
||||
ALIGN64 BOOL GatewayUseSameCredentials; /* 1991 */
|
||||
ALIGN64 BOOL GatewayEnabled; /* 1992 */
|
||||
UINT64 padding2048[2048 - 1993]; /* 1993 */
|
||||
ALIGN64 BOOL GatewayBypassLocal; /* 1993 */
|
||||
UINT64 padding2048[2048 - 1994]; /* 1994 */
|
||||
UINT64 padding2112[2112 - 2048]; /* 2048 */
|
||||
|
||||
/**
|
||||
|
@ -110,13 +110,8 @@ int mppc_decompress(MPPC_CONTEXT* mppc, BYTE* pSrcData, UINT32 SrcSize, BYTE** p
|
||||
|
||||
if (!(flags & PACKET_COMPRESSED))
|
||||
{
|
||||
CopyMemory(HistoryPtr, pSrcData, SrcSize);
|
||||
HistoryPtr += SrcSize;
|
||||
HistoryOffset += SrcSize;
|
||||
mppc->HistoryPtr = HistoryPtr;
|
||||
mppc->HistoryOffset = HistoryOffset;
|
||||
*ppDstData = HistoryPtr;
|
||||
*pDstSize = SrcSize;
|
||||
*ppDstData = pSrcData;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -532,6 +527,7 @@ int mppc_compress(MPPC_CONTEXT* mppc, BYTE* pSrcData, UINT32 SrcSize, BYTE* pDst
|
||||
*pFlags |= PACKET_FLUSHED;
|
||||
ZeroMemory(HistoryBuffer, HistoryBufferSize);
|
||||
ZeroMemory(mppc->MatchBuffer, sizeof(mppc->MatchBuffer));
|
||||
*pDstSize = SrcSize;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -582,6 +578,7 @@ int mppc_compress(MPPC_CONTEXT* mppc, BYTE* pSrcData, UINT32 SrcSize, BYTE* pDst
|
||||
*pFlags = PACKET_FLUSHED;
|
||||
ZeroMemory(HistoryBuffer, HistoryBufferSize);
|
||||
ZeroMemory(mppc->MatchBuffer, sizeof(mppc->MatchBuffer));
|
||||
*pDstSize = SrcSize;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -737,6 +734,7 @@ int mppc_compress(MPPC_CONTEXT* mppc, BYTE* pSrcData, UINT32 SrcSize, BYTE* pDst
|
||||
*pFlags |= PACKET_FLUSHED;
|
||||
ZeroMemory(HistoryBuffer, HistoryBufferSize);
|
||||
ZeroMemory(mppc->MatchBuffer, sizeof(mppc->MatchBuffer));
|
||||
*pDstSize = SrcSize;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1167,10 +1167,7 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY
|
||||
|
||||
if (!(flags & PACKET_COMPRESSED))
|
||||
{
|
||||
CopyMemory(HistoryPtr, pSrcData, SrcSize);
|
||||
HistoryPtr += SrcSize;
|
||||
ncrush->HistoryPtr = HistoryPtr;
|
||||
*ppDstData = HistoryPtr;
|
||||
*ppDstData = pSrcData;
|
||||
*pDstSize = SrcSize;
|
||||
return 1;
|
||||
}
|
||||
|
@ -746,6 +746,10 @@ BOOL freerdp_get_param_bool(rdpSettings* settings, int id)
|
||||
return settings->GatewayEnabled;
|
||||
break;
|
||||
|
||||
case FreeRDP_GatewayBypassLocal:
|
||||
return settings->GatewayBypassLocal;
|
||||
break;
|
||||
|
||||
case FreeRDP_RemoteApplicationMode:
|
||||
return settings->RemoteApplicationMode;
|
||||
break;
|
||||
@ -1218,6 +1222,10 @@ int freerdp_set_param_bool(rdpSettings* settings, int id, BOOL param)
|
||||
settings->GatewayEnabled = param;
|
||||
break;
|
||||
|
||||
case FreeRDP_GatewayBypassLocal:
|
||||
settings->GatewayBypassLocal = param;
|
||||
break;
|
||||
|
||||
case FreeRDP_RemoteApplicationMode:
|
||||
settings->RemoteApplicationMode = param;
|
||||
break;
|
||||
|
@ -46,29 +46,38 @@ int bulk_decompress(rdpBulk* bulk, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstD
|
||||
UINT32 UncompressedBytes;
|
||||
UINT32 type = flags & 0x0F;
|
||||
|
||||
switch (type)
|
||||
if (flags & PACKET_COMPRESSED)
|
||||
{
|
||||
case PACKET_COMPR_TYPE_8K:
|
||||
mppc_set_compression_level(bulk->mppcRecv, 0);
|
||||
status = mppc_decompress(bulk->mppcRecv, pSrcData, SrcSize, ppDstData, pDstSize, flags);
|
||||
break;
|
||||
switch (type)
|
||||
{
|
||||
case PACKET_COMPR_TYPE_8K:
|
||||
mppc_set_compression_level(bulk->mppcRecv, 0);
|
||||
status = mppc_decompress(bulk->mppcRecv, pSrcData, SrcSize, ppDstData, pDstSize, flags);
|
||||
break;
|
||||
|
||||
case PACKET_COMPR_TYPE_64K:
|
||||
mppc_set_compression_level(bulk->mppcRecv, 1);
|
||||
status = mppc_decompress(bulk->mppcRecv, pSrcData, SrcSize, ppDstData, pDstSize, flags);
|
||||
break;
|
||||
case PACKET_COMPR_TYPE_64K:
|
||||
mppc_set_compression_level(bulk->mppcRecv, 1);
|
||||
status = mppc_decompress(bulk->mppcRecv, pSrcData, SrcSize, ppDstData, pDstSize, flags);
|
||||
break;
|
||||
|
||||
case PACKET_COMPR_TYPE_RDP6:
|
||||
status = ncrush_decompress(bulk->ncrushRecv, pSrcData, SrcSize, ppDstData, pDstSize, flags);
|
||||
break;
|
||||
case PACKET_COMPR_TYPE_RDP6:
|
||||
status = ncrush_decompress(bulk->ncrushRecv, pSrcData, SrcSize, ppDstData, pDstSize, flags);
|
||||
break;
|
||||
|
||||
case PACKET_COMPR_TYPE_RDP61:
|
||||
status = -1;
|
||||
break;
|
||||
case PACKET_COMPR_TYPE_RDP61:
|
||||
status = -1;
|
||||
break;
|
||||
|
||||
case PACKET_COMPR_TYPE_RDP8:
|
||||
status = -1;
|
||||
break;
|
||||
case PACKET_COMPR_TYPE_RDP8:
|
||||
status = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*ppDstData = pSrcData;
|
||||
*pDstSize = SrcSize;
|
||||
status = 1;
|
||||
}
|
||||
|
||||
if (status >= 0)
|
||||
@ -87,8 +96,8 @@ int bulk_decompress(rdpBulk* bulk, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstD
|
||||
CompressionRatio = ((double) CompressedBytes) / ((double) UncompressedBytes);
|
||||
TotalCompressionRatio = ((double) bulk->TotalCompressedBytes) / ((double) bulk->TotalUncompressedBytes);
|
||||
|
||||
printf("Type: %d Compression Ratio: %f Total: %f %d / %d\n",
|
||||
type, CompressionRatio, TotalCompressionRatio, CompressedBytes, UncompressedBytes);
|
||||
printf("Type: %d Flags: 0x%04X Compression Ratio: %f Total: %f %d / %d\n",
|
||||
type, flags, CompressionRatio, TotalCompressionRatio, CompressedBytes, UncompressedBytes);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -113,7 +122,7 @@ int bulk_compress(rdpBulk* bulk, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstDat
|
||||
mppc_set_compression_level(bulk->mppcSend, bulk->CompressionLevel);
|
||||
status = mppc_compress(bulk->mppcSend, pSrcData, SrcSize, *ppDstData, pDstSize, pFlags);
|
||||
|
||||
if ((status >= 0) && (*pFlags & PACKET_COMPRESSED))
|
||||
if (status >= 0)
|
||||
{
|
||||
CompressedBytes = *pDstSize;
|
||||
UncompressedBytes = SrcSize;
|
||||
@ -123,13 +132,17 @@ int bulk_compress(rdpBulk* bulk, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstDat
|
||||
|
||||
#ifdef WITH_BULK_DEBUG
|
||||
{
|
||||
UINT32 type;
|
||||
double CompressionRatio;
|
||||
double TotalCompressionRatio;
|
||||
|
||||
type = bulk->CompressionLevel;
|
||||
|
||||
CompressionRatio = ((double) CompressedBytes) / ((double) UncompressedBytes);
|
||||
TotalCompressionRatio = ((double) bulk->TotalCompressedBytes) / ((double) bulk->TotalUncompressedBytes);
|
||||
|
||||
printf("Compression Ratio: %f Total: %f\n", CompressionRatio, TotalCompressionRatio);
|
||||
printf("Type: %d Flags: 0x%04X Compression Ratio: %f Total: %f %d / %d\n",
|
||||
type, *pFlags, CompressionRatio, TotalCompressionRatio, CompressedBytes, UncompressedBytes);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -231,6 +231,9 @@ BOOL rdp_client_connect(rdpRdp* rdp)
|
||||
nego_set_negotiation_enabled(rdp->nego, settings->NegotiateSecurityLayer);
|
||||
nego_set_restricted_admin_mode_required(rdp->nego, settings->RestrictedAdminModeRequired);
|
||||
|
||||
nego_set_gateway_enabled(rdp->nego, settings->GatewayEnabled);
|
||||
nego_set_gateway_bypass_local(rdp->nego, settings->GatewayBypassLocal);
|
||||
|
||||
nego_enable_rdp(rdp->nego, settings->RdpSecurity);
|
||||
nego_enable_tls(rdp->nego, settings->TlsSecurity);
|
||||
nego_enable_nla(rdp->nego, settings->NlaSecurity);
|
||||
@ -268,6 +271,12 @@ BOOL rdp_client_connect(rdpRdp* rdp)
|
||||
{
|
||||
connectErrorCode = MCSCONNECTINITIALERROR;
|
||||
}
|
||||
|
||||
if (!freerdp_get_last_error(rdp->context))
|
||||
{
|
||||
freerdp_set_last_error(rdp->context, FREERDP_ERROR_MCS_CONNECT_INITIAL_ERROR);
|
||||
}
|
||||
|
||||
fprintf(stderr, "Error: unable to send MCS Connect Initial\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -342,6 +342,8 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s)
|
||||
BYTE fragmentation;
|
||||
BYTE compression;
|
||||
BYTE compressionFlags;
|
||||
UINT32 DstSize = 0;
|
||||
BYTE* pDstData = NULL;
|
||||
rdpTransport* transport;
|
||||
|
||||
status = 0;
|
||||
@ -363,26 +365,20 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s)
|
||||
cs = s;
|
||||
next_pos = Stream_GetPosition(s) + size;
|
||||
|
||||
if (compressionFlags & PACKET_COMPRESSED)
|
||||
if (bulk_decompress(rdp->bulk, Stream_Pointer(s), size, &pDstData, &DstSize, compressionFlags))
|
||||
{
|
||||
UINT32 DstSize = 0;
|
||||
BYTE* pDstData = NULL;
|
||||
size = DstSize;
|
||||
cs = StreamPool_Take(transport->ReceivePool, DstSize);
|
||||
|
||||
if (bulk_decompress(rdp->bulk, Stream_Pointer(s), size, &pDstData, &DstSize, compressionFlags))
|
||||
{
|
||||
size = DstSize;
|
||||
cs = StreamPool_Take(transport->ReceivePool, DstSize);
|
||||
|
||||
Stream_SetPosition(cs, 0);
|
||||
Stream_Write(cs, pDstData, DstSize);
|
||||
Stream_SealLength(cs);
|
||||
Stream_SetPosition(cs, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "bulk_decompress() failed\n");
|
||||
Stream_Seek(s, size);
|
||||
}
|
||||
Stream_SetPosition(cs, 0);
|
||||
Stream_Write(cs, pDstData, DstSize);
|
||||
Stream_SealLength(cs);
|
||||
Stream_SetPosition(cs, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "bulk_decompress() failed\n");
|
||||
Stream_Seek(s, size);
|
||||
}
|
||||
|
||||
if (fragmentation == FASTPATH_FRAGMENT_SINGLE)
|
||||
@ -855,6 +851,7 @@ BOOL fastpath_send_update_pdu(rdpFastPath* fastpath, BYTE updateCode, wStream* s
|
||||
{
|
||||
CompressionMaxSize = bulk_compression_max_size(rdp->bulk);
|
||||
maxLength = (maxLength < CompressionMaxSize) ? maxLength : CompressionMaxSize;
|
||||
maxLength -= 20;
|
||||
}
|
||||
|
||||
totalLength = Stream_GetPosition(s);
|
||||
|
@ -65,6 +65,7 @@ BOOL freerdp_connect(freerdp* instance)
|
||||
|
||||
/* We always set the return code to 0 before we start the connect sequence*/
|
||||
connectErrorCode = 0;
|
||||
freerdp_set_last_error(instance->context, FREERDP_ERROR_SUCCESS);
|
||||
|
||||
rdp = instance->context->rdp;
|
||||
settings = instance->settings;
|
||||
@ -87,6 +88,12 @@ BOOL freerdp_connect(freerdp* instance)
|
||||
{
|
||||
connectErrorCode = PREECONNECTERROR;
|
||||
}
|
||||
|
||||
if (!freerdp_get_last_error(rdp->context))
|
||||
{
|
||||
freerdp_set_last_error(instance->context, FREERDP_ERROR_PRE_CONNECT_FAILED);
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s:%d: freerdp_pre_connect failed\n", __FILE__, __LINE__);
|
||||
|
||||
goto freerdp_connect_finally;
|
||||
@ -124,6 +131,11 @@ BOOL freerdp_connect(freerdp* instance)
|
||||
connectErrorCode = POSTCONNECTERROR;
|
||||
}
|
||||
|
||||
if (!freerdp_get_last_error(rdp->context))
|
||||
{
|
||||
freerdp_set_last_error(instance->context, FREERDP_ERROR_POST_CONNECT_FAILED);
|
||||
}
|
||||
|
||||
goto freerdp_connect_finally;
|
||||
}
|
||||
|
||||
@ -177,6 +189,7 @@ BOOL freerdp_connect(freerdp* instance)
|
||||
if (rdp->errorInfo == ERRINFO_SERVER_INSUFFICIENT_PRIVILEGES)
|
||||
{
|
||||
connectErrorCode = INSUFFICIENTPRIVILEGESERROR;
|
||||
freerdp_set_last_error(instance->context, FREERDP_ERROR_INSUFFICIENT_PRIVILEGES);
|
||||
}
|
||||
|
||||
if (!connectErrorCode)
|
||||
@ -465,6 +478,19 @@ UINT32 freerdp_error_info(freerdp* instance)
|
||||
return instance->context->rdp->errorInfo;
|
||||
}
|
||||
|
||||
UINT32 freerdp_get_last_error(rdpContext* context)
|
||||
{
|
||||
return context->LastError;
|
||||
}
|
||||
|
||||
void freerdp_set_last_error(rdpContext* context, UINT32 lastError)
|
||||
{
|
||||
if (lastError)
|
||||
fprintf(stderr, "freerdp_set_last_error 0x%04X\n", lastError);
|
||||
|
||||
context->LastError = lastError;
|
||||
}
|
||||
|
||||
/** Allocator function for the rdp_freerdp structure.
|
||||
* @return an allocated structure filled with 0s. Need to be deallocated using freerdp_free()
|
||||
*/
|
||||
|
@ -142,6 +142,7 @@ int rpc_ncacn_http_ntlm_init(rdpRpc* rpc, TSG_CHANNEL channel)
|
||||
if (!proceed)
|
||||
{
|
||||
connectErrorCode = CANCELEDBYUSER;
|
||||
freerdp_set_last_error(instance->context, FREERDP_ERROR_CONNECT_CANCELLED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -120,6 +120,7 @@ int rpc_send_bind_pdu(rdpRpc* rpc)
|
||||
if (!proceed)
|
||||
{
|
||||
connectErrorCode = CANCELEDBYUSER;
|
||||
freerdp_set_last_error(instance->context, FREERDP_ERROR_CONNECT_CANCELLED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -154,9 +154,17 @@ BOOL rts_connect(rdpRpc* rpc)
|
||||
http_response_print(http_response);
|
||||
http_response_free(http_response);
|
||||
|
||||
if (!connectErrorCode && http_response->StatusCode == HTTP_STATUS_DENIED)
|
||||
if (http_response->StatusCode == HTTP_STATUS_DENIED)
|
||||
{
|
||||
connectErrorCode = AUTHENTICATIONERROR;
|
||||
if (!connectErrorCode)
|
||||
{
|
||||
connectErrorCode = AUTHENTICATIONERROR;
|
||||
}
|
||||
|
||||
if (!freerdp_get_last_error(((freerdp*)(rpc->settings->instance))->context))
|
||||
{
|
||||
freerdp_set_last_error(((freerdp*)(rpc->settings->instance))->context, FREERDP_ERROR_AUTHENTICATION_FAILED);
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
|
@ -407,16 +407,17 @@ void gcc_write_client_data_blocks(wStream* s, rdpMcs* mcs)
|
||||
|
||||
if (settings->NegotiationFlags & EXTENDED_CLIENT_DATA_SUPPORTED)
|
||||
{
|
||||
if (settings->SpanMonitors)
|
||||
if (settings->UseMultimon && !settings->SpanMonitors)
|
||||
{
|
||||
gcc_write_client_monitor_data(s, mcs);
|
||||
}
|
||||
|
||||
gcc_write_client_message_channel_data(s, mcs);
|
||||
gcc_write_client_multitransport_channel_data(s, mcs);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (settings->UseMultimon)
|
||||
if (settings->UseMultimon && !settings->SpanMonitors)
|
||||
{
|
||||
fprintf(stderr, "WARNING: true multi monitor support was not advertised by server!\n");
|
||||
|
||||
|
@ -212,7 +212,25 @@ BOOL nego_security_connect(rdpNego* nego)
|
||||
BOOL nego_tcp_connect(rdpNego* nego)
|
||||
{
|
||||
if (!nego->tcp_connected)
|
||||
nego->tcp_connected = transport_connect(nego->transport, nego->hostname, nego->port);
|
||||
{
|
||||
if (nego->GatewayEnabled && nego->GatewayBypassLocal)
|
||||
{
|
||||
/* Attempt a direct connection first, and then fallback to using the gateway */
|
||||
|
||||
transport_set_gateway_enabled(nego->transport, FALSE);
|
||||
nego->tcp_connected = transport_connect(nego->transport, nego->hostname, nego->port);
|
||||
|
||||
if (!nego->tcp_connected)
|
||||
{
|
||||
transport_set_gateway_enabled(nego->transport, TRUE);
|
||||
nego->tcp_connected = transport_connect(nego->transport, nego->hostname, nego->port);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nego->tcp_connected = transport_connect(nego->transport, nego->hostname, nego->port);
|
||||
}
|
||||
}
|
||||
|
||||
return nego->tcp_connected;
|
||||
}
|
||||
@ -1034,6 +1052,16 @@ void nego_set_restricted_admin_mode_required(rdpNego* nego, BOOL RestrictedAdmin
|
||||
nego->RestrictedAdminModeRequired = RestrictedAdminModeRequired;
|
||||
}
|
||||
|
||||
void nego_set_gateway_enabled(rdpNego* nego, BOOL GatewayEnabled)
|
||||
{
|
||||
nego->GatewayEnabled = GatewayEnabled;
|
||||
}
|
||||
|
||||
void nego_set_gateway_bypass_local(rdpNego* nego, BOOL GatewayBypassLocal)
|
||||
{
|
||||
nego->GatewayBypassLocal = GatewayBypassLocal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable RDP security protocol.
|
||||
* @param nego pointer to the negotiation structure
|
||||
|
@ -110,6 +110,8 @@ struct rdp_nego
|
||||
BOOL NegotiateSecurityLayer;
|
||||
BYTE enabled_protocols[16];
|
||||
BOOL RestrictedAdminModeRequired;
|
||||
BOOL GatewayEnabled;
|
||||
BOOL GatewayBypassLocal;
|
||||
|
||||
rdpTransport* transport;
|
||||
};
|
||||
@ -142,6 +144,8 @@ void nego_init(rdpNego* nego);
|
||||
void nego_set_target(rdpNego* nego, char* hostname, int port);
|
||||
void nego_set_negotiation_enabled(rdpNego* nego, BOOL NegotiateSecurityLayer_enabled);
|
||||
void nego_set_restricted_admin_mode_required(rdpNego* nego, BOOL RestrictedAdminModeRequired);
|
||||
void nego_set_gateway_enabled(rdpNego* nego, BOOL GatewayEnabled);
|
||||
void nego_set_gateway_bypass_local(rdpNego* nego, BOOL GatewayBypassLocal);
|
||||
void nego_enable_rdp(rdpNego* nego, BOOL enable_rdp);
|
||||
void nego_enable_tls(rdpNego* nego, BOOL enable_tls);
|
||||
void nego_enable_nla(rdpNego* nego, BOOL enable_nla);
|
||||
|
@ -153,6 +153,7 @@ int credssp_ntlm_client_init(rdpCredssp* credssp)
|
||||
if (!proceed)
|
||||
{
|
||||
connectErrorCode = CANCELEDBYUSER;
|
||||
freerdp_set_last_error(instance->context, FREERDP_ERROR_CONNECT_CANCELLED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -238,12 +238,17 @@ BOOL rdp_set_error_info(rdpRdp* rdp, UINT32 errorInfo)
|
||||
ErrorInfoEventArgs e;
|
||||
rdpContext* context = rdp->instance->context;
|
||||
|
||||
rdp->context->LastError = MAKE_FREERDP_ERROR(ERRINFO, errorInfo);
|
||||
rdp_print_errinfo(rdp->errorInfo);
|
||||
|
||||
EventArgsInit(&e, "freerdp");
|
||||
e.code = rdp->errorInfo;
|
||||
PubSub_OnErrorInfo(context->pubSub, context, &e);
|
||||
}
|
||||
else
|
||||
{
|
||||
rdp->context->LastError = FREERDP_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -651,6 +651,7 @@ rdpSettings* freerdp_settings_clone(rdpSettings* settings)
|
||||
_settings->PlayRemoteFx = settings->PlayRemoteFx; /* 1857 */
|
||||
_settings->GatewayUseSameCredentials = settings->GatewayUseSameCredentials; /* 1991 */
|
||||
_settings->GatewayEnabled = settings->GatewayEnabled; /* 1992 */
|
||||
_settings->GatewayBypassLocal = settings->GatewayBypassLocal; /* 1993 */
|
||||
_settings->RemoteApplicationMode = settings->RemoteApplicationMode; /* 2112 */
|
||||
_settings->DisableRemoteAppCapsCheck = settings->DisableRemoteAppCapsCheck; /* 2121 */
|
||||
_settings->RemoteAppLanguageBarSupported = settings->RemoteAppLanguageBarSupported; /* 2124 */
|
||||
|
@ -71,25 +71,8 @@ void transport_attach(rdpTransport* transport, int sockfd)
|
||||
transport->TcpOut = transport->TcpIn;
|
||||
}
|
||||
|
||||
BOOL transport_disconnect(rdpTransport* transport)
|
||||
void transport_stop(rdpTransport* transport)
|
||||
{
|
||||
BOOL status = TRUE;
|
||||
|
||||
if (!transport)
|
||||
return FALSE;
|
||||
|
||||
if (transport->layer == TRANSPORT_LAYER_TLS)
|
||||
status &= tls_disconnect(transport->TlsIn);
|
||||
|
||||
if ((transport->layer == TRANSPORT_LAYER_TSG) || (transport->layer == TRANSPORT_LAYER_TSG_TLS))
|
||||
{
|
||||
status &= tsg_disconnect(transport->tsg);
|
||||
}
|
||||
else
|
||||
{
|
||||
status &= tcp_disconnect(transport->TcpIn);
|
||||
}
|
||||
|
||||
if (transport->async)
|
||||
{
|
||||
if (transport->stopEvent)
|
||||
@ -104,6 +87,28 @@ BOOL transport_disconnect(rdpTransport* transport)
|
||||
transport->stopEvent = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOL transport_disconnect(rdpTransport* transport)
|
||||
{
|
||||
BOOL status = TRUE;
|
||||
|
||||
if (!transport)
|
||||
return FALSE;
|
||||
|
||||
transport_stop(transport);
|
||||
|
||||
if (transport->layer == TRANSPORT_LAYER_TLS)
|
||||
status &= tls_disconnect(transport->TlsIn);
|
||||
|
||||
if ((transport->layer == TRANSPORT_LAYER_TSG) || (transport->layer == TRANSPORT_LAYER_TSG_TLS))
|
||||
{
|
||||
status &= tsg_disconnect(transport->tsg);
|
||||
}
|
||||
else
|
||||
{
|
||||
status &= tcp_disconnect(transport->TcpIn);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
@ -219,6 +224,12 @@ BIO_METHOD* BIO_s_tsg(void)
|
||||
|
||||
BOOL transport_connect_tls(rdpTransport* transport)
|
||||
{
|
||||
freerdp* instance;
|
||||
rdpContext* context;
|
||||
|
||||
instance = (freerdp*) transport->settings->instance;
|
||||
context = instance->context;
|
||||
|
||||
if (transport->layer == TRANSPORT_LAYER_TSG)
|
||||
{
|
||||
transport->TsgTls = tls_new(transport->settings);
|
||||
@ -239,6 +250,9 @@ BOOL transport_connect_tls(rdpTransport* transport)
|
||||
if (!connectErrorCode)
|
||||
connectErrorCode = TLSCONNECTERROR;
|
||||
|
||||
if (!freerdp_get_last_error(context))
|
||||
freerdp_set_last_error(context, FREERDP_ERROR_TLS_CONNECT_FAILED);
|
||||
|
||||
tls_free(transport->TsgTls);
|
||||
transport->TsgTls = NULL;
|
||||
|
||||
@ -268,6 +282,9 @@ BOOL transport_connect_tls(rdpTransport* transport)
|
||||
if (!connectErrorCode)
|
||||
connectErrorCode = TLSCONNECTERROR;
|
||||
|
||||
if (!freerdp_get_last_error(context))
|
||||
freerdp_set_last_error(context, FREERDP_ERROR_TLS_CONNECT_FAILED);
|
||||
|
||||
tls_free(transport->TlsIn);
|
||||
|
||||
if (transport->TlsIn == transport->TlsOut)
|
||||
@ -313,6 +330,11 @@ BOOL transport_connect_nla(rdpTransport* transport)
|
||||
if (!connectErrorCode)
|
||||
connectErrorCode = AUTHENTICATIONERROR;
|
||||
|
||||
if (!freerdp_get_last_error(instance->context))
|
||||
{
|
||||
freerdp_set_last_error(instance->context, FREERDP_ERROR_AUTHENTICATION_FAILED);
|
||||
}
|
||||
|
||||
fprintf(stderr, "Authentication failure, check credentials.\n"
|
||||
"If credentials are valid, the NTLMSSP implementation may be to blame.\n");
|
||||
|
||||
@ -374,7 +396,7 @@ BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 por
|
||||
|
||||
transport->async = settings->AsyncTransport;
|
||||
|
||||
if (transport->settings->GatewayEnabled)
|
||||
if (transport->GatewayEnabled)
|
||||
{
|
||||
transport->layer = TRANSPORT_LAYER_TSG;
|
||||
transport->TcpOut = tcp_new(settings);
|
||||
@ -1012,6 +1034,11 @@ BOOL transport_set_blocking_mode(rdpTransport* transport, BOOL blocking)
|
||||
return status;
|
||||
}
|
||||
|
||||
void transport_set_gateway_enabled(rdpTransport* transport, BOOL GatewayEnabled)
|
||||
{
|
||||
transport->GatewayEnabled = GatewayEnabled;
|
||||
}
|
||||
|
||||
static void* transport_client_thread(void* arg)
|
||||
{
|
||||
DWORD status;
|
||||
@ -1055,7 +1082,7 @@ static void* transport_client_thread(void* arg)
|
||||
|
||||
transport_get_read_handles(transport, (HANDLE*) &handles, &nCount);
|
||||
|
||||
status = WaitForMultipleObjects(nCount, handles, FALSE, 100);
|
||||
status = WaitForMultipleObjects(nCount, handles, FALSE, INFINITE);
|
||||
if (transport->layer == TRANSPORT_LAYER_CLOSED)
|
||||
{
|
||||
rdpRdp* rdp = (rdpRdp*) transport->rdp;
|
||||
@ -1107,6 +1134,7 @@ rdpTransport* transport_new(rdpSettings* settings)
|
||||
transport->connectedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
transport->blocking = TRUE;
|
||||
transport->GatewayEnabled = FALSE;
|
||||
|
||||
InitializeCriticalSectionAndSpinCount(&(transport->ReadLock), 4000);
|
||||
InitializeCriticalSectionAndSpinCount(&(transport->WriteLock), 4000);
|
||||
@ -1121,20 +1149,7 @@ void transport_free(rdpTransport* transport)
|
||||
{
|
||||
if (transport)
|
||||
{
|
||||
if (transport->async)
|
||||
{
|
||||
if (transport->stopEvent)
|
||||
{
|
||||
SetEvent(transport->stopEvent);
|
||||
WaitForSingleObject(transport->thread, INFINITE);
|
||||
|
||||
CloseHandle(transport->thread);
|
||||
CloseHandle(transport->stopEvent);
|
||||
|
||||
transport->thread = NULL;
|
||||
transport->stopEvent = NULL;
|
||||
}
|
||||
}
|
||||
transport_stop(transport);
|
||||
|
||||
if (transport->ReceiveBuffer)
|
||||
Stream_Release(transport->ReceiveBuffer);
|
||||
|
@ -75,6 +75,7 @@ struct rdp_transport
|
||||
HANDLE stopEvent;
|
||||
HANDLE thread;
|
||||
BOOL async;
|
||||
BOOL GatewayEnabled;
|
||||
CRITICAL_SECTION ReadLock;
|
||||
CRITICAL_SECTION WriteLock;
|
||||
wLog* log;
|
||||
@ -88,15 +89,16 @@ BOOL transport_disconnect(rdpTransport* transport);
|
||||
BOOL transport_connect_rdp(rdpTransport* transport);
|
||||
BOOL transport_connect_tls(rdpTransport* transport);
|
||||
BOOL transport_connect_nla(rdpTransport* transport);
|
||||
BOOL transport_connect_tsg(rdpTransport* transport);
|
||||
BOOL transport_accept_rdp(rdpTransport* transport);
|
||||
BOOL transport_accept_tls(rdpTransport* transport);
|
||||
BOOL transport_accept_nla(rdpTransport* transport);
|
||||
void transport_stop(rdpTransport* transport);
|
||||
int transport_read(rdpTransport* transport, wStream* s);
|
||||
int transport_write(rdpTransport* transport, wStream* s);
|
||||
void transport_get_fds(rdpTransport* transport, void** rfds, int* rcount);
|
||||
int transport_check_fds(rdpTransport* transport);
|
||||
BOOL transport_set_blocking_mode(rdpTransport* transport, BOOL blocking);
|
||||
void transport_set_gateway_enabled(rdpTransport* transport, BOOL GatewayEnabled);
|
||||
void transport_get_read_handles(rdpTransport* transport, HANDLE* events, DWORD* count);
|
||||
|
||||
wStream* transport_receive_pool_take(rdpTransport* transport);
|
||||
|
@ -787,7 +787,9 @@ BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int po
|
||||
tls_print_certificate_name_mismatch_error(hostname, common_name, alt_names, alt_names_count);
|
||||
|
||||
if (instance->VerifyCertificate)
|
||||
{
|
||||
accept_certificate = instance->VerifyCertificate(instance, subject, issuer, fingerprint);
|
||||
}
|
||||
|
||||
if (!accept_certificate)
|
||||
{
|
||||
@ -807,7 +809,9 @@ BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int po
|
||||
tls_print_certificate_error(hostname, fingerprint, tls->certificate_store->file);
|
||||
|
||||
if (instance->VerifyChangedCertificate)
|
||||
{
|
||||
accept_certificate = instance->VerifyChangedCertificate(instance, subject, issuer, fingerprint, "");
|
||||
}
|
||||
|
||||
if (!accept_certificate)
|
||||
{
|
||||
|
@ -90,7 +90,7 @@ int freerdp_tcp_connect(const char* hostname, int port)
|
||||
|
||||
if (status != 0)
|
||||
{
|
||||
fprintf(stderr, "tcp_connect: getaddrinfo (%s)\n", gai_strerror(status));
|
||||
//fprintf(stderr, "tcp_connect: getaddrinfo (%s)\n", gai_strerror(status));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -328,14 +328,14 @@ BOOL CancelWaitableTimer(HANDLE hTimer)
|
||||
* http://www.cs.wustl.edu/~schmidt/Timer_Queue.html
|
||||
*/
|
||||
|
||||
static void timespec_add_ms(struct timespec* tspec, UINT32 ms)
|
||||
void timespec_add_ms(struct timespec* tspec, UINT32 ms)
|
||||
{
|
||||
UINT64 ns = tspec->tv_nsec + (ms * 1000000);
|
||||
tspec->tv_sec += (ns / 1000000000);
|
||||
tspec->tv_nsec = (ns % 1000000000);
|
||||
}
|
||||
|
||||
static UINT64 timespec_to_ms(struct timespec* tspec)
|
||||
UINT64 timespec_to_ms(struct timespec* tspec)
|
||||
{
|
||||
UINT64 ms;
|
||||
ms = tspec->tv_sec * 1000;
|
||||
|
@ -408,7 +408,7 @@ void InitializeWtsApiStubs(void)
|
||||
if (!g_WtsApiModule)
|
||||
return;
|
||||
|
||||
pInitWtsApi = GetProcAddress(g_WtsApiModule, "InitWtsApi");
|
||||
pInitWtsApi = (INIT_WTSAPI_FN) GetProcAddress(g_WtsApiModule, "InitWtsApi");
|
||||
|
||||
if (pInitWtsApi)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user