From 67fb97f68f90f71a753d6679c744699a4ef3eb8a Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Tue, 10 Feb 2015 18:05:40 +0100 Subject: [PATCH 1/5] wtsapi: add TestWtsApiExtra Move wtsapi tests that only make sense when run within a session ("interactive") to TestWtsApiExtra since they either brake automated builds or don't make sense if the return value isn't checked. TestWtsApiExtra is not build by default but can be enabled by specifying -DTESTS_WTSAPI_EXTRA=ON (this option is only available if BUILD_TESTING is enabled). The tests set the ctest label WTSAPI_EXTRA and can therefore also be run explicitly with ctest -L WTSAPI_EXTRA. --- cmake/ConfigOptions.cmake | 3 ++ winpr/libwinpr/wtsapi/test/.gitignore | 3 +- winpr/libwinpr/wtsapi/test/CMakeLists.txt | 36 ++++++++++++- .../test/TestWtsApiExtraDisconnectSession.c | 22 ++++++++ .../TestWtsApiExtraDynamicVirtualChannel.c | 54 +++++++++++++++++++ ...ssion.c => TestWtsApiExtraLogoffSession.c} | 6 +-- .../wtsapi/test/TestWtsApiExtraSendMessage.c | 29 ++++++++++ ...nnel.c => TestWtsApiExtraVirtualChannel.c} | 18 ++++--- 8 files changed, 157 insertions(+), 14 deletions(-) create mode 100644 winpr/libwinpr/wtsapi/test/TestWtsApiExtraDisconnectSession.c create mode 100644 winpr/libwinpr/wtsapi/test/TestWtsApiExtraDynamicVirtualChannel.c rename winpr/libwinpr/wtsapi/test/{TestWtsApiLogoffSession.c => TestWtsApiExtraLogoffSession.c} (67%) create mode 100644 winpr/libwinpr/wtsapi/test/TestWtsApiExtraSendMessage.c rename winpr/libwinpr/wtsapi/test/{TestWtsApiVirtualChannel.c => TestWtsApiExtraVirtualChannel.c} (73%) diff --git a/cmake/ConfigOptions.cmake b/cmake/ConfigOptions.cmake index bb20759f1..282659e01 100644 --- a/cmake/ConfigOptions.cmake +++ b/cmake/ConfigOptions.cmake @@ -1,3 +1,4 @@ +include(CMakeDependentOption) if((CMAKE_SYSTEM_PROCESSOR MATCHES "i386|i686|x86|AMD64") AND (CMAKE_SIZEOF_VOID_P EQUAL 4)) set(TARGET_ARCH "x86") @@ -59,6 +60,8 @@ endif() option(WITH_SMARTCARD_INSPECT "Enable SmartCard API Inspector" OFF) option(BUILD_TESTING "Build unit tests" OFF) +CMAKE_DEPENDENT_OPTION(TESTS_WTSAPI_EXTRA "Build extra WTSAPI tests (interactive)" OFF "BUILD_TESTING" ON) + option(WITH_SAMPLE "Build sample code" OFF) option(WITH_CLIENT "Build client binaries" ON) diff --git a/winpr/libwinpr/wtsapi/test/.gitignore b/winpr/libwinpr/wtsapi/test/.gitignore index 8ac76a2e4..bef7371b7 100644 --- a/winpr/libwinpr/wtsapi/test/.gitignore +++ b/winpr/libwinpr/wtsapi/test/.gitignore @@ -1,3 +1,4 @@ TestWtsApi TestWtsApi.c - +TestWtsApiExtra +TestWtsApiExtra.c diff --git a/winpr/libwinpr/wtsapi/test/CMakeLists.txt b/winpr/libwinpr/wtsapi/test/CMakeLists.txt index b26197ee0..c79d823f6 100644 --- a/winpr/libwinpr/wtsapi/test/CMakeLists.txt +++ b/winpr/libwinpr/wtsapi/test/CMakeLists.txt @@ -8,11 +8,10 @@ set(${MODULE_PREFIX}_TESTS TestWtsApiEnumerateProcesses.c TestWtsApiEnumerateSessions.c TestWtsApiQuerySessionInformation.c - TestWtsApiLogoffSession.c TestWtsApiShutdownSystem.c TestWtsApiSessionNotification.c TestWtsApiWaitSystemEvent.c - TestWtsApiVirtualChannel.c) + ) create_test_sourcelist(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_DRIVER} @@ -32,3 +31,36 @@ endforeach() set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR/Test") +if(TESTS_WTSAPI_EXTRA) + +set(MODULE_NAME "TestWtsApiExtra") +set(MODULE_PREFIX "TEST_WTSAPI_EXTRA") + +set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c) + +set(${MODULE_PREFIX}_TESTS + TestWtsApiExtraDisconnectSession.c + TestWtsApiExtraDynamicVirtualChannel.c + TestWtsApiExtraLogoffSession.c + TestWtsApiExtraSendMessage.c + TestWtsApiExtraVirtualChannel.c + ) + +create_test_sourcelist(${MODULE_PREFIX}_SRCS + ${${MODULE_PREFIX}_DRIVER} + ${${MODULE_PREFIX}_TESTS}) + +add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) + +target_link_libraries(${MODULE_NAME} winpr) + +set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}") + +foreach(test ${${MODULE_PREFIX}_TESTS}) + get_filename_component(TestName ${test} NAME_WE) + add_test(${TestName} ${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME} ${TestName}) + set_tests_properties(${TestName} PROPERTIES LABELS "WTSAPI_EXTRA") +endforeach() + +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR/Test") +endif() diff --git a/winpr/libwinpr/wtsapi/test/TestWtsApiExtraDisconnectSession.c b/winpr/libwinpr/wtsapi/test/TestWtsApiExtraDisconnectSession.c new file mode 100644 index 000000000..ed7373537 --- /dev/null +++ b/winpr/libwinpr/wtsapi/test/TestWtsApiExtraDisconnectSession.c @@ -0,0 +1,22 @@ + +#include +#include +#include + +int TestWtsApiExtraDisconnectSession(int argc, char* argv[]) +{ + BOOL bSuccess; + HANDLE hServer; + + hServer = WTS_CURRENT_SERVER_HANDLE; + + bSuccess = WTSDisconnectSession(hServer, WTS_CURRENT_SESSION, FALSE); + + if (!bSuccess) + { + printf("WTSDisconnectSession failed: %d\n", (int) GetLastError()); + return -1; + } + + return 0; +} diff --git a/winpr/libwinpr/wtsapi/test/TestWtsApiExtraDynamicVirtualChannel.c b/winpr/libwinpr/wtsapi/test/TestWtsApiExtraDynamicVirtualChannel.c new file mode 100644 index 000000000..04c71c09e --- /dev/null +++ b/winpr/libwinpr/wtsapi/test/TestWtsApiExtraDynamicVirtualChannel.c @@ -0,0 +1,54 @@ + +#include +#include +#include + +int TestWtsApiExtraDynamicVirtualChannel(int argc, char* argv[]) +{ + BOOL bSuccess; + ULONG length; + ULONG bytesRead; + ULONG bytesWritten; + BYTE buffer[1024]; + HANDLE hVirtualChannel; + + length = sizeof(buffer); + + hVirtualChannel = WTSVirtualChannelOpenEx( WTS_CURRENT_SESSION, "ECHO",WTS_CHANNEL_OPTION_DYNAMIC); + + + if (hVirtualChannel == INVALID_HANDLE_VALUE) + { + printf("WTSVirtualChannelOpen failed: %d\n", (int) GetLastError()); + return -1; + } + printf("WTSVirtualChannelOpen opend"); + bytesWritten = 0; + bSuccess = WTSVirtualChannelWrite(hVirtualChannel, (PCHAR) buffer, length, &bytesWritten); + + if (!bSuccess) + { + printf("WTSVirtualChannelWrite failed: %d\n", (int) GetLastError()); + return -1; + } + printf("WTSVirtualChannelWrite written"); + + bytesRead = 0; + bSuccess = WTSVirtualChannelRead(hVirtualChannel, 5000, (PCHAR) buffer, length, &bytesRead); + + if (!bSuccess) + { + printf("WTSVirtualChannelRead failed: %d\n", (int) GetLastError()); + return -1; + } + printf("WTSVirtualChannelRead read"); + + if (!WTSVirtualChannelClose(hVirtualChannel)) + { + printf("WTSVirtualChannelClose failed\n"); + return -1; + } + + return 0; +} + diff --git a/winpr/libwinpr/wtsapi/test/TestWtsApiLogoffSession.c b/winpr/libwinpr/wtsapi/test/TestWtsApiExtraLogoffSession.c similarity index 67% rename from winpr/libwinpr/wtsapi/test/TestWtsApiLogoffSession.c rename to winpr/libwinpr/wtsapi/test/TestWtsApiExtraLogoffSession.c index bd7545161..907f268f2 100644 --- a/winpr/libwinpr/wtsapi/test/TestWtsApiLogoffSession.c +++ b/winpr/libwinpr/wtsapi/test/TestWtsApiExtraLogoffSession.c @@ -3,7 +3,7 @@ #include #include -int TestWtsApiLogoffSession(int argc, char* argv[]) +int TestWtsApiExtraLogoffSession(int argc, char* argv[]) { BOOL bSuccess; HANDLE hServer; @@ -12,12 +12,12 @@ int TestWtsApiLogoffSession(int argc, char* argv[]) sessionId = 123; hServer = WTS_CURRENT_SERVER_HANDLE; - bSuccess = WTSLogoffSession(hServer, sessionId, FALSE); + bSuccess = WTSLogoffSession(hServer, WTS_CURRENT_SESSION, FALSE); if (!bSuccess) { printf("WTSLogoffSession failed: %d\n", (int) GetLastError()); - //return -1; + return -1; } return 0; diff --git a/winpr/libwinpr/wtsapi/test/TestWtsApiExtraSendMessage.c b/winpr/libwinpr/wtsapi/test/TestWtsApiExtraSendMessage.c new file mode 100644 index 000000000..06c332ad4 --- /dev/null +++ b/winpr/libwinpr/wtsapi/test/TestWtsApiExtraSendMessage.c @@ -0,0 +1,29 @@ + +#include +#include +#include +#include + +#define TITLE "thats the title" +#define MESSAGE "thats the message" + +int TestWtsApiExtraSendMessage(int argc, char* argv[]) +{ + BOOL bSuccess; + HANDLE hServer; + DWORD result; + + hServer = WTS_CURRENT_SERVER_HANDLE; + + bSuccess = WTSSendMessage(hServer, WTS_CURRENT_SESSION,TITLE,strlen(TITLE) + 1, MESSAGE, strlen(MESSAGE) + 1, MB_CANCELTRYCONTINUE, 3 , &result,TRUE); + + if (!bSuccess) + { + printf("WTSSendMessage failed: %d\n", (int) GetLastError()); + return -1; + } + + printf("WTSSendMessage got result: %d\n", (int) result); + + return 0; +} diff --git a/winpr/libwinpr/wtsapi/test/TestWtsApiVirtualChannel.c b/winpr/libwinpr/wtsapi/test/TestWtsApiExtraVirtualChannel.c similarity index 73% rename from winpr/libwinpr/wtsapi/test/TestWtsApiVirtualChannel.c rename to winpr/libwinpr/wtsapi/test/TestWtsApiExtraVirtualChannel.c index 4a502278a..30bd89783 100644 --- a/winpr/libwinpr/wtsapi/test/TestWtsApiVirtualChannel.c +++ b/winpr/libwinpr/wtsapi/test/TestWtsApiExtraVirtualChannel.c @@ -3,7 +3,7 @@ #include #include -int TestWtsApiVirtualChannel(int argc, char* argv[]) +int TestWtsApiExtraVirtualChannel(int argc, char* argv[]) { BOOL bSuccess; ULONG length; @@ -14,22 +14,23 @@ int TestWtsApiVirtualChannel(int argc, char* argv[]) length = sizeof(buffer); - hVirtualChannel = WTSVirtualChannelOpen(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, "RDPDBG"); + hVirtualChannel = WTSVirtualChannelOpen(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, "sample"); - if (!hVirtualChannel) + if (hVirtualChannel == INVALID_HANDLE_VALUE) { printf("WTSVirtualChannelOpen failed: %d\n", (int) GetLastError()); - //return -1; + return -1; } - + printf("WTSVirtualChannelOpen opend"); bytesWritten = 0; bSuccess = WTSVirtualChannelWrite(hVirtualChannel, (PCHAR) buffer, length, &bytesWritten); if (!bSuccess) { printf("WTSVirtualChannelWrite failed: %d\n", (int) GetLastError()); - //return -1; + return -1; } + printf("WTSVirtualChannelWrite written"); bytesRead = 0; bSuccess = WTSVirtualChannelRead(hVirtualChannel, 5000, (PCHAR) buffer, length, &bytesRead); @@ -37,13 +38,14 @@ int TestWtsApiVirtualChannel(int argc, char* argv[]) if (!bSuccess) { printf("WTSVirtualChannelRead failed: %d\n", (int) GetLastError()); - //return -1; + return -1; } + printf("WTSVirtualChannelRead read"); if (!WTSVirtualChannelClose(hVirtualChannel)) { printf("WTSVirtualChannelClose failed\n"); - //return -1; + return -1; } return 0; From 9b1450f759982ce53049a3ccab1431a9f994aea0 Mon Sep 17 00:00:00 2001 From: Kurt McAlpine Date: Wed, 11 Feb 2015 11:15:25 +1300 Subject: [PATCH 2/5] Replaced ternary operator with condition only --- .../freerdpcore/domain/BookmarkBase.java | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/domain/BookmarkBase.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/domain/BookmarkBase.java index 2347f9f1c..eb8176ca2 100644 --- a/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/domain/BookmarkBase.java +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/domain/BookmarkBase.java @@ -45,13 +45,13 @@ public class BookmarkBase implements Parcelable, Cloneable { } public PerformanceFlags(Parcel parcel) { - remotefx = (parcel.readInt() == 1) ? true : false; - wallpaper = (parcel.readInt() == 1) ? true : false; - theming = (parcel.readInt() == 1) ? true : false; - fullWindowDrag = (parcel.readInt() == 1) ? true : false; - menuAnimations = (parcel.readInt() == 1) ? true : false; - fontSmoothing = (parcel.readInt() == 1) ? true : false; - desktopComposition = (parcel.readInt() == 1) ? true : false; + remotefx = parcel.readInt() == 1; + wallpaper = parcel.readInt() == 1; + theming = parcel.readInt() == 1; + fullWindowDrag = (parcel.readInt() == 1); + menuAnimations = parcel.readInt() == 1; + fontSmoothing = parcel.readInt() == 1; + desktopComposition = parcel.readInt() == 1; } public boolean getRemoteFX() { @@ -286,10 +286,10 @@ public class BookmarkBase implements Parcelable, Cloneable { } // Session Settings public DebugSettings(Parcel parcel) { - asyncChannel = (parcel.readInt() == 1) ? true : false; - asyncTransport = (parcel.readInt() == 1) ? true : false; - asyncInput = (parcel.readInt() == 1) ? true : false; - asyncUpdate = (parcel.readInt() == 1) ? true : false; + asyncChannel = parcel.readInt() == 1; + asyncTransport = parcel.readInt() == 1; + asyncInput = parcel.readInt() == 1; + asyncUpdate = parcel.readInt() == 1; debug = parcel.readInt(); } @@ -393,16 +393,16 @@ public class BookmarkBase implements Parcelable, Cloneable { } public AdvancedSettings(Parcel parcel) { - enable3GSettings = (parcel.readInt() == 1) ? true : false; + enable3GSettings = parcel.readInt() == 1; screen3G = parcel.readParcelable(ScreenSettings.class .getClassLoader()); performance3G = parcel.readParcelable(PerformanceFlags.class .getClassLoader()); - redirectSDCard = (parcel.readInt() == 1) ? true : false; + redirectSDCard = parcel.readInt() == 1; redirectSound = parcel.readInt(); - redirectMicrophone = (parcel.readInt() == 1) ? true : false; + redirectMicrophone = parcel.readInt() == 1; security = parcel.readInt(); - consoleMode = (parcel.readInt() == 1) ? true : false; + consoleMode = parcel.readInt() == 1; remoteProgram = parcel.readString(); workDir = parcel.readString(); } From 6a8d21cab9a3adb5785c5feb7b79c27dd9e3ce3e Mon Sep 17 00:00:00 2001 From: David FORT Date: Wed, 11 Feb 2015 21:38:32 +0100 Subject: [PATCH 3/5] Fix server-side protocol negociation Before this patch, RDP security was (wrongly) the fallback when negociating a security protocol between the client and the server. For example when a client was claiming TLS-only when connecting to a FreeRDP based-server with RDP security only, the result of the negociation was that the server started to do RDP security. The expected behaviour is to send a nego failure packet with error code SSL_NOT_ALLOWED_BY_SERVER. This patch fixes this. We also try to handle all cases of failed negociation and return the corresponding error code. --- libfreerdp/core/connection.c | 40 ++++++++++++++++++++++++++++++------ libfreerdp/core/nego.c | 10 +++------ libfreerdp/core/nego.h | 4 +++- 3 files changed, 40 insertions(+), 14 deletions(-) diff --git a/libfreerdp/core/connection.c b/libfreerdp/core/connection.c index 5841b3dee..fd4d8a091 100644 --- a/libfreerdp/core/connection.c +++ b/libfreerdp/core/connection.c @@ -1011,20 +1011,48 @@ BOOL rdp_server_accept_nego(rdpRdp* rdp, wStream* s) { nego->SelectedProtocol = PROTOCOL_TLS; } - else if ((settings->RdpSecurity) && (nego->SelectedProtocol == PROTOCOL_RDP)) + else if ((settings->RdpSecurity) && (nego->RequestedProtocols == PROTOCOL_RDP)) { nego->SelectedProtocol = PROTOCOL_RDP; } else { + /* + * when here client and server aren't compatible, we select the right + * error message to return to the client in the nego failure packet + */ + nego->SelectedProtocol = PROTOCOL_FAILED_NEGO; + + if (settings->RdpSecurity) + { + WLog_ERR(TAG, "server supports only Standard RDP Security"); + nego->SelectedProtocol |= SSL_NOT_ALLOWED_BY_SERVER; + } + else + { + if (settings->NlaSecurity && !settings->TlsSecurity) + { + WLog_ERR(TAG, "server supports only NLA Security"); + nego->SelectedProtocol |= HYBRID_REQUIRED_BY_SERVER; + } + else + { + WLog_ERR(TAG, "server supports only a SSL based Security (TLS or NLA)"); + nego->SelectedProtocol |= SSL_REQUIRED_BY_SERVER; + } + } + WLog_ERR(TAG, "Protocol security negotiation failure"); } - WLog_INFO(TAG, "Negotiated Security: NLA:%d TLS:%d RDP:%d", - (nego->SelectedProtocol & PROTOCOL_NLA) ? 1 : 0, - (nego->SelectedProtocol & PROTOCOL_TLS) ? 1 : 0, - (nego->SelectedProtocol == PROTOCOL_RDP) ? 1: 0 - ); + if (!(nego->SelectedProtocol & PROTOCOL_FAILED_NEGO)) + { + WLog_INFO(TAG, "Negotiated Security: NLA:%d TLS:%d RDP:%d", + (nego->SelectedProtocol & PROTOCOL_NLA) ? 1 : 0, + (nego->SelectedProtocol & PROTOCOL_TLS) ? 1 : 0, + (nego->SelectedProtocol == PROTOCOL_RDP) ? 1: 0 + ); + } if (!nego_send_negotiation_response(nego)) return FALSE; diff --git a/libfreerdp/core/nego.c b/libfreerdp/core/nego.c index 6655292d2..9c4e117ce 100644 --- a/libfreerdp/core/nego.c +++ b/libfreerdp/core/nego.c @@ -918,20 +918,16 @@ BOOL nego_send_negotiation_response(rdpNego* nego) bm = Stream_GetPosition(s); Stream_Seek(s, length); - if ((nego->SelectedProtocol == PROTOCOL_RDP) && !settings->RdpSecurity) + if (nego->SelectedProtocol & PROTOCOL_FAILED_NEGO) { + UINT32 errorCode = (nego->SelectedProtocol & ~PROTOCOL_FAILED_NEGO); flags = 0; Stream_Write_UINT8(s, TYPE_RDP_NEG_FAILURE); Stream_Write_UINT8(s, flags); /* flags */ Stream_Write_UINT16(s, 8); /* RDP_NEG_DATA length (8) */ - /* - * TODO: Check for other possibilities, - * like SSL_NOT_ALLOWED_BY_SERVER. - */ - WLog_ERR(TAG, "client supports only Standard RDP Security"); - Stream_Write_UINT32(s, SSL_REQUIRED_BY_SERVER); + Stream_Write_UINT32(s, errorCode); length += 8; status = FALSE; } diff --git a/libfreerdp/core/nego.h b/libfreerdp/core/nego.h index 30b082de5..61684e3d9 100644 --- a/libfreerdp/core/nego.h +++ b/libfreerdp/core/nego.h @@ -34,7 +34,9 @@ enum RDP_NEG_PROTOCOLS PROTOCOL_RDP = 0x00000000, PROTOCOL_TLS = 0x00000001, PROTOCOL_NLA = 0x00000002, - PROTOCOL_EXT = 0x00000008 + PROTOCOL_EXT = 0x00000008, + + PROTOCOL_FAILED_NEGO = 0x80000000 /* only used internally, not on the wire */ }; /* Protocol Security Negotiation Failure Codes */ From ee8d0a64405dbd13b1b83835c64e049fde18866b Mon Sep 17 00:00:00 2001 From: bjcollins Date: Wed, 11 Feb 2015 17:24:06 -0600 Subject: [PATCH 4/5] Fix remote app in xfreerdp. Remove use of the visibleOffset, this completely breaks the display of all windows except for the main application window. Instead, just maintain a local offset correction of the windowOffset. Apply workaround to determining the workArea for remote app mode. --- client/X11/xf_monitor.c | 7 +++- client/X11/xf_rail.c | 88 ++++++++++++++++++----------------------- client/X11/xf_window.c | 18 ++++++--- client/X11/xf_window.h | 3 ++ 4 files changed, 60 insertions(+), 56 deletions(-) diff --git a/client/X11/xf_monitor.c b/client/X11/xf_monitor.c index 65689e1c5..0afaafb33 100644 --- a/client/X11/xf_monitor.c +++ b/client/X11/xf_monitor.c @@ -163,7 +163,12 @@ BOOL xf_detect_monitors(xfContext* xfc) } #endif - if (!xf_GetWorkArea(xfc)) + /* WORKAROUND: With Remote Application Mode - using NET_WM_WORKAREA + * causes issues with the ability to fully size the window vertically + * (the bottom of the window area is never updated). So, we just set + * the workArea to match the full Screen width/height. + */ + if (settings->RemoteApplicationMode || !xf_GetWorkArea(xfc)) { xfc->workArea.x = 0; xfc->workArea.y = 0; diff --git a/client/X11/xf_rail.c b/client/X11/xf_rail.c index cad67bea5..8a6330b9c 100644 --- a/client/X11/xf_rail.c +++ b/client/X11/xf_rail.c @@ -113,43 +113,31 @@ void xf_rail_send_client_system_command(xfContext* xfc, UINT32 windowId, UINT16 */ void xf_rail_adjust_position(xfContext* xfc, xfAppWindow* appWindow) { - UINT32 offsetX = 0; - UINT32 offsetY = 0; RAIL_WINDOW_MOVE_ORDER windowMove; if (!appWindow->is_mapped || appWindow->local_move.state != LMS_NOT_ACTIVE) return; /* If current window position disagrees with RDP window position, send update to RDP server */ - if (appWindow->x != appWindow->visibleOffsetX || - appWindow->y != appWindow->visibleOffsetY || + if (appWindow->x != (appWindow->windowOffsetX - appWindow->localWindowOffsetCorrX) || + appWindow->y != (appWindow->windowOffsetY - appWindow->localWindowOffsetCorrY) || appWindow->width != appWindow->windowWidth || appWindow->height != appWindow->windowHeight) { - /* - * Although the rail server can give negative window coordinates when updating windowOffsetX and windowOffsetY, - * we can only send unsigned integers to the rail server. Therefore, we always bring negative coordinates up to 0 - * when attempting to adjust the rail window. - */ - - if (appWindow->windowOffsetX < 0) - offsetX = offsetX - appWindow->windowOffsetX; - - if (appWindow->windowOffsetY < 0) - offsetY = offsetY - appWindow->windowOffsetY; - /* * windowOffset corresponds to the window location on the rail server - * but our local window is based on the visibleOffset since using the windowOffset - * can result in blank areas for a maximized window + * but our local window is based uses a local offset since the windowOffset + * can be negative and but X does not support negative values. Not using an + * offset can result in blank areas for a maximized window */ windowMove.windowId = appWindow->windowId; /* - * Calculate new offsets for the rail server window - * Negative offset correction + rail server window offset + (difference in visibleOffset and new window local offset) + * Calculate new size/position for the rail window(new values for windowOffsetX/windowOffsetY/windowWidth/windowHeight) on the server + * New position is based on: Current local rail window offset + + * Local offset correction(current correction value to translate the local window offset to the server rail window offset) */ - windowMove.left = offsetX + appWindow->windowOffsetX + (appWindow->x - appWindow->visibleOffsetX); - windowMove.top = offsetY + appWindow->windowOffsetY + (appWindow->y - appWindow->visibleOffsetY); + windowMove.left = appWindow->x + appWindow->localWindowOffsetCorrX; + windowMove.top = appWindow->y + appWindow->localWindowOffsetCorrY; windowMove.right = windowMove.left + appWindow->width; windowMove.bottom = windowMove.top + appWindow->height; @@ -162,37 +150,25 @@ void xf_rail_end_local_move(xfContext* xfc, xfAppWindow* appWindow) int x, y; int child_x; int child_y; - UINT32 offsetX = 0; - UINT32 offsetY = 0; unsigned int mask; Window root_window; Window child_window; RAIL_WINDOW_MOVE_ORDER windowMove; rdpInput* input = xfc->instance->input; - /* - * Although the rail server can give negative window coordinates when updating windowOffsetX and windowOffsetY, - * we can only send unsigned integers to the rail server. Therefore, we always bring negative coordinates up to 0 when - * attempting to adjust the rail window. - */ - - if (appWindow->windowOffsetX < 0) - offsetX = offsetX - appWindow->windowOffsetX; - - if (appWindow->windowOffsetY < 0) - offsetY = offsetY - appWindow->windowOffsetY; - /* * For keyboard moves send and explicit update to RDP server */ windowMove.windowId = appWindow->windowId; /* - * Calculate new offsets for the rail server window - * Negative offset correction + rail server window offset + (difference in visibleOffset and new window local offset) + * Calculate new size/position for the rail window(new values for windowOffsetX/windowOffsetY/windowWidth/windowHeight) on the server + * New position is based on: Current local rail window offset + + * Local offset correction(current correction value to translate the local window offset to the server rail window offset) + * */ - windowMove.left = offsetX + appWindow->windowOffsetX + (appWindow->x - appWindow->visibleOffsetX); - windowMove.top = offsetY + appWindow->windowOffsetY + (appWindow->y - appWindow->visibleOffsetY); + windowMove.left = appWindow->x + appWindow->localWindowOffsetCorrX; + windowMove.top = appWindow->y + appWindow->localWindowOffsetCorrY; windowMove.right = windowMove.left + appWindow->width; /* In the update to RDP the position is one past the window */ windowMove.bottom = windowMove.top + appWindow->height; @@ -218,8 +194,8 @@ void xf_rail_end_local_move(xfContext* xfc, xfAppWindow* appWindow) * we can start to receive GDI orders for the new window dimensions before we * receive the RAIL ORDER for the new window size. This avoids that race condition. */ - appWindow->windowOffsetX = offsetX + appWindow->windowOffsetX + (appWindow->x - appWindow->visibleOffsetX); - appWindow->windowOffsetY = offsetY + appWindow->windowOffsetY + (appWindow->y - appWindow->visibleOffsetY); + appWindow->windowOffsetX = windowMove.left; + appWindow->windowOffsetY = windowMove.top; appWindow->windowWidth = appWindow->width; appWindow->windowHeight = appWindow->height; appWindow->local_move.state = LMS_TERMINATING; @@ -320,6 +296,9 @@ static void xf_rail_window_common(rdpContext* context, WINDOW_ORDER_INFO* orderI appWindow->width = appWindow->windowWidth = windowState->windowWidth; appWindow->height = appWindow->windowHeight = windowState->windowHeight; + appWindow->localWindowOffsetCorrX = 0; + appWindow->localWindowOffsetCorrY = 0; + if (fieldFlags & WINDOW_ORDER_FIELD_TITLE) { char* title = NULL; @@ -358,6 +337,21 @@ static void xf_rail_window_common(rdpContext* context, WINDOW_ORDER_INFO* orderI { appWindow->windowOffsetX = windowState->windowOffsetX; appWindow->windowOffsetY = windowState->windowOffsetY; + + /* + * The rail server can give negative window coordinates when updating windowOffsetX and windowOffsetY, + * but we can only send unsigned integers to the rail server. Therefore, we maintain a local offset. + */ + + if (appWindow->windowOffsetX < 0) + appWindow->localWindowOffsetCorrX = 0 - appWindow->windowOffsetX; + else + appWindow->localWindowOffsetCorrX = 0; + + if (appWindow->windowOffsetY < 0) + appWindow->localWindowOffsetCorrY = 0 - appWindow->windowOffsetY; + else + appWindow->localWindowOffsetCorrY = 0; } if (fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE) @@ -491,20 +485,16 @@ static void xf_rail_window_common(rdpContext* context, WINDOW_ORDER_INFO* orderI return; /* Do nothing if window is already in the correct position */ - if (appWindow->x == appWindow->visibleOffsetX && - appWindow->y == appWindow->visibleOffsetY && + if (appWindow->x == (appWindow->windowOffsetX - appWindow->localWindowOffsetCorrX) && + appWindow->y == (appWindow->windowOffsetY - appWindow->localWindowOffsetCorrY) && appWindow->width == appWindow->windowWidth && appWindow->height == appWindow->windowHeight) { - /* - * Just ensure entire window area is updated to handle cases where we - * have drawn locally before getting new bitmap from the server - */ xf_UpdateWindowArea(xfc, appWindow, 0, 0, appWindow->windowWidth, appWindow->windowHeight); return; } - xf_MoveWindow(xfc, appWindow, appWindow->visibleOffsetX, appWindow->visibleOffsetY, + xf_MoveWindow(xfc, appWindow, appWindow->windowOffsetX - appWindow->localWindowOffsetCorrX, appWindow->windowOffsetY - appWindow->localWindowOffsetCorrY, appWindow->windowWidth, appWindow->windowHeight); } diff --git a/client/X11/xf_window.c b/client/X11/xf_window.c index 38c32fabe..c04c979ff 100644 --- a/client/X11/xf_window.c +++ b/client/X11/xf_window.c @@ -886,14 +886,20 @@ void xf_SetWindowVisibilityRects(xfContext* xfc, xfAppWindow* appWindow, RECTANG void xf_UpdateWindowArea(xfContext* xfc, xfAppWindow* appWindow, int x, int y, int width, int height) { int ax, ay; + UINT32 translatedWindowOffsetX; + UINT32 translatedWindowOffsetY; - ax = x + appWindow->visibleOffsetX; - ay = y + appWindow->visibleOffsetY; + /* Translate the server rail window offset to a local offset */ + translatedWindowOffsetX = (appWindow->windowOffsetX - appWindow->localWindowOffsetCorrX); + translatedWindowOffsetY = (appWindow->windowOffsetY - appWindow->localWindowOffsetCorrY); - if (ax + width > appWindow->visibleOffsetX + appWindow->width) - width = (appWindow->visibleOffsetX + appWindow->width - 1) - ax; - if (ay + height > appWindow->visibleOffsetY + appWindow->height) - height = (appWindow->visibleOffsetY + appWindow->height - 1) - ay; + ax = x + translatedWindowOffsetX; + ay = y + translatedWindowOffsetY; + + if (ax + width > translatedWindowOffsetX + appWindow->width) + width = (translatedWindowOffsetX + appWindow->width - 1) - ax; + if (ay + height > translatedWindowOffsetY + appWindow->height) + height = (translatedWindowOffsetY + appWindow->height - 1) - ay; xf_lock_x11(xfc, TRUE); diff --git a/client/X11/xf_window.h b/client/X11/xf_window.h index 990274483..70ae312ee 100644 --- a/client/X11/xf_window.h +++ b/client/X11/xf_window.h @@ -118,6 +118,9 @@ struct xf_app_window UINT32 numVisibilityRects; RECTANGLE_16* visibilityRects; + UINT32 localWindowOffsetCorrX; + UINT32 localWindowOffsetCorrY; + GC gc; int shmid; Window handle; From b302da2e927c35b14c25bdf14e260f32742be309 Mon Sep 17 00:00:00 2001 From: Martin Haimberger Date: Thu, 12 Feb 2015 01:31:00 -0800 Subject: [PATCH 5/5] wtsapi: added handler for LogonUser and LogoffUser --- libfreerdp/core/channels.c | 4 +++- libfreerdp/core/server.c | 9 +++++++++ libfreerdp/core/server.h | 3 +++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/libfreerdp/core/channels.c b/libfreerdp/core/channels.c index 53e36b918..9bc8ee0c7 100644 --- a/libfreerdp/core/channels.c +++ b/libfreerdp/core/channels.c @@ -243,7 +243,9 @@ static WtsApiFunctionTable FreeRDP_WtsApiFunctionTable = FreeRDP_WTSEnableChildSessions, /* EnableChildSessions */ FreeRDP_WTSIsChildSessionsEnabled, /* IsChildSessionsEnabled */ FreeRDP_WTSGetChildSessionId, /* GetChildSessionId */ - FreeRDP_WTSGetActiveConsoleSessionId /* GetActiveConsoleSessionId */ + FreeRDP_WTSGetActiveConsoleSessionId, /* GetActiveConsoleSessionId */ + FreeRDP_WTSLogonUser, + FreeRDP_WTSLogoffUser }; PWtsApiFunctionTable FreeRDP_InitWtsApi(void) diff --git a/libfreerdp/core/server.c b/libfreerdp/core/server.c index 92716fbb8..a9406e4af 100644 --- a/libfreerdp/core/server.c +++ b/libfreerdp/core/server.c @@ -1375,3 +1375,12 @@ DWORD WINAPI FreeRDP_WTSGetActiveConsoleSessionId(void) { return 0xFFFFFFFF; } +BOOL WINAPI FreeRDP_WTSLogoffUser(HANDLE hServer) +{ + return FALSE; +} + +BOOL WINAPI FreeRDP_WTSLogonUser(HANDLE hServer, LPCSTR username, LPCSTR password, LPCSTR domain) +{ + return FALSE; +} diff --git a/libfreerdp/core/server.h b/libfreerdp/core/server.h index 53ce96101..7d53cc9b4 100644 --- a/libfreerdp/core/server.h +++ b/libfreerdp/core/server.h @@ -173,4 +173,7 @@ BOOL CDECL FreeRDP_WTSGetChildSessionId(PULONG pSessionId); DWORD WINAPI FreeRDP_WTSGetActiveConsoleSessionId(void); +BOOL WINAPI FreeRDP_WTSLogoffUser(HANDLE hServer); +BOOL WINAPI FreeRDP_WTSLogonUser(HANDLE hServer, LPCSTR username, LPCSTR password, LPCSTR domain); + #endif /* FREERDP_CORE_SERVER_H */