diff --git a/channels/rdpsnd/client/rdpsnd_main.c b/channels/rdpsnd/client/rdpsnd_main.c index 4211e0bc4..c4fc84637 100644 --- a/channels/rdpsnd/client/rdpsnd_main.c +++ b/channels/rdpsnd/client/rdpsnd_main.c @@ -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); diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c index 4a92692f5..f7e5942af 100644 --- a/client/X11/xf_client.c +++ b/client/X11/xf_client.c @@ -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) diff --git a/client/X11/xf_event.c b/client/X11/xf_event.c index 6bd6d561f..d6f0c8dd7 100644 --- a/client/X11/xf_event.c +++ b/client/X11/xf_event.c @@ -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); diff --git a/client/X11/xf_event.h b/client/X11/xf_event.h index 05d4e3e04..4198ab2f2 100644 --- a/client/X11/xf_event.h +++ b/client/X11/xf_event.h @@ -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, ...); diff --git a/client/X11/xf_input.c b/client/X11/xf_input.c index 8d1adf509..9549bdb3a 100644 --- a/client/X11/xf_input.c +++ b/client/X11/xf_input.c @@ -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; diff --git a/client/X11/xf_keyboard.c b/client/X11/xf_keyboard.c index e6427e190..358b6d099 100644 --- a/client/X11/xf_keyboard.c +++ b/client/X11/xf_keyboard.c @@ -26,6 +26,8 @@ #include #include +#include +#include #include #include @@ -33,66 +35,153 @@ #include +#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; } diff --git a/client/X11/xf_keyboard.h b/client/X11/xf_keyboard.h index 0b84efa43..05f9f2c39 100644 --- a/client/X11/xf_keyboard.h +++ b/client/X11/xf_keyboard.h @@ -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 */ diff --git a/client/X11/xfreerdp.h b/client/X11/xfreerdp.h index 9cb78b946..aa01ae905 100644 --- a/client/X11/xfreerdp.h +++ b/client/X11/xfreerdp.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; diff --git a/client/common/cmdline.c b/client/common/cmdline.c index 7cfd12d35..31fc28a6a 100644 --- a/client/common/cmdline.c +++ b/client/common/cmdline.c @@ -56,6 +56,7 @@ COMMAND_LINE_ARGUMENT_A args[] = { "pth", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, "pass-the-hash", "Pass the hash (restricted admin mode)" }, { "client-hostname", COMMAND_LINE_VALUE_REQUIRED, "", 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") { diff --git a/client/common/file.c b/client/common/file.c index cc3aa31b2..c73be9198 100644 --- a/client/common/file.c +++ b/client/common/file.c @@ -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) diff --git a/include/freerdp/error.h b/include/freerdp/error.h index 2f284b4f7..9cd8f4daa 100755 --- a/include/freerdp/error.h +++ b/include/freerdp/error.h @@ -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 diff --git a/include/freerdp/freerdp.h b/include/freerdp/freerdp.h index 4a9c7aeac..caddcc629 100644 --- a/include/freerdp/freerdp.h +++ b/include/freerdp/freerdp.h @@ -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 diff --git a/include/freerdp/settings.h b/include/freerdp/settings.h index ffee66a45..92d3ac45c 100644 --- a/include/freerdp/settings.h +++ b/include/freerdp/settings.h @@ -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 */ /** diff --git a/libfreerdp/codec/mppc.c b/libfreerdp/codec/mppc.c index cee62980b..2d1ace2ae 100644 --- a/libfreerdp/codec/mppc.c +++ b/libfreerdp/codec/mppc.c @@ -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; } diff --git a/libfreerdp/codec/ncrush.c b/libfreerdp/codec/ncrush.c index 7769bf530..4b3c891fb 100644 --- a/libfreerdp/codec/ncrush.c +++ b/libfreerdp/codec/ncrush.c @@ -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; } diff --git a/libfreerdp/common/settings.c b/libfreerdp/common/settings.c index d0f373544..d9b9a414b 100644 --- a/libfreerdp/common/settings.c +++ b/libfreerdp/common/settings.c @@ -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; diff --git a/libfreerdp/core/bulk.c b/libfreerdp/core/bulk.c index e4883bec2..29319b14b 100644 --- a/libfreerdp/core/bulk.c +++ b/libfreerdp/core/bulk.c @@ -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 } diff --git a/libfreerdp/core/connection.c b/libfreerdp/core/connection.c index 675419b92..eac8777c1 100644 --- a/libfreerdp/core/connection.c +++ b/libfreerdp/core/connection.c @@ -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; } diff --git a/libfreerdp/core/fastpath.c b/libfreerdp/core/fastpath.c index 5174056bb..ba9af739a 100644 --- a/libfreerdp/core/fastpath.c +++ b/libfreerdp/core/fastpath.c @@ -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); diff --git a/libfreerdp/core/freerdp.c b/libfreerdp/core/freerdp.c index 8cb606953..5fc0977ed 100644 --- a/libfreerdp/core/freerdp.c +++ b/libfreerdp/core/freerdp.c @@ -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() */ diff --git a/libfreerdp/core/gateway/ncacn_http.c b/libfreerdp/core/gateway/ncacn_http.c index 83daaa33f..bc374b67d 100644 --- a/libfreerdp/core/gateway/ncacn_http.c +++ b/libfreerdp/core/gateway/ncacn_http.c @@ -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; } diff --git a/libfreerdp/core/gateway/rpc_bind.c b/libfreerdp/core/gateway/rpc_bind.c index 4057263fc..3360ec0b3 100644 --- a/libfreerdp/core/gateway/rpc_bind.c +++ b/libfreerdp/core/gateway/rpc_bind.c @@ -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; } diff --git a/libfreerdp/core/gateway/rts.c b/libfreerdp/core/gateway/rts.c index e5820cecd..9c4b2ec3c 100644 --- a/libfreerdp/core/gateway/rts.c +++ b/libfreerdp/core/gateway/rts.c @@ -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; diff --git a/libfreerdp/core/gcc.c b/libfreerdp/core/gcc.c index ac6950ab2..c7cb18f2f 100644 --- a/libfreerdp/core/gcc.c +++ b/libfreerdp/core/gcc.c @@ -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"); diff --git a/libfreerdp/core/nego.c b/libfreerdp/core/nego.c index a35f43e9a..ef1053fe9 100644 --- a/libfreerdp/core/nego.c +++ b/libfreerdp/core/nego.c @@ -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 diff --git a/libfreerdp/core/nego.h b/libfreerdp/core/nego.h index d82257fc7..4da38beb1 100644 --- a/libfreerdp/core/nego.h +++ b/libfreerdp/core/nego.h @@ -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); diff --git a/libfreerdp/core/nla.c b/libfreerdp/core/nla.c index 970652d4f..426db64eb 100644 --- a/libfreerdp/core/nla.c +++ b/libfreerdp/core/nla.c @@ -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; } diff --git a/libfreerdp/core/rdp.c b/libfreerdp/core/rdp.c index dfa5b20fb..8dd4ccbb5 100644 --- a/libfreerdp/core/rdp.c +++ b/libfreerdp/core/rdp.c @@ -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; } diff --git a/libfreerdp/core/settings.c b/libfreerdp/core/settings.c index 13ea60567..b49c8fd39 100644 --- a/libfreerdp/core/settings.c +++ b/libfreerdp/core/settings.c @@ -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 */ diff --git a/libfreerdp/core/transport.c b/libfreerdp/core/transport.c index 5aefdb936..dc2395cc5 100644 --- a/libfreerdp/core/transport.c +++ b/libfreerdp/core/transport.c @@ -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); diff --git a/libfreerdp/core/transport.h b/libfreerdp/core/transport.h index 1ba273f7a..49532f144 100644 --- a/libfreerdp/core/transport.h +++ b/libfreerdp/core/transport.h @@ -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); diff --git a/libfreerdp/crypto/tls.c b/libfreerdp/crypto/tls.c index 8313a0f72..805105097 100644 --- a/libfreerdp/crypto/tls.c +++ b/libfreerdp/crypto/tls.c @@ -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) { diff --git a/libfreerdp/utils/tcp.c b/libfreerdp/utils/tcp.c index 0f938729e..0938ec7b3 100644 --- a/libfreerdp/utils/tcp.c +++ b/libfreerdp/utils/tcp.c @@ -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; } diff --git a/winpr/libwinpr/synch/timer.c b/winpr/libwinpr/synch/timer.c index 8a4d20631..d6b06691b 100644 --- a/winpr/libwinpr/synch/timer.c +++ b/winpr/libwinpr/synch/timer.c @@ -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; diff --git a/winpr/libwinpr/wtsapi/wtsapi.c b/winpr/libwinpr/wtsapi/wtsapi.c index e428b1aa3..6a8dea945 100644 --- a/winpr/libwinpr/wtsapi/wtsapi.c +++ b/winpr/libwinpr/wtsapi/wtsapi.c @@ -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) {