From a56e3f259b7a50b125b18d1cb164ad5625a179be Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Fri, 15 Nov 2013 16:19:49 +0100 Subject: [PATCH 01/32] winpr: disabled schannel test not practicable for now since it requires local key setup --- winpr/libwinpr/sspi/test/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/winpr/libwinpr/sspi/test/CMakeLists.txt b/winpr/libwinpr/sspi/test/CMakeLists.txt index 809a0a614..4ea3599d6 100644 --- a/winpr/libwinpr/sspi/test/CMakeLists.txt +++ b/winpr/libwinpr/sspi/test/CMakeLists.txt @@ -10,7 +10,7 @@ set(${MODULE_PREFIX}_TESTS TestInitializeSecurityContext.c TestAcquireCredentialsHandle.c TestNTLM.c - TestSchannel.c) + ) create_test_sourcelist(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_DRIVER} From 440d945f5d1f53a8d9ba905fcd982224c1b2e4b4 Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Fri, 15 Nov 2013 16:58:54 +0100 Subject: [PATCH 02/32] client/common: fixed TestClientRdpFile test Unified ascii and unicode string handling. --- client/common/file.c | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/client/common/file.c b/client/common/file.c index 4ca74fea6..75f2c5e1e 100644 --- a/client/common/file.c +++ b/client/common/file.c @@ -226,43 +226,43 @@ BOOL freerdp_client_rdp_file_set_string(rdpFile* file, char* name, char* value) #endif if (_stricmp(name, "username") == 0) - file->Username = value; + file->Username = _strdup(value); else if (_stricmp(name, "domain") == 0) - file->Domain = value; + file->Domain = _strdup(value); else if (_stricmp(name, "full address") == 0) - file->FullAddress = value; + file->FullAddress = _strdup(value); else if (_stricmp(name, "alternate full address") == 0) - file->AlternateFullAddress = value; + file->AlternateFullAddress = _strdup(value); else if (_stricmp(name, "usbdevicestoredirect") == 0) - file->UsbDevicesToRedirect = value; + file->UsbDevicesToRedirect = _strdup(value); else if (_stricmp(name, "loadbalanceinfo") == 0) - file->LoadBalanceInfo = value; + file->LoadBalanceInfo = _strdup(value); else if (_stricmp(name, "remoteapplicationname") == 0) - file->RemoteApplicationName = value; + file->RemoteApplicationName = _strdup(value); else if (_stricmp(name, "remoteapplicationicon") == 0) - file->RemoteApplicationIcon = value; + file->RemoteApplicationIcon = _strdup(value); else if (_stricmp(name, "remoteapplicationprogram") == 0) - file->RemoteApplicationProgram = value; + file->RemoteApplicationProgram = _strdup(value); else if (_stricmp(name, "remoteapplicationfile") == 0) - file->RemoteApplicationFile = value; + file->RemoteApplicationFile = _strdup(value); else if (_stricmp(name, "remoteapplicationguid") == 0) - file->RemoteApplicationGuid = value; + file->RemoteApplicationGuid = _strdup(value); else if (_stricmp(name, "remoteapplicationcmdline") == 0) - file->RemoteApplicationCmdLine = value; + file->RemoteApplicationCmdLine = _strdup(value); else if (_stricmp(name, "alternate shell") == 0) - file->AlternateShell = value; + file->AlternateShell = _strdup(value); else if (_stricmp(name, "shell working directory") == 0) - file->ShellWorkingDirectory = value; + file->ShellWorkingDirectory = _strdup(value); else if (_stricmp(name, "gatewayhostname") == 0) - file->GatewayHostname = value; + file->GatewayHostname = _strdup(value); else if (_stricmp(name, "kdcproxyname") == 0) - file->KdcProxyName = value; + file->KdcProxyName = _strdup(value); else if (_stricmp(name, "drivestoredirect") == 0) - file->DrivesToRedirect = value; + file->DrivesToRedirect = _strdup(value); else if (_stricmp(name, "devicestoredirect") == 0) - file->DevicesToRedirect = value; + file->DevicesToRedirect = _strdup(value); else if (_stricmp(name, "winposstr") == 0) - file->WinPosStr = value; + file->WinPosStr = _strdup(value); else return FALSE; @@ -297,10 +297,10 @@ void freerdp_client_parse_rdp_file_string_unicode(rdpFile* file, WCHAR* name, WC WideCharToMultiByte(CP_UTF8, 0, value, length, valueA, length, NULL, NULL); valueA[length] = '\0'; - if (!freerdp_client_rdp_file_set_string(file, nameA, valueA)) - free(valueA); + freerdp_client_rdp_file_set_string(file, nameA, valueA); free(nameA); + free(valueA); } void freerdp_client_parse_rdp_file_string_ascii(rdpFile* file, char* name, char* value) From 693506ab9f70b6d81d4d1b05fdd37bb78647338b Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Mon, 18 Nov 2013 09:28:17 +0100 Subject: [PATCH 03/32] Added script to automate gprof reporting. --- scripts/gprof_generate.sh.cmake | 56 +++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100755 scripts/gprof_generate.sh.cmake diff --git a/scripts/gprof_generate.sh.cmake b/scripts/gprof_generate.sh.cmake new file mode 100755 index 000000000..bf2cc5ed3 --- /dev/null +++ b/scripts/gprof_generate.sh.cmake @@ -0,0 +1,56 @@ +#!/bin/bash +# +# This script tries to pull gprof profiling information generated by aFreeRDP +# from the target using adb and generating human readable profiling data from +# it. +# +# Any arguments supplied to the script will be appended to adb. +# +# Requirements: +# - ANDROID_SDK is set to the android SDK directory or adb is in path. +# + +if [ -d $ANDROID_SDK ]; then + ADB=$ANDROID_SDK/platform-tools/adb +else + ADB=`which adb` +fi + +GCC=@CMAKE_C_COMPILER@ +GPROF=${GCC/gcc/gprof} +LIB=@CMAKE_BINARY_DIR@/client/Android/FreeRDPCore/jni/armeabi-v7a/libfreerdp-android.so + +if [ ! -f $LIB ]; then + echo "Missing libfreerdp-android.so" + echo "Please build the project first." + exit -1 +fi + +if [ ! -f $GPROF ]; then + echo "gprof could not be found at $GPROF." + echo "Please assure, that you are using a GCC based android toolchain." + exit -2 +fi + +if [ ! -f $ADB ] || [ ! -x $ADB ]; then + echo "adb could not be found." + echo "assure, that either ANDROID_SDK is set to the path of your android SDK" + echo "or that adb is in path." + exit -3 +fi + +# Do the acutal work in a temporary directory. +SRC=`mktemp -d` +cd $SRC +$ADB $@ pull /sdcard/gmon.out +if [ ! -f gmon.out ]; then + echo "Could not pull profiling information from device!" + RC=-4 +else + echo "Pulled profiling information from device, starting conversion..." + $GPROF $LIB -PprofCount -QprofCount -P__gnu_mcount_nc -Q__gnu_mcount_nc + RC=0 +fi +rm -rf $SRC + +exit $RC From 4dd596c1d52274f3c48f62062ca62dd26cda18c9 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Mon, 18 Nov 2013 10:27:11 +0100 Subject: [PATCH 04/32] Updated script to set up external android libraries. --- scripts/android_setup_build_env.sh | 51 +++++++++++++++++++----------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/scripts/android_setup_build_env.sh b/scripts/android_setup_build_env.sh index d96f5de72..d7f151d32 100755 --- a/scripts/android_setup_build_env.sh +++ b/scripts/android_setup_build_env.sh @@ -10,28 +10,26 @@ # Usage: # android_setup_build_env.sh -OPENSSL_SCM=https://github.com/bmiklautz/android-external-openssl-ndk-static +OPENSSL_SCM=https://github.com/akallabeth/openssl-android NDK_PROFILER_SCM=https://github.com/richq/android-ndk-profiler SCRIPT_NAME=`basename $0` - if [ $# -ne 1 ]; then - - echo "Missing command line argument." - echo "$SCRIPT_NAME " - exit -1 + echo "Missing command line argument, current directory as root." + ROOT=`pwd` + ROOT=$ROOT/external +else + ROOT=`readlink -f $1` fi -if [ ! -d $1 ]; then - echo "Argument '$1' is not a directory." +if [ ! -d $ROOT ]; then + echo "Argument '$ROOT' is not a directory." exit -2 fi -SRC=`realpath $1` - -echo "Using '$SRC' as root." +echo "Using '$ROOT' as root." echo "Preparing OpenSSL..." -OPENSSL_SRC=$SRC/external/openssl +OPENSSL_SRC=$ROOT/openssl-build if [ -d $OPENSSL_SRC ]; then cd $OPENSSL_SRC git pull @@ -39,21 +37,35 @@ if [ -d $OPENSSL_SRC ]; then else git clone $OPENSSL_SCM $OPENSSL_SRC RETVAL=$? - cd $OPENSSL_SRC fi if [ $RETVAL -ne 0 ]; then echo "Failed to execute git command [$RETVAL]" exit -3 fi -ndk-build -RETVAL=$? + +cd $OPENSSL_SRC +make clean +# The makefile has a bug, which aborts during +# first compilation. Rerun make to build the whole lib. +make +make +RETVAL=0 # TODO: Check, why 2 is returned. if [ $RETVAL -ne 0 ]; then - echo "Failed to execute ndk-build command [$RETVAL]" + echo "Failed to execute make command [$RETVAL]" exit -4 fi +# Copy the created library to the default openssl directory, +# so that CMake will detect it automatically. +SSL_ROOT=`find $OPENSSL_SRC -type d -name "openssl-?.?.*"` +rm -f $ROOT/openssl +ln -s $SSL_ROOT $ROOT/openssl +mkdir -p $ROOT/openssl/obj/local/armeabi/ +cp $ROOT/openssl/libssl.a $ROOT/openssl/obj/local/armeabi/ +cp $ROOT/openssl/libcrypto.a $ROOT/openssl/obj/local/armeabi/ + echo "Preparing NDK profiler..." -NDK_PROFILER_SRC=$SRC/external/android-ndk-profiler +NDK_PROFILER_SRC=$ROOT/android-ndk-profiler if [ -d $NDK_PROFILER_SRC ]; then cd $NDK_PROFILER_SRC git pull @@ -61,13 +73,14 @@ if [ -d $NDK_PROFILER_SRC ]; then else git clone $NDK_PROFILER_SCM $NDK_PROFILER_SRC RETVAL=$? - cd $NDK_PROFILER_SRC fi if [ $RETVAL -ne 0 ]; then echo "Failed to execute git command [$RETVAL]" exit -5 fi -ndk-build +cd $NDK_PROFILER_SRC +ndk-build V=1 APP_ABI=armeabi-v7a clean +ndk-build V=1 APP_ABI=armeabi-v7a RETVAL=$? if [ $RETVAL -ne 0 ]; then echo "Failed to execute ndk-build command [$RETVAL]" From 90f1be51dd2370d66ea30b4a2cc94f23da36c8a3 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Mon, 18 Nov 2013 10:27:45 +0100 Subject: [PATCH 05/32] Updated android build readme. --- docs/README.android | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/README.android b/docs/README.android index a0db45320..17cf83c91 100644 --- a/docs/README.android +++ b/docs/README.android @@ -29,14 +29,14 @@ FreeRDP requires openssl libraries for building but they are not part of the Android NDK and therefore they need to be prebuild manually. Multiple source versions and builds of static openssl libraries are floating around. At the time of writing we have tested and used: -https://github.com/bmiklautz/Android-external-openssl-ndk-static. +https://github.com/bmiklautz/Android-external-openssl-ndk-static +https://github.com/akallabeth/openssl-android However, any other static build should work as well. To build openssl: -git clone git@github.com:bmiklautz/android-external-openssl-ndk-static.git -cd android-external-openssl-ndk-static -ndk-build # found in the Android NDK +From the project root folder run './scripts/android_setup_build_env.sh' +This will set up openssl and gprof helper libraries as required for FreeRDP. Building From 755c66f7283fb4f69fc9ca152b5a68326820a260 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Mon, 18 Nov 2013 10:28:59 +0100 Subject: [PATCH 06/32] Updated readme. --- docs/README.android | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/README.android b/docs/README.android index 17cf83c91..6896f8d89 100644 --- a/docs/README.android +++ b/docs/README.android @@ -35,6 +35,7 @@ However, any other static build should work as well. To build openssl: +Set up ANDROID_NDK and ANDROID_SDK to the absolute paths on your machine. From the project root folder run './scripts/android_setup_build_env.sh' This will set up openssl and gprof helper libraries as required for FreeRDP. From 391615bcfb237f03a6430ab6e7ce845a6f4cc3e9 Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Mon, 18 Nov 2013 12:50:32 +0100 Subject: [PATCH 07/32] android build: generate gprof file only if WITH_GPROF --- CMakeLists.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1638f0fdc..7d9966037 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -301,8 +301,9 @@ endif() set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/client/Android/FreeRDPCore/jni/${ANDROID_ABI}) CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/scripts/regenerate_jni_headers.sh.cmake ${CMAKE_BINARY_DIR}/scripts/regenerate_jni_headers.sh @ONLY) - CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/scripts/gprof_generate.sh.cmake - ${CMAKE_BINARY_DIR}/scripts/gprof_generate.sh @ONLY) + if (WITH_GPROF) + CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/scripts/gprof_generate.sh.cmake ${CMAKE_BINARY_DIR}/scripts/gprof_generate.sh @ONLY) + endif(WITH_GPROF) endif() From 1262d236a33f83ffece2933da1d633a4f23793a7 Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Mon, 18 Nov 2013 12:53:17 +0100 Subject: [PATCH 08/32] android build: ignore renderscript toolchain When detecting toolchains ignore renderscript because its not a compiler toolchain. --- cmake/AndroidToolchain.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/AndroidToolchain.cmake b/cmake/AndroidToolchain.cmake index f98385764..05d7574c3 100644 --- a/cmake/AndroidToolchain.cmake +++ b/cmake/AndroidToolchain.cmake @@ -639,6 +639,7 @@ if( BUILD_WITH_STANDALONE_TOOLCHAIN ) endif() macro( __GLOB_NDK_TOOLCHAINS __availableToolchainsVar __availableToolchainsLst __toolchain_subpath ) + list( REMOVE_ITEM ${__availableToolchainsLst} "renderscript" ) foreach( __toolchain ${${__availableToolchainsLst}} ) if( "${__toolchain}" MATCHES "-clang3[.][0-9]$" AND NOT EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/${__toolchain}${__toolchain_subpath}" ) string( REGEX REPLACE "-clang3[.][0-9]$" "-4.6" __gcc_toolchain "${__toolchain}" ) From 7457dd3de4719746948436d8664858bdfcd0c2dc Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Mon, 18 Nov 2013 19:58:01 +0100 Subject: [PATCH 09/32] android build: Fixed program path detection --- CMakeLists.txt | 4 ++-- client/Android/CMakeLists.txt | 11 +++++------ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d9966037..70603918b 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -68,11 +68,11 @@ endif() # Allow to search the host machine for git if(ANDROID OR IOS) - SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER, BOTH) + SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH) endif(ANDROID OR IOS) include(GetGitRevisionDescription) if(ANDROID OR IOS) - SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER, ONLY) + SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY) endif(ANDROID OR IOS) git_describe(GIT_REVISION --match "[0-9]*" --abbrev=4 --tags --always) diff --git a/client/Android/CMakeLists.txt b/client/Android/CMakeLists.txt index 4e7874a1d..05fe21dbd 100644 --- a/client/Android/CMakeLists.txt +++ b/client/Android/CMakeLists.txt @@ -19,11 +19,10 @@ if (NOT ANDROID_NDK) message(FATAL_ERROR "ANDROID_NDK not set but required for building android native library.") endif() -SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER, BOTH) -find_program(NDK_COMMAND ndk-build) -SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER, ONLY) +set(CMAKE_PROGRAM_PATH ${ANDROID_NDK}) +find_program(NDK_COMMAND ndk-build CMAKE_FIND_ROOT_PATH_BOTH) -if(NDK_COMMAND STREQUAL "ANT_COMMAND-NOTFOUND") +if(NDK_COMMAND STREQUAL "NDK_COMMAND-NOTFOUND") message(FATAL_ERROR "ndk-build not found but required to build native lib") endif() @@ -34,9 +33,9 @@ if(ANDROID_BUILD_JAVA) endif() # And isn't shiped with the android ndk/sdk so # we need to find it on the local machine - SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER, BOTH) + SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH) find_program(ANT_COMMAND ant) - SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER, ONLY) + SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY) if(ANT_COMMAND STREQUAL "ANT_COMMAND-NOTFOUND") message(FATAL_ERROR "ant not found but required to build android java") From 0ddf2922f9c1a528f9445972d3b6abe6c35e4b25 Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Mon, 18 Nov 2013 20:23:00 +0100 Subject: [PATCH 10/32] android build: fixes for out of tree builds Fixed the last places to be able to build android out of tree with Unix Makefiles generator. Note: When using eclipse use in source tree builds. --- client/Android/FreeRDPCore/ant.properties.cmake | 2 +- client/Android/aFreeRDP/CMakeLists.txt | 8 ++++++++ client/Android/aFreeRDP/ant.properties.cmake | 3 +-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/client/Android/FreeRDPCore/ant.properties.cmake b/client/Android/FreeRDPCore/ant.properties.cmake index 13e49ee77..83cd860ec 100644 --- a/client/Android/FreeRDPCore/ant.properties.cmake +++ b/client/Android/FreeRDPCore/ant.properties.cmake @@ -15,6 +15,6 @@ # 'key.alias' for the name of the key to use. # The password will be asked during the build when you use the 'release' target. build.dir=@CMAKE_CURRENT_BINARY_DIR@ -source.dir=@CMAKE_CURRENT_SOURCE_DIR@/src +source.path=@CMAKE_CURRENT_SOURCE_DIR@/src:@CMAKE_CURRENT_BINARY_DIR@/src out.dir=@CMAKE_CURRENT_BINARY_DIR@/bin diff --git a/client/Android/aFreeRDP/CMakeLists.txt b/client/Android/aFreeRDP/CMakeLists.txt index 597349aac..388ffe33c 100644 --- a/client/Android/aFreeRDP/CMakeLists.txt +++ b/client/Android/aFreeRDP/CMakeLists.txt @@ -26,6 +26,14 @@ CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/build.xml.cmake ${CMAKE_CURRENT_BINARY_DIR}/build.xml @ONLY) CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/project.properties.cmake ${CMAKE_CURRENT_BINARY_DIR}/project.properties @ONLY) + +# The following is required if building android out of tree +if (${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_BINARY_DIR}) +set (AFREERDP_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src") +else() +set (AFREERDP_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src:${CMAKE_CURRENT_SOURCE_DIR}/../FreeRDPCore/src") +endif() + CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/ant.properties.cmake ${CMAKE_CURRENT_BINARY_DIR}/ant.properties @ONLY) diff --git a/client/Android/aFreeRDP/ant.properties.cmake b/client/Android/aFreeRDP/ant.properties.cmake index 13e49ee77..1cbbf9ffc 100644 --- a/client/Android/aFreeRDP/ant.properties.cmake +++ b/client/Android/aFreeRDP/ant.properties.cmake @@ -15,6 +15,5 @@ # 'key.alias' for the name of the key to use. # The password will be asked during the build when you use the 'release' target. build.dir=@CMAKE_CURRENT_BINARY_DIR@ -source.dir=@CMAKE_CURRENT_SOURCE_DIR@/src +source.dir=@AFREERDP_SOURCE_DIR@ out.dir=@CMAKE_CURRENT_BINARY_DIR@/bin - From 261651b43b3e1a200fa3372d9119c3b34187a269 Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Mon, 18 Nov 2013 20:29:00 +0100 Subject: [PATCH 11/32] core: don't use c99 style initialization fixes #1602 --- libfreerdp/core/input.c | 2 +- libfreerdp/core/update.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libfreerdp/core/input.c b/libfreerdp/core/input.c index fc5b5f4ee..4e001ba03 100644 --- a/libfreerdp/core/input.c +++ b/libfreerdp/core/input.c @@ -494,7 +494,7 @@ static void input_free_queued_message(void *obj) rdpInput* input_new(rdpRdp* rdp) { - const wObject cb = { .fnObjectFree = input_free_queued_message }; + const wObject cb = { NULL, NULL, NULL, input_free_queued_message , NULL }; rdpInput* input; input = (rdpInput*) malloc(sizeof(rdpInput)); diff --git a/libfreerdp/core/update.c b/libfreerdp/core/update.c index a4cebdf08..97e5fa789 100644 --- a/libfreerdp/core/update.c +++ b/libfreerdp/core/update.c @@ -1553,7 +1553,7 @@ static void update_free_queued_message(void *obj) rdpUpdate* update_new(rdpRdp* rdp) { - const wObject cb = { .fnObjectFree = update_free_queued_message }; + const wObject cb = { NULL, NULL, NULL, update_free_queued_message, NULL }; rdpUpdate* update; update = (rdpUpdate*) malloc(sizeof(rdpUpdate)); From c03a2e54972a12c1d2d8da2d19f914390c918b75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 19 Nov 2013 14:29:31 -0500 Subject: [PATCH 12/32] channels/rdpsnd: add option for configuring audio quality mode --- channels/rdpsnd/client/rdpsnd_main.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/channels/rdpsnd/client/rdpsnd_main.c b/channels/rdpsnd/client/rdpsnd_main.c index 1fc4c9e25..aedf8bf59 100644 --- a/channels/rdpsnd/client/rdpsnd_main.c +++ b/channels/rdpsnd/client/rdpsnd_main.c @@ -65,6 +65,7 @@ struct rdpsnd_plugin HANDLE ScheduleThread; BYTE cBlockNo; + UINT16 wQualityMode; int wCurrentFormatNo; AUDIO_FORMAT* ServerFormats; @@ -139,7 +140,7 @@ void rdpsnd_send_quality_mode_pdu(rdpsndPlugin* rdpsnd) Stream_Write_UINT8(pdu, SNDC_QUALITYMODE); /* msgType */ Stream_Write_UINT8(pdu, 0); /* bPad */ Stream_Write_UINT16(pdu, 4); /* BodySize */ - Stream_Write_UINT16(pdu, HIGH_QUALITY); /* wQualityMode */ + Stream_Write_UINT16(pdu, rdpsnd->wQualityMode); /* wQualityMode */ Stream_Write_UINT16(pdu, 0); /* Reserved */ rdpsnd_virtual_channel_write(rdpsnd, pdu); @@ -597,6 +598,7 @@ COMMAND_LINE_ARGUMENT_A rdpsnd_args[] = { "rate", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "rate" }, { "channel", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "channel" }, { "latency", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "latency" }, + { "quality", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "quality mode" }, { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } }; @@ -606,10 +608,13 @@ static void rdpsnd_process_addin_args(rdpsndPlugin* rdpsnd, ADDIN_ARGV* args) DWORD flags; COMMAND_LINE_ARGUMENT_A* arg; + rdpsnd->wQualityMode = HIGH_QUALITY; /* default quality mode */ + flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON; status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv, rdpsnd_args, flags, rdpsnd, NULL, NULL); + if (status < 0) return; @@ -646,6 +651,24 @@ static void rdpsnd_process_addin_args(rdpsndPlugin* rdpsnd, ADDIN_ARGV* args) { rdpsnd->latency = atoi(arg->Value); } + CommandLineSwitchCase(arg, "quality") + { + int wQualityMode = DYNAMIC_QUALITY; + + if (_stricmp(arg->Value, "dynamic") == 0) + wQualityMode = DYNAMIC_QUALITY; + else if (_stricmp(arg->Value, "medium") == 0) + wQualityMode = MEDIUM_QUALITY; + else if (_stricmp(arg->Value, "high") == 0) + wQualityMode = HIGH_QUALITY; + else + wQualityMode = atoi(arg->Value); + + if ((wQualityMode < 0) || (wQualityMode > 2)) + wQualityMode = DYNAMIC_QUALITY; + + rdpsnd->wQualityMode = (UINT16) wQualityMode; + } CommandLineSwitchDefault(arg) { From aa999c5f620261050ab098bc7c3ffbca5569ffe3 Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Tue, 19 Nov 2013 20:49:41 +0100 Subject: [PATCH 13/32] android toolchain: fixed cmake syntax warning --- cmake/AndroidToolchain.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/AndroidToolchain.cmake b/cmake/AndroidToolchain.cmake index 05d7574c3..13330c6ab 100644 --- a/cmake/AndroidToolchain.cmake +++ b/cmake/AndroidToolchain.cmake @@ -722,7 +722,7 @@ __INIT_VARIABLE( ANDROID_ABI OBSOLETE_ARM_TARGET OBSOLETE_ARM_TARGETS VALUES ${A # verify that target ABI is supported list( FIND ANDROID_SUPPORTED_ABIS "${ANDROID_ABI}" __androidAbiIdx ) if( __androidAbiIdx EQUAL -1 ) - string( REPLACE ";" "\", \"", PRINTABLE_ANDROID_SUPPORTED_ABIS "${ANDROID_SUPPORTED_ABIS}" ) + string( REPLACE ";" "\", \"" PRINTABLE_ANDROID_SUPPORTED_ABIS "${ANDROID_SUPPORTED_ABIS}" ) message( FATAL_ERROR "Specified ANDROID_ABI = \"${ANDROID_ABI}\" is not supported by this cmake toolchain or your NDK/toolchain. Supported values are: \"${PRINTABLE_ANDROID_SUPPORTED_ABIS}\" " ) From c065b0a72f52ea0ee12e4057a0bbad57bb2aed20 Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Tue, 19 Nov 2013 20:51:51 +0100 Subject: [PATCH 14/32] android toolchain: support for ndk r9b --- cmake/AndroidToolchain.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/AndroidToolchain.cmake b/cmake/AndroidToolchain.cmake index 13330c6ab..71353e553 100644 --- a/cmake/AndroidToolchain.cmake +++ b/cmake/AndroidToolchain.cmake @@ -326,7 +326,7 @@ endif() # rpath makes low sence for Android set( CMAKE_SKIP_RPATH TRUE CACHE BOOL "If set, runtime paths are not added when using shared libraries." ) -set( ANDROID_SUPPORTED_NDK_VERSIONS ${ANDROID_EXTRA_NDK_VERSIONS} -r9 -r8e -r8d -r8c -r8b -r8 -r7c -r7b -r7 -r6b -r6 -r5c -r5b -r5 "" ) +set( ANDROID_SUPPORTED_NDK_VERSIONS ${ANDROID_EXTRA_NDK_VERSIONS} -r9b -r9 -r8e -r8d -r8c -r8b -r8 -r7c -r7b -r7 -r6b -r6 -r5c -r5b -r5 "" ) if(NOT DEFINED ANDROID_NDK_SEARCH_PATHS) if( CMAKE_HOST_WIN32 ) file( TO_CMAKE_PATH "$ENV{PROGRAMFILES}" ANDROID_NDK_SEARCH_PATHS ) @@ -639,7 +639,6 @@ if( BUILD_WITH_STANDALONE_TOOLCHAIN ) endif() macro( __GLOB_NDK_TOOLCHAINS __availableToolchainsVar __availableToolchainsLst __toolchain_subpath ) - list( REMOVE_ITEM ${__availableToolchainsLst} "renderscript" ) foreach( __toolchain ${${__availableToolchainsLst}} ) if( "${__toolchain}" MATCHES "-clang3[.][0-9]$" AND NOT EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/${__toolchain}${__toolchain_subpath}" ) string( REGEX REPLACE "-clang3[.][0-9]$" "-4.6" __gcc_toolchain "${__toolchain}" ) @@ -691,6 +690,7 @@ if( BUILD_WITH_ANDROID_NDK ) endif() __LIST_FILTER( __availableToolchainsLst "^[.]" ) __LIST_FILTER( __availableToolchainsLst "llvm" ) + __LIST_FILTER( __availableToolchainsLst "renderscript" ) __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH}" ) if( NOT __availableToolchains AND NOT ANDROID_NDK_TOOLCHAINS_SUBPATH STREQUAL ANDROID_NDK_TOOLCHAINS_SUBPATH2 ) __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH2}" ) From c1fa455c30b9ee484a16a14347846c080b0f4895 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 19 Nov 2013 15:31:38 -0500 Subject: [PATCH 15/32] channels/rdpsnd: add wlog debug output --- channels/rdpsnd/client/rdpsnd_main.c | 42 ++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/channels/rdpsnd/client/rdpsnd_main.c b/channels/rdpsnd/client/rdpsnd_main.c index aedf8bf59..fad04b364 100644 --- a/channels/rdpsnd/client/rdpsnd_main.c +++ b/channels/rdpsnd/client/rdpsnd_main.c @@ -33,6 +33,7 @@ #include #include +#include #include #include #include @@ -62,6 +63,7 @@ struct rdpsnd_plugin UINT32 OpenHandle; wMessagePipe* MsgPipe; + wLog* log; HANDLE ScheduleThread; BYTE cBlockNo; @@ -92,7 +94,7 @@ struct rdpsnd_plugin rdpsndDevicePlugin* device; }; -static void rdpsnd_send_wave_confirm_pdu(rdpsndPlugin* rdpsnd, UINT16 wTimeStamp, BYTE cConfirmedBlockNo); +static void rdpsnd_confirm_wave(rdpsndPlugin* rdpsnd, RDPSND_WAVE* wave); static void* rdpsnd_schedule_thread(void* arg) { @@ -124,9 +126,10 @@ static void* rdpsnd_schedule_thread(void* arg) Sleep(wTimeDiff); } - rdpsnd_send_wave_confirm_pdu(rdpsnd, wave->wTimeStampB, wave->cBlockNo); - free(wave); + rdpsnd_confirm_wave(rdpsnd, wave); + message.wParam = NULL; + free(wave); } return NULL; @@ -143,6 +146,8 @@ void rdpsnd_send_quality_mode_pdu(rdpsndPlugin* rdpsnd) Stream_Write_UINT16(pdu, rdpsnd->wQualityMode); /* wQualityMode */ Stream_Write_UINT16(pdu, 0); /* Reserved */ + WLog_Print(rdpsnd->log, WLOG_DEBUG, "QualityMode: %d", rdpsnd->wQualityMode); + rdpsnd_virtual_channel_write(rdpsnd, pdu); } @@ -259,6 +264,8 @@ void rdpsnd_send_client_audio_formats(rdpsndPlugin* rdpsnd) Stream_Write(pdu, clientFormat->data, clientFormat->cbSize); } + WLog_Print(rdpsnd->log, WLOG_DEBUG, "Client Audio Formats"); + rdpsnd_virtual_channel_write(rdpsnd, pdu); } @@ -311,6 +318,8 @@ void rdpsnd_recv_server_audio_formats_pdu(rdpsndPlugin* rdpsnd, wStream* s) rdpsnd_select_supported_audio_formats(rdpsnd); + WLog_Print(rdpsnd->log, WLOG_DEBUG, "Server Audio Formats"); + rdpsnd_send_client_audio_formats(rdpsnd); if (wVersion >= 6) @@ -331,6 +340,9 @@ void rdpsnd_send_training_confirm_pdu(rdpsndPlugin* rdpsnd, UINT16 wTimeStamp, U Stream_Write_UINT16(pdu, wTimeStamp); Stream_Write_UINT16(pdu, wPackSize); + WLog_Print(rdpsnd->log, WLOG_DEBUG, "Training Response: wTimeStamp: %d wPackSize: %d", + wTimeStamp, wPackSize); + rdpsnd_virtual_channel_write(rdpsnd, pdu); } @@ -342,6 +354,9 @@ static void rdpsnd_recv_training_pdu(rdpsndPlugin* rdpsnd, wStream* s) Stream_Read_UINT16(s, wTimeStamp); Stream_Read_UINT16(s, wPackSize); + WLog_Print(rdpsnd->log, WLOG_DEBUG, "Training Request: wTimeStamp: %d wPackSize: %d", + wTimeStamp, wPackSize); + rdpsnd_send_training_confirm_pdu(rdpsnd, wTimeStamp, wPackSize); } @@ -362,6 +377,9 @@ static void rdpsnd_recv_wave_info_pdu(rdpsndPlugin* rdpsnd, wStream* s, UINT16 B format = &rdpsnd->ClientFormats[wFormatNo]; + WLog_Print(rdpsnd->log, WLOG_DEBUG, "WaveInfo: cBlockNo: %d wFormatNo: %d", + rdpsnd->cBlockNo, wFormatNo); + if (!rdpsnd->isOpen) { rdpsnd->isOpen = TRUE; @@ -400,6 +418,14 @@ void rdpsnd_send_wave_confirm_pdu(rdpsndPlugin* rdpsnd, UINT16 wTimeStamp, BYTE rdpsnd_virtual_channel_write(rdpsnd, pdu); } +void rdpsnd_confirm_wave(rdpsndPlugin* rdpsnd, RDPSND_WAVE* wave) +{ + WLog_Print(rdpsnd->log, WLOG_DEBUG, "WaveConfirm: cBlockNo: %d wTimeStamp: %d wTimeDiff: %d", + wave->cBlockNo, wave->wTimeStampB, wave->wTimeStampB - wave->wTimeStampA); + + rdpsnd_send_wave_confirm_pdu(rdpsnd, wave->wTimeStampB, wave->cBlockNo); +} + static void rdpsnd_device_send_wave_confirm_pdu(rdpsndDevicePlugin* device, RDPSND_WAVE* wave) { MessageQueue_Post(device->rdpsnd->MsgPipe->Out, NULL, 0, (void*) wave, NULL); @@ -439,6 +465,9 @@ static void rdpsnd_recv_wave_pdu(rdpsndPlugin* rdpsnd, wStream* s) format = &rdpsnd->ClientFormats[rdpsnd->wCurrentFormatNo]; wave->wAudioLength = rdpsnd_compute_audio_time_length(format, size); + WLog_Print(rdpsnd->log, WLOG_DEBUG, "Wave: cBlockNo: %d wTimeStamp: %d", + wave->cBlockNo, wave->wTimeStampA); + if (!rdpsnd->device) { free(wave); @@ -469,6 +498,8 @@ static void rdpsnd_recv_wave_pdu(rdpsndPlugin* rdpsnd, wStream* s) static void rdpsnd_recv_close_pdu(rdpsndPlugin* rdpsnd) { + WLog_Print(rdpsnd->log, WLOG_DEBUG, "Close"); + if (rdpsnd->device) { IFCALL(rdpsnd->device->Close, rdpsnd->device); @@ -483,6 +514,8 @@ static void rdpsnd_recv_volume_pdu(rdpsndPlugin* rdpsnd, wStream* s) Stream_Read_UINT32(s, dwVolume); + WLog_Print(rdpsnd->log, WLOG_DEBUG, "Volume: 0x%04X", dwVolume); + if (rdpsnd->device) { IFCALL(rdpsnd->device->SetVolume, rdpsnd->device, dwVolume); @@ -1041,6 +1074,9 @@ int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) CopyMemory(&(rdpsnd->channelEntryPoints), pEntryPoints, pEntryPoints->cbSize); + 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); From 690a6b624db56bdc3fc80a58dd90d6df8aedf2db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 20 Nov 2013 15:21:29 -0500 Subject: [PATCH 16/32] libfreerdp-crypto: don't report SSL_ERROR_SYSCALL with errno value 0 as error --- libfreerdp/crypto/tls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfreerdp/crypto/tls.c b/libfreerdp/crypto/tls.c index b7cda06df..4d5e8c4ca 100644 --- a/libfreerdp/crypto/tls.c +++ b/libfreerdp/crypto/tls.c @@ -400,7 +400,7 @@ int tls_read(rdpTls* tls, BYTE* data, int length) break; case SSL_ERROR_SYSCALL: - if (errno == EAGAIN) + if ((errno == EAGAIN) || (errno == 0)) { status = 0; } From b79ce071378472a61240df4914f0a6194084b856 Mon Sep 17 00:00:00 2001 From: Zhang Zhaolong Date: Thu, 21 Nov 2013 13:28:54 +0800 Subject: [PATCH 17/32] fix memory realloc size error. --- client/Windows/wf_cliprdr.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/client/Windows/wf_cliprdr.c b/client/Windows/wf_cliprdr.c index 1cd11aaae..bc286d2dd 100644 --- a/client/Windows/wf_cliprdr.c +++ b/client/Windows/wf_cliprdr.c @@ -83,7 +83,7 @@ static void map_ensure_capacity(cliprdrContext *cliprdr) { if (cliprdr->map_size >= cliprdr->map_capacity) { cliprdr->format_mappings = (formatMapping *)realloc(cliprdr->format_mappings, - cliprdr->map_capacity * 2); + sizeof(formatMapping) * cliprdr->map_capacity * 2); cliprdr->map_capacity *= 2; } } @@ -475,6 +475,7 @@ static void wf_cliprdr_process_cb_format_list_event(wfContext *wfc, RDP_CB_FORMA map = &cliprdr->format_mappings[i++]; Read_UINT32(p, map->remote_format_id); + map->name = NULL; /* get name_len */ for (tmp = p, name_len = 0; tmp + 1 < end_mark; tmp += 2, name_len += 2) { @@ -508,6 +509,7 @@ static void wf_cliprdr_process_cb_format_list_event(wfContext *wfc, RDP_CB_FORMA map = &cliprdr->format_mappings[i++]; Read_UINT32(p, map->remote_format_id); + map->name = NULL; if (event->raw_format_unicode) { /* get name_len, in bytes, if the file name is truncated, no terminated null will be included. */ From c196e0b2c18e4d2a015c1dda58fbe7fb5e09efa2 Mon Sep 17 00:00:00 2001 From: Zhang Zhaolong Date: Thu, 21 Nov 2013 13:35:21 +0800 Subject: [PATCH 18/32] fix name length to copy. --- client/Windows/wf_cliprdr.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/client/Windows/wf_cliprdr.c b/client/Windows/wf_cliprdr.c index bc286d2dd..6aad04e88 100644 --- a/client/Windows/wf_cliprdr.c +++ b/client/Windows/wf_cliprdr.c @@ -143,10 +143,19 @@ static void cliprdr_send_format_list(cliprdrContext *cliprdr) ZeroMemory(format_data + len, 32); if (format >= CF_MAX) { static wchar_t wName[MAX_PATH] = {0}; + int wLen; ZeroMemory(wName, MAX_PATH*2); GetClipboardFormatNameW(format, wName, MAX_PATH); - memcpy(format_data + len, wName, 32); /* truncate the long name to 32 bytes */ + wLen = wcslen(wName); + if (wLen < 16) + { + memcpy(format_data + len, wName, wLen * sizeof(WCHAR)); + } + else + { + memcpy(format_data + len, wName, 32); /* truncate the long name to 32 bytes */ + } } len += 32; } From 304fb6d13729ea5ab0dbc0ca1573f2adee0944ea Mon Sep 17 00:00:00 2001 From: Zhang Zhaolong Date: Thu, 21 Nov 2013 13:45:16 +0800 Subject: [PATCH 19/32] reformat coding styles. --- client/Windows/wf_cliprdr.c | 176 +++++++++++++++++++++++++----------- 1 file changed, 121 insertions(+), 55 deletions(-) diff --git a/client/Windows/wf_cliprdr.c b/client/Windows/wf_cliprdr.c index 6aad04e88..af72fc464 100644 --- a/client/Windows/wf_cliprdr.c +++ b/client/Windows/wf_cliprdr.c @@ -51,10 +51,13 @@ static UINT32 get_local_format_id_by_name(cliprdrContext *cliprdr, void *format_ formatMapping *map; int i; - for (i = 0; i < cliprdr->map_size; i++) { + for (i = 0; i < cliprdr->map_size; i++) + { map = &cliprdr->format_mappings[i]; - if ((cliprdr->capabilities & CAPS_USE_LONG_FORMAT_NAMES) != 0) { - if (map->name) { + if ((cliprdr->capabilities & CAPS_USE_LONG_FORMAT_NAMES) != 0) + { + if (map->name) + { if (memcmp(map->name, format_name, wcslen((LPCWSTR)format_name)) == 0) return map->local_format_id; } @@ -69,9 +72,11 @@ static UINT32 get_remote_format_id(cliprdrContext *cliprdr, UINT32 local_format) formatMapping *map; int i; - for (i = 0; i < cliprdr->map_size; i++) { + for (i = 0; i < cliprdr->map_size; i++) + { map = &cliprdr->format_mappings[i]; - if (map->local_format_id == local_format) { + if (map->local_format_id == local_format) + { return map->remote_format_id; } } @@ -81,7 +86,8 @@ static UINT32 get_remote_format_id(cliprdrContext *cliprdr, UINT32 local_format) static void map_ensure_capacity(cliprdrContext *cliprdr) { - if (cliprdr->map_size >= cliprdr->map_capacity) { + if (cliprdr->map_size >= cliprdr->map_capacity) + { cliprdr->format_mappings = (formatMapping *)realloc(cliprdr->format_mappings, sizeof(formatMapping) * cliprdr->map_capacity * 2); cliprdr->map_capacity *= 2; @@ -93,13 +99,16 @@ static void clear_format_map(cliprdrContext *cliprdr) formatMapping *map; int i; - if (cliprdr->format_mappings) { - for (i = 0; i < cliprdr->map_size; i++) { + if (cliprdr->format_mappings) + { + for (i = 0; i < cliprdr->map_size; i++) + { map = &cliprdr->format_mappings[i]; map->remote_format_id = 0; map->local_format_id = 0; - if (map->name) { + if (map->name) + { free(map->name); map->name = NULL; } @@ -119,7 +128,8 @@ static void cliprdr_send_format_list(cliprdrContext *cliprdr) int len = 0; int namelen; - if (!OpenClipboard(cliprdr->hwndClipboard)) { + if (!OpenClipboard(cliprdr->hwndClipboard)) + { DEBUG_CLIPRDR("OpenClipboard failed with 0x%x", GetLastError()); return; } @@ -130,18 +140,24 @@ static void cliprdr_send_format_list(cliprdrContext *cliprdr) format_data = (BYTE *)calloc(1, data_size); assert(format_data != NULL); - while (format = EnumClipboardFormats(format)) { + while (format = EnumClipboardFormats(format)) + { Write_UINT32(format_data + len, format); len += 4; - if ((cliprdr->capabilities & CAPS_USE_LONG_FORMAT_NAMES) != 0) { - if (format >= CF_MAX) { + if ((cliprdr->capabilities & CAPS_USE_LONG_FORMAT_NAMES) != 0) + { + if (format >= CF_MAX) + { namelen = GetClipboardFormatNameW(format, (LPWSTR)(format_data + len), MAX_PATH); len += namelen * sizeof(WCHAR); } len += 2; /* end of Unicode string */ - } else { + } + else + { ZeroMemory(format_data + len, 32); - if (format >= CF_MAX) { + if (format >= CF_MAX) + { static wchar_t wName[MAX_PATH] = {0}; int wLen; @@ -205,7 +221,8 @@ static LRESULT CALLBACK cliprdr_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM { static cliprdrContext *cliprdr = NULL; - switch (Msg) { + switch (Msg) + { case WM_CREATE: cliprdr = (cliprdrContext *)((CREATESTRUCT *)lParam)->lpCreateParams; cliprdr->hwndNextViewer = SetClipboardViewer(hWnd); @@ -221,17 +238,23 @@ static LRESULT CALLBACK cliprdr_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM break; case WM_CHANGECBCHAIN: - if (cliprdr->hwndNextViewer == (HWND)wParam) { + if (cliprdr->hwndNextViewer == (HWND)wParam) + { cliprdr->hwndNextViewer = (HWND)lParam; - } else if (cliprdr->hwndNextViewer != NULL) { + } + else if (cliprdr->hwndNextViewer != NULL) + { SendMessage(cliprdr->hwndNextViewer, Msg, wParam, lParam); } break; case WM_DRAWCLIPBOARD: - if (cliprdr->channel_initialized) { - if (GetClipboardOwner() != cliprdr->hwndClipboard) { - if (!cliprdr->hmem) { + if (cliprdr->channel_initialized) + { + if (GetClipboardOwner() != cliprdr->hwndClipboard) + { + if (!cliprdr->hmem) + { cliprdr->hmem = GlobalFree(cliprdr->hmem); } cliprdr_send_format_list(cliprdr); @@ -243,7 +266,8 @@ static LRESULT CALLBACK cliprdr_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM case WM_RENDERALLFORMATS: /* discard all contexts in clipboard */ - if (!OpenClipboard(cliprdr->hwndClipboard)) { + if (!OpenClipboard(cliprdr->hwndClipboard)) + { DEBUG_CLIPRDR("OpenClipboard failed with 0x%x", GetLastError()); break; } @@ -252,12 +276,14 @@ static LRESULT CALLBACK cliprdr_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM break; case WM_RENDERFORMAT: - if (cliprdr_send_data_request(cliprdr, (UINT32)wParam) != 0) { + if (cliprdr_send_data_request(cliprdr, (UINT32)wParam) != 0) + { DEBUG_CLIPRDR("error: cliprdr_send_data_request failed."); break; } - if (SetClipboardData(wParam, cliprdr->hmem) == NULL) { + if (SetClipboardData(wParam, cliprdr->hmem) == NULL) + { DEBUG_CLIPRDR("SetClipboardData failed with 0x%x", GetLastError()); cliprdr->hmem = GlobalFree(cliprdr->hmem); } @@ -301,7 +327,8 @@ static int create_cliprdr_window(cliprdrContext *cliprdr) L"rdpclip", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, GetModuleHandle(NULL), cliprdr); - if (cliprdr->hwndClipboard == NULL) { + if (cliprdr->hwndClipboard == NULL) + { DEBUG_CLIPRDR("error: CreateWindowEx failed with %x.", GetLastError()); return -1; } @@ -317,16 +344,21 @@ static void *cliprdr_thread_func(void *arg) int ret; HRESULT result; - if ((ret = create_cliprdr_window(cliprdr)) != 0) { + if ((ret = create_cliprdr_window(cliprdr)) != 0) + { DEBUG_CLIPRDR("error: create clipboard window failed."); return NULL; } - while ((mcode = GetMessage(&msg, 0, 0, 0) != 0)) { - if (mcode == -1) { + while ((mcode = GetMessage(&msg, 0, 0, 0) != 0)) + { + if (mcode == -1) + { DEBUG_CLIPRDR("error: clipboard thread GetMessage failed."); break; - } else { + } + else + { TranslateMessage(&msg); DispatchMessage(&msg); } @@ -371,7 +403,8 @@ void wf_cliprdr_uninit(wfContext* wfc) if (cliprdr->hwndClipboard) PostMessage(cliprdr->hwndClipboard, WM_QUIT, 0, 0); - if (cliprdr->cliprdr_thread) { + if (cliprdr->cliprdr_thread) + { WaitForSingleObject(cliprdr->cliprdr_thread, INFINITE); CloseHandle(cliprdr->cliprdr_thread); } @@ -415,23 +448,32 @@ static void wf_cliprdr_process_cb_data_request_event(wfContext *wfc, RDP_CB_DATA local_format = event->format; - if (local_format == 0x9) { /* FORMAT_ID_PALETTE */ + if (local_format == 0x9) /* FORMAT_ID_PALETTE */ + { /* TODO: implement this */ DEBUG_CLIPRDR("FORMAT_ID_PALETTE is not supported yet."); - } else if (local_format == 0x3) { /* FORMAT_ID_MATEFILE */ + } + else if (local_format == 0x3) /* FORMAT_ID_MATEFILE */ + { /* TODO: implement this */ DEBUG_CLIPRDR("FORMAT_ID_MATEFILE is not supported yet."); - } else if (local_format == RegisterClipboardFormatW(L"FileGroupDescriptorW")) { + } + else if (local_format == RegisterClipboardFormatW(L"FileGroupDescriptorW")) + { /* TODO: implement this */ DEBUG_CLIPRDR("FileGroupDescriptorW is not supported yet."); - } else { - if (!OpenClipboard(cliprdr->hwndClipboard)) { + } + else + { + if (!OpenClipboard(cliprdr->hwndClipboard)) + { DEBUG_CLIPRDR("OpenClipboard failed with 0x%x", GetLastError()); return; } hClipdata = GetClipboardData(event->format); - if (!hClipdata) { + if (!hClipdata) + { DEBUG_CLIPRDR("GetClipboardData failed."); CloseClipboard(); return; @@ -475,8 +517,10 @@ static void wf_cliprdr_process_cb_format_list_event(wfContext *wfc, RDP_CB_FORMA clear_format_map(cliprdr); - if ((cliprdr->capabilities & CAPS_USE_LONG_FORMAT_NAMES) != 0) { - while (left_size >= 6) { + if ((cliprdr->capabilities & CAPS_USE_LONG_FORMAT_NAMES) != 0) + { + while (left_size >= 6) + { formatMapping *map; BYTE* tmp; int name_len; @@ -487,17 +531,21 @@ static void wf_cliprdr_process_cb_format_list_event(wfContext *wfc, RDP_CB_FORMA map->name = NULL; /* get name_len */ - for (tmp = p, name_len = 0; tmp + 1 < end_mark; tmp += 2, name_len += 2) { + for (tmp = p, name_len = 0; tmp + 1 < end_mark; tmp += 2, name_len += 2) + { if (*((unsigned short*) tmp) == 0) break; } - if (name_len > 0) { + if (name_len > 0) + { map->name = malloc(name_len + 2); memcpy(map->name, p, name_len + 2); map->local_format_id = RegisterClipboardFormatW((LPCWSTR)map->name); - } else { + } + else + { map->local_format_id = map->remote_format_id; } @@ -508,10 +556,13 @@ static void wf_cliprdr_process_cb_format_list_event(wfContext *wfc, RDP_CB_FORMA map_ensure_capacity(cliprdr); } - } else { + } + else + { int k; - for (k = 0; k < event->raw_format_data_size / 36; k++) { + for (k = 0; k < event->raw_format_data_size / 36; k++) + { formatMapping *map; int name_len; @@ -520,32 +571,43 @@ static void wf_cliprdr_process_cb_format_list_event(wfContext *wfc, RDP_CB_FORMA Read_UINT32(p, map->remote_format_id); map->name = NULL; - if (event->raw_format_unicode) { + if (event->raw_format_unicode) + { /* get name_len, in bytes, if the file name is truncated, no terminated null will be included. */ - for (name_len = 0; name_len < 32; name_len += 2) { + for (name_len = 0; name_len < 32; name_len += 2) + { if (*((unsigned short*) (p + name_len)) == 0) break; } - if (name_len > 0) { + if (name_len > 0) + { map->name = calloc(1, name_len + 2); memcpy(map->name, p, name_len); map->local_format_id = RegisterClipboardFormatW((LPCWSTR)map->name); - } else { + } + else + { map->local_format_id = map->remote_format_id; } - } else { + } + else + { /* get name_len, in bytes, if the file name is truncated, no terminated null will be included. */ - for (name_len = 0; name_len < 32; name_len += 1) { + for (name_len = 0; name_len < 32; name_len += 1) + { if (*((unsigned char*) (p + name_len)) == 0) break; } - if (name_len > 0) { + if (name_len > 0) + { map->name = calloc(1, name_len + 1); memcpy(map->name, p, name_len); map->local_format_id = RegisterClipboardFormatA((LPCSTR)map->name); - } else { + } + else + { map->local_format_id = map->remote_format_id; } } @@ -556,18 +618,21 @@ static void wf_cliprdr_process_cb_format_list_event(wfContext *wfc, RDP_CB_FORMA } } - if (!OpenClipboard(cliprdr->hwndClipboard)) { + if (!OpenClipboard(cliprdr->hwndClipboard)) + { DEBUG_CLIPRDR("OpenClipboard failed with 0x%x", GetLastError()); return; } - if (!EmptyClipboard()) { + if (!EmptyClipboard()) + { DEBUG_CLIPRDR("EmptyClipboard failed with 0x%x", GetLastError()); CloseClipboard(); return; } - for (i = 0; i < cliprdr->map_size; i++) { + for (i = 0; i < cliprdr->map_size; i++) + { SetClipboardData(cliprdr->format_mappings[i].local_format_id, NULL); } @@ -591,7 +656,8 @@ static void wf_cliprdr_process_cb_data_response_event(wfContext *wfc, RDP_CB_DAT void wf_process_cliprdr_event(wfContext *wfc, wMessage *event) { - switch (GetMessageType(event->id)) { + switch (GetMessageType(event->id)) + { case CliprdrChannel_ClipCaps: wf_cliprdr_process_cb_clip_caps_event(wfc, (RDP_CB_CLIP_CAPS *)event); break; From f7cf0eace75873fff38248054b696220d35758df Mon Sep 17 00:00:00 2001 From: Zhang Zhaolong Date: Thu, 21 Nov 2013 14:26:29 +0800 Subject: [PATCH 20/32] check return value. --- client/Windows/wf_cliprdr.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/client/Windows/wf_cliprdr.c b/client/Windows/wf_cliprdr.c index af72fc464..216332f95 100644 --- a/client/Windows/wf_cliprdr.c +++ b/client/Windows/wf_cliprdr.c @@ -101,7 +101,7 @@ static void clear_format_map(cliprdrContext *cliprdr) if (cliprdr->format_mappings) { - for (i = 0; i < cliprdr->map_size; i++) + for (i = 0; i < cliprdr->map_capacity; i++) { map = &cliprdr->format_mappings[i]; map->remote_format_id = 0; @@ -155,15 +155,13 @@ static void cliprdr_send_format_list(cliprdrContext *cliprdr) } else { - ZeroMemory(format_data + len, 32); if (format >= CF_MAX) { static wchar_t wName[MAX_PATH] = {0}; int wLen; ZeroMemory(wName, MAX_PATH*2); - GetClipboardFormatNameW(format, wName, MAX_PATH); - wLen = wcslen(wName); + wLen = GetClipboardFormatNameW(format, wName, MAX_PATH); if (wLen < 16) { memcpy(format_data + len, wName, wLen * sizeof(WCHAR)); @@ -205,6 +203,8 @@ int cliprdr_send_data_request(cliprdrContext *cliprdr, UINT32 format) return -1; cliprdr_event->format = get_remote_format_id(cliprdr, format); + if (cliprdr_event->format == 0) + return -1; ret = freerdp_channels_send_event(cliprdr->channels, (wMessage *)cliprdr_event); @@ -227,7 +227,8 @@ static LRESULT CALLBACK cliprdr_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM cliprdr = (cliprdrContext *)((CREATESTRUCT *)lParam)->lpCreateParams; cliprdr->hwndNextViewer = SetClipboardViewer(hWnd); - if (cliprdr->hwndNextViewer == NULL && GetLastError() != 0) { + if (cliprdr->hwndNextViewer == NULL && GetLastError() != 0) + { DEBUG_CLIPRDR("error: SetClipboardViewer failed with 0x%0x.", GetLastError()); } cliprdr->hwndClipboard = hWnd; From bf065f3e892e0a94e442de9a7155a7ac170f2add Mon Sep 17 00:00:00 2001 From: eroen Date: Thu, 21 Nov 2013 11:35:53 +0100 Subject: [PATCH 21/32] ffmpeg-2 -- AVCODEC_MAX_AUDIO_FRAME_SIZE deprecated: http://git.videolan.org/?p=ffmpeg.git;a=commit;h=0eea212943544d40f99b05571aa7159d78667154 broken with libavcodec 54 --- channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c b/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c index adf8e04f1..0d5b95608 100644 --- a/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c +++ b/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c @@ -43,6 +43,12 @@ #define AVMEDIA_TYPE_AUDIO 1 #endif +#if LIBAVCODEC_VERSION_MAJOR < 54 +#define MAX_AUDIO_FRAME_SIZE AVCODEC_MAX_AUDIO_FRAME_SIZE +#else +#define MAX_AUDIO_FRAME_SIZE 192000 +#endif + typedef struct _TSMFFFmpegDecoder { ITSMFDecoder iface; @@ -351,7 +357,7 @@ static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder* decoder, const BYTE* data, UI #endif if (mdecoder->decoded_size_max == 0) - mdecoder->decoded_size_max = AVCODEC_MAX_AUDIO_FRAME_SIZE + 16; + mdecoder->decoded_size_max = MAX_AUDIO_FRAME_SIZE + 16; mdecoder->decoded_data = malloc(mdecoder->decoded_size_max); ZeroMemory(mdecoder->decoded_data, mdecoder->decoded_size_max); /* align the memory for SSE2 needs */ @@ -363,7 +369,7 @@ static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder* decoder, const BYTE* data, UI while (src_size > 0) { /* Ensure enough space for decoding */ - if (mdecoder->decoded_size_max - mdecoder->decoded_size < AVCODEC_MAX_AUDIO_FRAME_SIZE) + if (mdecoder->decoded_size_max - mdecoder->decoded_size < MAX_AUDIO_FRAME_SIZE) { mdecoder->decoded_size_max = mdecoder->decoded_size_max * 2 + 16; mdecoder->decoded_data = realloc(mdecoder->decoded_data, mdecoder->decoded_size_max); From cbcf0de3fac985afaeeef7daf104c94ad8cdca26 Mon Sep 17 00:00:00 2001 From: eroen Date: Thu, 21 Nov 2013 13:14:04 +0100 Subject: [PATCH 22/32] ffmpeg-2 -- dsp_mask deprecated: http://git.videolan.org/?p=ffmpeg.git;a=commit;h=95510be8c35753da8f48062b28b65e7acdab965f broken with libavcodec 55 --- channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c b/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c index 0d5b95608..1f99ec31b 100644 --- a/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c +++ b/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c @@ -104,6 +104,7 @@ static BOOL tsmf_ffmpeg_init_audio_stream(ITSMFDecoder* decoder, const TS_AM_MED mdecoder->codec_context->channels = media_type->Channels; mdecoder->codec_context->block_align = media_type->BlockAlign; +#if LIBAVCODEC_VERSION_MAJOR < 55 #ifdef AV_CPU_FLAG_SSE2 mdecoder->codec_context->dsp_mask = AV_CPU_FLAG_SSE2 | AV_CPU_FLAG_MMX2; #else @@ -113,6 +114,13 @@ static BOOL tsmf_ffmpeg_init_audio_stream(ITSMFDecoder* decoder, const TS_AM_MED mdecoder->codec_context->dsp_mask = FF_MM_SSE2 | FF_MM_MMX2; #endif #endif +#else /* LIBAVCODEC_VERSION_MAJOR < 55 */ +#ifdef AV_CPU_FLAG_SSE2 + av_set_cpu_flags_mask(AV_CPU_FLAG_SSE2 | AV_CPU_FLAG_MMX2); +#else + av_set_cpu_flags_mask(FF_MM_SSE2 | FF_MM_MMX2); +#endif +#endif /* LIBAVCODEC_VERSION_MAJOR < 55 */ return TRUE; } From 6fe23e1a3860528a8ecdfc8e9ccfdbd0e3945869 Mon Sep 17 00:00:00 2001 From: eroen Date: Thu, 21 Nov 2013 13:26:03 +0100 Subject: [PATCH 23/32] ffmpeg-2 -- CodecID deprecated: http://git.videolan.org/?p=ffmpeg.git;a=commit;h=104e10fb426f903ba9157fdbfe30292d0e4c3d72 broken with libavcodec 55 --- channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c b/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c index 1f99ec31b..09b4f685c 100644 --- a/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c +++ b/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c @@ -54,7 +54,11 @@ typedef struct _TSMFFFmpegDecoder ITSMFDecoder iface; int media_type; +#if LIBAVCODEC_VERSION_MAJOR < 55 enum CodecID codec_id; +#else + enum AVCodecID codec_id; +#endif AVCodecContext* codec_context; AVCodec* codec; AVFrame* frame; From 204842561b9bbbaf8b5bf9c324d474da14040be8 Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Thu, 21 Nov 2013 20:06:21 +0100 Subject: [PATCH 24/32] winpr-thread: fixed bugs in _CreateProcessExA * don't run fork/exec if the command isn't found * return from forked process with exit --- winpr/libwinpr/thread/process.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/winpr/libwinpr/thread/process.c b/winpr/libwinpr/thread/process.c index cac0f73e6..d3945f28e 100644 --- a/winpr/libwinpr/thread/process.c +++ b/winpr/libwinpr/thread/process.c @@ -180,13 +180,14 @@ BOOL _CreateProcessExA(HANDLE hToken, DWORD dwLogonFlags, pid_t pid; int flags; int numArgs; - LPSTR* pArgs; - char** envp; + LPSTR* pArgs = NULL; + char** envp = NULL; char* filename = NULL; WINPR_THREAD* thread; WINPR_PROCESS* process; WINPR_ACCESS_TOKEN* token; LPTCH lpszEnvironmentBlock; + BOOL ret = FALSE; pid = 0; envp = NULL; @@ -210,6 +211,8 @@ BOOL _CreateProcessExA(HANDLE hToken, DWORD dwLogonFlags, } filename = FindApplicationPath(pArgs[0]); + if (NULL == filename) + goto finish; /* fork and exec */ @@ -218,7 +221,7 @@ BOOL _CreateProcessExA(HANDLE hToken, DWORD dwLogonFlags, if (pid < 0) { /* fork failure */ - return FALSE; + goto finish; } if (pid == 0) @@ -252,7 +255,8 @@ BOOL _CreateProcessExA(HANDLE hToken, DWORD dwLogonFlags, if (execve(filename, pArgs, envp) < 0) { - return FALSE; + /* execve failed - end the process */ + _exit(1); } } else @@ -263,7 +267,9 @@ BOOL _CreateProcessExA(HANDLE hToken, DWORD dwLogonFlags, process = (WINPR_PROCESS*) malloc(sizeof(WINPR_PROCESS)); if (!process) - return FALSE; + { + goto finish; + } ZeroMemory(process, sizeof(WINPR_PROCESS)); @@ -278,7 +284,9 @@ BOOL _CreateProcessExA(HANDLE hToken, DWORD dwLogonFlags, ZeroMemory(thread, sizeof(WINPR_THREAD)); if (!thread) - return FALSE; + { + goto finish; + } WINPR_HANDLE_SET_TYPE(thread, HANDLE_TYPE_THREAD); @@ -289,7 +297,13 @@ BOOL _CreateProcessExA(HANDLE hToken, DWORD dwLogonFlags, lpProcessInformation->dwProcessId = (DWORD) pid; lpProcessInformation->dwThreadId = (DWORD) pid; - free(filename); + ret = TRUE; + +finish: + if (filename) + { + free(filename); + } if (pArgs) { @@ -312,7 +326,7 @@ BOOL _CreateProcessExA(HANDLE hToken, DWORD dwLogonFlags, free(envp); } - return TRUE; + return ret; } BOOL CreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, From 76c842285d21086c0b6d491af973da845690c3e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Fri, 22 Nov 2013 12:11:39 -0500 Subject: [PATCH 25/32] channels/rdpsnd: initial attempt at adding GSM610 support --- CMakeLists.txt | 5 + channels/rdpsnd/client/pulse/CMakeLists.txt | 6 +- channels/rdpsnd/client/pulse/rdpsnd_pulse.c | 141 +++++++++++++++----- cmake/FindGSM.cmake | 13 ++ config.h.in | 1 + libfreerdp/codec/audio.c | 32 ++++- 6 files changed, 164 insertions(+), 34 deletions(-) create mode 100644 cmake/FindGSM.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index e57790cba..c2316d5d2 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -381,6 +381,10 @@ set(JPEG_FEATURE_TYPE "OPTIONAL") set(JPEG_FEATURE_PURPOSE "codec") set(JPEG_FEATURE_DESCRIPTION "use JPEG library") +set(GSM_FEATURE_TYPE "OPTIONAL") +set(GSM_FEATURE_PURPOSE "codec") +set(GSM_FEATURE_DESCRIPTION "GSM audio codec library") + if(WIN32) set(X11_FEATURE_TYPE "DISABLED") set(ZLIB_FEATURE_TYPE "DISABLED") @@ -445,6 +449,7 @@ find_feature(FFmpeg ${FFMPEG_FEATURE_TYPE} ${FFMPEG_FEATURE_PURPOSE} ${FFMPEG_FE find_feature(Gstreamer ${GSTREAMER_FEATURE_TYPE} ${GSTREAMER_FEATURE_PURPOSE} ${GSTREAMER_FEATURE_DESCRIPTION}) find_feature(JPEG ${JPEG_FEATURE_TYPE} ${JPEG_FEATURE_PURPOSE} ${JPEG_FEATURE_DESCRIPTION}) +find_feature(GSM ${GSM_FEATURE_TYPE} ${GSM_FEATURE_PURPOSE} ${GSM_FEATURE_DESCRIPTION}) if(TARGET_ARCH MATCHES "x86|x64") if (NOT APPLE) diff --git a/channels/rdpsnd/client/pulse/CMakeLists.txt b/channels/rdpsnd/client/pulse/CMakeLists.txt index d652ba234..6b6de1ecc 100644 --- a/channels/rdpsnd/client/pulse/CMakeLists.txt +++ b/channels/rdpsnd/client/pulse/CMakeLists.txt @@ -32,7 +32,11 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MODULE freerdp MODULES freerdp-codec freerdp-utils) -set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${PULSE_LIBRARY}) +list(APPEND ${MODULE_PREFIX}_LIBS ${PULSE_LIBRARY}) + +if(GSM_FOUND) + list(APPEND ${MODULE_PREFIX}_LIBS ${GSM_LIBRARIES}) +endif() target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) diff --git a/channels/rdpsnd/client/pulse/rdpsnd_pulse.c b/channels/rdpsnd/client/pulse/rdpsnd_pulse.c index cb0bea63d..e20cce9be 100644 --- a/channels/rdpsnd/client/pulse/rdpsnd_pulse.c +++ b/channels/rdpsnd/client/pulse/rdpsnd_pulse.c @@ -26,10 +26,15 @@ #include #include +#include #include #include +#ifdef WITH_GSM +#include +#endif + #include #include #include @@ -52,6 +57,11 @@ struct rdpsnd_pulse_plugin int latency; FREERDP_DSP_CONTEXT* dsp_context; + +#ifdef WITH_GSM + gsm gsm_context; + wStream* gsmBuffer; +#endif }; static void rdpsnd_pulse_context_state_callback(pa_context* context, void* userdata) @@ -241,6 +251,7 @@ static void rdpsnd_pulse_set_format_spec(rdpsndPulsePlugin* pulse, AUDIO_FORMAT* break; case WAVE_FORMAT_GSM610: + sample_spec.format = PA_SAMPLE_S16LE; break; } @@ -331,6 +342,14 @@ static void rdpsnd_pulse_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, if (state == PA_STREAM_READY) { freerdp_dsp_context_reset_adpcm(pulse->dsp_context); + +#ifdef WITH_GSM + if (pulse->gsm_context) + gsm_destroy(pulse->gsm_context); + + pulse->gsm_context = gsm_create(); +#endif + DEBUG_SVC("connected"); } else @@ -410,7 +429,18 @@ static BOOL rdpsnd_pulse_format_supported(rdpsndDevicePlugin* device, AUDIO_FORM return TRUE; } break; + +#ifdef WITH_GSM + case WAVE_FORMAT_GSM610: + if ((format->nSamplesPerSec <= PA_RATE_MAX) && + (format->nBlockAlign == 65) && (format->nChannels == 1)) + { + return TRUE; + } + break; +#endif } + return FALSE; } @@ -459,63 +489,108 @@ static void rdpsnd_pulse_set_volume(rdpsndDevicePlugin* device, UINT32 value) pa_threaded_mainloop_unlock(pulse->mainloop); } +static BYTE* rdpsnd_pulse_convert_audio(rdpsndDevicePlugin* device, BYTE* data, int* size) +{ + BYTE* pcmData = NULL; + rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*) device; + + if (pulse->format == WAVE_FORMAT_ADPCM) + { + pulse->dsp_context->decode_ms_adpcm(pulse->dsp_context, + data, *size, pulse->sample_spec.channels, pulse->block_size); + + *size = pulse->dsp_context->adpcm_size; + pcmData = pulse->dsp_context->adpcm_buffer; + } + else if (pulse->format == WAVE_FORMAT_DVI_ADPCM) + { + pulse->dsp_context->decode_ima_adpcm(pulse->dsp_context, + data, *size, pulse->sample_spec.channels, pulse->block_size); + + *size = pulse->dsp_context->adpcm_size; + pcmData = pulse->dsp_context->adpcm_buffer; + } +#ifdef WITH_GSM + else if (pulse->format == WAVE_FORMAT_GSM610) + { + int inPos = 0; + int inSize = *size; + UINT16 gsmBlockBuffer[160]; + + Stream_SetPosition(pulse->gsmBuffer, 0); + + while (inSize) + { + ZeroMemory(gsmBlockBuffer, sizeof(gsmBlockBuffer)); + gsm_decode(pulse->gsm_context, (gsm_byte*) &data[inPos], (gsm_signal*) gsmBlockBuffer); + + if ((inPos % 65) == 0) + { + inPos += 33; + inSize -= 33; + } + else + { + inPos += 32; + inSize -= 32; + } + + Stream_EnsureRemainingCapacity(pulse->gsmBuffer, 160 * 2); + Stream_Write(pulse->gsmBuffer, (void*) gsmBlockBuffer, 160 * 2); + } + + Stream_SealLength(pulse->gsmBuffer); + + pcmData = Stream_Buffer(pulse->gsmBuffer); + *size = Stream_Length(pulse->gsmBuffer); + } +#endif + else + { + pcmData = data; + } + + return pcmData; +} + static void rdpsnd_pulse_play(rdpsndDevicePlugin* device, BYTE* data, int size) { - int len; - int ret; - BYTE* src; + int length; + int status; + BYTE* pcmData; rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*) device; if (!pulse->stream) return; - if (pulse->format == WAVE_FORMAT_ADPCM) - { - pulse->dsp_context->decode_ms_adpcm(pulse->dsp_context, - data, size, pulse->sample_spec.channels, pulse->block_size); - - size = pulse->dsp_context->adpcm_size; - src = pulse->dsp_context->adpcm_buffer; - } - else if (pulse->format == WAVE_FORMAT_DVI_ADPCM) - { - pulse->dsp_context->decode_ima_adpcm(pulse->dsp_context, - data, size, pulse->sample_spec.channels, pulse->block_size); - - size = pulse->dsp_context->adpcm_size; - src = pulse->dsp_context->adpcm_buffer; - } - else - { - src = data; - } + pcmData = rdpsnd_pulse_convert_audio(device, data, &size); pa_threaded_mainloop_lock(pulse->mainloop); while (size > 0) { - while ((len = pa_stream_writable_size(pulse->stream)) == 0) + while ((length = pa_stream_writable_size(pulse->stream)) == 0) { pa_threaded_mainloop_wait(pulse->mainloop); } - if (len < 0) + if (length < 0) break; - if (len > size) - len = size; + if (length > size) + length = size; - ret = pa_stream_write(pulse->stream, src, len, NULL, 0LL, PA_SEEK_RELATIVE); + status = pa_stream_write(pulse->stream, pcmData, length, NULL, 0LL, PA_SEEK_RELATIVE); - if (ret < 0) + if (status < 0) { DEBUG_WARN("pa_stream_write failed (%d)", pa_context_errno(pulse->context)); break; } - src += len; - size -= len; + pcmData += length; + size -= length; } pa_threaded_mainloop_unlock(pulse->mainloop); @@ -595,6 +670,10 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE pulse->dsp_context = freerdp_dsp_context_new(); +#ifdef WITH_GSM + pulse->gsmBuffer = Stream_New(NULL, 4096); +#endif + pulse->mainloop = pa_threaded_mainloop_new(); if (!pulse->mainloop) diff --git a/cmake/FindGSM.cmake b/cmake/FindGSM.cmake new file mode 100644 index 000000000..366fd6764 --- /dev/null +++ b/cmake/FindGSM.cmake @@ -0,0 +1,13 @@ + +find_path(GSM_INCLUDE_DIR gsm/gsm.h) + +find_library(GSM_LIBRARY gsm) + +find_package_handle_standard_args(GSM DEFAULT_MSG GSM_INCLUDE_DIR GSM_LIBRARY) + +if(GSM_FOUND) + set(GSM_LIBRARIES ${GSM_LIBRARY}) + set(GSM_INCLUDE_DIRS ${GSM_INCLUDE_DIR}) +endif() + +mark_as_advanced(GSM_INCLUDE_DIR GSM_LIBRARY) diff --git a/config.h.in b/config.h.in index 043592ca6..aed1f6f09 100755 --- a/config.h.in +++ b/config.h.in @@ -44,6 +44,7 @@ #cmakedefine WITH_PULSE #cmakedefine WITH_IOSAUDIO #cmakedefine WITH_OPENSLES +#cmakedefine WITH_GSM /* Plugins */ #cmakedefine STATIC_CHANNELS diff --git a/libfreerdp/codec/audio.c b/libfreerdp/codec/audio.c index 1e45989d3..751885e78 100644 --- a/libfreerdp/codec/audio.c +++ b/libfreerdp/codec/audio.c @@ -35,8 +35,36 @@ UINT32 rdpsnd_compute_audio_time_length(AUDIO_FORMAT* format, int size) * http://msdn.microsoft.com/en-us/library/ms713497.aspx */ - wSamples = (size * 8) / format->wBitsPerSample; - mstime = (((wSamples * 1000) / format->nSamplesPerSec) / format->nChannels); + if (format->wBitsPerSample) + { + wSamples = (size * 8) / format->wBitsPerSample; + mstime = (((wSamples * 1000) / format->nSamplesPerSec) / format->nChannels); + } + else + { + mstime = 0; + + if (format->wFormatTag == WAVE_FORMAT_GSM610) + { + UINT16 nSamplesPerBlock; + + if ((format->cbSize == 2) && (format->data)) + { + nSamplesPerBlock = *((UINT16*) format->data); + + wSamples = (size / format->nBlockAlign) * nSamplesPerBlock; + mstime = (((wSamples * 1000) / format->nSamplesPerSec) / format->nChannels); + } + else + { + fprintf(stderr, "rdpsnd_compute_audio_time_length: invalid WAVE_FORMAT_GSM610 format\n"); + } + } + else + { + fprintf(stderr, "rdpsnd_compute_audio_time_length: unknown format %d\n", format->wFormatTag); + } + } return mstime; } From 21ec46036ba2d7d5e2a7a476661cf5d6530736ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Sat, 23 Nov 2013 21:35:44 -0500 Subject: [PATCH 26/32] channels/cliprdr: start implementing clean callback interface --- channels/cliprdr/client/cliprdr_format.c | 249 +++++++++++++++-------- channels/cliprdr/client/cliprdr_main.c | 181 +++++++++++++--- channels/cliprdr/client/cliprdr_main.h | 2 + client/Windows/wf_cliprdr.c | 6 +- include/freerdp/channels/cliprdr.h | 141 +++++++++++++ include/freerdp/client/cliprdr.h | 75 ++----- include/freerdp/message.h | 4 +- 7 files changed, 492 insertions(+), 166 deletions(-) create mode 100644 include/freerdp/channels/cliprdr.h diff --git a/channels/cliprdr/client/cliprdr_format.c b/channels/cliprdr/client/cliprdr_format.c index a32ce8e49..e7a5866ff 100644 --- a/channels/cliprdr/client/cliprdr_format.c +++ b/channels/cliprdr/client/cliprdr_format.c @@ -213,108 +213,193 @@ void cliprdr_process_long_format_names(cliprdrPlugin* cliprdr, wStream* s, UINT3 void cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags) { - int i; - UINT32 format; - BOOL supported; - CLIPRDR_FORMAT_NAME* format_name; - RDP_CB_FORMAT_LIST_EVENT* cb_event; + CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); - cb_event = (RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new(CliprdrChannel_Class, - CliprdrChannel_FormatList, NULL, NULL); - - if (dataLen > 0) + if (context->custom) { - cb_event->raw_format_data = (BYTE*) malloc(dataLen); - memcpy(cb_event->raw_format_data, Stream_Pointer(s), dataLen); - cb_event->raw_format_data_size = dataLen; - cb_event->raw_format_unicode = (msgFlags & CB_ASCII_NAMES) ? FALSE : TRUE; - } + int index; + int formatNameLength; + CLIPRDR_FORMAT* formats; + CLIPRDR_FORMAT_LIST formatList; - if (cliprdr->use_long_format_names) - cliprdr_process_long_format_names(cliprdr, s, dataLen, msgFlags); - else - cliprdr_process_short_format_names(cliprdr, s, dataLen, msgFlags); + formatList.msgType = CB_FORMAT_LIST; + formatList.msgFlags = msgFlags; + formatList.dataLen = dataLen; - if (cliprdr->num_format_names > 0) - cb_event->formats = (UINT32*) malloc(sizeof(UINT32) * cliprdr->num_format_names); + formatList.cFormats = 0; - cb_event->num_formats = 0; - - for (i = 0; i < cliprdr->num_format_names; i++) - { - supported = TRUE; - format_name = &cliprdr->format_names[i]; - format = format_name->id; - - switch (format) + while (dataLen) { - case CB_FORMAT_TEXT: - case CB_FORMAT_DIB: - case CB_FORMAT_UNICODETEXT: - break; + Stream_Seek(s, 4); /* formatId */ + dataLen -= 4; - default: - - if (format_name->length > 0) - { - DEBUG_CLIPRDR("format: %s", format_name->name); - - if (strcmp(format_name->name, "HTML Format") == 0) - { - format = CB_FORMAT_HTML; - break; - } - if (strcmp(format_name->name, "PNG") == 0) - { - format = CB_FORMAT_PNG; - break; - } - if (strcmp(format_name->name, "JFIF") == 0) - { - format = CB_FORMAT_JPEG; - break; - } - if (strcmp(format_name->name, "GIF") == 0) - { - format = CB_FORMAT_GIF; - break; - } - } - else - { - supported = FALSE; - } - - break; + formatNameLength = _wcslen((WCHAR*) Stream_Pointer(s)); + Stream_Seek(s, (formatNameLength + 1) * 2); + dataLen -= ((formatNameLength + 1) * 2); + formatList.cFormats++; } - if (supported) - cb_event->formats[cb_event->num_formats++] = format; + index = 0; + dataLen = formatList.dataLen; + Stream_Rewind(s, dataLen); - if (format_name->length > 0) - free(format_name->name); + formats = (CLIPRDR_FORMAT*) malloc(sizeof(CLIPRDR_FORMAT) * formatList.cFormats); + formatList.formats = formats; + + while (dataLen) + { + Stream_Read_UINT32(s, formats[index].formatId); /* formatId */ + dataLen -= 4; + + formats[index].formatName = NULL; + formatNameLength = _wcslen((WCHAR*) Stream_Pointer(s)); + + if (formatNameLength) + { + formatNameLength = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), + -1, &(formats[index].formatName), 0, NULL, NULL); + + Stream_Seek(s, formatNameLength * 2); + dataLen -= (formatNameLength * 2); + } + else + { + Stream_Seek(s, 2); + dataLen -= 2; + } + + index++; + } + + if (context->ServerFormatList) + context->ServerFormatList(context, &formatList); + + for (index = 0; index < formatList.cFormats; index++) + free(formats[index].formatName); + + free(formats); } + else + { + int i; + UINT32 format; + BOOL supported; + CLIPRDR_FORMAT_NAME* format_name; + RDP_CB_FORMAT_LIST_EVENT* cb_event; - free(cliprdr->format_names); - cliprdr->format_names = NULL; + cb_event = (RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new(CliprdrChannel_Class, + CliprdrChannel_FormatList, NULL, NULL); - cliprdr->num_format_names = 0; + if (dataLen > 0) + { + cb_event->raw_format_data = (BYTE*) malloc(dataLen); + memcpy(cb_event->raw_format_data, Stream_Pointer(s), dataLen); + cb_event->raw_format_data_size = dataLen; + cb_event->raw_format_unicode = (msgFlags & CB_ASCII_NAMES) ? FALSE : TRUE; + } - svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) cb_event); - cliprdr_send_format_list_response(cliprdr); + if (cliprdr->use_long_format_names) + cliprdr_process_long_format_names(cliprdr, s, dataLen, msgFlags); + else + cliprdr_process_short_format_names(cliprdr, s, dataLen, msgFlags); + + if (cliprdr->num_format_names > 0) + cb_event->formats = (UINT32*) malloc(sizeof(UINT32) * cliprdr->num_format_names); + + cb_event->num_formats = 0; + + for (i = 0; i < cliprdr->num_format_names; i++) + { + supported = TRUE; + format_name = &cliprdr->format_names[i]; + format = format_name->id; + + switch (format) + { + case CB_FORMAT_TEXT: + case CB_FORMAT_DIB: + case CB_FORMAT_UNICODETEXT: + break; + + default: + + if (format_name->length > 0) + { + DEBUG_CLIPRDR("format: %s", format_name->name); + + if (strcmp(format_name->name, "HTML Format") == 0) + { + format = CB_FORMAT_HTML; + break; + } + if (strcmp(format_name->name, "PNG") == 0) + { + format = CB_FORMAT_PNG; + break; + } + if (strcmp(format_name->name, "JFIF") == 0) + { + format = CB_FORMAT_JPEG; + break; + } + if (strcmp(format_name->name, "GIF") == 0) + { + format = CB_FORMAT_GIF; + break; + } + } + else + { + supported = FALSE; + } + + break; + } + + if (supported) + cb_event->formats[cb_event->num_formats++] = format; + + if (format_name->length > 0) + free(format_name->name); + } + + free(cliprdr->format_names); + cliprdr->format_names = NULL; + + cliprdr->num_format_names = 0; + + svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) cb_event); + cliprdr_send_format_list_response(cliprdr); + } } void cliprdr_process_format_list_response(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags) { - /* http://msdn.microsoft.com/en-us/library/hh872154.aspx */ - wMessage* event; + CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); - if ((msgFlags & CB_RESPONSE_FAIL) != 0) + /* http://msdn.microsoft.com/en-us/library/hh872154.aspx */ + + if (context->custom) { - /* In case of an error the clipboard will not be synchronized with the server. - * Post this event to restart format negociation and data transfer. */ - event = freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_MonitorReady, NULL, NULL); - svc_plugin_send_event((rdpSvcPlugin*) cliprdr, event); + CLIPRDR_FORMAT_LIST_RESPONSE formatListResponse; + + formatListResponse.msgType = CB_FORMAT_LIST_RESPONSE; + formatListResponse.msgFlags = msgFlags; + formatListResponse.dataLen = dataLen; + + if (context->ServerFormatListResponse) + context->ServerFormatListResponse(context, &formatListResponse); + } + else + { + if ((msgFlags & CB_RESPONSE_FAIL) != 0) + { + /* In case of an error the clipboard will not be synchronized with the server. + * Post this event to restart format negociation and data transfer. */ + + wMessage* event = freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_MonitorReady, NULL, NULL); + svc_plugin_send_event((rdpSvcPlugin*) cliprdr, event); + } } } diff --git a/channels/cliprdr/client/cliprdr_main.c b/channels/cliprdr/client/cliprdr_main.c index 16520be9a..7905e0bf0 100644 --- a/channels/cliprdr/client/cliprdr_main.c +++ b/channels/cliprdr/client/cliprdr_main.c @@ -53,6 +53,14 @@ static const char* const CB_MSG_TYPE_STRINGS[] = "CB_UNLOCK_CLIPDATA" }; +CliprdrClientContext* cliprdr_get_client_interface(cliprdrPlugin* cliprdr) +{ + CliprdrClientContext* pInterface; + rdpSvcPlugin* plugin = (rdpSvcPlugin*) cliprdr; + pInterface = (CliprdrClientContext*) *(plugin->channel_entry_points.ppInterface); + return pInterface; +} + wStream* cliprdr_packet_new(UINT16 msgType, UINT16 msgFlags, UINT32 dataLen) { wStream* s; @@ -110,7 +118,9 @@ static void cliprdr_process_general_capability(cliprdrPlugin* cliprdr, wStream* { UINT32 version; UINT32 generalFlags; - RDP_CB_CLIP_CAPS *caps_event; + CliprdrClientContext* context; + + context = cliprdr_get_client_interface(cliprdr); Stream_Read_UINT32(s, version); /* version (4 bytes) */ Stream_Read_UINT32(s, generalFlags); /* generalFlags (4 bytes) */ @@ -121,9 +131,6 @@ static void cliprdr_process_general_capability(cliprdrPlugin* cliprdr, wStream* cliprdr_print_general_capability_flags(generalFlags); #endif - caps_event = (RDP_CB_CLIP_CAPS *)freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_ClipCaps, NULL, NULL); - caps_event->capabilities = generalFlags; - if (generalFlags & CB_USE_LONG_FORMAT_NAMES) cliprdr->use_long_format_names = TRUE; @@ -138,8 +145,32 @@ static void cliprdr_process_general_capability(cliprdrPlugin* cliprdr, wStream* cliprdr->received_caps = TRUE; - svc_plugin_send_event((rdpSvcPlugin *)cliprdr, (wMessage *)caps_event); + if (context->custom) + { + CLIPRDR_CAPABILITIES capabilities; + CLIPRDR_GENERAL_CAPABILITY_SET generalCapabilitySet; + capabilities.cCapabilitiesSets = 1; + capabilities.capabilitySets = (CLIPRDR_CAPABILITY_SET*) &(generalCapabilitySet); + + generalCapabilitySet.capabilitySetType = CB_CAPSTYPE_GENERAL; + generalCapabilitySet.capabilitySetLength = 12; + + generalCapabilitySet.version = version; + generalCapabilitySet.generalFlags = generalFlags; + + if (context->ServerCapabilities) + context->ServerCapabilities(context, &capabilities); + } + else + { + RDP_CB_CLIP_CAPS* caps_event; + + caps_event = (RDP_CB_CLIP_CAPS*) freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_ClipCaps, NULL, NULL); + caps_event->capabilities = generalFlags; + + svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) caps_event); + } } static void cliprdr_process_clip_caps(cliprdrPlugin* cliprdr, wStream* s, UINT16 length, UINT16 flags) @@ -195,14 +226,30 @@ static void cliprdr_send_clip_caps(cliprdrPlugin* cliprdr) static void cliprdr_process_monitor_ready(cliprdrPlugin* cliprdr, wStream* s, UINT16 length, UINT16 flags) { - RDP_CB_MONITOR_READY_EVENT* event; + CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); - if (cliprdr->received_caps) - cliprdr_send_clip_caps(cliprdr); + if (context->custom) + { + CLIPRDR_MONITOR_READY monitorReady; - event = (RDP_CB_MONITOR_READY_EVENT *)freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_MonitorReady, NULL, NULL); + monitorReady.msgType = CB_MONITOR_READY; + monitorReady.msgFlags = flags; + monitorReady.dataLen = length; - svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage *)event); + if (context->MonitorReady) + context->MonitorReady(context, &monitorReady); + } + else + { + RDP_CB_MONITOR_READY_EVENT* event; + + if (cliprdr->received_caps) + cliprdr_send_clip_caps(cliprdr); + + event = (RDP_CB_MONITOR_READY_EVENT*) freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_MonitorReady, NULL, NULL); + + svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) event); + } } static void cliprdr_process_receive(rdpSvcPlugin* plugin, wStream* s) @@ -290,13 +337,95 @@ static void cliprdr_process_terminate(rdpSvcPlugin* plugin) * Callback Interface */ -int cliprdr_monitor_ready(CliprdrClientContext* context) +int cliprdr_client_capabilities(CliprdrClientContext* context, CLIPRDR_CAPABILITIES* capabilities) { + wStream* s; + CLIPRDR_GENERAL_CAPABILITY_SET* generalCapabilitySet; + cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle; + + s = cliprdr_packet_new(CB_CLIP_CAPS, 0, 4 + CB_CAPSTYPE_GENERAL_LEN); + + Stream_Write_UINT16(s, 1); /* cCapabilitiesSets */ + Stream_Write_UINT16(s, 0); /* pad1 */ + + generalCapabilitySet = (CLIPRDR_GENERAL_CAPABILITY_SET*) capabilities->capabilitySets; + + Stream_Write_UINT16(s, generalCapabilitySet->capabilitySetType); /* capabilitySetType */ + Stream_Write_UINT16(s, generalCapabilitySet->capabilitySetLength); /* lengthCapability */ + Stream_Write_UINT32(s, generalCapabilitySet->version); /* version */ + Stream_Write_UINT32(s, generalCapabilitySet->generalFlags); /* generalFlags */ + + cliprdr_packet_send(cliprdr, s); + return 0; } -int cliprdr_format_list(CliprdrClientContext* context) +int cliprdr_client_format_list(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST* formatList) { + int index; + wStream* s; + int length = 0; + int formatNameSize; + CLIPRDR_FORMAT* format; + cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle; + + for (index = 0; index < formatList->cFormats; index++) + { + format = (CLIPRDR_FORMAT*) &(formatList->formats[index]); + + length += 4; + + formatNameSize = 2; + + if (format->formatName) + formatNameSize = MultiByteToWideChar(CP_UTF8, 0, format->formatName, -1, NULL, 0) * 2; + + length += formatNameSize; + } + + s = cliprdr_packet_new(CB_FORMAT_LIST, 0, length); + + for (index = 0; index < formatList->cFormats; index++) + { + format = (CLIPRDR_FORMAT*) &(formatList->formats[index]); + + Stream_Write_UINT32(s, format->formatId); /* formatId (4 bytes) */ + + if (format->formatName) + { + int cchWideChar; + LPWSTR lpWideCharStr; + + lpWideCharStr = (LPWSTR) Stream_Pointer(s); + cchWideChar = (Stream_Capacity(s) - Stream_GetPosition(s)) / 2; + + formatNameSize = MultiByteToWideChar(CP_UTF8, 0, + format->formatName, -1, lpWideCharStr, cchWideChar) * 2; + + Stream_Seek(s, formatNameSize); + } + else + { + Stream_Write_UINT16(s, 0); + } + } + + cliprdr_packet_send(cliprdr, s); + + return 0; +} + +int cliprdr_client_format_list_response(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse) +{ + wStream* s; + cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle; + + formatListResponse->msgType = CB_FORMAT_LIST_RESPONSE; + formatListResponse->dataLen = 0; + + s = cliprdr_packet_new(formatListResponse->msgType, formatListResponse->msgFlags, formatListResponse->dataLen); + cliprdr_packet_send(cliprdr, s); + return 0; } @@ -315,25 +444,25 @@ int cliprdr_data_response(CliprdrClientContext* context) int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) { - cliprdrPlugin* _p; + cliprdrPlugin* cliprdr; CliprdrClientContext* context; CHANNEL_ENTRY_POINTS_EX* pEntryPointsEx; - _p = (cliprdrPlugin*) malloc(sizeof(cliprdrPlugin)); - ZeroMemory(_p, sizeof(cliprdrPlugin)); + cliprdr = (cliprdrPlugin*) malloc(sizeof(cliprdrPlugin)); + ZeroMemory(cliprdr, sizeof(cliprdrPlugin)); - _p->plugin.channel_def.options = + cliprdr->plugin.channel_def.options = CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP | CHANNEL_OPTION_COMPRESS_RDP | CHANNEL_OPTION_SHOW_PROTOCOL; - strcpy(_p->plugin.channel_def.name, "cliprdr"); + strcpy(cliprdr->plugin.channel_def.name, "cliprdr"); - _p->plugin.connect_callback = cliprdr_process_connect; - _p->plugin.receive_callback = cliprdr_process_receive; - _p->plugin.event_callback = cliprdr_process_event; - _p->plugin.terminate_callback = cliprdr_process_terminate; + cliprdr->plugin.connect_callback = cliprdr_process_connect; + cliprdr->plugin.receive_callback = cliprdr_process_receive; + cliprdr->plugin.event_callback = cliprdr_process_event; + cliprdr->plugin.terminate_callback = cliprdr_process_terminate; pEntryPointsEx = (CHANNEL_ENTRY_POINTS_EX*) pEntryPoints; @@ -341,16 +470,20 @@ int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) (pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER)) { context = (CliprdrClientContext*) malloc(sizeof(CliprdrClientContext)); + ZeroMemory(context, sizeof(CliprdrClientContext)); - context->MonitorReady = cliprdr_monitor_ready; - context->FormatList = cliprdr_format_list; + context->handle = (void*) cliprdr; + + context->ClientCapabilities = cliprdr_client_capabilities; + context->ClientFormatList = cliprdr_client_format_list; + context->ClientFormatListResponse = cliprdr_client_format_list_response; context->DataRequest = cliprdr_data_request; context->DataResponse = cliprdr_data_response; *(pEntryPointsEx->ppInterface) = (void*) context; } - svc_plugin_init((rdpSvcPlugin*) _p, pEntryPoints); + svc_plugin_init((rdpSvcPlugin*) cliprdr, pEntryPoints); return 1; } diff --git a/channels/cliprdr/client/cliprdr_main.h b/channels/cliprdr/client/cliprdr_main.h index 38d361031..b3eabcb9d 100644 --- a/channels/cliprdr/client/cliprdr_main.h +++ b/channels/cliprdr/client/cliprdr_main.h @@ -41,6 +41,8 @@ typedef struct cliprdr_plugin cliprdrPlugin; wStream* cliprdr_packet_new(UINT16 msgType, UINT16 msgFlags, UINT32 dataLen); void cliprdr_packet_send(cliprdrPlugin* cliprdr, wStream* data_out); +CliprdrClientContext* cliprdr_get_client_interface(cliprdrPlugin* cliprdr); + #ifdef WITH_DEBUG_CLIPRDR #define DEBUG_CLIPRDR(fmt, ...) DEBUG_CLASS(CLIPRDR, fmt, ## __VA_ARGS__) #else diff --git a/client/Windows/wf_cliprdr.c b/client/Windows/wf_cliprdr.c index 216332f95..031b53a1b 100644 --- a/client/Windows/wf_cliprdr.c +++ b/client/Windows/wf_cliprdr.c @@ -54,7 +54,7 @@ static UINT32 get_local_format_id_by_name(cliprdrContext *cliprdr, void *format_ for (i = 0; i < cliprdr->map_size; i++) { map = &cliprdr->format_mappings[i]; - if ((cliprdr->capabilities & CAPS_USE_LONG_FORMAT_NAMES) != 0) + if ((cliprdr->capabilities & CB_USE_LONG_FORMAT_NAMES) != 0) { if (map->name) { @@ -144,7 +144,7 @@ static void cliprdr_send_format_list(cliprdrContext *cliprdr) { Write_UINT32(format_data + len, format); len += 4; - if ((cliprdr->capabilities & CAPS_USE_LONG_FORMAT_NAMES) != 0) + if ((cliprdr->capabilities & CB_USE_LONG_FORMAT_NAMES) != 0) { if (format >= CF_MAX) { @@ -518,7 +518,7 @@ static void wf_cliprdr_process_cb_format_list_event(wfContext *wfc, RDP_CB_FORMA clear_format_map(cliprdr); - if ((cliprdr->capabilities & CAPS_USE_LONG_FORMAT_NAMES) != 0) + if ((cliprdr->capabilities & CB_USE_LONG_FORMAT_NAMES) != 0) { while (left_size >= 6) { diff --git a/include/freerdp/channels/cliprdr.h b/include/freerdp/channels/cliprdr.h new file mode 100644 index 000000000..31d16d92e --- /dev/null +++ b/include/freerdp/channels/cliprdr.h @@ -0,0 +1,141 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Clipboard Virtual Channel Extension + * + * Copyright 2013 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FREERDP_CHANNEL_CLIPRDR_H +#define FREERDP_CHANNEL_CLIPRDR_H + +#include +#include + +#define CLIPRDR_SVC_CHANNEL_NAME "cliprdr" + +/** + * Clipboard Formats + */ + +#define CB_FORMAT_RAW 0x0000 +#define CB_FORMAT_TEXT 0x0001 +#define CB_FORMAT_DIB 0x0008 +#define CB_FORMAT_UNICODETEXT 0x000D +#define CB_FORMAT_HTML 0xD010 +#define CB_FORMAT_PNG 0xD011 +#define CB_FORMAT_JPEG 0xD012 +#define CB_FORMAT_GIF 0xD013 + +/* CLIPRDR_HEADER.msgType */ +#define CB_MONITOR_READY 0x0001 +#define CB_FORMAT_LIST 0x0002 +#define CB_FORMAT_LIST_RESPONSE 0x0003 +#define CB_FORMAT_DATA_REQUEST 0x0004 +#define CB_FORMAT_DATA_RESPONSE 0x0005 +#define CB_TEMP_DIRECTORY 0x0006 +#define CB_CLIP_CAPS 0x0007 +#define CB_FILECONTENTS_REQUEST 0x0008 +#define CB_FILECONTENTS_RESPONSE 0x0009 +#define CB_LOCK_CLIPDATA 0x000A +#define CB_UNLOCK_CLIPDATA 0x000B + +/* CLIPRDR_HEADER.msgFlags */ +#define CB_RESPONSE_OK 0x0001 +#define CB_RESPONSE_FAIL 0x0002 +#define CB_ASCII_NAMES 0x0004 + +/* CLIPRDR_CAPS_SET.capabilitySetType */ +#define CB_CAPSTYPE_GENERAL 0x0001 + +/* CLIPRDR_GENERAL_CAPABILITY.lengthCapability */ +#define CB_CAPSTYPE_GENERAL_LEN 12 + +/* CLIPRDR_GENERAL_CAPABILITY.version */ +#define CB_CAPS_VERSION_1 0x00000001 +#define CB_CAPS_VERSION_2 0x00000002 + +/* CLIPRDR_GENERAL_CAPABILITY.generalFlags */ +#define CB_USE_LONG_FORMAT_NAMES 0x00000002 +#define CB_STREAM_FILECLIP_ENABLED 0x00000004 +#define CB_FILECLIP_NO_FILE_PATHS 0x00000008 +#define CB_CAN_LOCK_CLIPDATA 0x00000010 + +#define DEFINE_CLIPRDR_HEADER_COMMON() \ + UINT16 msgType; \ + UINT16 msgFlags; \ + UINT32 dataLen + +struct _CLIPRDR_HEADER +{ + DEFINE_CLIPRDR_HEADER_COMMON(); +}; +typedef struct _CLIPRDR_HEADER CLIPRDR_HEADER; + +struct _CLIPRDR_CAPABILITY_SET +{ + UINT16 capabilitySetType; + UINT16 capabilitySetLength; +}; +typedef struct _CLIPRDR_CAPABILITY_SET CLIPRDR_CAPABILITY_SET; + +struct _CLIPRDR_GENERAL_CAPABILITY_SET +{ + UINT16 capabilitySetType; + UINT16 capabilitySetLength; + + UINT32 version; + UINT32 generalFlags; +}; +typedef struct _CLIPRDR_GENERAL_CAPABILITY_SET CLIPRDR_GENERAL_CAPABILITY_SET; + +struct _CLIPRDR_CAPABILITIES +{ + DEFINE_CLIPRDR_HEADER_COMMON(); + + UINT32 cCapabilitiesSets; + CLIPRDR_CAPABILITY_SET* capabilitySets; +}; +typedef struct _CLIPRDR_CAPABILITIES CLIPRDR_CAPABILITIES; + +struct _CLIPRDR_MONITOR_READY +{ + DEFINE_CLIPRDR_HEADER_COMMON(); +}; +typedef struct _CLIPRDR_MONITOR_READY CLIPRDR_MONITOR_READY; + +struct _CLIPRDR_FORMAT +{ + UINT32 formatId; + char* formatName; +}; +typedef struct _CLIPRDR_FORMAT CLIPRDR_FORMAT; + +struct _CLIPRDR_FORMAT_LIST +{ + DEFINE_CLIPRDR_HEADER_COMMON(); + + UINT32 cFormats; + CLIPRDR_FORMAT* formats; +}; +typedef struct _CLIPRDR_FORMAT_LIST CLIPRDR_FORMAT_LIST; + +struct _CLIPRDR_FORMAT_LIST_RESPONSE +{ + DEFINE_CLIPRDR_HEADER_COMMON(); +}; +typedef struct _CLIPRDR_FORMAT_LIST_RESPONSE CLIPRDR_FORMAT_LIST_RESPONSE; + +#endif /* FREERDP_CHANNEL_CLIPRDR_H */ + diff --git a/include/freerdp/client/cliprdr.h b/include/freerdp/client/cliprdr.h index e7aa94195..641f1eb3a 100644 --- a/include/freerdp/client/cliprdr.h +++ b/include/freerdp/client/cliprdr.h @@ -1,6 +1,6 @@ /** * FreeRDP: A Remote Desktop Protocol Implementation - * Clipboard Virtual Channel Types + * Clipboard Virtual Channel Extension * * Copyright 2011 Vic Lee * @@ -22,72 +22,41 @@ #include +#include +#include + /** * Client Interface */ typedef struct _cliprdr_client_context CliprdrClientContext; -typedef int (*pcCliprdrMonitorReady)(CliprdrClientContext* context); -typedef int (*pcCliprdrFormatList)(CliprdrClientContext* context); +typedef int (*pcCliprdrServerCapabilities)(CliprdrClientContext* context, CLIPRDR_CAPABILITIES* capabilities); +typedef int (*pcCliprdrClientCapabilities)(CliprdrClientContext* context, CLIPRDR_CAPABILITIES* capabilities); +typedef int (*pcCliprdrMonitorReady)(CliprdrClientContext* context, CLIPRDR_MONITOR_READY* monitorReady); +typedef int (*pcCliprdrClientFormatList)(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST* formatList); +typedef int (*pcCliprdrServerFormatList)(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST* formatList); +typedef int (*pcCliprdrClientFormatListResponse)(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse); +typedef int (*pcCliprdrServerFormatListResponse)(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse); typedef int (*pcCliprdrDataRequest)(CliprdrClientContext* context); typedef int (*pcCliprdrDataResponse)(CliprdrClientContext* context); struct _cliprdr_client_context { + void* handle; + void* custom; + + pcCliprdrServerCapabilities ServerCapabilities; + pcCliprdrClientCapabilities ClientCapabilities; pcCliprdrMonitorReady MonitorReady; - pcCliprdrFormatList FormatList; + pcCliprdrClientFormatList ClientFormatList; + pcCliprdrServerFormatList ServerFormatList; + pcCliprdrClientFormatListResponse ClientFormatListResponse; + pcCliprdrServerFormatListResponse ServerFormatListResponse; pcCliprdrDataRequest DataRequest; pcCliprdrDataResponse DataResponse; }; -/** - * Clipboard Formats - */ - -#define CB_FORMAT_RAW 0x0000 -#define CB_FORMAT_TEXT 0x0001 -#define CB_FORMAT_DIB 0x0008 -#define CB_FORMAT_UNICODETEXT 0x000D -#define CB_FORMAT_HTML 0xD010 -#define CB_FORMAT_PNG 0xD011 -#define CB_FORMAT_JPEG 0xD012 -#define CB_FORMAT_GIF 0xD013 - -/* CLIPRDR_HEADER.msgType */ -#define CB_MONITOR_READY 0x0001 -#define CB_FORMAT_LIST 0x0002 -#define CB_FORMAT_LIST_RESPONSE 0x0003 -#define CB_FORMAT_DATA_REQUEST 0x0004 -#define CB_FORMAT_DATA_RESPONSE 0x0005 -#define CB_TEMP_DIRECTORY 0x0006 -#define CB_CLIP_CAPS 0x0007 -#define CB_FILECONTENTS_REQUEST 0x0008 -#define CB_FILECONTENTS_RESPONSE 0x0009 -#define CB_LOCK_CLIPDATA 0x000A -#define CB_UNLOCK_CLIPDATA 0x000B - -/* CLIPRDR_HEADER.msgFlags */ -#define CB_RESPONSE_OK 0x0001 -#define CB_RESPONSE_FAIL 0x0002 -#define CB_ASCII_NAMES 0x0004 - -/* CLIPRDR_CAPS_SET.capabilitySetType */ -#define CB_CAPSTYPE_GENERAL 0x0001 - -/* CLIPRDR_GENERAL_CAPABILITY.lengthCapability */ -#define CB_CAPSTYPE_GENERAL_LEN 12 - -/* CLIPRDR_GENERAL_CAPABILITY.version */ -#define CB_CAPS_VERSION_1 0x00000001 -#define CB_CAPS_VERSION_2 0x00000002 - -/* CLIPRDR_GENERAL_CAPABILITY.generalFlags */ -#define CB_USE_LONG_FORMAT_NAMES 0x00000002 -#define CB_STREAM_FILECLIP_ENABLED 0x00000004 -#define CB_FILECLIP_NO_FILE_PATHS 0x00000008 -#define CB_CAN_LOCK_CLIPDATA 0x00000010 - struct _CLIPRDR_FORMAT_NAME { UINT32 id; @@ -99,10 +68,6 @@ typedef struct _CLIPRDR_FORMAT_NAME CLIPRDR_FORMAT_NAME; /** * Clipboard Events */ -#define CAPS_USE_LONG_FORMAT_NAMES 0x00000002 -#define CAPS_STREAM_FILECLIP_ENABLED 0x00000004 -#define CAPS_FILECLIP_NO_FILE_PATH 0x00000008 -#define CAPS_CAN_LOCK_CLIPDATA 0x00000010 struct _RDP_CB_CLIP_CAPS { diff --git a/include/freerdp/message.h b/include/freerdp/message.h index e5e66dbf2..5369bf7a8 100644 --- a/include/freerdp/message.h +++ b/include/freerdp/message.h @@ -263,10 +263,10 @@ #define CliprdrChannel_ClipCaps 5 #define FREERDP_CLIPRDR_CHANNEL_MONITOR_READY MakeMessageId(CliprdrChannel, MonitorReady) -#define FREERDP_CLIPRDR_CHANNEL_FORMAT_LIST MakeMessageId(CliprdrChannel, FormatList) +#define FREERDP_CLIPRDR_CHANNEL_FORMAT_LIST MakeMessageId(CliprdrChannel, FormatList) #define FREERDP_CLIPRDR_CHANNEL_DATA_REQUEST MakeMessageId(CliprdrChannel, DataRequest) #define FREERDP_CLIPRDR_CHANNEL_DATA_RESPONSE MakeMessageId(CliprdrChannel, DataResponse) -#define FREERDP_CLIPRDR_CHANNEL_CLIP_CAPS MakeMessageId(CliprdrChannel, ClipCaps) +#define FREERDP_CLIPRDR_CHANNEL_CLIP_CAPS MakeMessageId(CliprdrChannel, ClipCaps) /** * Multimedia Redirection Channel From d7379cd4ff29bad9590961e8602ceae4b2814c39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Sat, 23 Nov 2013 23:45:31 -0500 Subject: [PATCH 27/32] channels/cliprdr: implement more of the callback interface --- channels/cliprdr/client/cliprdr_format.c | 28 ++++++++++++++---- channels/cliprdr/client/cliprdr_main.c | 29 ++++++++++++++++--- include/freerdp/channels/cliprdr.h | 36 ++++++++++++++++++++++++ include/freerdp/client/cliprdr.h | 12 +++++--- 4 files changed, 92 insertions(+), 13 deletions(-) diff --git a/channels/cliprdr/client/cliprdr_format.c b/channels/cliprdr/client/cliprdr_format.c index e7a5866ff..2125438fc 100644 --- a/channels/cliprdr/client/cliprdr_format.c +++ b/channels/cliprdr/client/cliprdr_format.c @@ -405,13 +405,31 @@ void cliprdr_process_format_list_response(cliprdrPlugin* cliprdr, wStream* s, UI void cliprdr_process_format_data_request(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags) { - RDP_CB_DATA_REQUEST_EVENT* cb_event; + CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); - cb_event = (RDP_CB_DATA_REQUEST_EVENT*) freerdp_event_new(CliprdrChannel_Class, - CliprdrChannel_DataRequest, NULL, NULL); + if (context->custom) + { + CLIPRDR_FORMAT_DATA_REQUEST formatDataRequest; - Stream_Read_UINT32(s, cb_event->format); - svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) cb_event); + formatDataRequest.msgType = CB_FORMAT_DATA_REQUEST; + formatDataRequest.msgFlags = msgFlags; + formatDataRequest.dataLen = dataLen; + + Stream_Read_UINT32(s, formatDataRequest.requestedFormatId); /* requestedFormatId (4 bytes) */ + + if (context->ServerFormatDataRequest) + context->ServerFormatDataRequest(context, &formatDataRequest); + } + else + { + RDP_CB_DATA_REQUEST_EVENT* cb_event; + + cb_event = (RDP_CB_DATA_REQUEST_EVENT*) freerdp_event_new(CliprdrChannel_Class, + CliprdrChannel_DataRequest, NULL, NULL); + + Stream_Read_UINT32(s, cb_event->format); + svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) cb_event); + } } void cliprdr_process_format_data_response_event(cliprdrPlugin* cliprdr, RDP_CB_DATA_RESPONSE_EVENT* cb_event) diff --git a/channels/cliprdr/client/cliprdr_main.c b/channels/cliprdr/client/cliprdr_main.c index 7905e0bf0..6ffdcf1c5 100644 --- a/channels/cliprdr/client/cliprdr_main.c +++ b/channels/cliprdr/client/cliprdr_main.c @@ -429,13 +429,34 @@ int cliprdr_client_format_list_response(CliprdrClientContext* context, CLIPRDR_F return 0; } -int cliprdr_data_request(CliprdrClientContext* context) +int cliprdr_client_format_data_request(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest) { + wStream* s; + cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle; + + formatDataRequest->msgType = CB_FORMAT_DATA_REQUEST; + formatDataRequest->dataLen = 4; + + s = cliprdr_packet_new(formatDataRequest->msgType, formatDataRequest->msgFlags, formatDataRequest->dataLen); + Stream_Write_UINT32(s, formatDataRequest->requestedFormatId); /* requestedFormatId (4 bytes) */ + + cliprdr_packet_send(cliprdr, s); + return 0; } -int cliprdr_data_response(CliprdrClientContext* context) +int cliprdr_client_format_data_response(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse) { + wStream* s; + cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle; + + formatDataResponse->msgType = CB_FORMAT_DATA_RESPONSE; + + s = cliprdr_packet_new(formatDataResponse->msgType, formatDataResponse->msgFlags, formatDataResponse->dataLen); + Stream_Write(s, formatDataResponse->requestedFormatData, formatDataResponse->dataLen); + + cliprdr_packet_send(cliprdr, s); + return 0; } @@ -477,8 +498,8 @@ int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) context->ClientCapabilities = cliprdr_client_capabilities; context->ClientFormatList = cliprdr_client_format_list; context->ClientFormatListResponse = cliprdr_client_format_list_response; - context->DataRequest = cliprdr_data_request; - context->DataResponse = cliprdr_data_response; + context->ClientFormatDataRequest = cliprdr_client_format_data_request; + context->ClientFormatDataResponse = cliprdr_client_format_data_response; *(pEntryPointsEx->ppInterface) = (void*) context; } diff --git a/include/freerdp/channels/cliprdr.h b/include/freerdp/channels/cliprdr.h index 31d16d92e..adb1ffb31 100644 --- a/include/freerdp/channels/cliprdr.h +++ b/include/freerdp/channels/cliprdr.h @@ -29,6 +29,26 @@ * Clipboard Formats */ +#define CLIPRDR_FORMAT_RAW 0 +#define CLIPRDR_FORMAT_TEXT 1 /* "Plain Text" */ +#define CLIPRDR_FORMAT_BITMAP 2 /* "Bitmap" */ +#define CLIPRDR_FORMAT_METAFILEPICT 3 /* "Windows Metafile" */ +#define CLIPRDR_FORMAT_SYLK 4 +#define CLIPRDR_FORMAT_DIF 5 +#define CLIPRDR_FORMAT_TIFF 6 +#define CLIPRDR_FORMAT_OEMTEXT 7 /* "OEM Text" */ +#define CLIPRDR_FORMAT_DIB 8 /* "Device Independent Bitmap (DIB)" */ +#define CLIPRDR_FORMAT_PALETTE 9 +#define CLIPRDR_FORMAT_PENDATA 10 +#define CLIPRDR_FORMAT_RIFF 11 +#define CLIPRDR_FORMAT_WAVE 12 +#define CLIPRDR_FORMAT_UNICODETEXT 13 /* "Unicode Text" */ +#define CLIPRDR_FORMAT_ENHMETAFILE 14 /* "Enhanced Metafile" */ +#define CLIPRDR_FORMAT_HDROP 15 /* "File List" */ +#define CLIPRDR_FORMAT_LOCALE 16 /* "Locale Identifier" */ +#define CLIPRDR_FORMAT_DIBV5 17 +#define CLIPRDR_FORMAT_MAX 18 + #define CB_FORMAT_RAW 0x0000 #define CB_FORMAT_TEXT 0x0001 #define CB_FORMAT_DIB 0x0008 @@ -137,5 +157,21 @@ struct _CLIPRDR_FORMAT_LIST_RESPONSE }; typedef struct _CLIPRDR_FORMAT_LIST_RESPONSE CLIPRDR_FORMAT_LIST_RESPONSE; +struct _CLIPRDR_FORMAT_DATA_REQUEST +{ + DEFINE_CLIPRDR_HEADER_COMMON(); + + UINT32 requestedFormatId; +}; +typedef struct _CLIPRDR_FORMAT_DATA_REQUEST CLIPRDR_FORMAT_DATA_REQUEST; + +struct _CLIPRDR_FORMAT_DATA_RESPONSE +{ + DEFINE_CLIPRDR_HEADER_COMMON(); + + BYTE* requestedFormatData; +}; +typedef struct _CLIPRDR_FORMAT_DATA_RESPONSE CLIPRDR_FORMAT_DATA_RESPONSE; + #endif /* FREERDP_CHANNEL_CLIPRDR_H */ diff --git a/include/freerdp/client/cliprdr.h b/include/freerdp/client/cliprdr.h index 641f1eb3a..b3a0542fa 100644 --- a/include/freerdp/client/cliprdr.h +++ b/include/freerdp/client/cliprdr.h @@ -38,8 +38,10 @@ typedef int (*pcCliprdrClientFormatList)(CliprdrClientContext* context, CLIPRDR_ typedef int (*pcCliprdrServerFormatList)(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST* formatList); typedef int (*pcCliprdrClientFormatListResponse)(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse); typedef int (*pcCliprdrServerFormatListResponse)(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse); -typedef int (*pcCliprdrDataRequest)(CliprdrClientContext* context); -typedef int (*pcCliprdrDataResponse)(CliprdrClientContext* context); +typedef int (*pcCliprdrClientFormatDataRequest)(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest); +typedef int (*pcCliprdrServerFormatDataRequest)(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest); +typedef int (*pcCliprdrClientFormatDataResponse)(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse); +typedef int (*pcCliprdrServerFormatDataResponse)(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse); struct _cliprdr_client_context { @@ -53,8 +55,10 @@ struct _cliprdr_client_context pcCliprdrServerFormatList ServerFormatList; pcCliprdrClientFormatListResponse ClientFormatListResponse; pcCliprdrServerFormatListResponse ServerFormatListResponse; - pcCliprdrDataRequest DataRequest; - pcCliprdrDataResponse DataResponse; + pcCliprdrClientFormatDataRequest ClientFormatDataRequest; + pcCliprdrServerFormatDataRequest ServerFormatDataRequest; + pcCliprdrClientFormatDataResponse ClientFormatDataResponse; + pcCliprdrServerFormatDataResponse ServerFormatDataResponse; }; struct _CLIPRDR_FORMAT_NAME From 6a11e6226bba30988bf089ce39729536bdf2bde2 Mon Sep 17 00:00:00 2001 From: Zhang Zhaolong Date: Sun, 24 Nov 2013 16:01:11 +0800 Subject: [PATCH 28/32] fix a gdi leak bug. --- client/Windows/wf_gdi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/client/Windows/wf_gdi.c b/client/Windows/wf_gdi.c index 15e9b4363..16359d858 100644 --- a/client/Windows/wf_gdi.c +++ b/client/Windows/wf_gdi.c @@ -466,7 +466,6 @@ void wf_gdi_multi_opaque_rect(wfContext* wfc, MULTI_OPAQUE_RECT_ORDER* multi_opa rect.bottom = rectangle->top + rectangle->height; brush = CreateSolidBrush(brush_color); - brush = CreateSolidBrush(brush_color); FillRect(wfc->drawing->hdc, &rect, brush); if (wfc->drawing == wfc->primary) From 4fbbc03ac95751c46102f303942f2a3c105fe861 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Sun, 24 Nov 2013 15:35:26 -0500 Subject: [PATCH 29/32] channels/cliprdr: fix conflict with CLIPRDR_HEADER --- channels/cliprdr/server/cliprdr_main.h | 8 -------- include/freerdp/server/cliprdr.h | 2 ++ 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/channels/cliprdr/server/cliprdr_main.h b/channels/cliprdr/server/cliprdr_main.h index 3e201eeb3..71165045b 100644 --- a/channels/cliprdr/server/cliprdr_main.h +++ b/channels/cliprdr/server/cliprdr_main.h @@ -28,14 +28,6 @@ #define CLIPRDR_HEADER_LENGTH 8 -struct _CLIPRDR_HEADER -{ - UINT16 msgType; - UINT16 msgFlags; - UINT32 dataLen; -}; -typedef struct _CLIPRDR_HEADER CLIPRDR_HEADER; - struct _cliprdr_server_private { HANDLE Thread; diff --git a/include/freerdp/server/cliprdr.h b/include/freerdp/server/cliprdr.h index 946eb7652..256e736ae 100644 --- a/include/freerdp/server/cliprdr.h +++ b/include/freerdp/server/cliprdr.h @@ -23,6 +23,8 @@ #include #include #include + +#include #include /** From 8fa7008435133305281fbf515e39e712ef7faf51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Sun, 24 Nov 2013 20:46:56 -0500 Subject: [PATCH 30/32] channels/cliprdr: add callback for data request response --- channels/cliprdr/client/cliprdr_format.c | 45 ++++++++++++++++++------ channels/cliprdr/client/cliprdr_main.c | 2 +- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/channels/cliprdr/client/cliprdr_format.c b/channels/cliprdr/client/cliprdr_format.c index 2125438fc..bcbec672d 100644 --- a/channels/cliprdr/client/cliprdr_format.c +++ b/channels/cliprdr/client/cliprdr_format.c @@ -464,17 +464,42 @@ void cliprdr_process_format_data_request_event(cliprdrPlugin* cliprdr, RDP_CB_DA void cliprdr_process_format_data_response(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags) { - RDP_CB_DATA_RESPONSE_EVENT* cb_event; - - cb_event = (RDP_CB_DATA_RESPONSE_EVENT*) freerdp_event_new(CliprdrChannel_Class, - CliprdrChannel_DataResponse, NULL, NULL); - - if (dataLen > 0) + CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); + + if (context->custom) { - cb_event->size = dataLen; - cb_event->data = (BYTE*) malloc(dataLen); - CopyMemory(cb_event->data, Stream_Pointer(s), dataLen); + CLIPRDR_FORMAT_DATA_RESPONSE formatDataResponse; + + formatDataResponse.msgType = CB_FORMAT_DATA_RESPONSE; + formatDataResponse.msgFlags = msgFlags; + formatDataResponse.dataLen = dataLen; + formatDataResponse.requestedFormatData = NULL; + + if (dataLen) + { + formatDataResponse.requestedFormatData = (BYTE*) malloc(dataLen); + Stream_Read(s, formatDataResponse.requestedFormatData, dataLen); + } + + if (context->ClientFormatDataResponse) + context->ClientFormatDataResponse(context, &formatDataResponse); + + free(formatDataResponse.requestedFormatData); } + else + { + RDP_CB_DATA_RESPONSE_EVENT* cb_event; - svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) cb_event); + cb_event = (RDP_CB_DATA_RESPONSE_EVENT*) freerdp_event_new(CliprdrChannel_Class, + CliprdrChannel_DataResponse, NULL, NULL); + + if (dataLen > 0) + { + cb_event->size = dataLen; + cb_event->data = (BYTE*) malloc(dataLen); + CopyMemory(cb_event->data, Stream_Pointer(s), dataLen); + } + + svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) cb_event); + } } diff --git a/channels/cliprdr/client/cliprdr_main.c b/channels/cliprdr/client/cliprdr_main.c index 6ffdcf1c5..e3fe0b607 100644 --- a/channels/cliprdr/client/cliprdr_main.c +++ b/channels/cliprdr/client/cliprdr_main.c @@ -265,7 +265,7 @@ static void cliprdr_process_receive(rdpSvcPlugin* plugin, wStream* s) DEBUG_CLIPRDR("msgType: %s (%d), msgFlags: %d dataLen: %d", CB_MSG_TYPE_STRINGS[msgType], msgType, msgFlags, dataLen); - + #ifdef WITH_DEBUG_CLIPRDR winpr_HexDump(Stream_Buffer(s), dataLen + 8); #endif From 128fb72ec6291166dd6051a3b3f7079bd75ce40a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Mon, 25 Nov 2013 00:25:16 -0500 Subject: [PATCH 31/32] mfreerdp: fix possible crash on gdi termination --- channels/cliprdr/client/cliprdr_format.c | 2 +- channels/cliprdr/client/cliprdr_main.c | 1 + client/Mac/MRDPView.m | 14 ++++++++++---- libfreerdp/core/freerdp.c | 3 --- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/channels/cliprdr/client/cliprdr_format.c b/channels/cliprdr/client/cliprdr_format.c index bcbec672d..e01cb656d 100644 --- a/channels/cliprdr/client/cliprdr_format.c +++ b/channels/cliprdr/client/cliprdr_format.c @@ -395,7 +395,7 @@ void cliprdr_process_format_list_response(cliprdrPlugin* cliprdr, wStream* s, UI if ((msgFlags & CB_RESPONSE_FAIL) != 0) { /* In case of an error the clipboard will not be synchronized with the server. - * Post this event to restart format negociation and data transfer. */ + * Post this event to restart format negotiation and data transfer. */ wMessage* event = freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_MonitorReady, NULL, NULL); svc_plugin_send_event((rdpSvcPlugin*) cliprdr, event); diff --git a/channels/cliprdr/client/cliprdr_main.c b/channels/cliprdr/client/cliprdr_main.c index e3fe0b607..24c9e8b07 100644 --- a/channels/cliprdr/client/cliprdr_main.c +++ b/channels/cliprdr/client/cliprdr_main.c @@ -435,6 +435,7 @@ int cliprdr_client_format_data_request(CliprdrClientContext* context, CLIPRDR_FO cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle; formatDataRequest->msgType = CB_FORMAT_DATA_REQUEST; + formatDataRequest->msgFlags = 0; formatDataRequest->dataLen = 4; s = cliprdr_packet_new(formatDataRequest->msgType, formatDataRequest->msgFlags, formatDataRequest->dataLen); diff --git a/client/Mac/MRDPView.m b/client/Mac/MRDPView.m index 27341189e..b213ea9d8 100644 --- a/client/Mac/MRDPView.m +++ b/client/Mac/MRDPView.m @@ -1051,6 +1051,10 @@ void mac_bitmap_update(rdpContext* context, BITMAP_UPDATE* bitmap) void mac_begin_paint(rdpContext* context) { rdpGdi* gdi = context->gdi; + + if (!gdi) + return; + gdi->primary->hdc->hwnd->invalid->null = 1; } @@ -1063,11 +1067,15 @@ void mac_end_paint(rdpContext* context) int i; rdpGdi* gdi; NSRect drawRect; + int ww, wh, dw, dh; mfContext* mfc = (mfContext*) context; MRDPView* view = (MRDPView*) mfc->view; - - int ww, wh, dw, dh; + gdi = context->gdi; + + if (!gdi) + return; + ww = mfc->client_width; wh = mfc->client_height; dw = mfc->context.settings->DesktopWidth; @@ -1081,8 +1089,6 @@ void mac_end_paint(rdpContext* context) if (context->gdi->drawing != context->gdi->primary) return; - - gdi = context->gdi; for (i = 0; i < gdi->primary->hdc->hwnd->ninvalid; i++) { diff --git a/libfreerdp/core/freerdp.c b/libfreerdp/core/freerdp.c index 6e0f8948b..57ea44526 100644 --- a/libfreerdp/core/freerdp.c +++ b/libfreerdp/core/freerdp.c @@ -40,7 +40,6 @@ #include #include #include -#include /* connectErrorCode is 'extern' in error.h. See comment there.*/ @@ -448,8 +447,6 @@ void freerdp_context_free(freerdp* instance) graphics_free(instance->context->graphics); instance->context->graphics = NULL; - gdi_free(instance); - PubSub_Free(instance->context->pubSub); free(instance->context); From 4987f2b0e1bd10fe68db2f897014971786a2fc27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Mon, 25 Nov 2013 12:08:58 -0500 Subject: [PATCH 32/32] libfreerdp-crypto: add robustness checks for VerifyX509Certificate --- libfreerdp/crypto/tls.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/libfreerdp/crypto/tls.c b/libfreerdp/crypto/tls.c index 4d5e8c4ca..19dda77c6 100644 --- a/libfreerdp/crypto/tls.c +++ b/libfreerdp/crypto/tls.c @@ -596,14 +596,33 @@ BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname) */ bio = BIO_new(BIO_s_mem()); + + if (!bio) + { + fprintf(stderr, "tls_verify_certificate: BIO_new() failure\n"); + return FALSE; + } status = PEM_write_bio_X509(bio, cert->px509); + if (status < 0) + { + fprintf(stderr, "tls_verify_certificate: PEM_write_bio_X509 failure: %d\n", status); + return FALSE; + } + offset = 0; length = 2048; pemCert = (BYTE*) malloc(length + 1); status = BIO_read(bio, pemCert, length); + + if (status < 0) + { + fprintf(stderr, "tls_verify_certificate: failed to read certificate\n"); + return FALSE; + } + offset += status; while (offset >= length) @@ -619,17 +638,27 @@ BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname) offset += status; } + if (status < 0) + { + fprintf(stderr, "tls_verify_certificate: failed to read certificate\n"); + return FALSE; + } + length = offset; pemCert[length] = '\0'; status = -1; - + if (instance->VerifyX509Certificate) { status = instance->VerifyX509Certificate(instance, pemCert, length, 0); } + + fprintf(stderr, "VerifyX509Certificate: (length = %d) status: %d\n%s\n", + length, status, pemCert); free(pemCert); + BIO_free(bio); return (status < 0) ? FALSE : TRUE; }