Debian release 2.0.0~git20180411.1.7a7b1802+dfsg1-2

-----BEGIN PGP SIGNATURE-----
 
 iQJVBAABCAA/FiEEm/uu6GwKpf+/IgeCmvRrMCV3GzEFAlr67DEhHG1pa2UuZ2Fi
 cmllbEBkYXMtbmV0endlcmt0ZWFtLmRlAAoJEJr0azAldxsxmnYP+gKvhwEKMTJW
 rIo7GQM7CRhTH2Zo1ITCA4ybYtwTn8qhTUcfx0DzeYaB2sRU/PtYa/J3Xo5j3FUe
 yKQmEivZxzjyLlZUAI8B3pQcVg6huI+WZq7somRteQDqFtBkwDVyqOTiAJNnvA5l
 xx0wzsUtKfupU6zLmltGxIzsv3vJFsYq3NG+5OLgGI3Ae03QAGs5gLcp2snN6o0P
 Ea8x5V5Np/slTli5DgDNW/UQ2HEf65w8gmd/vo+44DWqnz6k7kil+WHxVUHKcXvL
 bFg6+OaPP3GTHdY8+ZBlo56U8+8HJbIkTLFu+sDOr5BFJL92N5DUluOeHIRxKoix
 bchKYZold/VuTD5/fPIURWNah6bVY29CKJmbFgzaq/Q4iWaUKxbdHZqcq+25Tm1V
 nmuTt5eHwoQOdDDV3EvEE6t1Jyo4jLgwqPQZ9q6Ds4bSLwvhzXEcqH6aF05Xcttr
 s2SCErZ3YLtzWPQyL6KfWA14rfcqsAi8XIZq0YHYhZvtk+IntnSAujqb175H3uXI
 sX3ZQUF0cJ62ho7nAsAOUqjRARuNEQB/3r500DKBP7YNIi+4itUn2FembAl6XVsx
 hGNrv4wzAiffnu/cmsNpMWoxWzfe5GEyhOtNyMc55h6vf/91UIhPDEsOi6LeMb0f
 UuyQr354Fagv+/ZEtqnZWDw3ua7kivEy
 =QQTz
 -----END PGP SIGNATURE-----
gpgsig -----BEGIN PGP SIGNATURE-----
 Comment: Debian powered!
 
 iQKTBAABCgB9FiEE890J+NqH0d9QRsmbBhL0lE7NzVoFAlsDLbxfFIAAAAAALgAo
 aXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldEYz
 REQwOUY4REE4N0QxREY1MDQ2Qzk5QjA2MTJGNDk0NEVDRENENUEACgkQBhL0lE7N
 zVqA0xAAspmdmkPNbO36T0WRcXlKs4pxq4z+kbgBccMs/NB341Xk/AZdRYoou3St
 gCBhqlQpWqeXTyb8uSeCpMZywmaNTlZqm/8zED2xD2sXujTO9z628D+DYiueqIK6
 nEiKvSe+GPNHTf69bfmcM1GFwKVkFM0ViR+/Jdzp201gbcvrmFfNxgtvdhBKsU88
 gjfzVicTZd6bPBA5weMOKLKEbiCuXp0Hx/V2fSqYC62ep6lKppHBcgbGZ1zlBrgi
 aGtUS5kCBbXAdDCQWgE8zEf75FSnsH042LgR9UcNaHn3etYWREnfpOu49j/l8Oro
 PoevzSSc6e6QqQAE4PUwMj7kffIbpFF2/ovVaczsDbjPaTr7qpdF6at1bqujgBw+
 WEinCGKlM2ogGQxa2mi/ToZGJM66DwF6WPFL25RbWV73xZuOlodo3btfNiO/egz/
 /whD96gBMZ6lEgCvg8rKeEFk7I3VSWCCxEOox/HgHSEXOBhtFo3UDZXUB1Q8Rt4l
 NIZmWLbFpCjtbc5xJ1obSC8RWC3ibiYzdtpgBP9zd6qUdgkLO6is1BYMcWFeSn9W
 GQcoBOc/h+Xdrw3EpEfR0fBv2IvCeiYbXIuUS5QyUkoEW/jGYONyb6MUa+YjztdN
 402tB/57mEUPcq6fav5D8hmb5kiHYoxfXBbEGfd/e1JIVQFoLdI=
 =M36K
 -----END PGP SIGNATURE-----

Merge tag 'debian/2.0.0_git20180411.1.7a7b1802+dfsg1-2' into stretch-backports

Debian release 2.0.0~git20180411.1.7a7b1802+dfsg1-2
This commit is contained in:
Matteo F. Vescovi 2018-05-21 22:35:52 +02:00
commit 97ca4d06b0
462 changed files with 28921 additions and 11856 deletions

54
.travis.yml Normal file
View File

@ -0,0 +1,54 @@
sudo: required
dist: trusty
os: linux
language: c
compiler:
- gcc
matrix:
include:
- os: linux
compiler: gcc
- os: linux
compiler: clang
exclude:
- compiler: gcc
addons:
apt:
packages:
- gdb
- libx11-dev
- libxrandr-dev
- libxi-dev
- libxv-dev
- libcups2-dev
- libxdamage-dev
- libxcursor-dev
- libxext-dev
- libxinerama-dev
- libxkbcommon-dev
- libxkbfile-dev
- libxml2-dev
- libasound2-dev
- libgstreamer1.0-dev
- libgstreamer-plugins-base1.0-dev
- libpulse-dev
- libpcsclite-dev
- libgsm1-dev
- libavcodec-dev
- libavutil-dev
- libx264-dev
- libxext-dev
before_script:
- ulimit -c unlimited -S
script:
- sudo hostname travis-ci.local
- cmake -G "Unix Makefiles" -C ci/cmake-preloads/config-linux-all.txt -D CMAKE_BUILD_TYPE=Debug -DWITH_LIBSYSTEMD=OFF -DWITH_WAYLAND=OFF .
- make
- make test

View File

@ -59,7 +59,6 @@ include(FindPkgConfig)
include(TestBigEndian)
include(FindFeature)
include(AutoVersioning)
include(ConfigOptions)
include(ComplexLibrary)
include(FeatureSummary)
@ -68,6 +67,7 @@ include(CheckCXXCompilerFlag)
include(GNUInstallDirsWrapper)
include(CMakePackageConfigHelpers)
include(InstallFreeRDPMan)
include(GetGitRevisionDescription)
# Soname versioning
set(BUILD_NUMBER 0)
@ -75,10 +75,24 @@ if ($ENV{BUILD_NUMBER})
set(BUILD_NUMBER $ENV{BUILD_NUMBER})
endif()
set(WITH_LIBRARY_VERSIONING "ON")
set(FREERDP_VERSION_MAJOR "2")
set(FREERDP_VERSION_MINOR "0")
set(FREERDP_VERSION_REVISION "0")
set(FREERDP_VERSION_SUFFIX "dev")
set(RAW_VERSTION_STRING "2.0.0-rc2")
if(EXISTS "${CMAKE_SOURCE_DIR}/.source_tag")
file(READ ${CMAKE_SOURCE_DIR}/.source_tag RAW_VERSTION_STRING)
elseif(USE_VERSION_FROM_GIT_TAG)
git_get_exact_tag(_GIT_TAG --tags --always)
if (NOT ${_GIT_TAG} STREQUAL "n/a")
set(RAW_VERSTION_STRING ${_GIT_TAG})
endif()
endif()
string(STRIP ${RAW_VERSTION_STRING} RAW_VERSTION_STRING)
set(VERSION_REGEX "^.?([0-9]+)\\.([0-9]+)\\.([0-9]+)-?(.*)")
string(REGEX REPLACE "${VERSION_REGEX}" "\\1" FREERDP_VERSION_MAJOR "${RAW_VERSTION_STRING}")
string(REGEX REPLACE "${VERSION_REGEX}" "\\2" FREERDP_VERSION_MINOR "${RAW_VERSTION_STRING}")
string(REGEX REPLACE "${VERSION_REGEX}" "\\3" FREERDP_VERSION_REVISION "${RAW_VERSTION_STRING}")
string(REGEX REPLACE "${VERSION_REGEX}" "\\4" FREERDP_VERSION_SUFFIX "${RAW_VERSTION_STRING}")
set(FREERDP_API_VERSION "${FREERDP_VERSION_MAJOR}")
set(FREERDP_VERSION "${FREERDP_VERSION_MAJOR}.${FREERDP_VERSION_MINOR}.${FREERDP_VERSION_REVISION}")
if (FREERDP_VERSION_SUFFIX)
@ -86,6 +100,8 @@ if (FREERDP_VERSION_SUFFIX)
else()
set(FREERDP_VERSION_FULL "${FREERDP_VERSION}")
endif()
message("FREERDP_VERSION=${FREERDP_VERSION_FULL}")
set(FREERDP_INCLUDE_DIR "include/freerdp${FREERDP_VERSION_MAJOR}/")
# Compatibility options
@ -102,26 +118,42 @@ if (FREERDP_EXTERNAL_PATH)
get_filename_component (FREERDP_EXTERNAL_PATH "${FREERDP_EXTERNAL_PATH}" ABSOLUTE)
endif()
# Allow to search the host machine for git
# Allow to search the host machine for git/ccache
if(CMAKE_CROSSCOMPILING)
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH)
endif(CMAKE_CROSSCOMPILING)
find_program(CCACHE ccache)
if(CCACHE AND WITH_CCACHE)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE})
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ${CCACHE})
if(CMAKE_VERSION VERSION_GREATER 3.3.2)
if(NOT DEFINED CMAKE_C_COMPILER_LAUNCHER)
SET(CMAKE_C_COMPILER_LAUNCHER ${CCACHE})
endif(NOT DEFINED CMAKE_C_COMPILER_LAUNCHER)
if(NOT DEFINED CMAKE_CXX_COMPILER_LAUNCHER)
SET(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE})
endif(NOT DEFINED CMAKE_CXX_COMPILER_LAUNCHER)
else()
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE})
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ${CCACHE})
endif()
endif(CCACHE AND WITH_CCACHE)
include(GetGitRevisionDescription)
git_get_exact_tag(GIT_REVISION --tags --always)
if(EXISTS "${CMAKE_SOURCE_DIR}/.source_version" )
file(READ ${CMAKE_SOURCE_DIR}/.source_version GIT_REVISION)
if (${GIT_REVISION} STREQUAL "n/a")
git_rev_parse (GIT_REVISION --short)
string(STRIP ${GIT_REVISION} GIT_REVISION)
else()
git_get_exact_tag(GIT_REVISION --tags --always)
if (${GIT_REVISION} STREQUAL "n/a")
git_rev_parse (GIT_REVISION --short)
endif()
endif()
if(CMAKE_CROSSCOMPILING)
SET (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY)
endif(CMAKE_CROSSCOMPILING)
# /Allow to search the host machine for git/ccache
message(STATUS "Git Revision ${GIT_REVISION}")
@ -158,6 +190,9 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "BSD")
if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
set(FREEBSD TRUE)
endif()
if(${CMAKE_SYSTEM_NAME} MATCHES "kFreeBSD")
set(KFREEBSD TRUE)
endif()
if(${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD")
set(OPENBSD TRUE)
endif()
@ -189,6 +224,11 @@ if("${CMAKE_SYSTEM_NAME}" MATCHES "Linux")
add_definitions("-D_FILE_OFFSET_BITS=64")
endif()
# Use Standard conforming getpwnam_r() on Solaris.
if("${CMAKE_SYSTEM_NAME}" MATCHES "SunOS")
add_definitions("-D_POSIX_PTHREAD_SEMANTICS")
endif()
# Compiler-specific flags
if(CMAKE_COMPILER_IS_GNUCC)
if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64" OR CMAKE_SYSTEM_PROCESSOR MATCHES "i686")
@ -252,9 +292,6 @@ if(CMAKE_COMPILER_IS_GNUCC)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")
endif()
if(WITH_SSE2)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -msse2")
endif()
endif()
# When building with Unix Makefiles and doing any release builds
@ -278,9 +315,7 @@ if(${CMAKE_C_COMPILER_ID} STREQUAL "Clang")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-parameter")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-macros -Wno-padded")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-c11-extensions -Wno-gnu")
if(WITH_SSE2)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mssse3")
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-command-line-argument")
CHECK_C_COMPILER_FLAG(-Wno-deprecated-declarations Wno-deprecated-declarations)
if(Wno-deprecated-declarations)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated-declarations")
@ -300,7 +335,14 @@ if(${CMAKE_C_COMPILER_ID} STREQUAL "Clang" OR CMAKE_COMPILER_IS_GNUCC)
set(CMAKE_REQUIRED_FLAGS "-fsanitize=address")
CHECK_C_COMPILER_FLAG ("-fsanitize=address" fsanitize-address)
if(fsanitize-address)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address")
if(${CMAKE_C_COMPILER_ID} STREQUAL "Clang")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize-blacklist=${CMAKE_SOURCE_DIR}/scripts/blacklist-address-sanitizer.txt")
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fsanitize-address-use-after-scope")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=address")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address")
else()
message(FATAL_ERROR "Missing support for address sanitizer!")
endif()
if (DEFINED SAVE_CMAKE_REQUIRED_FLAGS)
set(CMAKE_REQUIRED_FLAGS ${SAVE_CMAKE_REQUIRED_FLAGS})
@ -312,14 +354,47 @@ if(${CMAKE_C_COMPILER_ID} STREQUAL "Clang" OR CMAKE_COMPILER_IS_GNUCC)
if(fno-omit-frame-pointer)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-omit-frame-pointer")
endif()
elseif(WITH_SANITIZE_LEAK)
elseif(WITH_SANITIZE_MEMORY)
if (DEFINED CMAKE_REQUIRED_FLAGS)
set(SAVE_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
endif()
set(CMAKE_REQUIRED_FLAGS "-fsanitize=leak")
CHECK_C_COMPILER_FLAG ("-fsanitize=leak" fsanitize-leak)
if(fsanitize-leak)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=leak")
set(CMAKE_REQUIRED_FLAGS "-fsanitize=memory")
CHECK_C_COMPILER_FLAG ("-fsanitize=memory" fsanitize-memory)
if(fsanitize-memory)
if(${CMAKE_C_COMPILER_ID} STREQUAL "Clang")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize-blacklist=${CMAKE_SOURCE_DIR}/scripts/blacklist-memory-sanitizer.txt")
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=memory -fsanitize-memory-track-origins -fsanitize-memory-use-after-dtor")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=memory")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=memory")
else()
message(FATAL_ERROR "Missing support for memory sanitizer!")
endif()
if (DEFINED SAVE_CMAKE_REQUIRED_FLAGS)
set(CMAKE_REQUIRED_FLAGS ${SAVE_CMAKE_REQUIRED_FLAGS})
else()
unset(CMAKE_REQUIRED_FLAGS)
endif()
CHECK_C_COMPILER_FLAG ("-fno-omit-frame-pointer" fno-omit-frame-pointer)
if(fno-omit-frame-pointer)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-omit-frame-pointer")
endif()
elseif(WITH_SANITIZE_THREAD)
if (DEFINED CMAKE_REQUIRED_FLAGS)
set(SAVE_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
endif()
set(CMAKE_REQUIRED_FLAGS "-fsanitize=thread")
CHECK_C_COMPILER_FLAG ("-fsanitize=thread" fsanitize-thread)
if(fsanitize-thread)
if(${CMAKE_C_COMPILER_ID} STREQUAL "Clang")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize-blacklist=${CMAKE_SOURCE_DIR}/scripts/blacklist-thread-sanitizer.txt")
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=thread")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=thread")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=thread")
else()
message(FATAL_ERROR "Missing support for thread sanitizer!")
endif()
if (DEFINED SAVE_CMAKE_REQUIRED_FLAGS)
set(CMAKE_REQUIRED_FLAGS ${SAVE_CMAKE_REQUIRED_FLAGS})
@ -399,7 +474,7 @@ if(WIN32)
elseif (${CMAKE_GENERATOR} MATCHES "Visual Studio*")
set(CMAKE_PDB_BINARY_DIR "${CMAKE_BINARY_DIR}/\${CMAKE_INSTALL_CONFIG_NAME}")
else()
message(FATAL "Unknown generator ${CMAKE_GENERATOR}")
message(FATAL_ERROR "Unknown generator ${CMAKE_GENERATOR}")
endif()
# Set product and vendor for dll and exe version information.
@ -566,12 +641,12 @@ else()
endif()
if(UNIX OR CYGWIN)
check_include_files(sys/eventfd.h HAVE_AIO_H)
check_include_files(sys/eventfd.h HAVE_EVENTFD_H)
if (HAVE_EVENTFD_H)
check_include_files(aio.h HAVE_AIO_H)
check_include_files(sys/eventfd.h HAVE_SYS_EVENTFD_H)
if (HAVE_SYS_EVENTFD_H)
check_symbol_exists(eventfd_read sys/eventfd.h WITH_EVENTFD_READ_WRITE)
endif()
check_include_files(sys/timerfd.h HAVE_TIMERFD_H)
check_include_files(sys/timerfd.h HAVE_SYS_TIMERFD_H)
check_include_files(poll.h HAVE_POLL_H)
list(APPEND CMAKE_REQUIRED_LIBRARIES m)
check_symbol_exists(ceill math.h HAVE_MATH_C99_LONG_DOUBLE)
@ -637,6 +712,10 @@ set(FFMPEG_FEATURE_TYPE "RECOMMENDED")
set(FFMPEG_FEATURE_PURPOSE "multimedia")
set(FFMPEG_FEATURE_DESCRIPTION "multimedia redirection, audio and video playback")
set(VAAPI_FEATURE_TYPE "OPTIONAL")
set(VAAPI_FEATURE_PURPOSE "multimedia")
set(VAAPI_FEATURE_DESCRIPTION "VA-API hardware acceleration for video playback")
set(GSTREAMER_0_10_FEATURE_TYPE "OPTIONAL")
set(GSTREAMER_0_10_FEATURE_PURPOSE "multimedia")
set(GSTREAMER_0_10_FEATURE_DESCRIPTION "multimedia redirection, audio and video playback, gstreamer 0.10 version")
@ -661,14 +740,14 @@ set(OPENH264_FEATURE_TYPE "OPTIONAL")
set(OPENH264_FEATURE_PURPOSE "codec")
set(OPENH264_FEATURE_DESCRIPTION "use OpenH264 library")
set(KRB5_FEATURE_TYPE "OPTIONAL")
set(KRB5_FEATURE_PURPOSE "auth")
set(KRB5_FEATURE_DESCRIPTION "add kerberos support")
set(GSM_FEATURE_TYPE "OPTIONAL")
set(GSM_FEATURE_PURPOSE "codec")
set(GSM_FEATURE_DESCRIPTION "GSM audio codec library")
set(GSSAPI_FEATURE_TYPE "OPTIONAL")
set(GSSAPI_FEATURE_PURPOSE "auth")
set(GSSAPI_FEATURE_DESCRIPTION "add kerberos support")
if(WIN32)
set(X11_FEATURE_TYPE "DISABLED")
set(WAYLAND_FEATURE_TYPE "DISABLED")
@ -680,6 +759,7 @@ if(WIN32)
set(CUPS_FEATURE_TYPE "DISABLED")
set(PCSC_FEATURE_TYPE "DISABLED")
set(FFMPEG_FEATURE_TYPE "DISABLED")
set(VAAPI_FEATURE_TYPE "DISABLED")
set(GSTREAMER_1_0_FEATURE_TYPE "DISABLED")
set(GSTREAMER_0_10_FEATURE_TYPE "OPTIONAL")
set(OPENSLES_FEATURE_TYPE "DISABLED")
@ -688,6 +768,7 @@ endif()
if(APPLE)
set(DIRECTFB_FEATURE_TYPE "DISABLED")
set(FFMPEG_FEATURE_TYPE "OPTIONAL")
set(VAAPI_FEATURE_TYPE "DISABLED")
set(GSTREAMER_1_0_FEATURE_TYPE "OPTIONAL")
set(X11_FEATURE_TYPE "OPTIONAL")
set(WAYLAND_FEATURE_TYPE "DISABLED")
@ -729,6 +810,7 @@ if(ANDROID)
set(CUPS_FEATURE_TYPE "DISABLED")
set(PCSC_FEATURE_TYPE "DISABLED")
set(FFMPEG_FEATURE_TYPE "DISABLED")
set(VAAPI_FEATURE_TYPE "DISABLED")
set(GSTREAMER_1_0_FEATURE_TYPE "DISABLED")
set(GSTREAMER_0_10_FEATURE_TYPE "DISABLED")
set(OPENSLES_FEATURE_TYPE "REQUIRED")
@ -762,7 +844,25 @@ find_feature(JPEG ${JPEG_FEATURE_TYPE} ${JPEG_FEATURE_PURPOSE} ${JPEG_FEATURE_DE
find_feature(x264 ${X264_FEATURE_TYPE} ${X264_FEATURE_PURPOSE} ${X264_FEATURE_DESCRIPTION})
find_feature(OpenH264 ${OPENH264_FEATURE_TYPE} ${OPENH264_FEATURE_PURPOSE} ${OPENH264_FEATURE_DESCRIPTION})
find_feature(GSM ${GSM_FEATURE_TYPE} ${GSM_FEATURE_PURPOSE} ${GSM_FEATURE_DESCRIPTION})
find_feature(KRB5 ${KRB5_FEATURE_TYPE} ${KRB5_FEATURE_PURPOSE} ${KRB5_FEATURE_DESCRIPTION})
find_feature(GSSAPI ${GSSAPI_FEATURE_TYPE} ${GSSAPI_FEATURE_PURPOSE} ${GSSAPI_FEATURE_DESCRIPTION})
if ( (WITH_GSSAPI) AND (NOT GSS_FOUND))
message(WARNING "-DWITH_GSSAPI=ON is set, but not GSSAPI implementation was found, disabling")
elseif(WITH_GSSAPI)
if(GSS_FLAVOUR STREQUAL "MIT")
add_definitions("-DWITH_GSSAPI -DWITH_GSSAPI_MIT")
if(GSS_VERSION_1_13)
add_definitions("-DHAVE_AT_LEAST_KRB_V1_13")
endif()
include_directories(${_GSS_INCLUDE_DIR})
elseif(GSS_FLAVOUR STREQUAL "Heimdal")
add_definitions("-DWITH_GSSAPI -DWITH_GSSAPI_HEIMDAL")
include_directories(${_GSS_INCLUDE_DIR})
else()
message(WARNING "Kerberos version not detected")
endif()
endif()
if(TARGET_ARCH MATCHES "x86|x64")
if (NOT APPLE)
@ -819,14 +919,15 @@ add_definitions("-DHAVE_CONFIG_H")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
# RPATH configuration
if(CMAKE_SKIP_RPATH)
set(CMAKE_SKIP_RPATH FALSE)
set(CMAKE_SKIP_INSTALL_RPATH TRUE)
endif()
set(CMAKE_SKIP_BUILD_RPATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
set(CMAKE_INSTALL_RPATH "\$ORIGIN/../${CMAKE_INSTALL_LIBDIR}:\$ORIGIN/..")
if (APPLE)
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE)
set(CMAKE_INSTALL_RPATH "@loader_path/../Frameworks")
else (APPLE)
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
set(CMAKE_INSTALL_RPATH "\$ORIGIN/../${CMAKE_INSTALL_LIBDIR}:\$ORIGIN/..")
endif(APPLE)
if (BUILD_SHARED_LIBS)
set(CMAKE_MACOSX_RPATH ON)

3006
ChangeLog

File diff suppressed because it is too large Load Diff

6
README
View File

@ -11,9 +11,9 @@ Resources
Project website: http://www.freerdp.com/
Issue tracker: https://github.com/FreeRDP/FreeRDP/issues
Sources: https://github.com/FreeRDP/FreeRDP/
Downloads: https://pub.freerdp.com/releases/
Wiki: https://github.com/FreeRDP/FreeRDP/wiki
Downloads and other resources: http://pub.freerdp.com
API doc: http://pub.freerdp.com/api/
API documentation: https://pub.freerdp.com/api/
IRC channel: #freerdp @ irc.freenode.net
Mailing list: https://lists.sourceforge.net/lists/listinfo/freerdp-devel
@ -32,5 +32,3 @@ Compilation
Instructions on how to get started compiling FreeRDP can be found on the wiki:
https://github.com/FreeRDP/FreeRDP/wiki/Compilation

View File

@ -219,7 +219,7 @@ static UINT audin_alsa_thread_receive(AudinALSADevice* alsa, BYTE* src,
return ret;
}
static void* audin_alsa_thread_func(void* arg)
static DWORD WINAPI audin_alsa_thread_func(LPVOID arg)
{
long error;
BYTE* buffer;
@ -300,8 +300,8 @@ out:
setChannelError(alsa->rdpcontext, error,
"audin_alsa_thread_func reported an error");
ExitThread((DWORD)error);
return NULL;
ExitThread(error);
return error;
}
/**
@ -427,7 +427,7 @@ static UINT audin_alsa_open(IAudinDevice* device, AudinReceive receive,
}
if (!(alsa->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) audin_alsa_thread_func, alsa, 0, NULL)))
audin_alsa_thread_func, alsa, 0, NULL)))
{
WLog_ERR(TAG, "CreateThread failed!");
goto error_out;

View File

@ -24,6 +24,7 @@
#include "config.h"
#endif
#include <errno.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
@ -31,10 +32,10 @@
#include <winpr/crt.h>
#include <winpr/cmdline.h>
#include <winpr/stream.h>
#include <winpr/wlog.h>
#include <freerdp/addin.h>
#include <winpr/stream.h>
#include <freerdp/freerdp.h>
#include "audin_main.h"
@ -70,7 +71,7 @@ struct _AUDIN_CHANNEL_CALLBACK
* Open PDU and Format Change PDU
*/
audinFormat* formats;
int formats_count;
UINT32 formats_count;
};
typedef struct _AUDIN_PLUGIN AUDIN_PLUGIN;
@ -92,37 +93,45 @@ struct _AUDIN_PLUGIN
rdpContext* rdpcontext;
BOOL attached;
wLog* log;
};
static BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, ADDIN_ARGV* args);
static UINT audin_write_and_free_stream(AUDIN_CHANNEL_CALLBACK* callback, wStream* s)
{
UINT error = ERROR_INTERNAL_ERROR;
const size_t length = Stream_GetPosition(s);
const BYTE* data = Stream_Buffer(s);
if (callback && callback->channel && callback->channel->Write)
error = callback->channel->Write(callback->channel, length, data, NULL);
Stream_Free(s, TRUE);
return error;
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT audin_process_version(IWTSVirtualChannelCallback* pChannelCallback, wStream* s)
static UINT audin_process_version(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* callback, wStream* s)
{
UINT error;
wStream* out;
UINT32 Version;
AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback;
Stream_Read_UINT32(s, Version);
DEBUG_DVC("Version=%"PRIu32"", Version);
out = Stream_New(NULL, 5);
if (!out)
{
WLog_ERR(TAG, "Stream_New failed!");
WLog_Print(audin->log, WLOG_ERROR, "Stream_New failed!");
return ERROR_OUTOFMEMORY;
}
Stream_Write_UINT8(out, MSG_SNDIN_VERSION);
Stream_Write_UINT32(out, Version);
error = callback->channel->Write(callback->channel, (UINT32) Stream_GetPosition(out),
Stream_Buffer(out), NULL);
Stream_Free(out, TRUE);
return error;
return audin_write_and_free_stream(callback, out);
}
/**
@ -130,11 +139,13 @@ static UINT audin_process_version(IWTSVirtualChannelCallback* pChannelCallback,
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT audin_send_incoming_data_pdu(IWTSVirtualChannelCallback* pChannelCallback)
static UINT audin_send_incoming_data_pdu(AUDIN_CHANNEL_CALLBACK* callback)
{
BYTE out_data[1];
AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback;
out_data[0] = MSG_SNDIN_DATA_INCOMING;
BYTE out_data[1] = { MSG_SNDIN_DATA_INCOMING };
if (!callback || !callback->channel || !callback->channel->Write)
return ERROR_INTERNAL_ERROR;
return callback->channel->Write(callback->channel, 1, out_data, NULL);
}
@ -143,23 +154,25 @@ static UINT audin_send_incoming_data_pdu(IWTSVirtualChannelCallback* pChannelCal
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback, wStream* s)
static UINT audin_process_formats(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* callback, wStream* s)
{
AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback;
AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) callback->plugin;
UINT32 i;
BYTE* fm;
UINT error;
wStream* out;
UINT32 NumFormats;
audinFormat format;
UINT32 cbSizeFormatsPacket;
size_t cbSizeFormatsPacket;
if (Stream_GetRemainingLength(s) < 8)
return ERROR_NO_DATA;
Stream_Read_UINT32(s, NumFormats);
DEBUG_DVC("NumFormats %"PRIu32"", NumFormats);
if ((NumFormats < 1) || (NumFormats > 1000))
{
WLog_ERR(TAG, "bad NumFormats %"PRIu32"", NumFormats);
WLog_Print(audin->log, WLOG_ERROR, "bad NumFormats %"PRIu32"", NumFormats);
return ERROR_INVALID_DATA;
}
@ -168,7 +181,7 @@ static UINT audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback,
if (!callback->formats)
{
WLog_ERR(TAG, "calloc failed!");
WLog_Print(audin->log, WLOG_ERROR, "calloc failed!");
return ERROR_INVALID_DATA;
}
@ -177,7 +190,7 @@ static UINT audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback,
if (!out)
{
error = CHANNEL_RC_NO_MEMORY;
WLog_ERR(TAG, "Stream_New failed!");
WLog_Print(audin->log, WLOG_ERROR, "Stream_New failed!");
goto out;
}
@ -186,6 +199,9 @@ static UINT audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback,
/* SoundFormats (variable) */
for (i = 0; i < NumFormats; i++)
{
if (Stream_GetRemainingLength(s) < 18)
return ERROR_NO_DATA;
Stream_GetPointer(s, fm);
Stream_Read_UINT16(s, format.wFormatTag);
Stream_Read_UINT16(s, format.nChannels);
@ -195,6 +211,10 @@ static UINT audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback,
Stream_Read_UINT16(s, format.wBitsPerSample);
Stream_Read_UINT16(s, format.cbSize);
format.data = Stream_Pointer(s);
if (Stream_GetRemainingLength(s) < format.cbSize)
return ERROR_NO_DATA;
Stream_Seek(s, format.cbSize);
DEBUG_DVC("wFormatTag=%"PRIu16" nChannels=%"PRIu16" nSamplesPerSec=%"PRIu32" "
"nBlockAlign=%"PRIu16" wBitsPerSample=%"PRIu16" cbSize=%"PRIu16"",
@ -220,7 +240,7 @@ static UINT audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback,
if (!Stream_EnsureRemainingCapacity(out, 18 + format.cbSize))
{
error = CHANNEL_RC_NO_MEMORY;
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
WLog_Print(audin->log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
goto out;
}
@ -228,18 +248,19 @@ static UINT audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback,
}
}
if ((error = audin_send_incoming_data_pdu(pChannelCallback)))
if ((error = audin_send_incoming_data_pdu(callback)))
{
WLog_ERR(TAG, "audin_send_incoming_data_pdu failed!");
WLog_Print(audin->log, WLOG_ERROR, "audin_send_incoming_data_pdu failed!");
goto out;
}
cbSizeFormatsPacket = (UINT32) Stream_GetPosition(out);
cbSizeFormatsPacket = Stream_GetPosition(out);
Stream_SetPosition(out, 0);
Stream_Write_UINT8(out, MSG_SNDIN_FORMATS); /* Header (1 byte) */
Stream_Write_UINT32(out, callback->formats_count); /* NumFormats (4 bytes) */
Stream_Write_UINT32(out, cbSizeFormatsPacket); /* cbSizeFormatsPacket (4 bytes) */
error = callback->channel->Write(callback->channel, cbSizeFormatsPacket, Stream_Buffer(out), NULL);
Stream_SetPosition(out, cbSizeFormatsPacket);
error = audin_write_and_free_stream(callback, out);
out:
if (error != CHANNEL_RC_OK)
@ -248,7 +269,6 @@ out:
callback->formats = NULL;
}
Stream_Free(out, TRUE);
return error;
}
@ -257,25 +277,20 @@ out:
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT audin_send_format_change_pdu(IWTSVirtualChannelCallback* pChannelCallback,
static UINT audin_send_format_change_pdu(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* callback,
UINT32 NewFormat)
{
UINT error;
wStream* out;
AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback;
out = Stream_New(NULL, 5);
wStream* out = Stream_New(NULL, 5);
if (!out)
{
WLog_ERR(TAG, "Stream_New failed!");
WLog_Print(audin->log, WLOG_ERROR, "Stream_New failed!");
return CHANNEL_RC_OK;
}
Stream_Write_UINT8(out, MSG_SNDIN_FORMATCHANGE);
Stream_Write_UINT32(out, NewFormat);
error = callback->channel->Write(callback->channel, 5, Stream_Buffer(out), NULL);
Stream_Free(out, TRUE);
return error;
return audin_write_and_free_stream(callback, out);
}
/**
@ -283,24 +298,20 @@ static UINT audin_send_format_change_pdu(IWTSVirtualChannelCallback* pChannelCal
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT audin_send_open_reply_pdu(IWTSVirtualChannelCallback* pChannelCallback, UINT32 Result)
static UINT audin_send_open_reply_pdu(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* callback,
UINT32 Result)
{
UINT error;
wStream* out;
AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback;
out = Stream_New(NULL, 5);
wStream* out = Stream_New(NULL, 5);
if (!out)
{
WLog_ERR(TAG, "Stream_New failed!");
WLog_Print(audin->log, WLOG_ERROR, "Stream_New failed!");
return CHANNEL_RC_NO_MEMORY;
}
Stream_Write_UINT8(out, MSG_SNDIN_OPEN_REPLY);
Stream_Write_UINT32(out, Result);
error = callback->channel->Write(callback->channel, 5, Stream_Buffer(out), NULL);
Stream_Free(out, TRUE);
return error;
return audin_write_and_free_stream(callback, out);
}
/**
@ -326,9 +337,9 @@ static UINT audin_receive_wave_data(const BYTE* data, int size, void* user_data)
if (!audin->attached)
return CHANNEL_RC_OK;
if ((error = audin_send_incoming_data_pdu((IWTSVirtualChannelCallback*) callback)))
if ((error = audin_send_incoming_data_pdu(callback)))
{
WLog_ERR(TAG, "audin_send_incoming_data_pdu failed!");
WLog_Print(audin->log, WLOG_ERROR, "audin_send_incoming_data_pdu failed!");
return error;
}
@ -336,16 +347,13 @@ static UINT audin_receive_wave_data(const BYTE* data, int size, void* user_data)
if (!out)
{
WLog_ERR(TAG, "Stream_New failed!");
WLog_Print(audin->log, WLOG_ERROR, "Stream_New failed!");
return ERROR_NOT_ENOUGH_MEMORY;
}
Stream_Write_UINT8(out, MSG_SNDIN_DATA);
Stream_Write(out, data, size);
error = callback->channel->Write(callback->channel, (UINT32) Stream_GetPosition(out),
Stream_Buffer(out), NULL);
Stream_Free(out, TRUE);
return error;
return audin_write_and_free_stream(callback, out);
}
/**
@ -353,14 +361,19 @@ static UINT audin_receive_wave_data(const BYTE* data, int size, void* user_data)
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT audin_process_open(IWTSVirtualChannelCallback* pChannelCallback, wStream* s)
static UINT audin_process_open(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* callback, wStream* s)
{
AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback;
AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) callback->plugin;
audinFormat* format;
UINT32 initialFormat;
UINT32 FramesPerPacket;
UINT error = CHANNEL_RC_OK;
if (!audin || !callback || !s)
return ERROR_INTERNAL_ERROR;
if (Stream_GetRemainingLength(s) < 8)
return ERROR_NO_DATA;
Stream_Read_UINT32(s, FramesPerPacket);
Stream_Read_UINT32(s, initialFormat);
DEBUG_DVC("FramesPerPacket=%"PRIu32" initialFormat=%"PRIu32"",
@ -368,8 +381,8 @@ static UINT audin_process_open(IWTSVirtualChannelCallback* pChannelCallback, wSt
if (initialFormat >= (UINT32) callback->formats_count)
{
WLog_ERR(TAG, "invalid format index %"PRIu32" (total %d)",
initialFormat, callback->formats_count);
WLog_Print(audin->log, WLOG_ERROR, "invalid format index %"PRIu32" (total %d)",
initialFormat, callback->formats_count);
return ERROR_INVALID_DATA;
}
@ -381,7 +394,7 @@ static UINT audin_process_open(IWTSVirtualChannelCallback* pChannelCallback, wSt
if (error != CHANNEL_RC_OK)
{
WLog_ERR(TAG, "SetFormat failed with errorcode %"PRIu32"", error);
WLog_Print(audin->log, WLOG_ERROR, "SetFormat failed with errorcode %"PRIu32"", error);
return error;
}
@ -389,19 +402,19 @@ static UINT audin_process_open(IWTSVirtualChannelCallback* pChannelCallback, wSt
if (error != CHANNEL_RC_OK)
{
WLog_ERR(TAG, "Open failed with errorcode %"PRIu32"", error);
WLog_Print(audin->log, WLOG_ERROR, "Open failed with errorcode %"PRIu32"", error);
return error;
}
}
if ((error = audin_send_format_change_pdu(pChannelCallback, initialFormat)))
if ((error = audin_send_format_change_pdu(audin, callback, initialFormat)))
{
WLog_ERR(TAG, "audin_send_format_change_pdu failed!");
WLog_Print(audin->log, WLOG_ERROR, "audin_send_format_change_pdu failed!");
return error;
}
if ((error = audin_send_open_reply_pdu(pChannelCallback, 0)))
WLog_ERR(TAG, "audin_send_open_reply_pdu failed!");
if ((error = audin_send_open_reply_pdu(audin, callback, 0)))
WLog_Print(audin->log, WLOG_ERROR, "audin_send_open_reply_pdu failed!");
return error;
}
@ -411,20 +424,26 @@ static UINT audin_process_open(IWTSVirtualChannelCallback* pChannelCallback, wSt
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT audin_process_format_change(IWTSVirtualChannelCallback* pChannelCallback, wStream* s)
static UINT audin_process_format_change(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* callback,
wStream* s)
{
AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback;
AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) callback->plugin;
UINT32 NewFormat;
audinFormat* format;
UINT error = CHANNEL_RC_OK;
if (!audin || !callback || !s)
return ERROR_INTERNAL_ERROR;
if (Stream_GetRemainingLength(s) < 4)
return ERROR_NO_DATA;
Stream_Read_UINT32(s, NewFormat);
DEBUG_DVC("NewFormat=%"PRIu32"", NewFormat);
if (NewFormat >= (UINT32) callback->formats_count)
if (NewFormat >= callback->formats_count)
{
WLog_ERR(TAG, "invalid format index %"PRIu32" (total %d)",
NewFormat, callback->formats_count);
WLog_Print(audin->log, WLOG_ERROR, "invalid format index %"PRIu32" (total %d)",
NewFormat, callback->formats_count);
return ERROR_INVALID_DATA;
}
@ -436,7 +455,7 @@ static UINT audin_process_format_change(IWTSVirtualChannelCallback* pChannelCall
if (error != CHANNEL_RC_OK)
{
WLog_ERR(TAG, "Close failed with errorcode %"PRIu32"", error);
WLog_Print(audin->log, WLOG_ERROR, "Close failed with errorcode %"PRIu32"", error);
return error;
}
@ -444,7 +463,7 @@ static UINT audin_process_format_change(IWTSVirtualChannelCallback* pChannelCall
if (error != CHANNEL_RC_OK)
{
WLog_ERR(TAG, "SetFormat failed with errorcode %"PRIu32"", error);
WLog_Print(audin->log, WLOG_ERROR, "SetFormat failed with errorcode %"PRIu32"", error);
return error;
}
@ -452,13 +471,13 @@ static UINT audin_process_format_change(IWTSVirtualChannelCallback* pChannelCall
if (error != CHANNEL_RC_OK)
{
WLog_ERR(TAG, "Open failed with errorcode %"PRIu32"", error);
WLog_Print(audin->log, WLOG_ERROR, "Open failed with errorcode %"PRIu32"", error);
return error;
}
}
if ((error = audin_send_format_change_pdu(pChannelCallback, NewFormat)))
WLog_ERR(TAG, "audin_send_format_change_pdu failed!");
if ((error = audin_send_format_change_pdu(audin, callback, NewFormat)))
WLog_Print(audin->log, WLOG_ERROR, "audin_send_format_change_pdu failed!");
return error;
}
@ -472,29 +491,43 @@ static UINT audin_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
{
UINT error;
BYTE MessageId;
AUDIN_PLUGIN* audin;
AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback;
if (!callback || !data)
return ERROR_INVALID_PARAMETER;
audin = (AUDIN_PLUGIN*) callback->plugin;
if (!audin)
return ERROR_INTERNAL_ERROR;
if (Stream_GetRemainingCapacity(data) < 1)
return ERROR_NO_DATA;
Stream_Read_UINT8(data, MessageId);
DEBUG_DVC("MessageId=0x%02"PRIx8"", MessageId);
switch (MessageId)
{
case MSG_SNDIN_VERSION:
error = audin_process_version(pChannelCallback, data);
error = audin_process_version(audin, callback, data);
break;
case MSG_SNDIN_FORMATS:
error = audin_process_formats(pChannelCallback, data);
error = audin_process_formats(audin, callback, data);
break;
case MSG_SNDIN_OPEN:
error = audin_process_open(pChannelCallback, data);
error = audin_process_open(audin, callback, data);
break;
case MSG_SNDIN_FORMATCHANGE:
error = audin_process_format_change(pChannelCallback, data);
error = audin_process_format_change(audin, callback, data);
break;
default:
WLog_ERR(TAG, "unknown MessageId=0x%02"PRIx8"", MessageId);
WLog_Print(audin->log, WLOG_ERROR, "unknown MessageId=0x%02"PRIx8"", MessageId);
error = ERROR_INVALID_DATA;
break;
}
@ -519,7 +552,7 @@ static UINT audin_on_close(IWTSVirtualChannelCallback* pChannelCallback)
IFCALLRET(audin->device->Close, error, audin->device);
if (error != CHANNEL_RC_OK)
WLog_ERR(TAG, "Close failed with errorcode %"PRIu32"", error);
WLog_Print(audin->log, WLOG_ERROR, "Close failed with errorcode %"PRIu32"", error);
}
free(callback->formats);
@ -537,13 +570,19 @@ static UINT audin_on_new_channel_connection(IWTSListenerCallback* pListenerCallb
IWTSVirtualChannelCallback** ppCallback)
{
AUDIN_CHANNEL_CALLBACK* callback;
AUDIN_PLUGIN* audin;
AUDIN_LISTENER_CALLBACK* listener_callback = (AUDIN_LISTENER_CALLBACK*) pListenerCallback;
if (!listener_callback || !listener_callback->plugin)
return ERROR_INTERNAL_ERROR;
audin = (AUDIN_PLUGIN*) listener_callback->plugin;
DEBUG_DVC("...");
callback = (AUDIN_CHANNEL_CALLBACK*) calloc(1, sizeof(AUDIN_CHANNEL_CALLBACK));
if (!callback)
{
WLog_ERR(TAG, "calloc failed!");
WLog_Print(audin->log, WLOG_ERROR, "calloc failed!");
return CHANNEL_RC_NO_MEMORY;
}
@ -569,7 +608,7 @@ static UINT audin_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManag
if (!audin->listener_callback)
{
WLog_ERR(TAG, "calloc failed!");
WLog_Print(audin->log, WLOG_ERROR, "calloc failed!");
return CHANNEL_RC_NO_MEMORY;
}
@ -597,7 +636,7 @@ static UINT audin_plugin_terminated(IWTSPlugin* pPlugin)
if (error != CHANNEL_RC_OK)
{
WLog_ERR(TAG, "Free failed with errorcode %"PRIu32"", error);
WLog_Print(audin->log, WLOG_ERROR, "Free failed with errorcode %"PRIu32"", error);
// dont stop on error
}
@ -648,7 +687,7 @@ static UINT audin_register_device_plugin(IWTSPlugin* pPlugin, IAudinDevice* devi
if (audin->device)
{
WLog_ERR(TAG, "existing device, abort.");
WLog_Print(audin->log, WLOG_ERROR, "existing device, abort.");
return ERROR_ALREADY_EXISTS;
}
@ -662,38 +701,34 @@ static UINT audin_register_device_plugin(IWTSPlugin* pPlugin, IAudinDevice* devi
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT audin_load_device_plugin(IWTSPlugin* pPlugin, const char* name, ADDIN_ARGV* args)
static UINT audin_load_device_plugin(AUDIN_PLUGIN* audin, char* name, ADDIN_ARGV* args)
{
PFREERDP_AUDIN_DEVICE_ENTRY entry;
FREERDP_AUDIN_DEVICE_ENTRY_POINTS entryPoints;
AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*)pPlugin;
UINT error;
if (!audin_process_addin_args(audin, args))
return CHANNEL_RC_INITIALIZATION_ERROR;
entry = (PFREERDP_AUDIN_DEVICE_ENTRY) freerdp_load_channel_addin_entry("audin", (LPSTR) name, NULL,
entry = (PFREERDP_AUDIN_DEVICE_ENTRY) freerdp_load_channel_addin_entry("audin", name, NULL,
0);
if (entry == NULL)
{
WLog_ERR(TAG, "freerdp_load_channel_addin_entry did not return any function pointers for %s ",
name);
WLog_Print(audin->log, WLOG_ERROR,
"freerdp_load_channel_addin_entry did not return any function pointers for %s ",
name);
return ERROR_INVALID_FUNCTION;
}
entryPoints.plugin = pPlugin;
entryPoints.plugin = (IWTSPlugin*) audin;
entryPoints.pRegisterAudinDevice = audin_register_device_plugin;
entryPoints.args = args;
entryPoints.rdpcontext = ((AUDIN_PLUGIN*)pPlugin)->rdpcontext;
entryPoints.rdpcontext = audin->rdpcontext;
if ((error = entry(&entryPoints)))
{
WLog_ERR(TAG, "%s entry returned error %"PRIu32".", name, error);
WLog_Print(audin->log, WLOG_ERROR, "%s entry returned error %"PRIu32".", name, error);
return error;
}
WLog_INFO(TAG, "Loaded %s backend for audin", name);
WLog_Print(audin->log, WLOG_INFO, "Loaded %s backend for audin", name);
return CHANNEL_RC_OK;
}
@ -702,14 +737,14 @@ static UINT audin_load_device_plugin(IWTSPlugin* pPlugin, const char* name, ADDI
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT audin_set_subsystem(AUDIN_PLUGIN* audin, char* subsystem)
static UINT audin_set_subsystem(AUDIN_PLUGIN* audin, const char* subsystem)
{
free(audin->subsystem);
audin->subsystem = _strdup(subsystem);
if (!audin->subsystem)
{
WLog_ERR(TAG, "_strdup failed!");
WLog_Print(audin->log, WLOG_ERROR, "_strdup failed!");
return ERROR_NOT_ENOUGH_MEMORY;
}
@ -728,7 +763,7 @@ static UINT audin_set_device_name(AUDIN_PLUGIN* audin, char* device_name)
if (!audin->device_name)
{
WLog_ERR(TAG, "_strdup failed!");
WLog_Print(audin->log, WLOG_ERROR, "_strdup failed!");
return ERROR_NOT_ENOUGH_MEMORY;
}
@ -763,6 +798,7 @@ BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, ADDIN_ARGV* args)
return FALSE;
arg = audin_args;
errno = 0;
do
{
@ -774,7 +810,7 @@ BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, ADDIN_ARGV* args)
{
if ((error = audin_set_subsystem(audin, arg->Value)))
{
WLog_ERR(TAG, "audin_set_subsystem failed with error %"PRIu32"!", error);
WLog_Print(audin->log, WLOG_ERROR, "audin_set_subsystem failed with error %"PRIu32"!", error);
return FALSE;
}
}
@ -782,21 +818,34 @@ BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, ADDIN_ARGV* args)
{
if ((error = audin_set_device_name(audin, arg->Value)))
{
WLog_ERR(TAG, "audin_set_device_name failed with error %"PRIu32"!", error);
WLog_Print(audin->log, WLOG_ERROR, "audin_set_device_name failed with error %"PRIu32"!", error);
return FALSE;
}
}
CommandLineSwitchCase(arg, "format")
{
audin->fixed_format = atoi(arg->Value);
unsigned long val = strtoul(arg->Value, NULL, 0);
if ((errno != 0) || (val > UINT16_MAX))
return FALSE;
audin->fixed_format = val;
}
CommandLineSwitchCase(arg, "rate")
{
audin->fixed_rate = atoi(arg->Value);
long val = strtol(arg->Value, NULL, 0);
if ((errno != 0) || (val < INT32_MIN) || (val > INT32_MAX))
return FALSE;
audin->fixed_rate = val;
}
CommandLineSwitchCase(arg, "channel")
{
audin->fixed_channel = atoi(arg->Value);
unsigned long val = strtoul(arg->Value, NULL, 0);
if ((errno != 0) || (val > UINT16_MAX))
audin->fixed_channel = val;
}
CommandLineSwitchDefault(arg)
{
@ -867,6 +916,7 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
return CHANNEL_RC_NO_MEMORY;
}
audin->log = WLog_Get(TAG);
audin->attached = TRUE;
audin->iface.Initialize = audin_plugin_initialize;
audin->iface.Connected = NULL;
@ -886,10 +936,10 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
if (audin->subsystem)
{
if ((error = audin_load_device_plugin((IWTSPlugin*) audin, audin->subsystem, args)))
if ((error = audin_load_device_plugin(audin, audin->subsystem, args)))
{
WLog_ERR(TAG, "audin_load_device_plugin %s failed with error %"PRIu32"!",
audin->subsystem, error);
WLog_Print(audin->log, WLOG_ERROR, "audin_load_device_plugin %s failed with error %"PRIu32"!",
audin->subsystem, error);
goto out;
}
}
@ -899,18 +949,18 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
{
if ((error = audin_set_subsystem(audin, entry->subsystem)))
{
WLog_ERR(TAG, "audin_set_subsystem for %s failed with error %"PRIu32"!",
entry->subsystem, error);
WLog_Print(audin->log, WLOG_ERROR, "audin_set_subsystem for %s failed with error %"PRIu32"!",
entry->subsystem, error);
}
else if ((error = audin_set_device_name(audin, entry->device)))
{
WLog_ERR(TAG, "audin_set_device_name for %s failed with error %"PRIu32"!",
entry->subsystem, error);
WLog_Print(audin->log, WLOG_ERROR, "audin_set_device_name for %s failed with error %"PRIu32"!",
entry->subsystem, error);
}
else if ((error = audin_load_device_plugin((IWTSPlugin*) audin, audin->subsystem, args)))
else if ((error = audin_load_device_plugin(audin, audin->subsystem, args)))
{
WLog_ERR(TAG, "audin_load_device_plugin %s failed with error %"PRIu32"!",
entry->subsystem, error);
WLog_Print(audin->log, WLOG_ERROR, "audin_load_device_plugin %s failed with error %"PRIu32"!",
entry->subsystem, error);
}
entry++;
@ -918,7 +968,7 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
}
if (audin->device == NULL)
WLog_ERR(TAG, "no sound device.");
WLog_Print(audin->log, WLOG_ERROR, "no sound device.");
error = pEntryPoints->RegisterPlugin(pEntryPoints, "audin", (IWTSPlugin*) audin);
out:

View File

@ -70,7 +70,7 @@ typedef struct _AudinOpenSLESDevice
rdpContext* rdpcontext;
} AudinOpenSLESDevice;
static void* audin_opensles_thread_func(void* arg)
static DWORD WINAPI audin_opensles_thread_func(LPVOID arg)
{
union
{
@ -173,8 +173,8 @@ out:
if (error && opensles->rdpcontext)
setChannelError(opensles->rdpcontext, error, "audin_opensles_thread_func reported an error");
ExitThread((DWORD)error);
return NULL;
ExitThread(error);
return error;
}
/**
@ -356,7 +356,7 @@ static UINT audin_opensles_open(IAudinDevice* device, AudinReceive receive,
goto error_out;
}
if (!(opensles->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) audin_opensles_thread_func,
audin_opensles_thread_func,
opensles, 0, NULL)))
{
WLog_ERR(TAG, "CreateThread failed!");

View File

@ -173,7 +173,7 @@ static UINT audin_oss_set_format(IAudinDevice* device, audinFormat* format,
return CHANNEL_RC_OK;
}
static void* audin_oss_thread_func(void* arg)
static DWORD WINAPI audin_oss_thread_func(LPVOID arg)
{
char dev_name[PATH_MAX] = "/dev/dsp";
char mixer_name[PATH_MAX] = "/dev/mixer";
@ -352,8 +352,8 @@ err_out:
}
free(buffer);
ExitThread(0);
return NULL;
ExitThread(error);
return error;
}
/**
@ -374,8 +374,7 @@ static UINT audin_oss_open(IAudinDevice* device, AudinReceive receive,
return ERROR_INTERNAL_ERROR;
}
if (!(oss->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE)audin_oss_thread_func, oss, 0, NULL)))
if (!(oss->thread = CreateThread(NULL, 0, audin_oss_thread_func, oss, 0, NULL)))
{
WLog_ERR(TAG, "CreateThread failed!");
CloseHandle(oss->stopEvent);
@ -471,6 +470,7 @@ static UINT audin_oss_parse_addin_args(AudinOSSDevice* device, ADDIN_ARGV* args)
return ERROR_INVALID_PARAMETER;
arg = audin_oss_args;
errno = 0;
do
{
@ -488,7 +488,17 @@ static UINT audin_oss_parse_addin_args(AudinOSSDevice* device, ADDIN_ARGV* args)
return CHANNEL_RC_NO_MEMORY;
}
oss->dev_unit = strtol(str_num, &eptr, 10);
{
long val = strtol(str_num, &eptr, 10);
if ((errno != 0) || (val < INT32_MIN) || (val > INT32_MAX))
{
free(str_num);
return CHANNEL_RC_NULL_DATA;
}
oss->dev_unit = val;
}
if (oss->dev_unit < 0 || *eptr != '\0')
oss->dev_unit = -1;

View File

@ -400,14 +400,15 @@ static UINT audin_pulse_close(IAudinDevice* device)
{
AudinPulseDevice* pulse = (AudinPulseDevice*) device;
if (!pulse->context || !pulse->stream)
return ERROR_INVALID_PARAMETER;
if (pulse->stream)
{
pa_threaded_mainloop_lock(pulse->mainloop);
pa_stream_disconnect(pulse->stream);
pa_stream_unref(pulse->stream);
pulse->stream = NULL;
pa_threaded_mainloop_unlock(pulse->mainloop);
}
pa_threaded_mainloop_lock(pulse->mainloop);
pa_stream_disconnect(pulse->stream);
pa_stream_unref(pulse->stream);
pulse->stream = NULL;
pa_threaded_mainloop_unlock(pulse->mainloop);
pulse->receive = NULL;
pulse->user_data = NULL;

View File

@ -94,7 +94,7 @@ static void CALLBACK waveInProc(HWAVEIN hWaveIn, UINT uMsg, DWORD_PTR dwInstance
setChannelError(winmm->rdpcontext, error, "waveInProc reported an error");
}
static DWORD audin_winmm_thread_func(void* arg)
static DWORD WINAPI audin_winmm_thread_func(LPVOID arg)
{
AudinWinmmDevice* winmm = (AudinWinmmDevice*) arg;
char *buffer;
@ -332,8 +332,7 @@ static UINT audin_winmm_open(IAudinDevice* device, AudinReceive receive, void* u
return ERROR_INTERNAL_ERROR;
}
if (!(winmm->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) audin_winmm_thread_func, winmm, 0, NULL)))
if (!(winmm->thread = CreateThread(NULL, 0, audin_winmm_thread_func, winmm, 0, NULL)))
{
WLog_ERR(TAG, "CreateThread failed!");
CloseHandle(winmm->stopEvent);

View File

@ -401,7 +401,7 @@ static UINT audin_server_recv_data(audin_server* audin, wStream* s,
return success;
}
static void* audin_server_thread_func(void* arg)
static DWORD WINAPI audin_server_thread_func(LPVOID arg)
{
wStream* s;
void* buffer;
@ -596,8 +596,8 @@ out:
setChannelError(audin->context.rdpcontext, error,
"audin_server_thread_func reported an error");
ExitThread((DWORD)error);
return NULL;
ExitThread(error);
return error;
}
static BOOL audin_server_open(audin_server_context* context)
@ -632,8 +632,7 @@ static BOOL audin_server_open(audin_server_context* context)
return FALSE;
}
if (!(audin->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) audin_server_thread_func, (void*) audin, 0, NULL)))
if (!(audin->thread = CreateThread(NULL, 0, audin_server_thread_func, (void*) audin, 0, NULL)))
{
WLog_ERR(TAG, "CreateThread failed!");
CloseHandle(audin->stopEvent);

View File

@ -42,7 +42,7 @@
UINT cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags)
{
UINT32 index;
UINT32 position;
size_t position;
BOOL asciiNames;
int formatNameLength;
char* szFormatName;

View File

@ -34,6 +34,7 @@
#include "cliprdr_main.h"
#include "cliprdr_format.h"
#ifdef WITH_DEBUG_CLIPRDR
static const char* const CB_MSG_TYPE_STRINGS[] =
{
"",
@ -49,6 +50,7 @@ static const char* const CB_MSG_TYPE_STRINGS[] =
"CB_LOCK_CLIPDATA",
"CB_UNLOCK_CLIPDATA"
};
#endif
CliprdrClientContext* cliprdr_get_client_interface(cliprdrPlugin* cliprdr)
{
@ -87,7 +89,7 @@ static wStream* cliprdr_packet_new(UINT16 msgType, UINT16 msgFlags,
*/
static UINT cliprdr_packet_send(cliprdrPlugin* cliprdr, wStream* s)
{
UINT32 pos;
size_t pos;
UINT32 dataLen;
UINT status = CHANNEL_RC_OK;
pos = Stream_GetPosition(s);
@ -160,6 +162,9 @@ static UINT cliprdr_process_general_capability(cliprdrPlugin* cliprdr,
return ERROR_INTERNAL_ERROR;
}
if (Stream_GetRemainingLength(s) < 8)
return ERROR_INVALID_DATA;
Stream_Read_UINT32(s, version); /* version (4 bytes) */
Stream_Read_UINT32(s, generalFlags); /* generalFlags (4 bytes) */
DEBUG_CLIPRDR("Version: %"PRIu32"", version);
@ -218,15 +223,25 @@ static UINT cliprdr_process_clip_caps(cliprdrPlugin* cliprdr, wStream* s,
UINT16 cCapabilitiesSets;
UINT16 capabilitySetType;
UINT error = CHANNEL_RC_OK;
if (Stream_GetRemainingLength(s) < 4)
return ERROR_INVALID_DATA;
Stream_Read_UINT16(s, cCapabilitiesSets); /* cCapabilitiesSets (2 bytes) */
Stream_Seek_UINT16(s); /* pad1 (2 bytes) */
WLog_Print(cliprdr->log, WLOG_DEBUG, "ServerCapabilities");
for (index = 0; index < cCapabilitiesSets; index++)
{
if (Stream_GetRemainingLength(s) < 4)
return ERROR_INVALID_DATA;
Stream_Read_UINT16(s, capabilitySetType); /* capabilitySetType (2 bytes) */
Stream_Read_UINT16(s, lengthCapability); /* lengthCapability (2 bytes) */
if (lengthCapability < 4 || Stream_GetRemainingLength(s) < lengthCapability-4)
return ERROR_INVALID_DATA;
switch (capabilitySetType)
{
case CB_CAPSTYPE_GENERAL:
@ -448,8 +463,7 @@ static UINT cliprdr_process_unlock_clipdata(cliprdrPlugin* cliprdr, wStream* s,
unlockClipboardData.msgType = CB_UNLOCK_CLIPDATA;
unlockClipboardData.msgFlags = flags;
unlockClipboardData.dataLen = length;
Stream_Read_UINT32(s,
unlockClipboardData.clipDataId); /* clipDataId (4 bytes) */
Stream_Read_UINT32(s, unlockClipboardData.clipDataId); /* clipDataId (4 bytes) */
IFCALLRET(context->ServerUnlockClipboardData, error, context,
&unlockClipboardData);
@ -470,9 +484,17 @@ static UINT cliprdr_order_recv(cliprdrPlugin* cliprdr, wStream* s)
UINT16 msgFlags;
UINT32 dataLen;
UINT error;
if (Stream_GetRemainingLength(s) < 8)
return ERROR_INVALID_DATA;
Stream_Read_UINT16(s, msgType); /* msgType (2 bytes) */
Stream_Read_UINT16(s, msgFlags); /* msgFlags (2 bytes) */
Stream_Read_UINT32(s, dataLen); /* dataLen (4 bytes) */
if (Stream_GetRemainingLength(s) < dataLen)
return ERROR_INVALID_DATA;
#ifdef WITH_DEBUG_CLIPRDR
WLog_DBG(TAG, "msgType: %s (%"PRIu16"), msgFlags: %"PRIu16" dataLen: %"PRIu32"",
CB_MSG_TYPE_STRINGS[msgType], msgType, msgFlags, dataLen);
@ -500,40 +522,35 @@ static UINT cliprdr_order_recv(cliprdrPlugin* cliprdr, wStream* s)
break;
case CB_FORMAT_LIST_RESPONSE:
if ((error = cliprdr_process_format_list_response(cliprdr, s, dataLen,
msgFlags)))
if ((error = cliprdr_process_format_list_response(cliprdr, s, dataLen, msgFlags)))
WLog_ERR(TAG, "cliprdr_process_format_list_response failed with error %"PRIu32"!",
error);
break;
case CB_FORMAT_DATA_REQUEST:
if ((error = cliprdr_process_format_data_request(cliprdr, s, dataLen,
msgFlags)))
if ((error = cliprdr_process_format_data_request(cliprdr, s, dataLen, msgFlags)))
WLog_ERR(TAG, "cliprdr_process_format_data_request failed with error %"PRIu32"!",
error);
break;
case CB_FORMAT_DATA_RESPONSE:
if ((error = cliprdr_process_format_data_response(cliprdr, s, dataLen,
msgFlags)))
if ((error = cliprdr_process_format_data_response(cliprdr, s, dataLen, msgFlags)))
WLog_ERR(TAG, "cliprdr_process_format_data_response failed with error %"PRIu32"!",
error);
break;
case CB_FILECONTENTS_REQUEST:
if ((error = cliprdr_process_filecontents_request(cliprdr, s, dataLen,
msgFlags)))
if ((error = cliprdr_process_filecontents_request(cliprdr, s, dataLen, msgFlags)))
WLog_ERR(TAG, "cliprdr_process_filecontents_request failed with error %"PRIu32"!",
error);
break;
case CB_FILECONTENTS_RESPONSE:
if ((error = cliprdr_process_filecontents_response(cliprdr, s, dataLen,
msgFlags)))
if ((error = cliprdr_process_filecontents_response(cliprdr, s, dataLen, msgFlags)))
WLog_ERR(TAG, "cliprdr_process_filecontents_response failed with error %"PRIu32"!",
error);
@ -586,12 +603,9 @@ static UINT cliprdr_client_capabilities(CliprdrClientContext* context,
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 */
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 */
WLog_Print(cliprdr->log, WLOG_DEBUG, "ClientCapabilities");
@ -618,9 +632,7 @@ static UINT cliprdr_temp_directory(CliprdrClientContext* context,
return ERROR_INTERNAL_ERROR;
}
length = ConvertToUnicode(CP_UTF8, 0, tempDirectory->szTempDir, -1, &wszTempDir,
0);
length = ConvertToUnicode(CP_UTF8, 0, tempDirectory->szTempDir, -1, &wszTempDir, 0);
if (length < 0)
return ERROR_INTERNAL_ERROR;
@ -796,8 +808,7 @@ static UINT cliprdr_client_lock_clipboard_data(CliprdrClientContext* context,
return ERROR_INTERNAL_ERROR;
}
Stream_Write_UINT32(s,
lockClipboardData->clipDataId); /* clipDataId (4 bytes) */
Stream_Write_UINT32(s, lockClipboardData->clipDataId); /* clipDataId (4 bytes) */
WLog_Print(cliprdr->log, WLOG_DEBUG,
"ClientLockClipboardData: clipDataId: 0x%08"PRIX32"",
lockClipboardData->clipDataId);
@ -822,8 +833,7 @@ static UINT cliprdr_client_unlock_clipboard_data(CliprdrClientContext* context,
return ERROR_INTERNAL_ERROR;
}
Stream_Write_UINT32(s,
unlockClipboardData->clipDataId); /* clipDataId (4 bytes) */
Stream_Write_UINT32(s, unlockClipboardData->clipDataId); /* clipDataId (4 bytes) */
WLog_Print(cliprdr->log, WLOG_DEBUG,
"ClientUnlockClipboardData: clipDataId: 0x%08"PRIX32"",
unlockClipboardData->clipDataId);
@ -852,8 +862,7 @@ static UINT cliprdr_client_format_data_request(CliprdrClientContext* context,
return ERROR_INTERNAL_ERROR;
}
Stream_Write_UINT32(s,
formatDataRequest->requestedFormatId); /* requestedFormatId (4 bytes) */
Stream_Write_UINT32(s, formatDataRequest->requestedFormatId); /* requestedFormatId (4 bytes) */
WLog_Print(cliprdr->log, WLOG_DEBUG, "ClientFormatDataRequest");
return cliprdr_packet_send(cliprdr, s);
}
@ -1048,7 +1057,7 @@ static VOID VCAPITYPE cliprdr_virtual_channel_open_event_ex(LPVOID lpUserParam,
"cliprdr_virtual_channel_open_event_ex reported an error");
}
static void* cliprdr_virtual_channel_client_thread(void* arg)
static DWORD WINAPI cliprdr_virtual_channel_client_thread(LPVOID arg)
{
wStream* data;
wMessage message;
@ -1090,8 +1099,8 @@ static void* cliprdr_virtual_channel_client_thread(void* arg)
setChannelError(cliprdr->context->rdpcontext, error,
"cliprdr_virtual_channel_client_thread reported an error");
ExitThread((DWORD)error);
return NULL;
ExitThread(error);
return error;
}
/**
@ -1122,8 +1131,7 @@ static UINT cliprdr_virtual_channel_event_connected(cliprdrPlugin* cliprdr,
return ERROR_NOT_ENOUGH_MEMORY;
}
if (!(cliprdr->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) cliprdr_virtual_channel_client_thread, (void*) cliprdr,
if (!(cliprdr->thread = CreateThread(NULL, 0, cliprdr_virtual_channel_client_thread, (void*) cliprdr,
0, NULL)))
{
WLog_ERR(TAG, "CreateThread failed!");
@ -1182,6 +1190,7 @@ static UINT cliprdr_virtual_channel_event_disconnected(cliprdrPlugin* cliprdr)
static UINT cliprdr_virtual_channel_event_terminated(cliprdrPlugin* cliprdr)
{
cliprdr->InitHandle = 0;
free(cliprdr->context);
free(cliprdr);
return CHANNEL_RC_OK;
}
@ -1201,8 +1210,7 @@ static VOID VCAPITYPE cliprdr_virtual_channel_init_event_ex(LPVOID lpUserParam,
switch (event)
{
case CHANNEL_EVENT_CONNECTED:
if ((error = cliprdr_virtual_channel_event_connected(cliprdr, pData,
dataLength)))
if ((error = cliprdr_virtual_channel_event_connected(cliprdr, pData, dataLength)))
WLog_ERR(TAG, "cliprdr_virtual_channel_event_connected failed with error %"PRIu32"!",
error);

View File

@ -91,7 +91,7 @@ wStream* cliprdr_server_packet_new(UINT16 msgType, UINT16 msgFlags,
*/
UINT cliprdr_server_packet_send(CliprdrServerPrivate* cliprdr, wStream* s)
{
UINT32 pos;
size_t pos;
BOOL status;
UINT32 dataLen;
UINT32 written;
@ -628,7 +628,7 @@ static UINT cliprdr_server_receive_format_list(CliprdrServerContext* context,
{
UINT32 index;
UINT32 dataLen;
UINT32 position;
size_t position;
BOOL asciiNames;
int formatNameLength;
char* szFormatName;
@ -1185,7 +1185,7 @@ static UINT cliprdr_server_init(CliprdrServerContext* context)
UINT cliprdr_server_read(CliprdrServerContext* context)
{
wStream* s;
int position;
size_t position;
DWORD BytesToRead;
DWORD BytesReturned;
CLIPRDR_HEADER header;
@ -1319,7 +1319,7 @@ UINT cliprdr_server_read(CliprdrServerContext* context)
return CHANNEL_RC_OK;
}
static void* cliprdr_server_thread(void* arg)
static DWORD WINAPI cliprdr_server_thread(LPVOID arg)
{
DWORD status;
DWORD nCount;
@ -1388,8 +1388,8 @@ out:
setChannelError(context->rdpcontext, error,
"cliprdr_server_thread reported an error");
ExitThread((DWORD)error);
return NULL;
ExitThread(error);
return error;
}
/**
@ -1478,8 +1478,7 @@ static UINT cliprdr_server_start(CliprdrServerContext* context)
return ERROR_INTERNAL_ERROR;
}
if (!(cliprdr->Thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) cliprdr_server_thread, (void*) context, 0, NULL)))
if (!(cliprdr->Thread = CreateThread(NULL, 0, cliprdr_server_thread, (void*) context, 0, NULL)))
{
WLog_ERR(TAG, "CreateThread failed!");
CloseHandle(cliprdr->StopEvent);

View File

@ -98,7 +98,6 @@ UINT disp_send_display_control_monitor_layout_pdu(DISP_CHANNEL_CALLBACK* callbac
type = DISPLAY_CONTROL_PDU_TYPE_MONITOR_LAYOUT;
s = Stream_New(NULL, length);
if(!s)
{
WLog_ERR(TAG, "Stream_New failed!");
@ -112,10 +111,9 @@ UINT disp_send_display_control_monitor_layout_pdu(DISP_CHANNEL_CALLBACK* callbac
NumMonitors = disp->MaxNumMonitors;
Stream_Write_UINT32(s, MonitorLayoutSize); /* MonitorLayoutSize (4 bytes) */
Stream_Write_UINT32(s, NumMonitors); /* NumMonitors (4 bytes) */
//WLog_ERR(TAG, "NumMonitors: %"PRIu32"", NumMonitors);
WLog_DBG(TAG, "disp_send_display_control_monitor_layout_pdu: NumMonitors=%"PRIu32"", NumMonitors);
for (index = 0; index < NumMonitors; index++)
{
@ -147,16 +145,11 @@ UINT disp_send_display_control_monitor_layout_pdu(DISP_CHANNEL_CALLBACK* callbac
Stream_Write_UINT32(s, Monitors[index].DesktopScaleFactor); /* DesktopScaleFactor (4 bytes) */
Stream_Write_UINT32(s, Monitors[index].DeviceScaleFactor); /* DeviceScaleFactor (4 bytes) */
#if 0
WLog_DBG(TAG, "\t: Flags: 0x%08"PRIX32"", Monitors[index].Flags);
WLog_DBG(TAG, "\t: Left: %"PRId32"", Monitors[index].Left);
WLog_DBG(TAG, "\t: Top: %"PRId32"", Monitors[index].Top);
WLog_DBG(TAG, "\t: Width: %"PRIu32"", Monitors[index].Width);
WLog_DBG(TAG, "\t: Height: %"PRIu32"", Monitors[index].Height);
WLog_DBG(TAG, "\t: PhysicalWidth: %"PRIu32"", Monitors[index].PhysicalWidth);
WLog_DBG(TAG, "\t: PhysicalHeight: %"PRIu32"", Monitors[index].PhysicalHeight);
WLog_DBG(TAG, "\t: Orientation: %"PRIu32"", Monitors[index].Orientation);
#endif
WLog_DBG(TAG, "\t%d : Flags: 0x%08"PRIX32" Left/Top: (%"PRId32",%"PRId32") W/H=%"PRIu32"x%"PRIu32")", index,
Monitors[index].Flags, Monitors[index].Left, Monitors[index].Top, Monitors[index].Width,
Monitors[index].Height);
WLog_DBG(TAG, "\t PhysicalWidth: %"PRIu32" PhysicalHeight: %"PRIu32" Orientation: %"PRIu32"",
Monitors[index].PhysicalWidth, Monitors[index].PhysicalHeight, Monitors[index].Orientation);
}
Stream_SealLength(s);
@ -176,8 +169,11 @@ UINT disp_send_display_control_monitor_layout_pdu(DISP_CHANNEL_CALLBACK* callbac
UINT disp_recv_display_control_caps_pdu(DISP_CHANNEL_CALLBACK* callback, wStream* s)
{
DISP_PLUGIN* disp;
DispClientContext *context;
UINT ret = CHANNEL_RC_OK;
disp = (DISP_PLUGIN*) callback->plugin;
context = (DispClientContext *)disp->iface.pInterface;
if (Stream_GetRemainingLength(s) < 12)
{
@ -188,10 +184,11 @@ UINT disp_recv_display_control_caps_pdu(DISP_CHANNEL_CALLBACK* callback, wStream
Stream_Read_UINT32(s, disp->MaxNumMonitors); /* MaxNumMonitors (4 bytes) */
Stream_Read_UINT32(s, disp->MaxMonitorAreaFactorA); /* MaxMonitorAreaFactorA (4 bytes) */
Stream_Read_UINT32(s, disp->MaxMonitorAreaFactorB); /* MaxMonitorAreaFactorB (4 bytes) */
//WLog_ERR(TAG, "DisplayControlCapsPdu: MaxNumMonitors: %"PRIu32" MaxMonitorAreaFactorA: %"PRIu32" MaxMonitorAreaFactorB: %"PRIu32"",
// disp->MaxNumMonitors, disp->MaxMonitorAreaFactorA, disp->MaxMonitorAreaFactorB);
return CHANNEL_RC_OK;
if (context->DisplayControlCaps)
ret = context->DisplayControlCaps(context, disp->MaxNumMonitors, disp->MaxMonitorAreaFactorA, disp->MaxMonitorAreaFactorB);
return ret;
}
/**
@ -360,11 +357,9 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
DispClientContext* context;
disp = (DISP_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "disp");
if (!disp)
{
disp = (DISP_PLUGIN*) calloc(1, sizeof(DISP_PLUGIN));
if (!disp)
{
WLog_ERR(TAG, "calloc failed!");
@ -375,9 +370,11 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
disp->iface.Connected = NULL;
disp->iface.Disconnected = NULL;
disp->iface.Terminated = disp_plugin_terminated;
disp->MaxNumMonitors = 16;
disp->MaxMonitorAreaFactorA = 8192;
disp->MaxMonitorAreaFactorB = 8192;
context = (DispClientContext*) calloc(1, sizeof(DispClientContext));
if (!context)
{
WLog_ERR(TAG, "calloc failed!");
@ -386,15 +383,10 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
}
context->handle = (void*) disp;
context->SendMonitorLayout = disp_send_monitor_layout;
disp->iface.pInterface = (void*) context;
disp->MaxNumMonitors = 16;
disp->MaxMonitorAreaFactorA = 8192;
disp->MaxMonitorAreaFactorB = 8192;
error = pEntryPoints->RegisterPlugin(pEntryPoints, "disp", (IWTSPlugin*) disp);
}
else

View File

@ -189,7 +189,7 @@ static IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin)
if (!dvcman)
{
WLog_ERR(TAG, "calloc failed!");
WLog_Print(plugin->log, WLOG_ERROR, "calloc failed!");
return NULL;
}
@ -201,7 +201,7 @@ static IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin)
if (!dvcman->channels)
{
WLog_ERR(TAG, "ArrayList_New failed!");
WLog_Print(plugin->log, WLOG_ERROR, "ArrayList_New failed!");
free(dvcman);
return NULL;
}
@ -211,7 +211,7 @@ static IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin)
if (!dvcman->pool)
{
WLog_ERR(TAG, "StreamPool_New failed!");
WLog_Print(plugin->log, WLOG_ERROR, "StreamPool_New failed!");
ArrayList_Free(dvcman->channels);
free(dvcman);
return NULL;
@ -225,13 +225,14 @@ static IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin)
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT dvcman_load_addin(IWTSVirtualChannelManager* pChannelMgr,
static UINT dvcman_load_addin(drdynvcPlugin* drdynvc,
IWTSVirtualChannelManager* pChannelMgr,
ADDIN_ARGV* args,
rdpSettings* settings)
{
DVCMAN_ENTRY_POINTS entryPoints;
PDVC_PLUGIN_ENTRY pDVCPluginEntry = NULL;
WLog_INFO(TAG, "Loading Dynamic Virtual Channel %s", args->argv[0]);
WLog_Print(drdynvc->log, WLOG_INFO, "Loading Dynamic Virtual Channel %s", args->argv[0]);
pDVCPluginEntry = (PDVC_PLUGIN_ENTRY) freerdp_load_channel_addin_entry(
args->argv[0],
NULL, NULL, FREERDP_ADDIN_CHANNEL_DYNAMIC);
@ -251,16 +252,17 @@ static UINT dvcman_load_addin(IWTSVirtualChannelManager* pChannelMgr,
return ERROR_INVALID_FUNCTION;
}
static DVCMAN_CHANNEL* dvcman_channel_new(IWTSVirtualChannelManager*
pChannelMgr,
static DVCMAN_CHANNEL* dvcman_channel_new(drdynvcPlugin* drdynvc,
IWTSVirtualChannelManager* pChannelMgr,
UINT32 ChannelId, const char* ChannelName)
{
DVCMAN_CHANNEL* channel;
if (dvcman_find_channel_by_id(pChannelMgr, ChannelId))
{
WLog_ERR(TAG, "Protocol error: Duplicated ChannelId %"PRIu32" (%s)!", ChannelId,
ChannelName);
WLog_Print(drdynvc->log, WLOG_ERROR, "Protocol error: Duplicated ChannelId %"PRIu32" (%s)!",
ChannelId,
ChannelName);
return NULL;
}
@ -268,7 +270,7 @@ static DVCMAN_CHANNEL* dvcman_channel_new(IWTSVirtualChannelManager*
if (!channel)
{
WLog_ERR(TAG, "calloc failed!");
WLog_Print(drdynvc->log, WLOG_ERROR, "calloc failed!");
return NULL;
}
@ -278,14 +280,14 @@ static DVCMAN_CHANNEL* dvcman_channel_new(IWTSVirtualChannelManager*
if (!channel->channel_name)
{
WLog_ERR(TAG, "_strdup failed!");
WLog_Print(drdynvc->log, WLOG_ERROR, "_strdup failed!");
free(channel);
return NULL;
}
if (!InitializeCriticalSectionEx(&(channel->lock), 0 , 0))
if (!InitializeCriticalSectionEx(&(channel->lock), 0, 0))
{
WLog_ERR(TAG, "InitializeCriticalSectionEx failed!");
WLog_Print(drdynvc->log, WLOG_ERROR, "InitializeCriticalSectionEx failed!");
free(channel->channel_name);
free(channel);
return NULL;
@ -297,31 +299,49 @@ static DVCMAN_CHANNEL* dvcman_channel_new(IWTSVirtualChannelManager*
static void dvcman_channel_free(void* arg)
{
DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*) arg;
UINT error = CHANNEL_RC_OK;
if (channel->channel_callback)
if (channel)
{
channel->channel_callback->OnClose(channel->channel_callback);
channel->channel_callback = NULL;
}
if (channel->channel_callback)
{
IFCALL(channel->channel_callback->OnClose,
channel->channel_callback);
}
if (channel->dvc_data)
{
Stream_Release(channel->dvc_data);
channel->dvc_data = NULL;
}
if (channel->status == CHANNEL_RC_OK)
{
IWTSVirtualChannel* ichannel = (IWTSVirtualChannel*) channel;
DeleteCriticalSection(&(channel->lock));
if (channel->dvcman && channel->dvcman->drdynvc)
{
DrdynvcClientContext* context = channel->dvcman->drdynvc->context;
if (channel->channel_name)
{
if (context)
{
IFCALLRET(context->OnChannelDisconnected, error,
context, channel->channel_name,
channel->pInterface);
}
}
error = IFCALLRESULT(CHANNEL_RC_OK, ichannel->Close, ichannel);
if (error != CHANNEL_RC_OK)
WLog_ERR(TAG, "Close failed with error %"PRIu32"!", error);
}
if (channel->dvc_data)
Stream_Release(channel->dvc_data);
DeleteCriticalSection(&(channel->lock));
free(channel->channel_name);
channel->channel_name = NULL;
}
free(channel);
}
static void dvcman_free(IWTSVirtualChannelManager* pChannelMgr)
static void dvcman_free(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pChannelMgr)
{
int i;
IWTSPlugin* pPlugin;
@ -345,7 +365,7 @@ static void dvcman_free(IWTSVirtualChannelManager* pChannelMgr)
if (pPlugin->Terminated)
if ((error = pPlugin->Terminated(pPlugin)))
WLog_ERR(TAG, "Terminated failed with error %"PRIu32"!", error);
WLog_Print(drdynvc->log, WLOG_ERROR, "Terminated failed with error %"PRIu32"!", error);
}
dvcman->num_plugins = 0;
@ -358,7 +378,7 @@ static void dvcman_free(IWTSVirtualChannelManager* pChannelMgr)
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT dvcman_init(IWTSVirtualChannelManager* pChannelMgr)
static UINT dvcman_init(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pChannelMgr)
{
int i;
IWTSPlugin* pPlugin;
@ -372,7 +392,7 @@ static UINT dvcman_init(IWTSVirtualChannelManager* pChannelMgr)
if (pPlugin->Initialize)
if ((error = pPlugin->Initialize(pPlugin, pChannelMgr)))
{
WLog_ERR(TAG, "Initialize failed with error %"PRIu32"!", error);
WLog_Print(drdynvc->log, WLOG_ERROR, "Initialize failed with error %"PRIu32"!", error);
return error;
}
}
@ -422,7 +442,8 @@ static UINT dvcman_close_channel_iface(IWTSVirtualChannel* pChannel)
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr,
static UINT dvcman_create_channel(drdynvcPlugin* drdynvc,
IWTSVirtualChannelManager* pChannelMgr,
UINT32 ChannelId, const char* ChannelName)
{
int i;
@ -434,13 +455,13 @@ static UINT dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr,
DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
UINT error;
if (!(channel = dvcman_channel_new(pChannelMgr, ChannelId, ChannelName)))
if (!(channel = dvcman_channel_new(drdynvc, pChannelMgr, ChannelId, ChannelName)))
{
WLog_ERR(TAG, "dvcman_channel_new failed!");
WLog_Print(drdynvc->log, WLOG_ERROR, "dvcman_channel_new failed!");
return CHANNEL_RC_NO_MEMORY;
}
channel->status = 1;
channel->status = ERROR_NOT_CONNECTED;
ArrayList_Add(dvcman->channels, channel);
for (i = 0; i < dvcman->num_listeners; i++)
@ -459,9 +480,9 @@ static UINT dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr,
(IWTSVirtualChannel*) channel, NULL, &bAccept, &pCallback)) == CHANNEL_RC_OK
&& bAccept)
{
WLog_DBG(TAG, "listener %s created new channel %"PRIu32"",
listener->channel_name, channel->channel_id);
channel->status = 0;
WLog_Print(drdynvc->log, WLOG_DEBUG, "listener %s created new channel %"PRIu32"",
listener->channel_name, channel->channel_id);
channel->status = CHANNEL_RC_OK;
channel->channel_callback = pCallback;
channel->pInterface = listener->iface.pInterface;
context = dvcman->drdynvc->context;
@ -469,7 +490,8 @@ static UINT dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr,
listener->iface.pInterface);
if (error)
WLog_ERR(TAG, "context.ReceiveSamples failed with error %"PRIu32"", error);
WLog_Print(drdynvc->log, WLOG_ERROR, "context.OnChannelConnected failed with error %"PRIu32"",
error);
return error;
}
@ -477,12 +499,12 @@ static UINT dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr,
{
if (error)
{
WLog_ERR(TAG, "OnNewChannelConnection failed with error %"PRIu32"!", error);
WLog_Print(drdynvc->log, WLOG_ERROR, "OnNewChannelConnection failed with error %"PRIu32"!", error);
return error;
}
else
{
WLog_ERR(TAG, "OnNewChannelConnection returned with bAccept FALSE!");
WLog_Print(drdynvc->log, WLOG_ERROR, "OnNewChannelConnection returned with bAccept FALSE!");
return ERROR_INTERNAL_ERROR;
}
}
@ -497,7 +519,8 @@ static UINT dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr,
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT dvcman_open_channel(IWTSVirtualChannelManager* pChannelMgr,
static UINT dvcman_open_channel(drdynvcPlugin* drdynvc,
IWTSVirtualChannelManager* pChannelMgr,
UINT32 ChannelId)
{
DVCMAN_CHANNEL* channel;
@ -507,7 +530,7 @@ static UINT dvcman_open_channel(IWTSVirtualChannelManager* pChannelMgr,
if (!channel)
{
WLog_ERR(TAG, "ChannelId %"PRIu32" not found!", ChannelId);
WLog_Print(drdynvc->log, WLOG_ERROR, "ChannelId %"PRIu32" not found!", ChannelId);
return ERROR_INTERNAL_ERROR;
}
@ -517,11 +540,11 @@ static UINT dvcman_open_channel(IWTSVirtualChannelManager* pChannelMgr,
if ((pCallback->OnOpen) && (error = pCallback->OnOpen(pCallback)))
{
WLog_ERR(TAG, "OnOpen failed with error %"PRIu32"!", error);
WLog_Print(drdynvc->log, WLOG_ERROR, "OnOpen failed with error %"PRIu32"!", error);
return error;
}
WLog_DBG(TAG, "open_channel: ChannelId %"PRIu32"", ChannelId);
WLog_Print(drdynvc->log, WLOG_DEBUG, "open_channel: ChannelId %"PRIu32"", ChannelId);
}
return CHANNEL_RC_OK;
@ -536,15 +559,13 @@ static UINT dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr,
UINT32 ChannelId)
{
DVCMAN_CHANNEL* channel;
IWTSVirtualChannel* ichannel;
DrdynvcClientContext* context;
DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
UINT error = CHANNEL_RC_OK;
DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
channel = (DVCMAN_CHANNEL*) dvcman_find_channel_by_id(pChannelMgr, ChannelId);
if (!channel)
{
//WLog_ERR(TAG, "ChannelId %"PRIu32" not found!", ChannelId);
//WLog_Print(drdynvc->log, WLOG_ERROR, "ChannelId %"PRIu32" not found!", ChannelId);
/**
* Windows 8 / Windows Server 2012 send close requests for channels that failed to be created.
* Do not warn, simply return success here.
@ -552,30 +573,8 @@ static UINT dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr,
return CHANNEL_RC_OK;
}
if (channel->status == CHANNEL_RC_OK)
{
context = dvcman->drdynvc->context;
IFCALLRET(context->OnChannelDisconnected, error, context, channel->channel_name,
channel->pInterface);
if (error)
{
WLog_ERR(TAG, "OnChannelDisconnected returned with error %"PRIu32"!", error);
return error;
}
WLog_DBG(TAG, "dvcman_close_channel: channel %"PRIu32" closed", ChannelId);
ichannel = (IWTSVirtualChannel*) channel;
if ((ichannel->Close) && (error = ichannel->Close(ichannel)))
{
WLog_ERR(TAG, "Close failed with error %"PRIu32"!", error);
return error;
}
}
ArrayList_Remove(dvcman->channels, channel);
return CHANNEL_RC_OK;
return error;
}
/**
@ -583,8 +582,8 @@ static UINT dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr,
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT dvcman_receive_channel_data_first(IWTSVirtualChannelManager*
pChannelMgr,
static UINT dvcman_receive_channel_data_first(drdynvcPlugin* drdynvc,
IWTSVirtualChannelManager* pChannelMgr,
UINT32 ChannelId, UINT32 length)
{
DVCMAN_CHANNEL* channel;
@ -596,7 +595,7 @@ static UINT dvcman_receive_channel_data_first(IWTSVirtualChannelManager*
* Windows Server 2012 R2 can send some messages over Microsoft::Windows::RDS::Geometry::v08.01
* even if the dynamic virtual channel wasn't registered on our side. Ignoring it works.
*/
WLog_ERR(TAG, "ChannelId %"PRIu32" not found!", ChannelId);
WLog_Print(drdynvc->log, WLOG_ERROR, "ChannelId %"PRIu32" not found!", ChannelId);
return CHANNEL_RC_OK;
}
@ -607,7 +606,7 @@ static UINT dvcman_receive_channel_data_first(IWTSVirtualChannelManager*
if (!channel->dvc_data)
{
WLog_ERR(TAG, "StreamPool_Take failed!");
WLog_Print(drdynvc->log, WLOG_ERROR, "StreamPool_Take failed!");
return CHANNEL_RC_NO_MEMORY;
}
@ -620,7 +619,8 @@ static UINT dvcman_receive_channel_data_first(IWTSVirtualChannelManager*
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr,
static UINT dvcman_receive_channel_data(drdynvcPlugin* drdynvc,
IWTSVirtualChannelManager* pChannelMgr,
UINT32 ChannelId, wStream* data)
{
UINT status = CHANNEL_RC_OK;
@ -632,7 +632,7 @@ static UINT dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr,
{
/* Windows 8.1 tries to open channels not created.
* Ignore cases like this. */
WLog_ERR(TAG, "ChannelId %"PRIu32" not found!", ChannelId);
WLog_Print(drdynvc->log, WLOG_ERROR, "ChannelId %"PRIu32" not found!", ChannelId);
return CHANNEL_RC_OK;
}
@ -642,7 +642,7 @@ static UINT dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr,
if (Stream_GetPosition(channel->dvc_data) + dataSize > (UINT32) Stream_Capacity(
channel->dvc_data))
{
WLog_ERR(TAG, "data exceeding declared length!");
WLog_Print(drdynvc->log, WLOG_ERROR, "data exceeding declared length!");
Stream_Release(channel->dvc_data);
channel->dvc_data = NULL;
return ERROR_INVALID_DATA;
@ -712,8 +712,14 @@ static UINT drdynvc_send(drdynvcPlugin* drdynvc, wStream* s)
switch (status)
{
case CHANNEL_RC_OK:
case CHANNEL_RC_NOT_CONNECTED:
return CHANNEL_RC_OK;
case CHANNEL_RC_NOT_CONNECTED:
Stream_Free(s, TRUE);
return CHANNEL_RC_OK;
case CHANNEL_RC_BAD_CHANNEL_HANDLE:
Stream_Free(s, TRUE);
WLog_ERR(TAG, "VirtualChannelWriteEx failed with CHANNEL_RC_BAD_CHANNEL_HANDLE");
return status;
default:
Stream_Free(s, TRUE);
@ -733,7 +739,7 @@ static UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId,
const BYTE* data, UINT32 dataSize)
{
wStream* data_out;
unsigned long pos;
size_t pos;
UINT32 cbChId;
UINT32 cbLen;
unsigned long chunkLength;
@ -922,7 +928,7 @@ static UINT32 drdynvc_read_variable_uint(wStream* s, int cbLen)
static UINT drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp,
int cbChId, wStream* s)
{
unsigned long pos;
size_t pos;
UINT status;
UINT32 ChannelId;
wStream* data_out;
@ -954,11 +960,11 @@ static UINT drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp,
WLog_Print(drdynvc->log, WLOG_DEBUG, "process_create_request: ChannelId=%"PRIu32" ChannelName=%s",
ChannelId,
Stream_Pointer(s));
channel_status = dvcman_create_channel(drdynvc->channel_mgr, ChannelId,
channel_status = dvcman_create_channel(drdynvc, drdynvc->channel_mgr, ChannelId,
(char*) Stream_Pointer(s));
data_out = Stream_New(NULL, pos + 4);
if (!s)
if (!data_out)
{
WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_New failed!");
return CHANNEL_RC_NO_MEMORY;
@ -976,22 +982,21 @@ static UINT drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp,
else
{
WLog_Print(drdynvc->log, WLOG_DEBUG, "no listener");
Stream_Write_UINT32(data_out,
(UINT32) 0xC0000001); /* same code used by mstsc */
Stream_Write_UINT32(data_out, (UINT32)0xC0000001); /* same code used by mstsc */
}
status = drdynvc_send(drdynvc, data_out);
if (status != CHANNEL_RC_OK)
{
WLog_ERR(TAG, "VirtualChannelWriteEx failed with %s [%08"PRIX32"]",
WTSErrorToString(status), status);
WLog_Print(drdynvc->log, WLOG_ERROR, "VirtualChannelWriteEx failed with %s [%08"PRIX32"]",
WTSErrorToString(status), status);
return status;
}
if (channel_status == CHANNEL_RC_OK)
{
if ((status = dvcman_open_channel(drdynvc->channel_mgr, ChannelId)))
if ((status = dvcman_open_channel(drdynvc, drdynvc->channel_mgr, ChannelId)))
{
WLog_Print(drdynvc->log, WLOG_ERROR, "dvcman_open_channel failed with error %"PRIu32"!", status);
return status;
@ -1019,15 +1024,16 @@ static UINT drdynvc_process_data_first(drdynvcPlugin* drdynvc, int Sp,
UINT32 ChannelId;
ChannelId = drdynvc_read_variable_uint(s, cbChId);
Length = drdynvc_read_variable_uint(s, Sp);
WLog_DBG(TAG, "process_data_first: Sp=%d cbChId=%d, ChannelId=%"PRIu32" Length=%"PRIu32"", Sp,
cbChId, ChannelId, Length);
status = dvcman_receive_channel_data_first(drdynvc->channel_mgr, ChannelId,
WLog_Print(drdynvc->log, WLOG_DEBUG,
"process_data_first: Sp=%d cbChId=%d, ChannelId=%"PRIu32" Length=%"PRIu32"", Sp,
cbChId, ChannelId, Length);
status = dvcman_receive_channel_data_first(drdynvc, drdynvc->channel_mgr, ChannelId,
Length);
if (status)
return status;
return dvcman_receive_channel_data(drdynvc->channel_mgr, ChannelId, s);
return dvcman_receive_channel_data(drdynvc, drdynvc->channel_mgr, ChannelId, s);
}
/**
@ -1043,7 +1049,7 @@ static UINT drdynvc_process_data(drdynvcPlugin* drdynvc, int Sp, int cbChId,
WLog_Print(drdynvc->log, WLOG_TRACE, "process_data: Sp=%d cbChId=%d, ChannelId=%"PRIu32"", Sp,
cbChId,
ChannelId);
return dvcman_receive_channel_data(drdynvc->channel_mgr, ChannelId, s);
return dvcman_receive_channel_data(drdynvc, drdynvc->channel_mgr, ChannelId, s);
}
/**
@ -1059,12 +1065,13 @@ static UINT drdynvc_process_close_request(drdynvcPlugin* drdynvc, int Sp,
UINT32 ChannelId;
wStream* data_out;
ChannelId = drdynvc_read_variable_uint(s, cbChId);
WLog_DBG(TAG, "process_close_request: Sp=%d cbChId=%d, ChannelId=%"PRIu32"", Sp,
cbChId, ChannelId);
WLog_Print(drdynvc->log, WLOG_DEBUG, "process_close_request: Sp=%d cbChId=%d, ChannelId=%"PRIu32"",
Sp,
cbChId, ChannelId);
if ((error = dvcman_close_channel(drdynvc->channel_mgr, ChannelId)))
{
WLog_ERR(TAG, "dvcman_close_channel failed with error %"PRIu32"!", error);
WLog_Print(drdynvc->log, WLOG_ERROR, "dvcman_close_channel failed with error %"PRIu32"!", error);
return error;
}
@ -1072,7 +1079,7 @@ static UINT drdynvc_process_close_request(drdynvcPlugin* drdynvc, int Sp,
if (!data_out)
{
WLog_ERR(TAG, "Stream_New failed!");
WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_New failed!");
return CHANNEL_RC_NO_MEMORY;
}
@ -1082,8 +1089,8 @@ static UINT drdynvc_process_close_request(drdynvcPlugin* drdynvc, int Sp,
error = drdynvc_send(drdynvc, data_out);
if (error)
WLog_ERR(TAG, "VirtualChannelWriteEx failed with %s [%08"PRIX32"]",
WTSErrorToString(error), error);
WLog_Print(drdynvc->log, WLOG_ERROR, "VirtualChannelWriteEx failed with %s [%08"PRIX32"]",
WTSErrorToString(error), error);
return error;
}
@ -1123,7 +1130,7 @@ static UINT drdynvc_order_recv(drdynvcPlugin* drdynvc, wStream* s)
return drdynvc_process_close_request(drdynvc, Sp, cbChId, s);
default:
WLog_ERR(TAG, "unknown drdynvc cmd 0x%x", Cmd);
WLog_Print(drdynvc->log, WLOG_ERROR, "unknown drdynvc cmd 0x%x", Cmd);
return ERROR_INTERNAL_ERROR;
}
}
@ -1153,13 +1160,13 @@ static UINT drdynvc_virtual_channel_event_data_received(drdynvcPlugin* drdynvc,
if (!(data_in = drdynvc->data_in))
{
WLog_ERR(TAG, "Stream_New failed!");
WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_New failed!");
return CHANNEL_RC_NO_MEMORY;
}
if (!Stream_EnsureRemainingCapacity(data_in, (int) dataLength))
{
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
Stream_Free(drdynvc->data_in, TRUE);
drdynvc->data_in = NULL;
return ERROR_INTERNAL_ERROR;
@ -1171,7 +1178,7 @@ static UINT drdynvc_virtual_channel_event_data_received(drdynvcPlugin* drdynvc,
{
if (Stream_Capacity(data_in) != Stream_GetPosition(data_in))
{
WLog_ERR(TAG, "drdynvc_plugin_process_received: read error");
WLog_Print(drdynvc->log, WLOG_ERROR, "drdynvc_plugin_process_received: read error");
return ERROR_INVALID_DATA;
}
@ -1181,7 +1188,7 @@ static UINT drdynvc_virtual_channel_event_data_received(drdynvcPlugin* drdynvc,
if (!MessageQueue_Post(drdynvc->queue, NULL, 0, (void*) data_in, NULL))
{
WLog_ERR(TAG, "MessageQueue_Post failed!");
WLog_Print(drdynvc->log, WLOG_ERROR, "MessageQueue_Post failed!");
return ERROR_INTERNAL_ERROR;
}
}
@ -1198,6 +1205,7 @@ static void VCAPITYPE drdynvc_virtual_channel_open_event_ex(LPVOID lpUserParam,
if (!drdynvc || (drdynvc->OpenHandle != openHandle))
{
WLog_ERR(TAG, "drdynvc_virtual_channel_open_event: error no match");
Stream_Free((wStream*) pData, TRUE);
return;
}
@ -1206,7 +1214,8 @@ static void VCAPITYPE drdynvc_virtual_channel_open_event_ex(LPVOID lpUserParam,
case CHANNEL_EVENT_DATA_RECEIVED:
if ((error = drdynvc_virtual_channel_event_data_received(drdynvc, pData, dataLength, totalLength,
dataFlags)))
WLog_ERR(TAG, "drdynvc_virtual_channel_event_data_received failed with error %"PRIu32"", error);
WLog_Print(drdynvc->log, WLOG_ERROR,
"drdynvc_virtual_channel_event_data_received failed with error %"PRIu32"", error);
break;
@ -1222,7 +1231,7 @@ static void VCAPITYPE drdynvc_virtual_channel_open_event_ex(LPVOID lpUserParam,
setChannelError(drdynvc->rdpcontext, error, "drdynvc_virtual_channel_open_event reported an error");
}
static void* drdynvc_virtual_channel_client_thread(void* arg)
static DWORD WINAPI drdynvc_virtual_channel_client_thread(LPVOID arg)
{
wStream* data;
wMessage message;
@ -1232,7 +1241,7 @@ static void* drdynvc_virtual_channel_client_thread(void* arg)
if (!drdynvc)
{
ExitThread((DWORD) CHANNEL_RC_BAD_CHANNEL_HANDLE);
return NULL;
return CHANNEL_RC_BAD_CHANNEL_HANDLE;
}
while (1)
@ -1289,7 +1298,21 @@ static void* drdynvc_virtual_channel_client_thread(void* arg)
"drdynvc_virtual_channel_client_thread reported an error");
ExitThread((DWORD) error);
return NULL;
return error;
}
static void drdynvc_queue_object_free(void* obj)
{
wStream* s;
wMessage* msg = (wMessage*)obj;
if (!msg || (msg->id != 0))
return;
s = (wStream*)msg->wParam;
if (s)
Stream_Free(s, TRUE);
}
/**
@ -1328,6 +1351,7 @@ static UINT drdynvc_virtual_channel_event_connected(drdynvcPlugin* drdynvc, LPVO
goto error;
}
drdynvc->queue->object.fnObjectFree = drdynvc_queue_object_free;
drdynvc->channel_mgr = dvcman_new(drdynvc);
if (!drdynvc->channel_mgr)
@ -1342,13 +1366,13 @@ static UINT drdynvc_virtual_channel_event_connected(drdynvcPlugin* drdynvc, LPVO
for (index = 0; index < settings->DynamicChannelCount; index++)
{
args = settings->DynamicChannelArray[index];
error = dvcman_load_addin(drdynvc->channel_mgr, args, settings);
error = dvcman_load_addin(drdynvc, drdynvc->channel_mgr, args, settings);
if (CHANNEL_RC_OK != error)
goto error;
}
if ((error = dvcman_init(drdynvc->channel_mgr)))
if ((error = dvcman_init(drdynvc, drdynvc->channel_mgr)))
{
WLog_Print(drdynvc->log, WLOG_ERROR, "dvcman_init failed with error %"PRIu32"!", error);
goto error;
@ -1356,8 +1380,7 @@ static UINT drdynvc_virtual_channel_event_connected(drdynvcPlugin* drdynvc, LPVO
drdynvc->state = DRDYNVC_STATE_CAPABILITIES;
if (!(drdynvc->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) drdynvc_virtual_channel_client_thread, (void*) drdynvc,
if (!(drdynvc->thread = CreateThread(NULL, 0, drdynvc_virtual_channel_client_thread, (void*) drdynvc,
0, NULL)))
{
error = ERROR_INTERNAL_ERROR;
@ -1418,7 +1441,7 @@ static UINT drdynvc_virtual_channel_event_disconnected(drdynvcPlugin* drdynvc)
if (drdynvc->channel_mgr)
{
dvcman_free(drdynvc->channel_mgr);
dvcman_free(drdynvc, drdynvc->channel_mgr);
drdynvc->channel_mgr = NULL;
}
@ -1436,6 +1459,7 @@ static UINT drdynvc_virtual_channel_event_terminated(drdynvcPlugin* drdynvc)
return CHANNEL_RC_BAD_CHANNEL_HANDLE;
drdynvc->InitHandle = 0;
free(drdynvc->context);
free(drdynvc);
return CHANNEL_RC_OK;
}
@ -1598,7 +1622,7 @@ BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS_EX pEntryPoints, PVOI
if (!context)
{
WLog_ERR(TAG, "calloc failed!");
WLog_Print(drdynvc->log, WLOG_ERROR, "calloc failed!");
free(drdynvc);
return FALSE;
}
@ -1610,7 +1634,7 @@ BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS_EX pEntryPoints, PVOI
drdynvc->rdpcontext = pEntryPointsEx->context;
}
drdynvc->log = WLog_Get("com.freerdp.channels.drdynvc.client");
drdynvc->log = WLog_Get(TAG);
WLog_Print(drdynvc->log, WLOG_DEBUG, "VirtualChannelEntryEx");
CopyMemory(&(drdynvc->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP_EX));
drdynvc->InitHandle = pInitHandle;

View File

@ -33,7 +33,7 @@
#define TAG CHANNELS_TAG("drdynvc.server")
static void* drdynvc_server_thread(void* arg)
static DWORD WINAPI drdynvc_server_thread(LPVOID arg)
{
#if 0
wStream* s;
@ -56,7 +56,7 @@ static void* drdynvc_server_thread(void* arg)
{
WLog_ERR(TAG, "Stream_New failed!");
ExitThread((DWORD) CHANNEL_RC_NO_MEMORY);
return NULL;
return CHANNEL_RC_NO_MEMORY;
}
if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle,
@ -111,7 +111,7 @@ static void* drdynvc_server_thread(void* arg)
#endif
// WTF ... this code only reads data into the stream until there is no more memory
ExitThread(0);
return NULL;
return 0;
}
/**
@ -136,8 +136,7 @@ static UINT drdynvc_server_start(DrdynvcServerContext* context)
return ERROR_INTERNAL_ERROR;
}
if (!(context->priv->Thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) drdynvc_server_thread, (void*) context, 0, NULL)))
if (!(context->priv->Thread = CreateThread(NULL, 0, drdynvc_server_thread, (void*) context, 0, NULL)))
{
WLog_ERR(TAG, "CreateThread failed!");
CloseHandle(context->priv->StopEvent);

View File

@ -181,8 +181,11 @@ static BOOL drive_file_remove_dir(const WCHAR* path)
return ret;
}
static void drive_file_set_fullpath(DRIVE_FILE* file, WCHAR* fullpath)
static BOOL drive_file_set_fullpath(DRIVE_FILE* file, WCHAR* fullpath)
{
if (!file || !fullpath)
return FALSE;
free(file->fullpath);
file->fullpath = fullpath;
file->filename = _wcsrchr(file->fullpath, L'/');
@ -191,9 +194,11 @@ static void drive_file_set_fullpath(DRIVE_FILE* file, WCHAR* fullpath)
file->filename = file->fullpath;
else
file->filename += 1;
return TRUE;
}
BOOL drive_file_init(DRIVE_FILE* file)
static BOOL drive_file_init(DRIVE_FILE* file)
{
UINT CreateDisposition = 0;
DWORD dwAttr = GetFileAttributesW(file->fullpath);
@ -315,6 +320,10 @@ DRIVE_FILE* drive_file_new(const WCHAR* base_path, const WCHAR* path, UINT32 Pat
UINT32 CreateOptions, UINT32 FileAttributes, UINT32 SharedAccess)
{
DRIVE_FILE* file;
if (!base_path || !path)
return NULL;
file = (DRIVE_FILE*) calloc(1, sizeof(DRIVE_FILE));
if (!file)
@ -350,6 +359,7 @@ DRIVE_FILE* drive_file_new(const WCHAR* base_path, const WCHAR* path, UINT32 Pat
BOOL drive_file_free(DRIVE_FILE* file)
{
BOOL rc = FALSE;
if (!file)
return FALSE;
@ -368,33 +378,32 @@ BOOL drive_file_free(DRIVE_FILE* file)
if (file->delete_pending)
{
if (file->is_dir)
drive_file_remove_dir(file->fullpath);
else if (!DeleteFileW(file->fullpath))
{
free(file->fullpath);
free(file);
return FALSE;
if (!drive_file_remove_dir(file->fullpath))
goto fail;
}
else if (!DeleteFileW(file->fullpath))
goto fail;
}
rc = TRUE;
fail:
DEBUG_WSTR("Free %s", file->fullpath);
free(file->fullpath);
free(file);
return TRUE;
return rc;
}
BOOL drive_file_seek(DRIVE_FILE* file, UINT64 Offset)
{
LONG lDistHigh;
DWORD dwPtrLow;
LARGE_INTEGER loffset;
if (!file)
return FALSE;
lDistHigh = Offset >> 32;
DEBUG_WSTR("Seek %s", file->fullpath);
dwPtrLow = SetFilePointer(file->file_handle, Offset & 0xFFFFFFFF, &lDistHigh, FILE_BEGIN);
return dwPtrLow != INVALID_SET_FILE_POINTER;
loffset.QuadPart = Offset;
return SetFilePointerEx(file->file_handle, loffset, NULL, FILE_BEGIN);
}
BOOL drive_file_read(DRIVE_FILE* file, BYTE* buffer, UINT32* Length)
@ -552,6 +561,9 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN
switch (FsInformationClass)
{
case FileBasicInformation:
if (Stream_GetRemainingLength(input) < 36)
return FALSE;
/* http://msdn.microsoft.com/en-us/library/cc232094.aspx */
Stream_Read_UINT64(input, liCreationTime.QuadPart);
Stream_Read_UINT64(input, liLastAccessTime.QuadPart);
@ -611,6 +623,9 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN
/* http://msdn.microsoft.com/en-us/library/cc232067.aspx */
case FileAllocationInformation:
if (Stream_GetRemainingLength(input) < 8)
return FALSE;
/* http://msdn.microsoft.com/en-us/library/cc232076.aspx */
Stream_Read_INT64(input, size);
@ -623,8 +638,7 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN
liSize.QuadPart = size & 0xFFFFFFFF;
if (SetFilePointer(file->file_handle, liSize.LowPart, &liSize.HighPart,
FILE_BEGIN) == INVALID_SET_FILE_POINTER)
if (!SetFilePointerEx(file->file_handle, liSize, NULL, FILE_BEGIN))
{
WLog_ERR(TAG, "Unable to truncate %s to %d (%"PRId32")", file->fullpath, size, GetLastError());
return FALSE;
@ -648,7 +662,12 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN
break; /* TODO: SetLastError ??? */
if (Length)
{
if (Stream_GetRemainingLength(input) < 1)
return FALSE;
Stream_Read_UINT8(input, delete_pending);
}
else
delete_pending = 1;
@ -668,13 +687,19 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN
break;
case FileRenameInformation:
if (Stream_GetRemainingLength(input) < 6)
return FALSE;
/* http://msdn.microsoft.com/en-us/library/cc232085.aspx */
Stream_Read_UINT8(input, ReplaceIfExists);
Stream_Seek_UINT8(input); /* RootDirectory */
Stream_Read_UINT32(input, FileNameLength);
if (Stream_GetRemainingLength(input) < FileNameLength)
return FALSE;
fullpath = drive_file_combine_fullpath(file->basepath, (WCHAR*)Stream_Pointer(input),
FileNameLength);
if (!fullpath)
{
WLog_ERR(TAG, "drive_file_combine_fullpath failed!");
@ -695,7 +720,8 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN
if (MoveFileExW(file->fullpath, fullpath,
MOVEFILE_COPY_ALLOWED | (ReplaceIfExists ? MOVEFILE_REPLACE_EXISTING : 0)))
{
drive_file_set_fullpath(file, fullpath);
if (!drive_file_set_fullpath(file, fullpath))
return FALSE;
}
else
{

View File

@ -66,6 +66,4 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN
BOOL drive_file_query_directory(DRIVE_FILE* file, UINT32 FsInformationClass, BYTE InitialQuery,
const WCHAR* path, UINT32 PathLength, wStream* output);
extern UINT sys_code_page;
#endif /* FREERDP_CHANNEL_DRIVE_CLIENT_FILE_H */
#endif /* FREERDP_CHANNEL_DRIVE_FILE_H */

View File

@ -64,6 +64,8 @@ struct _DRIVE_DEVICE
rdpContext* rdpcontext;
};
static UINT sys_code_page = 0;
static DWORD drive_map_windows_err(DWORD fs_errno)
{
DWORD rc;
@ -89,6 +91,14 @@ static DWORD drive_map_windows_err(DWORD fs_errno)
rc = STATUS_DEVICE_BUSY;
break;
case ERROR_INVALID_DRIVE:
rc = STATUS_NO_SUCH_DEVICE;
break;
case ERROR_NOT_READY:
rc = STATUS_NO_SUCH_DEVICE;
break;
case ERROR_FILE_EXISTS:
case ERROR_ALREADY_EXISTS:
rc = STATUS_OBJECT_NAME_COLLISION;
@ -116,7 +126,7 @@ static DWORD drive_map_windows_err(DWORD fs_errno)
default:
rc = STATUS_UNSUCCESSFUL;
WLog_ERR(TAG, "Error code not found: %"PRId32"", fs_errno);
WLog_ERR(TAG, "Error code not found: %"PRIu32"", fs_errno);
break;
}
@ -127,6 +137,10 @@ static DRIVE_FILE* drive_get_file_by_id(DRIVE_DEVICE* drive, UINT32 id)
{
DRIVE_FILE* file = NULL;
void* key = (void*)(size_t) id;
if (!drive)
return NULL;
file = (DRIVE_FILE*) ListDictionary_GetItemValue(drive->files, key);
return file;
}
@ -138,7 +152,6 @@ static DRIVE_FILE* drive_get_file_by_id(DRIVE_DEVICE* drive, UINT32 id)
*/
static UINT drive_process_irp_create(DRIVE_DEVICE* drive, IRP* irp)
{
void* key;
UINT32 FileId;
DRIVE_FILE* file;
BYTE Information;
@ -148,14 +161,25 @@ static UINT drive_process_irp_create(DRIVE_DEVICE* drive, IRP* irp)
UINT32 CreateDisposition;
UINT32 CreateOptions;
UINT32 PathLength;
UINT64 allocationSize;
const WCHAR* path;
if (!drive || !irp || !irp->devman || !irp->Complete)
return ERROR_INVALID_PARAMETER;
if (Stream_GetRemainingLength(irp->input) < 6*4+8)
return ERROR_INVALID_DATA;
Stream_Read_UINT32(irp->input, DesiredAccess);
Stream_Seek(irp->input, 8); /* AllocationSize(8) */
Stream_Read_UINT64(irp->input, allocationSize);
Stream_Read_UINT32(irp->input, FileAttributes);
Stream_Read_UINT32(irp->input, SharedAccess);
Stream_Read_UINT32(irp->input, CreateDisposition);
Stream_Read_UINT32(irp->input, CreateOptions);
Stream_Read_UINT32(irp->input, PathLength);
if (Stream_GetRemainingLength(irp->input) < PathLength)
return ERROR_INVALID_DATA;
path = (WCHAR*) Stream_Pointer(irp->input);
FileId = irp->devman->id_sequence++;
file = drive_file_new(drive->path, path, PathLength, FileId, DesiredAccess, CreateDisposition,
@ -169,7 +193,7 @@ static UINT drive_process_irp_create(DRIVE_DEVICE* drive, IRP* irp)
}
else
{
key = (void*)(size_t) file->id;
void* key = (void*)(size_t) file->id;
if (!ListDictionary_Add(drive->files, key, file))
{
@ -214,13 +238,14 @@ static UINT drive_process_irp_close(DRIVE_DEVICE* drive, IRP* irp)
{
void* key;
DRIVE_FILE* file;
if (!drive || !irp || !irp->Complete || !irp->output)
return ERROR_INVALID_PARAMETER;
file = drive_get_file_by_id(drive, irp->FileId);
key = (void*)(size_t) irp->FileId;
if (!file)
{
irp->IoStatus = STATUS_UNSUCCESSFUL;
}
else
{
ListDictionary_Remove(drive->files, key);
@ -245,11 +270,17 @@ static UINT drive_process_irp_read(DRIVE_DEVICE* drive, IRP* irp)
DRIVE_FILE* file;
UINT32 Length;
UINT64 Offset;
BYTE* buffer = NULL;
if (!drive || !irp || !irp->output || !irp->Complete)
return ERROR_INVALID_PARAMETER;
if (Stream_GetRemainingLength(irp->input) < 12)
return ERROR_INVALID_DATA;
Stream_Read_UINT32(irp->input, Length);
Stream_Read_UINT64(irp->input, Offset);
file = drive_get_file_by_id(drive, irp->FileId);
file = drive_get_file_by_id(drive, irp->FileId);
if (!file)
{
irp->IoStatus = STATUS_UNSUCCESSFUL;
@ -260,39 +291,29 @@ static UINT drive_process_irp_read(DRIVE_DEVICE* drive, IRP* irp)
irp->IoStatus = drive_map_windows_err(GetLastError());
Length = 0;
}
if (!Stream_EnsureRemainingCapacity(irp->output, Length + 4))
{
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
return ERROR_INTERNAL_ERROR;
}
else if (Length == 0)
Stream_Write_UINT32(irp->output, 0);
else
{
buffer = (BYTE*) malloc(Length);
if (!buffer)
{
WLog_ERR(TAG, "malloc failed!");
return CHANNEL_RC_OK;
}
BYTE* buffer = Stream_Pointer(irp->output) + sizeof(UINT32);
if (!drive_file_read(file, buffer, &Length))
{
irp->IoStatus = drive_map_windows_err(GetLastError());
free(buffer);
buffer = NULL;
Length = 0;
Stream_Write_UINT32(irp->output, 0);
}
}
Stream_Write_UINT32(irp->output, Length);
if (Length > 0)
{
if (!Stream_EnsureRemainingCapacity(irp->output, (int) Length))
else
{
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
return ERROR_INTERNAL_ERROR;
Stream_Write_UINT32(irp->output, Length);
Stream_Seek(irp->output, Length);
}
Stream_Write(irp->output, buffer, Length);
}
free(buffer);
return irp->Complete(irp);
}
@ -306,11 +327,18 @@ static UINT drive_process_irp_write(DRIVE_DEVICE* drive, IRP* irp)
DRIVE_FILE* file;
UINT32 Length;
UINT64 Offset;
if (!drive || !irp || !irp->input || !irp->output || !irp->Complete)
return ERROR_INVALID_PARAMETER;
if (Stream_GetRemainingLength(irp->input) < 32)
return ERROR_INVALID_DATA;
Stream_Read_UINT32(irp->input, Length);
Stream_Read_UINT64(irp->input, Offset);
Stream_Seek(irp->input, 20); /* Padding */
file = drive_get_file_by_id(drive, irp->FileId);
file = drive_get_file_by_id(drive, irp->FileId);
if (!file)
{
irp->IoStatus = STATUS_UNSUCCESSFUL;
@ -341,9 +369,16 @@ static UINT drive_process_irp_query_information(DRIVE_DEVICE* drive, IRP* irp)
{
DRIVE_FILE* file;
UINT32 FsInformationClass;
Stream_Read_UINT32(irp->input, FsInformationClass);
file = drive_get_file_by_id(drive, irp->FileId);
if (!drive || !irp || !irp->Complete)
return ERROR_INVALID_PARAMETER;
if (Stream_GetRemainingLength(irp->input) < 4)
return ERROR_INVALID_DATA;
Stream_Read_UINT32(irp->input, FsInformationClass);
file = drive_get_file_by_id(drive, irp->FileId);
if (!file)
{
irp->IoStatus = STATUS_UNSUCCESSFUL;
@ -366,11 +401,18 @@ static UINT drive_process_irp_set_information(DRIVE_DEVICE* drive, IRP* irp)
DRIVE_FILE* file;
UINT32 FsInformationClass;
UINT32 Length;
if (!drive || !irp || !irp->Complete || !irp->input || !irp->output)
return ERROR_INVALID_PARAMETER;
if (Stream_GetRemainingLength(irp->input) < 32)
return ERROR_INVALID_DATA;
Stream_Read_UINT32(irp->input, FsInformationClass);
Stream_Read_UINT32(irp->input, Length);
Stream_Seek(irp->input, 24); /* Padding */
file = drive_get_file_by_id(drive, irp->FileId);
file = drive_get_file_by_id(drive, irp->FileId);
if (!file)
{
irp->IoStatus = STATUS_UNSUCCESSFUL;
@ -398,7 +440,7 @@ static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive,
IRP* irp)
{
UINT32 FsInformationClass;
wStream* output = irp->output;
wStream* output = NULL;
char* volumeLabel = {"FREERDP"};
char* diskType = {"FAT32"};
WCHAR* outStr = NULL;
@ -408,6 +450,15 @@ static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive,
DWORD lpNumberOfFreeClusters;
DWORD lpTotalNumberOfClusters;
WIN32_FILE_ATTRIBUTE_DATA wfad;
if (!drive || !irp)
return ERROR_INVALID_PARAMETER;
output = irp->output;
if (Stream_GetRemainingLength(irp->input) < 4)
return ERROR_INVALID_DATA;
Stream_Read_UINT32(irp->input, FsInformationClass);
GetDiskFreeSpaceW(drive->path, &lpSectorsPerCluster, &lpBytesPerSector, &lpNumberOfFreeClusters,
&lpTotalNumberOfClusters);
@ -536,9 +587,16 @@ static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive,
static UINT drive_process_irp_silent_ignore(DRIVE_DEVICE* drive, IRP* irp)
{
UINT32 FsInformationClass;
wStream* output = irp->output;
if (!drive || !irp || !irp->output || !irp->Complete)
return ERROR_INVALID_PARAMETER;
if (Stream_GetRemainingLength(irp->input) < 4)
return ERROR_INVALID_DATA;
Stream_Read_UINT32(irp->input, FsInformationClass);
Stream_Write_UINT32(output, 0); /* Length */
Stream_Write_UINT32(irp->output, 0); /* Length */
return irp->Complete(irp);
}
@ -554,13 +612,20 @@ static UINT drive_process_irp_query_directory(DRIVE_DEVICE* drive, IRP* irp)
BYTE InitialQuery;
UINT32 PathLength;
UINT32 FsInformationClass;
if (!drive || !irp || !irp->Complete)
return ERROR_INVALID_PARAMETER;
if (Stream_GetRemainingLength(irp->input) < 32)
return ERROR_INVALID_DATA;
Stream_Read_UINT32(irp->input, FsInformationClass);
Stream_Read_UINT8(irp->input, InitialQuery);
Stream_Read_UINT32(irp->input, PathLength);
Stream_Seek(irp->input, 23); /* Padding */
path = (WCHAR*) Stream_Pointer(irp->input);
file = drive_get_file_by_id(drive, irp->FileId);
file = drive_get_file_by_id(drive, irp->FileId);
if (file == NULL)
{
irp->IoStatus = STATUS_UNSUCCESSFUL;
@ -582,21 +647,21 @@ static UINT drive_process_irp_query_directory(DRIVE_DEVICE* drive, IRP* irp)
*/
static UINT drive_process_irp_directory_control(DRIVE_DEVICE* drive, IRP* irp)
{
if (!drive || !irp)
return ERROR_INVALID_PARAMETER;
switch (irp->MinorFunction)
{
case IRP_MN_QUERY_DIRECTORY:
return drive_process_irp_query_directory(drive, irp);
break;
case IRP_MN_NOTIFY_CHANGE_DIRECTORY: /* TODO */
return irp->Discard(irp);
break;
default:
irp->IoStatus = STATUS_NOT_SUPPORTED;
Stream_Write_UINT32(irp->output, 0); /* Length */
return irp->Complete(irp);
break;
}
return CHANNEL_RC_OK;
@ -609,6 +674,9 @@ static UINT drive_process_irp_directory_control(DRIVE_DEVICE* drive, IRP* irp)
*/
static UINT drive_process_irp_device_control(DRIVE_DEVICE* drive, IRP* irp)
{
if (!drive || !irp)
return ERROR_INVALID_PARAMETER;
Stream_Write_UINT32(irp->output, 0); /* OutputBufferLength */
return irp->Complete(irp);
}
@ -621,6 +689,9 @@ static UINT drive_process_irp_device_control(DRIVE_DEVICE* drive, IRP* irp)
static UINT drive_process_irp(DRIVE_DEVICE* drive, IRP* irp)
{
UINT error;
if (!drive || !irp)
return ERROR_INVALID_PARAMETER;
irp->IoStatus = STATUS_SUCCESS;
switch (irp->MajorFunction)
@ -674,13 +745,19 @@ static UINT drive_process_irp(DRIVE_DEVICE* drive, IRP* irp)
return error;
}
static void* drive_thread_func(void* arg)
static DWORD WINAPI drive_thread_func(LPVOID arg)
{
IRP* irp;
wMessage message;
DRIVE_DEVICE* drive = (DRIVE_DEVICE*) arg;
UINT error = CHANNEL_RC_OK;
if(!drive)
{
error = ERROR_INVALID_PARAMETER;
goto fail;
}
while (1)
{
if (!MessageQueue_Wait(drive->IrpQueue))
@ -703,18 +780,21 @@ static void* drive_thread_func(void* arg)
irp = (IRP*) message.wParam;
if (irp)
{
if ((error = drive_process_irp(drive, irp)))
{
WLog_ERR(TAG, "drive_process_irp failed with error %"PRIu32"!", error);
break;
}
}
}
if (error && drive->rdpcontext)
fail:
if (error && drive && drive->rdpcontext)
setChannelError(drive->rdpcontext, error, "drive_thread_func reported an error");
ExitThread((DWORD)error);
return NULL;
ExitThread(error);
return error;
}
/**
@ -726,6 +806,9 @@ static UINT drive_irp_request(DEVICE* device, IRP* irp)
{
DRIVE_DEVICE* drive = (DRIVE_DEVICE*) device;
if (!drive)
return ERROR_INVALID_PARAMETER;
if (!MessageQueue_Post(drive->IrpQueue, NULL, 0, (void*) irp, NULL))
{
WLog_ERR(TAG, "MessageQueue_Post failed!");
@ -735,10 +818,11 @@ static UINT drive_irp_request(DEVICE* device, IRP* irp)
return CHANNEL_RC_OK;
}
static void drive_free_resources(DRIVE_DEVICE* drive)
static UINT drive_free_int(DRIVE_DEVICE* drive)
{
UINT error = CHANNEL_RC_OK;
if (!drive)
return;
return ERROR_INVALID_PARAMETER;
CloseHandle(drive->thread);
ListDictionary_Free(drive->files);
@ -746,6 +830,7 @@ static void drive_free_resources(DRIVE_DEVICE* drive)
Stream_Free(drive->device.data, TRUE);
free(drive->path);
free(drive);
return error;
}
/**
@ -758,6 +843,9 @@ static UINT drive_free(DEVICE* device)
DRIVE_DEVICE* drive = (DRIVE_DEVICE*) device;
UINT error = CHANNEL_RC_OK;
if (!drive)
return ERROR_INVALID_PARAMETER;
if (MessageQueue_PostQuit(drive->IrpQueue, 0)
&& (WaitForSingleObject(drive->thread, INFINITE) == WAIT_FAILED))
{
@ -766,8 +854,7 @@ static UINT drive_free(DEVICE* device)
return error;
}
drive_free_resources(drive);
return error;
return drive_free_int(drive);
}
/**
@ -775,10 +862,10 @@ static UINT drive_free(DEVICE* device)
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT drive_register_drive_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints,
static UINT drive_register_drive_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints,
char* name, char* path)
{
int i, length;
size_t i, length;
DRIVE_DEVICE* drive;
UINT error;
#ifdef WIN32
@ -813,7 +900,7 @@ UINT drive_register_drive_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints,
drive->device.IRPRequest = drive_irp_request;
drive->device.Free = drive_free;
drive->rdpcontext = pEntryPoints->rdpcontext;
length = (int) strlen(name);
length = strlen(name);
drive->device.data = Stream_New(NULL, length + 1);
if (!drive->device.data)
@ -862,7 +949,7 @@ UINT drive_register_drive_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints,
goto out_error;
}
if (!(drive->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) drive_thread_func, drive,
if (!(drive->thread = CreateThread(NULL, 0, drive_thread_func, drive,
CREATE_SUSPENDED, NULL)))
{
WLog_ERR(TAG, "CreateThread failed!");
@ -874,7 +961,7 @@ UINT drive_register_drive_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints,
return CHANNEL_RC_OK;
out_error:
drive_free_resources(drive);
drive_free_int(drive);
return error;
}
@ -884,8 +971,6 @@ out_error:
#define DeviceServiceEntry FREERDP_API DeviceServiceEntry
#endif
UINT sys_code_page = 0;
/**
* Function description
*
@ -920,30 +1005,13 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
}
else if (strcmp(drive->Path, "%") == 0)
{
char* home_env = NULL;
/* home directory */
home_env = getenv("HOME");
free(drive->Path);
drive->Path = GetKnownPath(KNOWN_PATH_HOME);
if (home_env)
if (!drive->Path)
{
drive->Path = _strdup(home_env);
if (!drive->Path)
{
WLog_ERR(TAG, "_strdup failed!");
return CHANNEL_RC_NO_MEMORY;
}
}
else
{
drive->Path = _strdup("/");
if (!drive->Path)
{
WLog_ERR(TAG, "_strdup failed!");
return CHANNEL_RC_NO_MEMORY;
}
WLog_ERR(TAG, "_strdup failed!");
return CHANNEL_RC_NO_MEMORY;
}
}

View File

@ -105,7 +105,7 @@ static UINT echo_server_open_channel(echo_server* echo)
return echo->echo_channel ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
}
static void* echo_server_thread_func(void* arg)
static DWORD WINAPI echo_server_thread_func(LPVOID arg)
{
wStream* s;
void* buffer;
@ -206,8 +206,8 @@ static void* echo_server_thread_func(void* arg)
{
WLog_ERR(TAG, "Stream_New failed!");
WTSVirtualChannelClose(echo->echo_channel);
ExitThread((DWORD)ERROR_NOT_ENOUGH_MEMORY);
return NULL;
ExitThread(ERROR_NOT_ENOUGH_MEMORY);
return ERROR_NOT_ENOUGH_MEMORY;
}
while (ready)
@ -264,8 +264,8 @@ out:
setChannelError(echo->context.rdpcontext, error,
"echo_server_thread_func reported an error");
ExitThread((DWORD)error);
return NULL;
ExitThread(error);
return error;
}
/**
@ -285,8 +285,7 @@ static UINT echo_server_open(echo_server_context* context)
return ERROR_INTERNAL_ERROR;
}
if (!(echo->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) echo_server_thread_func, (void*) echo, 0, NULL)))
if (!(echo->thread = CreateThread(NULL, 0, echo_server_thread_func, (void*) echo, 0, NULL)))
{
WLog_ERR(TAG, "CreateEvent failed!");
CloseHandle(echo->stopEvent);

View File

@ -1011,7 +1011,7 @@ static VOID VCAPITYPE encomsp_virtual_channel_open_event_ex(LPVOID lpUserParam,
return;
}
static void* encomsp_virtual_channel_client_thread(void* arg)
static DWORD WINAPI encomsp_virtual_channel_client_thread(LPVOID arg)
{
wStream* data;
wMessage message;
@ -1054,8 +1054,8 @@ static void* encomsp_virtual_channel_client_thread(void* arg)
setChannelError(encomsp->rdpcontext, error,
"encomsp_virtual_channel_client_thread reported an error");
ExitThread((DWORD)error);
return NULL;
ExitThread(error);
return error;
}
/**
@ -1087,7 +1087,7 @@ static UINT encomsp_virtual_channel_event_connected(encomspPlugin* encomsp,
}
if (!(encomsp->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) encomsp_virtual_channel_client_thread, (void*) encomsp,
encomsp_virtual_channel_client_thread, (void*) encomsp,
0, NULL)))
{
WLog_ERR(TAG, "CreateThread failed!");
@ -1148,6 +1148,7 @@ static UINT encomsp_virtual_channel_event_disconnected(encomspPlugin* encomsp)
static UINT encomsp_virtual_channel_event_terminated(encomspPlugin* encomsp)
{
encomsp->InitHandle = 0;
free(encomsp->context);
free(encomsp);
return CHANNEL_RC_OK;
}

View File

@ -174,7 +174,7 @@ static UINT encomsp_server_receive_pdu(EncomspServerContext* context,
return error;
}
static void* encomsp_server_thread(void* arg)
static DWORD WINAPI encomsp_server_thread(LPVOID arg)
{
wStream* s;
DWORD nCount;
@ -285,8 +285,8 @@ out:
setChannelError(context->rdpcontext, error,
"encomsp_server_thread reported an error");
ExitThread((DWORD)error);
return NULL;
ExitThread(error);
return error;
}
/**
@ -309,7 +309,7 @@ static UINT encomsp_server_start(EncomspServerContext* context)
}
if (!(context->priv->Thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) encomsp_server_thread, (void*) context, 0, NULL)))
encomsp_server_thread, (void*) context, 0, NULL)))
{
WLog_ERR(TAG, "CreateThread failed!");
CloseHandle(context->priv->StopEvent);

View File

@ -0,0 +1,22 @@
# FreeRDP: A Remote Desktop Protocol Implementation
# FreeRDP cmake build script
#
# Copyright 2017 David Fort <contact@hardening-consulting.com>
#
# 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.
define_channel("geometry")
if(WITH_CLIENT_CHANNELS)
add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME})
endif()

View File

@ -0,0 +1,11 @@
set(OPTION_DEFAULT OFF)
set(OPTION_CLIENT_DEFAULT ON)
set(OPTION_SERVER_DEFAULT OFF)
define_channel_options(NAME "geometry" TYPE "dynamic"
DESCRIPTION "Geometry tracking Virtual Channel Extension"
SPECIFICATIONS "[MS-RDPEGT]"
DEFAULT ${OPTION_DEFAULT})
define_channel_client_options(${OPTION_CLIENT_DEFAULT})

View File

@ -0,0 +1,39 @@
# FreeRDP: A Remote Desktop Protocol Implementation
# FreeRDP cmake build script
#
# Copyright 2017 David Fort <contact@hardening-consulting.com>
#
# 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.
define_channel_client("geometry")
set(${MODULE_PREFIX}_SRCS
geometry_main.c
geometry_main.h)
include_directories(..)
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE "DVCPluginEntry")
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} winpr)
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
if (WITH_DEBUG_SYMBOLS AND MSVC AND NOT BUILTIN_CHANNELS AND BUILD_SHARED_LIBS)
install(FILES ${CMAKE_BINARY_DIR}/${MODULE_NAME}.pdb DESTINATION ${FREERDP_ADDIN_PATH} COMPONENT symbols)
endif()
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")

View File

@ -0,0 +1,481 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Geometry tracking Virtual Channel Extension
*
* Copyright 2017 David Fort <contact@hardening-consulting.com>
*
* 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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/interlocked.h>
#include <winpr/print.h>
#include <winpr/stream.h>
#include <winpr/cmdline.h>
#include <winpr/collections.h>
#include <freerdp/addin.h>
#include <freerdp/client/geometry.h>
#include <freerdp/channels/log.h>
#define TAG CHANNELS_TAG("geometry.client")
#include "geometry_main.h"
struct _GEOMETRY_CHANNEL_CALLBACK
{
IWTSVirtualChannelCallback iface;
IWTSPlugin* plugin;
IWTSVirtualChannelManager* channel_mgr;
IWTSVirtualChannel* channel;
};
typedef struct _GEOMETRY_CHANNEL_CALLBACK GEOMETRY_CHANNEL_CALLBACK;
struct _GEOMETRY_LISTENER_CALLBACK
{
IWTSListenerCallback iface;
IWTSPlugin* plugin;
IWTSVirtualChannelManager* channel_mgr;
GEOMETRY_CHANNEL_CALLBACK* channel_callback;
};
typedef struct _GEOMETRY_LISTENER_CALLBACK GEOMETRY_LISTENER_CALLBACK;
struct _GEOMETRY_PLUGIN
{
IWTSPlugin iface;
IWTSListener* listener;
GEOMETRY_LISTENER_CALLBACK* listener_callback;
GeometryClientContext* context;
};
typedef struct _GEOMETRY_PLUGIN GEOMETRY_PLUGIN;
static UINT32 mappedGeometryHash(UINT64 *g)
{
return (UINT32)((*g >> 32) + (*g & 0xffffffff));
}
static BOOL mappedGeometryKeyCompare(UINT64 *g1, UINT64 *g2)
{
return *g1 == *g2;
}
void mappedGeometryRef(MAPPED_GEOMETRY *g)
{
InterlockedIncrement(&g->refCounter);
}
void mappedGeometryUnref(MAPPED_GEOMETRY *g)
{
if (InterlockedDecrement(&g->refCounter))
return;
g->MappedGeometryUpdate = NULL;
g->MappedGeometryClear = NULL;
g->custom = NULL;
free(g->geometry.rects);
free(g);
}
void freerdp_rgndata_reset(FREERDP_RGNDATA *data)
{
data->nRectCount = 0;
}
static UINT32 geometry_read_RGNDATA(wStream *s, UINT32 len, FREERDP_RGNDATA *rgndata)
{
UINT32 dwSize, iType;
INT32 right, bottom;
if (len < 32)
{
WLog_ERR(TAG, "invalid RGNDATA");
return ERROR_INVALID_DATA;
}
Stream_Read_UINT32(s, dwSize);
if (dwSize != 32)
{
WLog_ERR(TAG, "invalid RGNDATA dwSize");
return ERROR_INVALID_DATA;
}
Stream_Read_UINT32(s, iType);
if (iType != RDH_RECTANGLE)
{
WLog_ERR(TAG, "iType %"PRIu32" for RGNDATA is not supported", iType);
return ERROR_UNSUPPORTED_TYPE;
}
Stream_Read_UINT32(s, rgndata->nRectCount);
Stream_Seek_UINT32(s); /* nRgnSize IGNORED */
Stream_Read_INT32(s, rgndata->boundingRect.x);
Stream_Read_INT32(s, rgndata->boundingRect.y);
Stream_Read_INT32(s, right);
Stream_Read_INT32(s, bottom);
rgndata->boundingRect.width = right - rgndata->boundingRect.x;
rgndata->boundingRect.height = bottom - rgndata->boundingRect.y;
len -= 32;
if (len / (4 * 4) < rgndata->nRectCount)
{
WLog_ERR(TAG, "not enough data for region rectangles");
}
if (rgndata->nRectCount)
{
int i;
RDP_RECT *tmp = realloc(rgndata->rects, rgndata->nRectCount * sizeof(RDP_RECT));
if (!tmp)
{
WLog_ERR(TAG, "unable to allocate memory for %"PRIu32" RECTs", rgndata->nRectCount);
return CHANNEL_RC_NO_MEMORY;
}
rgndata->rects = tmp;
for (i = 0; i < rgndata->nRectCount; i++)
{
Stream_Read_INT32(s, rgndata->rects[i].x);
Stream_Read_INT32(s, rgndata->rects[i].y);
Stream_Read_INT32(s, right);
Stream_Read_INT32(s, bottom);
rgndata->rects[i].width = right - rgndata->rects[i].x;
rgndata->rects[i].height = bottom - rgndata->rects[i].y;
}
}
return CHANNEL_RC_OK;
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT geometry_recv_pdu(GEOMETRY_CHANNEL_CALLBACK* callback, wStream* s)
{
UINT32 length, cbGeometryBuffer;
MAPPED_GEOMETRY *mappedGeometry;
GEOMETRY_PLUGIN* geometry;
GeometryClientContext *context;
UINT ret = CHANNEL_RC_OK;
UINT32 version, updateType, geometryType;
UINT64 id;
geometry = (GEOMETRY_PLUGIN*) callback->plugin;
context = (GeometryClientContext*)geometry->iface.pInterface;
if (Stream_GetRemainingLength(s) < 4)
{
WLog_ERR(TAG, "not enough remaining data");
return ERROR_INVALID_DATA;
}
Stream_Read_UINT32(s, length); /* Length (4 bytes) */
if (length < 73 || Stream_GetRemainingLength(s) < (length - 4))
{
WLog_ERR(TAG, "invalid packet length");
return ERROR_INVALID_DATA;
}
Stream_Read_UINT32(s, version);
Stream_Read_UINT64(s, id);
Stream_Read_UINT32(s, updateType);
Stream_Seek_UINT32(s); /* flags */
mappedGeometry = HashTable_GetItemValue(context->geometries, &id);
if (updateType == GEOMETRY_CLEAR )
{
if (!mappedGeometry)
{
WLog_ERR(TAG, "geometry 0x%"PRIx64" not found here, ignoring clear command", id);
return CHANNEL_RC_OK;
}
WLog_DBG(TAG, "clearing geometry 0x%"PRIx64"", id);
if (mappedGeometry->MappedGeometryClear && !mappedGeometry->MappedGeometryClear(mappedGeometry))
return ERROR_INTERNAL_ERROR;
if (!HashTable_Remove(context->geometries, &id))
WLog_ERR(TAG, "geometry not removed from geometries");
}
else if (updateType == GEOMETRY_UPDATE)
{
BOOL newOne = FALSE;
if (!mappedGeometry)
{
newOne = TRUE;
WLog_DBG(TAG, "creating geometry 0x%"PRIx64"", id);
mappedGeometry = calloc(1, sizeof(MAPPED_GEOMETRY));
if (!mappedGeometry)
return CHANNEL_RC_NO_MEMORY;
mappedGeometry->refCounter = 1;
mappedGeometry->mappingId = id;
if (HashTable_Add(context->geometries, &(mappedGeometry->mappingId), mappedGeometry) < 0)
{
WLog_ERR(TAG, "unable to register geometry 0x%"PRIx64" in the table", id);
free(mappedGeometry);
return CHANNEL_RC_NO_MEMORY;
}
}
else
{
WLog_DBG(TAG, "updating geometry 0x%"PRIx64"", id);
}
Stream_Read_UINT64(s, mappedGeometry->topLevelId);
Stream_Read_INT32(s, mappedGeometry->left);
Stream_Read_INT32(s, mappedGeometry->top);
Stream_Read_INT32(s, mappedGeometry->right);
Stream_Read_INT32(s, mappedGeometry->bottom);
Stream_Read_INT32(s, mappedGeometry->topLevelLeft);
Stream_Read_INT32(s, mappedGeometry->topLevelTop);
Stream_Read_INT32(s, mappedGeometry->topLevelRight);
Stream_Read_INT32(s, mappedGeometry->topLevelBottom);
Stream_Read_UINT32(s, geometryType);
Stream_Read_UINT32(s, cbGeometryBuffer);
if (Stream_GetRemainingLength(s) < cbGeometryBuffer)
{
WLog_ERR(TAG, "invalid packet length");
return ERROR_INVALID_DATA;
}
if (cbGeometryBuffer)
{
ret = geometry_read_RGNDATA(s, cbGeometryBuffer, &mappedGeometry->geometry);
if (ret != CHANNEL_RC_OK)
return ret;
}
else
{
freerdp_rgndata_reset(&mappedGeometry->geometry);
}
if (newOne)
{
if (context->MappedGeometryAdded && !context->MappedGeometryAdded(context, mappedGeometry))
{
WLog_ERR(TAG, "geometry added callback failed");
ret = ERROR_INTERNAL_ERROR;
}
}
else
{
if (mappedGeometry->MappedGeometryUpdate && !mappedGeometry->MappedGeometryUpdate(mappedGeometry))
{
WLog_ERR(TAG, "geometry update callback failed");
ret = ERROR_INTERNAL_ERROR;
}
}
}
else
{
WLog_ERR(TAG, "unknown updateType=%"PRIu32"", updateType);
ret = CHANNEL_RC_OK;
}
return ret;
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT geometry_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream* data)
{
GEOMETRY_CHANNEL_CALLBACK* callback = (GEOMETRY_CHANNEL_CALLBACK*) pChannelCallback;
return geometry_recv_pdu(callback, data);
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT geometry_on_close(IWTSVirtualChannelCallback* pChannelCallback)
{
free(pChannelCallback);
return CHANNEL_RC_OK;
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT geometry_on_new_channel_connection(IWTSListenerCallback* pListenerCallback,
IWTSVirtualChannel* pChannel, BYTE* Data, BOOL* pbAccept,
IWTSVirtualChannelCallback** ppCallback)
{
GEOMETRY_CHANNEL_CALLBACK* callback;
GEOMETRY_LISTENER_CALLBACK* listener_callback = (GEOMETRY_LISTENER_CALLBACK*) pListenerCallback;
callback = (GEOMETRY_CHANNEL_CALLBACK*) calloc(1, sizeof(GEOMETRY_CHANNEL_CALLBACK));
if (!callback)
{
WLog_ERR(TAG, "calloc failed!");
return CHANNEL_RC_NO_MEMORY;
}
callback->iface.OnDataReceived = geometry_on_data_received;
callback->iface.OnClose = geometry_on_close;
callback->plugin = listener_callback->plugin;
callback->channel_mgr = listener_callback->channel_mgr;
callback->channel = pChannel;
listener_callback->channel_callback = callback;
*ppCallback = (IWTSVirtualChannelCallback*) callback;
return CHANNEL_RC_OK;
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT geometry_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr)
{
UINT status;
GEOMETRY_PLUGIN* geometry = (GEOMETRY_PLUGIN*) pPlugin;
geometry->listener_callback = (GEOMETRY_LISTENER_CALLBACK*) calloc(1,
sizeof(GEOMETRY_LISTENER_CALLBACK));
if (!geometry->listener_callback)
{
WLog_ERR(TAG, "calloc failed!");
return CHANNEL_RC_NO_MEMORY;
}
geometry->listener_callback->iface.OnNewChannelConnection = geometry_on_new_channel_connection;
geometry->listener_callback->plugin = pPlugin;
geometry->listener_callback->channel_mgr = pChannelMgr;
status = pChannelMgr->CreateListener(pChannelMgr, GEOMETRY_DVC_CHANNEL_NAME, 0,
(IWTSListenerCallback*) geometry->listener_callback, &(geometry->listener));
geometry->listener->pInterface = geometry->iface.pInterface;
return status;
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT geometry_plugin_terminated(IWTSPlugin* pPlugin)
{
GEOMETRY_PLUGIN* geometry = (GEOMETRY_PLUGIN*) pPlugin;
GeometryClientContext* context = (GeometryClientContext *)geometry->iface.pInterface;
if (context)
HashTable_Free(context->geometries);
free(geometry->listener_callback);
free(geometry->iface.pInterface);
free(pPlugin);
return CHANNEL_RC_OK;
}
/**
* Channel Client Interface
*/
#ifdef BUILTIN_CHANNELS
#define DVCPluginEntry geometry_DVCPluginEntry
#else
#define DVCPluginEntry FREERDP_API DVCPluginEntry
#endif
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
{
UINT error = CHANNEL_RC_OK;
GEOMETRY_PLUGIN* geometry;
GeometryClientContext* context;
geometry = (GEOMETRY_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "geometry");
if (!geometry)
{
geometry = (GEOMETRY_PLUGIN*) calloc(1, sizeof(GEOMETRY_PLUGIN));
if (!geometry)
{
WLog_ERR(TAG, "calloc failed!");
return CHANNEL_RC_NO_MEMORY;
}
geometry->iface.Initialize = geometry_plugin_initialize;
geometry->iface.Connected = NULL;
geometry->iface.Disconnected = NULL;
geometry->iface.Terminated = geometry_plugin_terminated;
context = (GeometryClientContext*) calloc(1, sizeof(GeometryClientContext));
if (!context)
{
WLog_ERR(TAG, "calloc failed!");
goto error_context;
}
context->geometries = HashTable_New(FALSE);
context->geometries->hash = (HASH_TABLE_HASH_FN)mappedGeometryHash;
context->geometries->keyCompare = (HASH_TABLE_KEY_COMPARE_FN)mappedGeometryKeyCompare;
context->geometries->valueFree = (HASH_TABLE_VALUE_FREE_FN)mappedGeometryUnref;
context->handle = (void*) geometry;
geometry->iface.pInterface = (void*) context;
geometry->context = context;
error = pEntryPoints->RegisterPlugin(pEntryPoints, "geometry", (IWTSPlugin*) geometry);
}
else
{
WLog_ERR(TAG, "could not get geometry Plugin.");
return CHANNEL_RC_BAD_CHANNEL;
}
return error;
error_context:
free(geometry);
return CHANNEL_RC_NO_MEMORY;
}

View File

@ -0,0 +1,34 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Geometry tracking virtual channel extension
*
* Copyright 2017 David Fort <contact@hardening-consulting.com>
*
* 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_GEOMETRY_CLIENT_MAIN_H
#define FREERDP_CHANNEL_GEOMETRY_CLIENT_MAIN_H
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <freerdp/dvc.h>
#include <freerdp/types.h>
#include <freerdp/addin.h>
#include <freerdp/client/geometry.h>
#endif /* FREERDP_CHANNEL_GEOMETRY_CLIENT_MAIN_H */

View File

@ -304,7 +304,7 @@ static UINT parallel_process_irp(PARALLEL_DEVICE* parallel, IRP* irp)
return CHANNEL_RC_OK;
}
static void* parallel_thread_func(void* arg)
static DWORD WINAPI parallel_thread_func(LPVOID arg)
{
IRP* irp;
wMessage message;
@ -343,8 +343,8 @@ static void* parallel_thread_func(void* arg)
setChannelError(parallel->rdpcontext, error,
"parallel_thread_func reported an error");
ExitThread((DWORD)error);
return NULL;
ExitThread(error);
return error;
}
/**
@ -375,8 +375,8 @@ static UINT parallel_free(DEVICE* device)
UINT error;
PARALLEL_DEVICE* parallel = (PARALLEL_DEVICE*) device;
if (MessageQueue_PostQuit(parallel->queue, 0)
&& (WaitForSingleObject(parallel->thread, INFINITE) == WAIT_FAILED))
if (!MessageQueue_PostQuit(parallel->queue, 0)
|| (WaitForSingleObject(parallel->thread, INFINITE) == WAIT_FAILED))
{
error = GetLastError();
WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"!", error);
@ -405,7 +405,7 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
{
char* name;
char* path;
int i;
size_t i;
size_t length;
RDPDR_PARALLEL* device;
PARALLEL_DEVICE* parallel;
@ -414,10 +414,10 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
name = device->Name;
path = device->Path;
if (!name || (name[0] == '*'))
if (!name || (name[0] == '*') || !path)
{
/* TODO: implement auto detection of parallel ports */
return CHANNEL_RC_OK;
return CHANNEL_RC_INITIALIZATION_ERROR;
}
if (name[0] && path[0])
@ -466,7 +466,7 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
}
if (!(parallel->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) parallel_thread_func, (void*) parallel, 0, NULL)))
parallel_thread_func, (void*) parallel, 0, NULL)))
{
WLog_ERR(TAG, "CreateThread failed!");
error = ERROR_INTERNAL_ERROR;

View File

@ -231,7 +231,7 @@ static UINT printer_process_irp(PRINTER_DEVICE* printer_dev, IRP* irp)
return CHANNEL_RC_OK;
}
static void* printer_thread_func(void* arg)
static DWORD WINAPI printer_thread_func(LPVOID arg)
{
IRP* irp;
PRINTER_DEVICE* printer_dev = (PRINTER_DEVICE*) arg;
@ -275,8 +275,8 @@ static void* printer_thread_func(void* arg)
setChannelError(printer_dev->rdpcontext, error,
"printer_thread_func reported an error");
ExitThread((DWORD) error);
return NULL;
ExitThread(error);
return error;
}
/**
@ -445,8 +445,7 @@ UINT printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints,
goto error_out;
}
if (!(printer_dev->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) printer_thread_func, (void*) printer_dev, 0, NULL)))
if (!(printer_dev->thread = CreateThread(NULL, 0, printer_thread_func, (void*) printer_dev, 0, NULL)))
{
WLog_ERR(TAG, "CreateThread failed!");
error = ERROR_INTERNAL_ERROR;

View File

@ -38,6 +38,10 @@
RailClientContext* rail_get_client_interface(railPlugin* rail)
{
RailClientContext* pInterface;
if (!rail)
return NULL;
pInterface = (RailClientContext*) rail->channelEntryPoints.pInterface;
return pInterface;
}
@ -52,14 +56,10 @@ static UINT rail_send(railPlugin* rail, wStream* s)
UINT status;
if (!rail)
{
status = CHANNEL_RC_BAD_INIT_HANDLE;
}
else
{
status = rail->channelEntryPoints.pVirtualChannelWriteEx(rail->InitHandle, rail->OpenHandle,
Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s);
}
return CHANNEL_RC_BAD_INIT_HANDLE;
status = rail->channelEntryPoints.pVirtualChannelWriteEx(rail->InitHandle, rail->OpenHandle,
Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s);
if (status != CHANNEL_RC_OK)
{
@ -79,6 +79,10 @@ static UINT rail_send(railPlugin* rail, wStream* s)
UINT rail_send_channel_data(railPlugin* rail, void* data, size_t length)
{
wStream* s = NULL;
if (!rail || !data)
return ERROR_INVALID_PARAMETER;
s = Stream_New(NULL, length);
if (!s)
@ -97,17 +101,15 @@ UINT rail_send_channel_data(railPlugin* rail, void* data, size_t length)
*/
static void rail_client_clean_exec_order(RAIL_EXEC_ORDER* exec)
{
if (!exec)
return;
if (!exec)
return;
free(exec->exeOrFile.string);
exec->exeOrFile.string = NULL;
free(exec->workingDir.string);
exec->workingDir.string = NULL;
free(exec->arguments.string);
exec->arguments.string = NULL;
free(exec->exeOrFile.string);
exec->exeOrFile.string = NULL;
free(exec->workingDir.string);
exec->workingDir.string = NULL;
free(exec->arguments.string);
exec->arguments.string = NULL;
}
/**
@ -124,13 +126,18 @@ static UINT rail_client_execute(RailClientContext* context,
{
char* exeOrFile;
UINT error;
railPlugin* rail = (railPlugin*) context->handle;
railPlugin* rail;
if (!context || !exec)
return ERROR_INVALID_PARAMETER;
rail = (railPlugin*) context->handle;
exeOrFile = exec->RemoteApplicationProgram;
if (!exeOrFile)
return ERROR_INVALID_PARAMETER;
if (strlen(exeOrFile) >= 2)
if (strnlen(exeOrFile, MAX_PATH) >= 2)
{
if (strncmp(exeOrFile, "||", 2) != 0)
exec->flags |= RAIL_EXEC_FLAG_FILE;
@ -155,7 +162,12 @@ static UINT rail_client_execute(RailClientContext* context,
static UINT rail_client_activate(RailClientContext* context,
RAIL_ACTIVATE_ORDER* activate)
{
railPlugin* rail = (railPlugin*) context->handle;
railPlugin* rail;
if (!context || !activate)
return ERROR_INVALID_PARAMETER;
rail = (railPlugin*) context->handle;
return rail_send_client_activate_order(rail, activate);
}
@ -168,10 +180,14 @@ static UINT rail_send_client_sysparam(RailClientContext* context,
RAIL_SYSPARAM_ORDER* sysparam)
{
wStream* s;
int length;
railPlugin* rail = (railPlugin*) context->handle;
size_t length = RAIL_SYSPARAM_ORDER_LENGTH;
railPlugin* rail;
UINT error;
length = RAIL_SYSPARAM_ORDER_LENGTH;
if (!context || !sysparam)
return ERROR_INVALID_PARAMETER;
rail = (railPlugin*) context->handle;
switch (sysparam->param)
{
@ -231,6 +247,9 @@ static UINT rail_client_system_param(RailClientContext* context,
{
UINT error = CHANNEL_RC_OK;
if (!context || !sysparam)
return ERROR_INVALID_PARAMETER;
if (sysparam->params & SPI_MASK_SET_HIGH_CONTRAST)
{
sysparam->param = SPI_SET_HIGH_CONTRAST;
@ -319,6 +338,9 @@ static UINT rail_client_system_param(RailClientContext* context,
static UINT rail_server_system_param(RailClientContext* context,
RAIL_SYSPARAM_ORDER* sysparam)
{
if (!context || !sysparam)
return ERROR_INVALID_PARAMETER;
return CHANNEL_RC_OK; /* stub - should be registered by client */
}
@ -330,7 +352,12 @@ static UINT rail_server_system_param(RailClientContext* context,
static UINT rail_client_system_command(RailClientContext* context,
RAIL_SYSCOMMAND_ORDER* syscommand)
{
railPlugin* rail = (railPlugin*) context->handle;
railPlugin* rail;
if (!context || !syscommand)
return ERROR_INVALID_PARAMETER;
rail = (railPlugin*) context->handle;
return rail_send_client_syscommand_order(rail, syscommand);
}
@ -342,7 +369,12 @@ static UINT rail_client_system_command(RailClientContext* context,
static UINT rail_client_handshake(RailClientContext* context,
RAIL_HANDSHAKE_ORDER* handshake)
{
railPlugin* rail = (railPlugin*) context->handle;
railPlugin* rail;
if (!context || !handshake)
return ERROR_INVALID_PARAMETER;
rail = (railPlugin*) context->handle;
return rail_send_handshake_order(rail, handshake);
}
@ -354,6 +386,9 @@ static UINT rail_client_handshake(RailClientContext* context,
static UINT rail_server_handshake(RailClientContext* context,
RAIL_HANDSHAKE_ORDER* handshake)
{
if (!context || !handshake)
return ERROR_INVALID_PARAMETER;
return CHANNEL_RC_OK; /* stub - should be registered by client */
}
@ -365,7 +400,12 @@ static UINT rail_server_handshake(RailClientContext* context,
static UINT rail_client_handshake_ex(RailClientContext* context,
RAIL_HANDSHAKE_EX_ORDER* handshakeEx)
{
railPlugin* rail = (railPlugin*) context->handle;
railPlugin* rail;
if (!context || !handshakeEx)
return ERROR_INVALID_PARAMETER;
rail = (railPlugin*) context->handle;
return rail_send_handshake_ex_order(rail, handshakeEx);
}
@ -377,6 +417,9 @@ static UINT rail_client_handshake_ex(RailClientContext* context,
static UINT rail_server_handshake_ex(RailClientContext* context,
RAIL_HANDSHAKE_EX_ORDER* handshakeEx)
{
if (!context || !handshakeEx)
return ERROR_INVALID_PARAMETER;
return CHANNEL_RC_OK; /* stub - should be registered by client */
}
@ -388,7 +431,12 @@ static UINT rail_server_handshake_ex(RailClientContext* context,
static UINT rail_client_notify_event(RailClientContext* context,
RAIL_NOTIFY_EVENT_ORDER* notifyEvent)
{
railPlugin* rail = (railPlugin*) context->handle;
railPlugin* rail;
if (!context || !notifyEvent)
return ERROR_INVALID_PARAMETER;
rail = (railPlugin*) context->handle;
return rail_send_client_notify_event_order(rail, notifyEvent);
}
@ -400,7 +448,12 @@ static UINT rail_client_notify_event(RailClientContext* context,
static UINT rail_client_window_move(RailClientContext* context,
RAIL_WINDOW_MOVE_ORDER* windowMove)
{
railPlugin* rail = (railPlugin*) context->handle;
railPlugin* rail;
if (!context || !windowMove)
return ERROR_INVALID_PARAMETER;
rail = (railPlugin*) context->handle;
return rail_send_client_window_move_order(rail, windowMove);
}
@ -412,6 +465,9 @@ static UINT rail_client_window_move(RailClientContext* context,
static UINT rail_server_local_move_size(RailClientContext* context,
RAIL_LOCALMOVESIZE_ORDER* localMoveSize)
{
if (!context || !localMoveSize)
return ERROR_INVALID_PARAMETER;
return CHANNEL_RC_OK; /* stub - should be registered by client */
}
@ -423,6 +479,9 @@ static UINT rail_server_local_move_size(RailClientContext* context,
static UINT rail_server_min_max_info(RailClientContext* context,
RAIL_MINMAXINFO_ORDER* minMaxInfo)
{
if (!context || !minMaxInfo)
return ERROR_INVALID_PARAMETER;
return CHANNEL_RC_OK; /* stub - should be registered by client */
}
@ -434,7 +493,12 @@ static UINT rail_server_min_max_info(RailClientContext* context,
static UINT rail_client_information(RailClientContext* context,
RAIL_CLIENT_STATUS_ORDER* clientStatus)
{
railPlugin* rail = (railPlugin*) context->handle;
railPlugin* rail;
if (!context || !clientStatus)
return ERROR_INVALID_PARAMETER;
rail = (railPlugin*) context->handle;
return rail_send_client_status_order(rail, clientStatus);
}
@ -446,7 +510,12 @@ static UINT rail_client_information(RailClientContext* context,
static UINT rail_client_system_menu(RailClientContext* context,
RAIL_SYSMENU_ORDER* sysmenu)
{
railPlugin* rail = (railPlugin*) context->handle;
railPlugin* rail;
if (!context || !sysmenu)
return ERROR_INVALID_PARAMETER;
rail = (railPlugin*) context->handle;
return rail_send_client_sysmenu_order(rail, sysmenu);
}
@ -458,7 +527,12 @@ static UINT rail_client_system_menu(RailClientContext* context,
static UINT rail_client_language_bar_info(RailClientContext* context,
RAIL_LANGBAR_INFO_ORDER* langBarInfo)
{
railPlugin* rail = (railPlugin*) context->handle;
railPlugin* rail;
if (!context || !langBarInfo)
return ERROR_INVALID_PARAMETER;
rail = (railPlugin*) context->handle;
return rail_send_client_langbar_info_order(rail, langBarInfo);
}
@ -470,6 +544,9 @@ static UINT rail_client_language_bar_info(RailClientContext* context,
static UINT rail_server_language_bar_info(RailClientContext* context,
RAIL_LANGBAR_INFO_ORDER* langBarInfo)
{
if (!context || !langBarInfo)
return ERROR_INVALID_PARAMETER;
return CHANNEL_RC_OK; /* stub - should be registered by client */
}
@ -481,6 +558,9 @@ static UINT rail_server_language_bar_info(RailClientContext* context,
static UINT rail_server_execute_result(RailClientContext* context,
RAIL_EXEC_RESULT_ORDER* execResult)
{
if (!context || !execResult)
return ERROR_INVALID_PARAMETER;
return CHANNEL_RC_OK; /* stub - should be registered by client */
}
@ -492,7 +572,12 @@ static UINT rail_server_execute_result(RailClientContext* context,
static UINT rail_client_get_appid_request(RailClientContext* context,
RAIL_GET_APPID_REQ_ORDER* getAppIdReq)
{
railPlugin* rail = (railPlugin*) context->handle;
railPlugin* rail;
if (!context || !getAppIdReq || !context->handle)
return ERROR_INVALID_PARAMETER;
rail = (railPlugin*) context->handle;
return rail_send_client_get_appid_req_order(rail, getAppIdReq);
}
@ -504,6 +589,9 @@ static UINT rail_client_get_appid_request(RailClientContext* context,
static UINT rail_server_get_appid_response(RailClientContext* context,
RAIL_GET_APPID_RESP_ORDER* getAppIdResp)
{
if (!context || !getAppIdResp)
return ERROR_INVALID_PARAMETER;
return CHANNEL_RC_OK; /* stub - should be registered by client */
}
@ -606,7 +694,7 @@ static VOID VCAPITYPE rail_virtual_channel_open_event_ex(LPVOID lpUserParam, DWO
return;
}
static void* rail_virtual_channel_client_thread(void* arg)
static DWORD WINAPI rail_virtual_channel_client_thread(LPVOID arg)
{
wStream* data;
wMessage message;
@ -635,9 +723,9 @@ static void* rail_virtual_channel_client_thread(void* arg)
if (message.id == 0)
{
data = (wStream*) message.wParam;
error = rail_order_recv(rail, data);
Stream_Free(data, TRUE);
if (error)
{
WLog_ERR(TAG, "rail_order_recv failed with error %"PRIu32"!", error);
@ -650,8 +738,8 @@ static void* rail_virtual_channel_client_thread(void* arg)
setChannelError(rail->rdpcontext, error,
"rail_virtual_channel_client_thread reported an error");
ExitThread((DWORD)error);
return NULL;
ExitThread(error);
return error;
}
/**
@ -682,7 +770,7 @@ static UINT rail_virtual_channel_event_connected(railPlugin* rail, LPVOID pData,
}
if (!(rail->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) rail_virtual_channel_client_thread, (void*) rail, 0,
rail_virtual_channel_client_thread, (void*) rail, 0,
NULL)))
{
WLog_ERR(TAG, "CreateThread failed!");
@ -738,6 +826,7 @@ static UINT rail_virtual_channel_event_disconnected(railPlugin* rail)
static void rail_virtual_channel_event_terminated(railPlugin* rail)
{
rail->InitHandle = 0;
free(rail->context);
free(rail);
}
@ -848,7 +937,6 @@ BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS pEntryPoints, PVOID p
isFreerdp = TRUE;
}
WLog_Init();
rail->log = WLog_Get("com.freerdp.channels.rail.client");
WLog_Print(rail->log, WLOG_DEBUG, "VirtualChannelEntryEx");
CopyMemory(&(rail->channelEntryPoints), pEntryPoints,

View File

@ -32,7 +32,6 @@
#include "rail_orders.h"
/**
* Function description
*
@ -40,6 +39,9 @@
*/
static UINT rail_write_unicode_string(wStream* s, RAIL_UNICODE_STRING* unicode_string)
{
if (!s || !unicode_string)
return ERROR_INVALID_PARAMETER;
if (!Stream_EnsureRemainingCapacity(s, 2 + unicode_string->length))
{
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
@ -58,6 +60,9 @@ static UINT rail_write_unicode_string(wStream* s, RAIL_UNICODE_STRING* unicode_s
*/
static UINT rail_write_unicode_string_value(wStream* s, RAIL_UNICODE_STRING* unicode_string)
{
if (!s || !unicode_string)
return ERROR_INVALID_PARAMETER;
if (unicode_string->length > 0)
{
if (!Stream_EnsureRemainingCapacity(s, unicode_string->length))
@ -80,6 +85,10 @@ static UINT rail_write_unicode_string_value(wStream* s, RAIL_UNICODE_STRING* uni
UINT rail_send_pdu(railPlugin* rail, wStream* s, UINT16 orderType)
{
UINT16 orderLength;
if (!rail || !s)
return ERROR_INVALID_PARAMETER;
orderLength = (UINT16) Stream_GetPosition(s);
Stream_SetPosition(s, 0);
rail_write_pdu_header(s, orderType, orderLength);
@ -94,8 +103,11 @@ UINT rail_send_pdu(railPlugin* rail, wStream* s, UINT16 orderType)
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT rail_write_high_contrast(wStream* s, RAIL_HIGH_CONTRAST* highContrast)
static UINT rail_write_high_contrast(wStream* s, RAIL_HIGH_CONTRAST* highContrast)
{
if (!s || !highContrast)
return ERROR_INVALID_PARAMETER;
highContrast->colorSchemeLength = highContrast->colorScheme.length + 2;
Stream_Write_UINT32(s, highContrast->flags); /* flags (4 bytes) */
Stream_Write_UINT32(s, highContrast->colorSchemeLength); /* colorSchemeLength (4 bytes) */
@ -107,8 +119,11 @@ UINT rail_write_high_contrast(wStream* s, RAIL_HIGH_CONTRAST* highContrast)
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT rail_read_server_exec_result_order(wStream* s, RAIL_EXEC_RESULT_ORDER* execResult)
static UINT rail_read_server_exec_result_order(wStream* s, RAIL_EXEC_RESULT_ORDER* execResult)
{
if (!s || !execResult)
return ERROR_INVALID_PARAMETER;
if (Stream_GetRemainingLength(s) < 8)
{
WLog_ERR(TAG, "Stream_GetRemainingLength failed!");
@ -128,10 +143,13 @@ UINT rail_read_server_exec_result_order(wStream* s, RAIL_EXEC_RESULT_ORDER* exec
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT rail_read_server_sysparam_order(wStream* s, RAIL_SYSPARAM_ORDER* sysparam)
static UINT rail_read_server_sysparam_order(wStream* s, RAIL_SYSPARAM_ORDER* sysparam)
{
BYTE body;
if (!s || !sysparam)
return ERROR_INVALID_PARAMETER;
if (Stream_GetRemainingLength(s) < 5)
{
WLog_ERR(TAG, "Stream_GetRemainingLength failed!");
@ -163,8 +181,11 @@ UINT rail_read_server_sysparam_order(wStream* s, RAIL_SYSPARAM_ORDER* sysparam)
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT rail_read_server_minmaxinfo_order(wStream* s, RAIL_MINMAXINFO_ORDER* minmaxinfo)
static UINT rail_read_server_minmaxinfo_order(wStream* s, RAIL_MINMAXINFO_ORDER* minmaxinfo)
{
if (!s || !minmaxinfo)
return ERROR_INVALID_PARAMETER;
if (Stream_GetRemainingLength(s) < 20)
{
WLog_ERR(TAG, "Stream_GetRemainingLength failed!");
@ -188,10 +209,14 @@ UINT rail_read_server_minmaxinfo_order(wStream* s, RAIL_MINMAXINFO_ORDER* minmax
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT rail_read_server_localmovesize_order(wStream* s, RAIL_LOCALMOVESIZE_ORDER* localMoveSize)
static UINT rail_read_server_localmovesize_order(wStream* s,
RAIL_LOCALMOVESIZE_ORDER* localMoveSize)
{
UINT16 isMoveSizeStart;
if (!s || !localMoveSize)
return ERROR_INVALID_PARAMETER;
if (Stream_GetRemainingLength(s) < 12)
{
WLog_ERR(TAG, "Stream_GetRemainingLength failed!");
@ -212,8 +237,12 @@ UINT rail_read_server_localmovesize_order(wStream* s, RAIL_LOCALMOVESIZE_ORDER*
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT rail_read_server_get_appid_resp_order(wStream* s, RAIL_GET_APPID_RESP_ORDER* getAppidResp)
static UINT rail_read_server_get_appid_resp_order(wStream* s,
RAIL_GET_APPID_RESP_ORDER* getAppidResp)
{
if (!s || !getAppidResp)
return ERROR_INVALID_PARAMETER;
if (Stream_GetRemainingLength(s) < 516)
{
WLog_ERR(TAG, "Stream_GetRemainingLength failed!");
@ -231,8 +260,11 @@ UINT rail_read_server_get_appid_resp_order(wStream* s, RAIL_GET_APPID_RESP_ORDER
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT rail_read_langbar_info_order(wStream* s, RAIL_LANGBAR_INFO_ORDER* langbarInfo)
static UINT rail_read_langbar_info_order(wStream* s, RAIL_LANGBAR_INFO_ORDER* langbarInfo)
{
if (!s || !langbarInfo)
return ERROR_INVALID_PARAMETER;
if (Stream_GetRemainingLength(s) < 4)
{
WLog_ERR(TAG, "Stream_GetRemainingLength failed!");
@ -243,9 +275,13 @@ UINT rail_read_langbar_info_order(wStream* s, RAIL_LANGBAR_INFO_ORDER* langbarIn
return CHANNEL_RC_OK;
}
void rail_write_client_status_order(wStream* s, RAIL_CLIENT_STATUS_ORDER* clientStatus)
static UINT rail_write_client_status_order(wStream* s, RAIL_CLIENT_STATUS_ORDER* clientStatus)
{
if (!s || !clientStatus)
return ERROR_INVALID_PARAMETER;
Stream_Write_UINT32(s, clientStatus->flags); /* flags (4 bytes) */
return ERROR_SUCCESS;
}
/**
@ -253,9 +289,13 @@ void rail_write_client_status_order(wStream* s, RAIL_CLIENT_STATUS_ORDER* client
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT rail_write_client_exec_order(wStream* s, RAIL_EXEC_ORDER* exec)
static UINT rail_write_client_exec_order(wStream* s, RAIL_EXEC_ORDER* exec)
{
UINT error;
if (!s || !exec)
return ERROR_INVALID_PARAMETER;
Stream_Write_UINT16(s, exec->flags); /* flags (2 bytes) */
Stream_Write_UINT16(s, exec->exeOrFile.length); /* exeOrFileLength (2 bytes) */
Stream_Write_UINT16(s, exec->workingDir.length); /* workingDirLength (2 bytes) */
@ -291,6 +331,10 @@ UINT rail_write_client_sysparam_order(wStream* s, RAIL_SYSPARAM_ORDER* sysparam)
{
BYTE body;
UINT error = CHANNEL_RC_OK;
if (!s || !sysparam)
return ERROR_INVALID_PARAMETER;
Stream_Write_UINT32(s, sysparam->param); /* systemParam (4 bytes) */
switch (sysparam->param)
@ -344,51 +388,80 @@ UINT rail_write_client_sysparam_order(wStream* s, RAIL_SYSPARAM_ORDER* sysparam)
return error;
}
void rail_write_client_activate_order(wStream* s, RAIL_ACTIVATE_ORDER* activate)
static UINT rail_write_client_activate_order(wStream* s, RAIL_ACTIVATE_ORDER* activate)
{
BYTE enabled;
if (!s || !activate)
return ERROR_INVALID_PARAMETER;
Stream_Write_UINT32(s, activate->windowId); /* windowId (4 bytes) */
enabled = activate->enabled;
Stream_Write_UINT8(s, enabled); /* enabled (1 byte) */
return ERROR_SUCCESS;
}
void rail_write_client_sysmenu_order(wStream* s, RAIL_SYSMENU_ORDER* sysmenu)
static UINT rail_write_client_sysmenu_order(wStream* s, RAIL_SYSMENU_ORDER* sysmenu)
{
if (!s || !sysmenu)
return ERROR_INVALID_PARAMETER;
Stream_Write_UINT32(s, sysmenu->windowId); /* windowId (4 bytes) */
Stream_Write_UINT16(s, sysmenu->left); /* left (2 bytes) */
Stream_Write_UINT16(s, sysmenu->top); /* top (2 bytes) */
return ERROR_SUCCESS;
}
void rail_write_client_syscommand_order(wStream* s, RAIL_SYSCOMMAND_ORDER* syscommand)
static UINT rail_write_client_syscommand_order(wStream* s, RAIL_SYSCOMMAND_ORDER* syscommand)
{
if (!s || !syscommand)
return ERROR_INVALID_PARAMETER;
Stream_Write_UINT32(s, syscommand->windowId); /* windowId (4 bytes) */
Stream_Write_UINT16(s, syscommand->command); /* command (2 bytes) */
return ERROR_SUCCESS;
}
void rail_write_client_notify_event_order(wStream* s, RAIL_NOTIFY_EVENT_ORDER* notifyEvent)
static UINT rail_write_client_notify_event_order(wStream* s, RAIL_NOTIFY_EVENT_ORDER* notifyEvent)
{
if (!s || !notifyEvent)
return ERROR_INVALID_PARAMETER;
Stream_Write_UINT32(s, notifyEvent->windowId); /* windowId (4 bytes) */
Stream_Write_UINT32(s, notifyEvent->notifyIconId); /* notifyIconId (4 bytes) */
Stream_Write_UINT32(s, notifyEvent->message); /* notifyIconId (4 bytes) */
return ERROR_SUCCESS;
}
void rail_write_client_window_move_order(wStream* s, RAIL_WINDOW_MOVE_ORDER* windowMove)
static UINT rail_write_client_window_move_order(wStream* s, RAIL_WINDOW_MOVE_ORDER* windowMove)
{
if (!s || !windowMove)
return ERROR_INVALID_PARAMETER;
Stream_Write_UINT32(s, windowMove->windowId); /* windowId (4 bytes) */
Stream_Write_UINT16(s, windowMove->left); /* left (2 bytes) */
Stream_Write_UINT16(s, windowMove->top); /* top (2 bytes) */
Stream_Write_UINT16(s, windowMove->right); /* right (2 bytes) */
Stream_Write_UINT16(s, windowMove->bottom); /* bottom (2 bytes) */
return ERROR_SUCCESS;
}
void rail_write_client_get_appid_req_order(wStream* s, RAIL_GET_APPID_REQ_ORDER* getAppidReq)
static UINT rail_write_client_get_appid_req_order(wStream* s, RAIL_GET_APPID_REQ_ORDER* getAppidReq)
{
if (!s || !getAppidReq)
return ERROR_INVALID_PARAMETER;
Stream_Write_UINT32(s, getAppidReq->windowId); /* windowId (4 bytes) */
return ERROR_SUCCESS;
}
void rail_write_langbar_info_order(wStream* s, RAIL_LANGBAR_INFO_ORDER* langbarInfo)
static UINT rail_write_langbar_info_order(wStream* s, RAIL_LANGBAR_INFO_ORDER* langbarInfo)
{
if (!s || !langbarInfo)
return ERROR_INVALID_PARAMETER;
Stream_Write_UINT32(s, langbarInfo->languageBarStatus); /* languageBarStatus (4 bytes) */
return ERROR_SUCCESS;
}
/**
@ -396,11 +469,14 @@ void rail_write_langbar_info_order(wStream* s, RAIL_LANGBAR_INFO_ORDER* langbarI
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT rail_recv_handshake_order(railPlugin* rail, RAIL_HANDSHAKE_ORDER* handshake, wStream* s)
static UINT rail_recv_handshake_order(railPlugin* rail, RAIL_HANDSHAKE_ORDER* handshake, wStream* s)
{
RailClientContext* context = rail_get_client_interface(rail);
UINT error;
if (!context || !handshake || !s)
return ERROR_INVALID_PARAMETER;
if ((error = rail_read_handshake_order(s, handshake)))
{
WLog_ERR(TAG, "rail_read_handshake_order failed with error %"PRIu32"!", error);
@ -423,12 +499,15 @@ UINT rail_recv_handshake_order(railPlugin* rail, RAIL_HANDSHAKE_ORDER* handshake
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT rail_recv_handshake_ex_order(railPlugin* rail, RAIL_HANDSHAKE_EX_ORDER* handshakeEx,
wStream* s)
static UINT rail_recv_handshake_ex_order(railPlugin* rail, RAIL_HANDSHAKE_EX_ORDER* handshakeEx,
wStream* s)
{
RailClientContext* context = rail_get_client_interface(rail);
UINT error;
if (!context || !handshakeEx || !s)
return ERROR_INVALID_PARAMETER;
if ((error = rail_read_handshake_ex_order(s, handshakeEx)))
{
WLog_ERR(TAG, "rail_read_handshake_ex_order failed with error %"PRIu32"!", error);
@ -451,10 +530,15 @@ UINT rail_recv_handshake_ex_order(railPlugin* rail, RAIL_HANDSHAKE_EX_ORDER* han
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT rail_recv_exec_result_order(railPlugin* rail, RAIL_EXEC_RESULT_ORDER* execResult, wStream* s)
static UINT rail_recv_exec_result_order(railPlugin* rail, RAIL_EXEC_RESULT_ORDER* execResult,
wStream* s)
{
RailClientContext* context = rail_get_client_interface(rail);
UINT error;
if (!context || !execResult || !s)
return ERROR_INVALID_PARAMETER;
ZeroMemory(execResult, sizeof(RAIL_EXEC_RESULT_ORDER));
if ((error = rail_read_server_exec_result_order(s, execResult)))
@ -479,11 +563,15 @@ UINT rail_recv_exec_result_order(railPlugin* rail, RAIL_EXEC_RESULT_ORDER* execR
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT rail_recv_server_sysparam_order(railPlugin* rail, RAIL_SYSPARAM_ORDER* sysparam, wStream* s)
static UINT rail_recv_server_sysparam_order(railPlugin* rail, RAIL_SYSPARAM_ORDER* sysparam,
wStream* s)
{
RailClientContext* context = rail_get_client_interface(rail);
UINT error;
if (!context || !sysparam || !s)
return ERROR_INVALID_PARAMETER;
if ((error = rail_read_server_sysparam_order(s, sysparam)))
{
WLog_ERR(TAG, "rail_read_server_sysparam_order failed with error %"PRIu32"!", error);
@ -506,12 +594,15 @@ UINT rail_recv_server_sysparam_order(railPlugin* rail, RAIL_SYSPARAM_ORDER* sysp
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT rail_recv_server_minmaxinfo_order(railPlugin* rail, RAIL_MINMAXINFO_ORDER* minMaxInfo,
wStream* s)
static UINT rail_recv_server_minmaxinfo_order(railPlugin* rail, RAIL_MINMAXINFO_ORDER* minMaxInfo,
wStream* s)
{
RailClientContext* context = rail_get_client_interface(rail);
UINT error;
if (!context || !minMaxInfo || !s)
return ERROR_INVALID_PARAMETER;
if ((error = rail_read_server_minmaxinfo_order(s, minMaxInfo)))
{
WLog_ERR(TAG, "rail_read_server_minmaxinfo_order failed with error %"PRIu32"!", error);
@ -534,12 +625,16 @@ UINT rail_recv_server_minmaxinfo_order(railPlugin* rail, RAIL_MINMAXINFO_ORDER*
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT rail_recv_server_localmovesize_order(railPlugin* rail, RAIL_LOCALMOVESIZE_ORDER* localMoveSize,
static UINT rail_recv_server_localmovesize_order(railPlugin* rail,
RAIL_LOCALMOVESIZE_ORDER* localMoveSize,
wStream* s)
{
RailClientContext* context = rail_get_client_interface(rail);
UINT error;
if (!context || !localMoveSize || !s)
return ERROR_INVALID_PARAMETER;
if ((error = rail_read_server_localmovesize_order(s, localMoveSize)))
{
WLog_ERR(TAG, "rail_read_server_localmovesize_order failed with error %"PRIu32"!", error);
@ -562,12 +657,15 @@ UINT rail_recv_server_localmovesize_order(railPlugin* rail, RAIL_LOCALMOVESIZE_O
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT rail_recv_server_get_appid_resp_order(railPlugin* rail,
static UINT rail_recv_server_get_appid_resp_order(railPlugin* rail,
RAIL_GET_APPID_RESP_ORDER* getAppIdResp, wStream* s)
{
RailClientContext* context = rail_get_client_interface(rail);
UINT error;
if (!context || !getAppIdResp || !s)
return ERROR_INVALID_PARAMETER;
if ((error = rail_read_server_get_appid_resp_order(s, getAppIdResp)))
{
WLog_ERR(TAG, "rail_read_server_get_appid_resp_order failed with error %"PRIu32"!", error);
@ -590,12 +688,15 @@ UINT rail_recv_server_get_appid_resp_order(railPlugin* rail,
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT rail_recv_langbar_info_order(railPlugin* rail, RAIL_LANGBAR_INFO_ORDER* langBarInfo,
wStream* s)
static UINT rail_recv_langbar_info_order(railPlugin* rail, RAIL_LANGBAR_INFO_ORDER* langBarInfo,
wStream* s)
{
RailClientContext* context = rail_get_client_interface(rail);
UINT error;
if (!context || !langBarInfo)
return ERROR_INVALID_PARAMETER;
if ((error = rail_read_langbar_info_order(s, langBarInfo)))
{
WLog_ERR(TAG, "rail_read_langbar_info_order failed with error %"PRIu32"!", error);
@ -624,6 +725,9 @@ UINT rail_order_recv(railPlugin* rail, wStream* s)
UINT16 orderLength;
UINT error;
if (!rail || !s)
return ERROR_INVALID_PARAMETER;
if ((error = rail_read_pdu_header(s, &orderType, &orderLength)))
{
WLog_ERR(TAG, "rail_read_pdu_header failed with error %"PRIu32"!", error);
@ -688,7 +792,6 @@ UINT rail_order_recv(railPlugin* rail, wStream* s)
default:
WLog_ERR(TAG, "Unknown RAIL PDU order reveived.");
return ERROR_INVALID_DATA;
break;
}
return CHANNEL_RC_OK;
@ -703,6 +806,10 @@ UINT rail_send_handshake_order(railPlugin* rail, RAIL_HANDSHAKE_ORDER* handshake
{
wStream* s;
UINT error;
if (!rail || !handshake)
return ERROR_INVALID_PARAMETER;
s = rail_pdu_init(RAIL_HANDSHAKE_ORDER_LENGTH);
if (!s)
@ -726,6 +833,10 @@ UINT rail_send_handshake_ex_order(railPlugin* rail, RAIL_HANDSHAKE_EX_ORDER* han
{
wStream* s;
UINT error;
if (!rail || !handshakeEx)
return ERROR_INVALID_PARAMETER;
s = rail_pdu_init(RAIL_HANDSHAKE_EX_ORDER_LENGTH);
if (!s)
@ -749,6 +860,10 @@ UINT rail_send_client_status_order(railPlugin* rail, RAIL_CLIENT_STATUS_ORDER* c
{
wStream* s;
UINT error;
if (!rail || !clientStatus)
return ERROR_INVALID_PARAMETER;
s = rail_pdu_init(RAIL_CLIENT_STATUS_ORDER_LENGTH);
if (!s)
@ -757,8 +872,11 @@ UINT rail_send_client_status_order(railPlugin* rail, RAIL_CLIENT_STATUS_ORDER* c
return CHANNEL_RC_NO_MEMORY;
}
rail_write_client_status_order(s, clientStatus);
error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_CLIENTSTATUS);
error = rail_write_client_status_order(s, clientStatus);
if (error == ERROR_SUCCESS)
error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_CLIENTSTATUS);
Stream_Free(s, TRUE);
return error;
}
@ -773,6 +891,10 @@ UINT rail_send_client_exec_order(railPlugin* rail, RAIL_EXEC_ORDER* exec)
wStream* s;
UINT error;
size_t length;
if (!rail || !exec)
return ERROR_INVALID_PARAMETER;
length = RAIL_EXEC_ORDER_LENGTH +
exec->exeOrFile.length +
exec->workingDir.length +
@ -806,12 +928,14 @@ UINT rail_send_client_exec_order(railPlugin* rail, RAIL_EXEC_ORDER* exec)
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT rail_send_client_sysparam_order(railPlugin* rail, RAIL_SYSPARAM_ORDER* sysparam)
static UINT rail_send_client_sysparam_order(railPlugin* rail, RAIL_SYSPARAM_ORDER* sysparam)
{
wStream* s;
int length;
size_t length = RAIL_SYSPARAM_ORDER_LENGTH;
UINT error;
length = RAIL_SYSPARAM_ORDER_LENGTH;
if (!rail || !sysparam)
return ERROR_INVALID_PARAMETER;
switch (sysparam->param)
{
@ -866,10 +990,13 @@ UINT rail_send_client_sysparam_order(railPlugin* rail, RAIL_SYSPARAM_ORDER* sysp
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT rail_send_client_sysparams_order(railPlugin* rail, RAIL_SYSPARAM_ORDER* sysparam)
static UINT rail_send_client_sysparams_order(railPlugin* rail, RAIL_SYSPARAM_ORDER* sysparam)
{
UINT error = CHANNEL_RC_OK;
if (!rail || !sysparam)
return ERROR_INVALID_PARAMETER;
if (sysparam->params & SPI_MASK_SET_HIGH_CONTRAST)
{
sysparam->param = SPI_SET_HIGH_CONTRAST;
@ -959,6 +1086,10 @@ UINT rail_send_client_activate_order(railPlugin* rail, RAIL_ACTIVATE_ORDER* acti
{
wStream* s;
UINT error;
if (!rail || !activate)
return ERROR_INVALID_PARAMETER;
s = rail_pdu_init(RAIL_ACTIVATE_ORDER_LENGTH);
if (!s)
@ -967,8 +1098,11 @@ UINT rail_send_client_activate_order(railPlugin* rail, RAIL_ACTIVATE_ORDER* acti
return CHANNEL_RC_NO_MEMORY;
}
rail_write_client_activate_order(s, activate);
error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_ACTIVATE);
error = rail_write_client_activate_order(s, activate);
if (error == ERROR_SUCCESS)
error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_ACTIVATE);
Stream_Free(s, TRUE);
return error;
}
@ -982,6 +1116,10 @@ UINT rail_send_client_sysmenu_order(railPlugin* rail, RAIL_SYSMENU_ORDER* sysmen
{
wStream* s;
UINT error;
if (!rail || !sysmenu)
return ERROR_INVALID_PARAMETER;
s = rail_pdu_init(RAIL_SYSMENU_ORDER_LENGTH);
if (!s)
@ -990,8 +1128,11 @@ UINT rail_send_client_sysmenu_order(railPlugin* rail, RAIL_SYSMENU_ORDER* sysmen
return CHANNEL_RC_NO_MEMORY;
}
rail_write_client_sysmenu_order(s, sysmenu);
error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_SYSMENU);
error = rail_write_client_sysmenu_order(s, sysmenu);
if (error == ERROR_SUCCESS)
error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_SYSMENU);
Stream_Free(s, TRUE);
return error;
}
@ -1005,6 +1146,10 @@ UINT rail_send_client_syscommand_order(railPlugin* rail, RAIL_SYSCOMMAND_ORDER*
{
wStream* s;
UINT error;
if (!rail || !syscommand)
return ERROR_INVALID_PARAMETER;
s = rail_pdu_init(RAIL_SYSCOMMAND_ORDER_LENGTH);
if (!s)
@ -1013,8 +1158,11 @@ UINT rail_send_client_syscommand_order(railPlugin* rail, RAIL_SYSCOMMAND_ORDER*
return CHANNEL_RC_NO_MEMORY;
}
rail_write_client_syscommand_order(s, syscommand);
error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_SYSCOMMAND);
error = rail_write_client_syscommand_order(s, syscommand);
if (error == ERROR_SUCCESS)
error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_SYSCOMMAND);
Stream_Free(s, TRUE);
return error;
}
@ -1028,6 +1176,10 @@ UINT rail_send_client_notify_event_order(railPlugin* rail, RAIL_NOTIFY_EVENT_ORD
{
wStream* s;
UINT error;
if (!rail || !notifyEvent)
return ERROR_INVALID_PARAMETER;
s = rail_pdu_init(RAIL_NOTIFY_EVENT_ORDER_LENGTH);
if (!s)
@ -1036,8 +1188,11 @@ UINT rail_send_client_notify_event_order(railPlugin* rail, RAIL_NOTIFY_EVENT_ORD
return CHANNEL_RC_NO_MEMORY;
}
rail_write_client_notify_event_order(s, notifyEvent);
error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_NOTIFY_EVENT);
error = rail_write_client_notify_event_order(s, notifyEvent);
if (ERROR_SUCCESS == error)
error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_NOTIFY_EVENT);
Stream_Free(s, TRUE);
return error;
}
@ -1051,6 +1206,10 @@ UINT rail_send_client_window_move_order(railPlugin* rail, RAIL_WINDOW_MOVE_ORDER
{
wStream* s;
UINT error;
if (!rail || !windowMove)
return ERROR_INVALID_PARAMETER;
s = rail_pdu_init(RAIL_WINDOW_MOVE_ORDER_LENGTH);
if (!s)
@ -1059,8 +1218,11 @@ UINT rail_send_client_window_move_order(railPlugin* rail, RAIL_WINDOW_MOVE_ORDER
return CHANNEL_RC_NO_MEMORY;
}
rail_write_client_window_move_order(s, windowMove);
error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_WINDOWMOVE);
error = rail_write_client_window_move_order(s, windowMove);
if (error == ERROR_SUCCESS)
error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_WINDOWMOVE);
Stream_Free(s, TRUE);
return error;
}
@ -1074,6 +1236,10 @@ UINT rail_send_client_get_appid_req_order(railPlugin* rail, RAIL_GET_APPID_REQ_O
{
wStream* s;
UINT error;
if (!rail || !getAppIdReq)
return ERROR_INVALID_PARAMETER;
s = rail_pdu_init(RAIL_GET_APPID_REQ_ORDER_LENGTH);
if (!s)
@ -1082,8 +1248,11 @@ UINT rail_send_client_get_appid_req_order(railPlugin* rail, RAIL_GET_APPID_REQ_O
return CHANNEL_RC_NO_MEMORY;
}
rail_write_client_get_appid_req_order(s, getAppIdReq);
error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_GET_APPID_REQ);
error = rail_write_client_get_appid_req_order(s, getAppIdReq);
if (error == ERROR_SUCCESS)
error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_GET_APPID_REQ);
Stream_Free(s, TRUE);
return error;
}
@ -1097,6 +1266,10 @@ UINT rail_send_client_langbar_info_order(railPlugin* rail, RAIL_LANGBAR_INFO_ORD
{
wStream* s;
UINT error;
if (!rail || !langBarInfo)
return ERROR_INVALID_PARAMETER;
s = rail_pdu_init(RAIL_LANGBAR_INFO_ORDER_LENGTH);
if (!s)
@ -1105,8 +1278,11 @@ UINT rail_send_client_langbar_info_order(railPlugin* rail, RAIL_LANGBAR_INFO_ORD
return CHANNEL_RC_NO_MEMORY;
}
rail_write_langbar_info_order(s, langBarInfo);
error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_LANGBARINFO);
error = rail_write_langbar_info_order(s, langBarInfo);
if (ERROR_SUCCESS == error)
error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_LANGBARINFO);
Stream_Free(s, TRUE);
return error;
}

View File

@ -29,23 +29,7 @@
#define TAG CHANNELS_TAG("rail.client")
UINT rail_read_server_exec_result_order(wStream* s, RAIL_EXEC_RESULT_ORDER* exec_result);
UINT rail_read_server_sysparam_order(wStream* s, RAIL_SYSPARAM_ORDER* sysparam);
UINT rail_read_server_minmaxinfo_order(wStream* s, RAIL_MINMAXINFO_ORDER* minmaxinfo);
UINT rail_read_server_localmovesize_order(wStream* s, RAIL_LOCALMOVESIZE_ORDER* localmovesize);
UINT rail_read_server_get_appid_resp_order(wStream* s, RAIL_GET_APPID_RESP_ORDER* get_appid_resp);
UINT rail_read_langbar_info_order(wStream* s, RAIL_LANGBAR_INFO_ORDER* langbar_info);
void rail_write_client_status_order(wStream* s, RAIL_CLIENT_STATUS_ORDER* client_status);
UINT rail_write_client_exec_order(wStream* s, RAIL_EXEC_ORDER* exec);
UINT rail_write_client_sysparam_order(wStream* s, RAIL_SYSPARAM_ORDER* sysparam);
void rail_write_client_activate_order(wStream* s, RAIL_ACTIVATE_ORDER* activate);
void rail_write_client_sysmenu_order(wStream* s, RAIL_SYSMENU_ORDER* sysmenu);
void rail_write_client_syscommand_order(wStream* s, RAIL_SYSCOMMAND_ORDER* syscommand);
void rail_write_client_notify_event_order(wStream* s, RAIL_NOTIFY_EVENT_ORDER* notify_event);
void rail_write_client_window_move_order(wStream* s, RAIL_WINDOW_MOVE_ORDER* window_move);
void rail_write_client_get_appid_req_order(wStream* s, RAIL_GET_APPID_REQ_ORDER* get_appid_req);
void rail_write_langbar_info_order(wStream* s, RAIL_LANGBAR_INFO_ORDER* langbar_info);
UINT rail_order_recv(railPlugin* rail, wStream* s);
UINT rail_send_pdu(railPlugin* rail, wStream* s, UINT16 orderType);
@ -54,11 +38,10 @@ UINT rail_send_handshake_order(railPlugin* rail, RAIL_HANDSHAKE_ORDER* handshake
UINT rail_send_handshake_ex_order(railPlugin* rail, RAIL_HANDSHAKE_EX_ORDER* handshakeEx);
UINT rail_send_client_status_order(railPlugin* rail, RAIL_CLIENT_STATUS_ORDER* clientStatus);
UINT rail_send_client_exec_order(railPlugin* rail, RAIL_EXEC_ORDER* exec);
UINT rail_send_client_sysparam_order(railPlugin* rail, RAIL_SYSPARAM_ORDER* sysparam);
UINT rail_send_client_sysparams_order(railPlugin* rail, RAIL_SYSPARAM_ORDER* sysparam);
UINT rail_send_client_activate_order(railPlugin* rail, RAIL_ACTIVATE_ORDER* activate);
UINT rail_send_client_sysmenu_order(railPlugin* rail, RAIL_SYSMENU_ORDER* sysmenu);
UINT rail_send_client_syscommand_order(railPlugin* rail, RAIL_SYSCOMMAND_ORDER* syscommand);
UINT rail_send_client_notify_event_order(railPlugin* rail, RAIL_NOTIFY_EVENT_ORDER* notifyEvent);
UINT rail_send_client_window_move_order(railPlugin* rail, RAIL_WINDOW_MOVE_ORDER* windowMove);
UINT rail_send_client_get_appid_req_order(railPlugin* rail, RAIL_GET_APPID_REQ_ORDER* getAppIdReq);

View File

@ -55,9 +55,7 @@ void rail_string_to_unicode_string(char* string, RAIL_UNICODE_STRING* unicode_st
{
WCHAR* buffer = NULL;
int length = 0;
free(unicode_string->string);
unicode_string->string = NULL;
unicode_string->length = 0;
@ -65,7 +63,6 @@ void rail_string_to_unicode_string(char* string, RAIL_UNICODE_STRING* unicode_st
return;
length = ConvertToUnicode(CP_UTF8, 0, string, -1, &buffer, 0) * 2;
unicode_string->string = (BYTE*) buffer;
unicode_string->length = (UINT16) length;
}
@ -77,12 +74,14 @@ void rail_string_to_unicode_string(char* string, RAIL_UNICODE_STRING* unicode_st
*/
UINT rail_read_pdu_header(wStream* s, UINT16* orderType, UINT16* orderLength)
{
if (!s || !orderType || !orderLength)
return ERROR_INVALID_PARAMETER;
if (Stream_GetRemainingLength(s) < 4)
return ERROR_INVALID_DATA;
Stream_Read_UINT16(s, *orderType); /* orderType (2 bytes) */
Stream_Read_UINT16(s, *orderLength); /* orderLength (2 bytes) */
return CHANNEL_RC_OK;
}
@ -96,8 +95,10 @@ wStream* rail_pdu_init(size_t length)
{
wStream* s;
s = Stream_New(NULL, length + RAIL_PDU_HEADER_LENGTH);
if (!s)
return NULL;
Stream_Seek(s, RAIL_PDU_HEADER_LENGTH);
return s;
}
@ -113,7 +114,6 @@ UINT rail_read_handshake_order(wStream* s, RAIL_HANDSHAKE_ORDER* handshake)
return ERROR_INVALID_DATA;
Stream_Read_UINT32(s, handshake->buildNumber); /* buildNumber (4 bytes) */
return CHANNEL_RC_OK;
}
@ -134,7 +134,6 @@ UINT rail_read_handshake_ex_order(wStream* s, RAIL_HANDSHAKE_EX_ORDER* handshake
Stream_Read_UINT32(s, handshakeEx->buildNumber); /* buildNumber (4 bytes) */
Stream_Read_UINT32(s, handshakeEx->railHandshakeFlags); /* railHandshakeFlags (4 bytes) */
return CHANNEL_RC_OK;
}

View File

@ -59,13 +59,13 @@ static UINT irp_free(IRP* irp)
*/
static UINT irp_complete(IRP* irp)
{
int pos;
size_t pos;
rdpdrPlugin* rdpdr;
UINT error;
rdpdr = (rdpdrPlugin*) irp->devman->plugin;
pos = (int) Stream_GetPosition(irp->output);
pos = Stream_GetPosition(irp->output);
Stream_SetPosition(irp->output, RDPDR_DEVICE_IO_RESPONSE_LENGTH - 4);
Stream_Write_UINT32(irp->output, irp->IoStatus); /* IoStatus (4 bytes) */
Stream_SetPosition(irp->output, pos);

View File

@ -118,9 +118,9 @@ void first_hotplug(rdpdrPlugin* rdpdr)
{
}
static void* drive_hotplug_thread_func(void* arg)
static DWORD WINAPI drive_hotplug_thread_func(LPVOID arg)
{
return NULL;
return CHANNEL_RC_OK;
}
static UINT drive_hotplug_thread_terminate(rdpdrPlugin* rdpdr)
@ -280,7 +280,7 @@ LRESULT CALLBACK hotplug_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
return DefWindowProc(hWnd, Msg, wParam, lParam);
}
static void* drive_hotplug_thread_func(void* arg)
static DWORD WINAPI drive_hotplug_thread_func(LPVOID arg)
{
rdpdrPlugin* rdpdr;
WNDCLASSEX wnd_cls;
@ -331,7 +331,7 @@ static void* drive_hotplug_thread_func(void* arg)
}
UnregisterDeviceNotification(hDevNotify);
return NULL;
return CHANNEL_RC_OK;
}
/**
@ -420,6 +420,7 @@ static UINT handle_hotplug(rdpdrPlugin* rdpdr)
for (j = 0; j < count; j++)
{
char* path = NULL;
BOOL dev_found = FALSE;
device_ext = (DEVICE_DRIVE_EXT*)ListDictionary_GetItemValue(
rdpdr->devman->devices, (void*)keys[j]);
@ -430,13 +431,19 @@ static UINT handle_hotplug(rdpdrPlugin* rdpdr)
if (device_ext->path == NULL)
continue;
/* not plugable device */
if (strstr(device_ext->path, "/Volumes/") == NULL)
if (ConvertFromUnicode(CP_UTF8, 0, device_ext->path, 0, &path, 0, NULL, FALSE) <= 0)
continue;
/* not plugable device */
if (strstr(path, "/Volumes/") == NULL)
{
free(path);
continue;
}
for (i = 0; i < size; i++)
{
if (strstr(device_ext->path, dev_array[i].path) != NULL)
if (strstr(path, dev_array[i].path) != NULL)
{
dev_found = TRUE;
dev_array[i].to_add = FALSE;
@ -444,6 +451,8 @@ static UINT handle_hotplug(rdpdrPlugin* rdpdr)
}
}
free(path);
if (!dev_found)
{
devman_unregister_device(rdpdr->devman, (void*)keys[j]);
@ -549,7 +558,7 @@ void first_hotplug(rdpdrPlugin* rdpdr)
}
}
static void* drive_hotplug_thread_func(void* arg)
static DWORD WINAPI drive_hotplug_thread_func(LPVOID arg)
{
rdpdrPlugin* rdpdr;
FSEventStreamRef fsev;
@ -570,7 +579,7 @@ static void* drive_hotplug_thread_func(void* arg)
FSEventStreamStop(fsev);
FSEventStreamRelease(fsev);
ExitThread(CHANNEL_RC_OK);
return NULL;
return CHANNEL_RC_OK;
}
@ -914,7 +923,7 @@ static void first_hotplug(rdpdrPlugin* rdpdr)
}
}
static void* drive_hotplug_thread_func(void* arg)
static DWORD WINAPI drive_hotplug_thread_func(LPVOID arg)
{
rdpdrPlugin* rdpdr;
int mfd;
@ -985,8 +994,8 @@ out:
"drive_hotplug_thread_func reported an error");
CloseHandle(rdpdr->stopEvent);
ExitThread((DWORD)error);
return NULL;
ExitThread(error);
return error;
}
/**
@ -1051,18 +1060,23 @@ static UINT rdpdr_process_connect(rdpdrPlugin* rdpdr)
{
device = settings->DeviceArray[index];
if (device->Name && (strcmp(device->Name, "*") == 0))
if (device->Type == RDPDR_DTYP_FILESYSTEM)
{
first_hotplug(rdpdr);
RDPDR_DRIVE* drive = (RDPDR_DRIVE*)device;
if (!(rdpdr->hotplugThread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) drive_hotplug_thread_func, rdpdr, 0, NULL)))
if (drive->Path && (strcmp(drive->Path, "*") == 0))
{
WLog_ERR(TAG, "CreateThread failed!");
return ERROR_INTERNAL_ERROR;
}
first_hotplug(rdpdr);
continue;
if (!(rdpdr->hotplugThread = CreateThread(NULL, 0,
drive_hotplug_thread_func, rdpdr, 0, NULL)))
{
WLog_ERR(TAG, "CreateThread failed!");
return ERROR_INTERNAL_ERROR;
}
continue;
}
}
if ((error = devman_load_device_service(rdpdr->devman, device,
@ -1185,12 +1199,12 @@ static UINT rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr,
{
int i;
BYTE c;
int pos;
size_t pos;
int index;
wStream* s;
UINT32 count;
int data_len;
int count_pos;
size_t data_len;
size_t count_pos;
DEVICE* device;
int keyCount;
ULONG_PTR* pKeys;
@ -1204,7 +1218,7 @@ static UINT rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr,
Stream_Write_UINT16(s, RDPDR_CTYP_CORE); /* Component (2 bytes) */
Stream_Write_UINT16(s, PAKID_CORE_DEVICELIST_ANNOUNCE); /* PacketId (2 bytes) */
count_pos = (int) Stream_GetPosition(s);
count_pos = Stream_GetPosition(s);
count = 0;
Stream_Seek_UINT32(s); /* deviceCount */
pKeys = NULL;
@ -1225,7 +1239,7 @@ static UINT rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr,
if ((rdpdr->versionMinor == 0x0005) ||
(device->type == RDPDR_DTYP_SMARTCARD) || userLoggedOn)
{
data_len = (int)(device->data == NULL ? 0 : Stream_GetPosition(device->data));
data_len = (device->data == NULL ? 0 : Stream_GetPosition(device->data));
if (!Stream_EnsureRemainingCapacity(s, 20 + data_len))
{
@ -1259,7 +1273,7 @@ static UINT rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr,
}
free(pKeys);
pos = (int) Stream_GetPosition(s);
pos = Stream_GetPosition(s);
Stream_SetPosition(s, count_pos);
Stream_Write_UINT32(s, count);
Stream_SetPosition(s, pos);
@ -1609,7 +1623,7 @@ static VOID VCAPITYPE rdpdr_virtual_channel_open_event_ex(LPVOID lpUserParam, DW
return;
}
static void* rdpdr_virtual_channel_client_thread(void* arg)
static DWORD WINAPI rdpdr_virtual_channel_client_thread(LPVOID arg)
{
wStream* data;
wMessage message;
@ -1619,7 +1633,7 @@ static void* rdpdr_virtual_channel_client_thread(void* arg)
if (!rdpdr)
{
ExitThread((DWORD) CHANNEL_RC_NULL_DATA);
return NULL;
return CHANNEL_RC_NULL_DATA;
}
if ((error = rdpdr_process_connect(rdpdr)))
@ -1630,8 +1644,8 @@ static void* rdpdr_virtual_channel_client_thread(void* arg)
setChannelError(rdpdr->rdpcontext, error,
"rdpdr_virtual_channel_client_thread reported an error");
ExitThread((DWORD) error);
return NULL;
ExitThread(error);
return error;
}
while (1)
@ -1657,14 +1671,14 @@ static void* rdpdr_virtual_channel_client_thread(void* arg)
"rdpdr_virtual_channel_client_thread reported an error");
ExitThread((DWORD) error);
return NULL;
return error;
}
}
}
}
ExitThread(0);
return NULL;
return 0;
}
/**
@ -1695,7 +1709,7 @@ static UINT rdpdr_virtual_channel_event_connected(rdpdrPlugin* rdpdr,
}
if (!(rdpdr->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) rdpdr_virtual_channel_client_thread, (void*) rdpdr, 0,
rdpdr_virtual_channel_client_thread, (void*) rdpdr, 0,
NULL)))
{
WLog_ERR(TAG, "CreateThread failed!");

View File

@ -149,12 +149,9 @@ static UINT rdpdr_server_receive_client_name_request(RdpdrServerContext*
Stream_Read_UINT32(s, UnicodeFlag); /* UnicodeFlag (4 bytes) */
Stream_Seek_UINT32(s); /* CodePage (4 bytes), MUST be set to zero */
Stream_Read_UINT32(s, ComputerNameLen); /* ComputerNameLen (4 bytes) */
if (UnicodeFlag > 1) /* must be 0x00000000 or 0x00000001 */
{
WLog_ERR(TAG, "invalid UnicodeFlag value: 0x%08"PRIX32"", UnicodeFlag);
return ERROR_INVALID_DATA;
}
/* UnicodeFlag is either 0 or 1, the other 31 bits must be ignored.
*/
UnicodeFlag = UnicodeFlag & 0x00000001;
/**
* Caution: ComputerNameLen is given *bytes*,
@ -768,7 +765,6 @@ static UINT rdpdr_server_receive_device_list_announce_request(
UINT32 DeviceId;
char PreferredDosName[9];
UINT32 DeviceDataLength;
BYTE* DeviceData;
if (Stream_GetRemainingLength(s) < 4)
{
@ -800,7 +796,6 @@ static UINT rdpdr_server_receive_device_list_announce_request(
return ERROR_INVALID_DATA;
}
DeviceData = Stream_Pointer(s);
WLog_DBG(TAG, "Device %d Name: %s Id: 0x%08"PRIX32" DataLength: %"PRIu32"",
i, PreferredDosName, DeviceId, DeviceDataLength);
@ -1134,7 +1129,7 @@ static UINT rdpdr_server_receive_pdu(RdpdrServerContext* context, wStream* s,
return error;
}
static void* rdpdr_server_thread(void* arg)
static DWORD WINAPI rdpdr_server_thread(LPVOID arg)
{
wStream* s;
DWORD status;
@ -1150,7 +1145,6 @@ static void* rdpdr_server_thread(void* arg)
buffer = NULL;
BytesReturned = 0;
ChannelEvent = NULL;
s = Stream_New(NULL, 4096);
if (!s)
@ -1239,8 +1233,8 @@ out:
setChannelError(context->rdpcontext, error,
"rdpdr_server_thread reported an error");
ExitThread((DWORD) error);
return NULL;
ExitThread(error);
return error;
}
/**
@ -1266,7 +1260,7 @@ static UINT rdpdr_server_start(RdpdrServerContext* context)
}
if (!(context->priv->Thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) rdpdr_server_thread, (void*) context, 0, NULL)))
rdpdr_server_thread, (void*) context, 0, NULL)))
{
WLog_ERR(TAG, "CreateThread failed!");
CloseHandle(context->priv->StopEvent);

View File

@ -169,7 +169,7 @@ UINT rdpei_add_frame(RdpeiClientContext* context)
return CHANNEL_RC_OK;
}
static void* rdpei_schedule_thread(void* arg)
static DWORD WINAPI rdpei_schedule_thread(LPVOID arg)
{
DWORD status;
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) arg;
@ -228,12 +228,12 @@ static void* rdpei_schedule_thread(void* arg)
out:
if (error && rdpei->rdpcontext)
if (error && rdpei && rdpei->rdpcontext)
setChannelError(rdpei->rdpcontext, error,
"rdpei_schedule_thread reported an error");
ExitThread(0);
return NULL;
ExitThread(error);
return error;
}
/**
@ -653,7 +653,7 @@ static UINT rdpei_plugin_initialize(IWTSPlugin* pPlugin,
goto error_out;
}
if (!(rdpei->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)
if (!(rdpei->thread = CreateThread(NULL, 0,
rdpei_schedule_thread, (void*) rdpei, 0, NULL)))
{
WLog_ERR(TAG, "CreateThread failed!");

View File

@ -139,8 +139,8 @@ static UINT rdpgfx_decode_AVC420(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd
wStream* s;
RDPGFX_AVC420_BITMAP_STREAM h264;
RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface;
s = Stream_New(cmd->data, cmd->length);
s = Stream_New(cmd->data, cmd->length);
if (!s)
{
WLog_ERR(TAG, "Stream_New failed!");
@ -186,7 +186,6 @@ static UINT rdpgfx_decode_AVC444(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd
RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface;
s = Stream_New(cmd->data, cmd->length);
if (!s)
{
WLog_ERR(TAG, "Stream_New failed!");
@ -275,7 +274,7 @@ UINT rdpgfx_decode(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd)
{
UINT error = CHANNEL_RC_OK;
RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface;
PROFILER_ENTER(context->SurfaceProfiler);
PROFILER_ENTER(context->SurfaceProfiler)
switch (cmd->codecId)
{
@ -304,6 +303,6 @@ UINT rdpgfx_decode(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd)
break;
}
PROFILER_EXIT(context->SurfaceProfiler);
PROFILER_EXIT(context->SurfaceProfiler)
return error;
}

View File

@ -74,7 +74,10 @@ static UINT rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback)
if (gfx->ThinClient)
capsSet->flags |= RDPGFX_CAPS_FLAG_THINCLIENT;
if (gfx->SmallCache)
/* in CAPVERSION_8 the spec says that we should not have both
* thinclient and smallcache (and thinclient implies a small cache)
*/
if (gfx->SmallCache && !gfx->ThinClient)
capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE;
capsSet = &capsSets[pdu.capsSetCount++];
@ -92,27 +95,29 @@ static UINT rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback)
capsSet->flags |= RDPGFX_CAPS_FLAG_AVC420_ENABLED;
#endif
capsSet = &capsSets[pdu.capsSetCount++];
capsSet->version = RDPGFX_CAPVERSION_10;
capsSet->flags = 0;
if (!gfx->H264 || gfx->AVC444)
{
capsSet = &capsSets[pdu.capsSetCount++];
capsSet->version = RDPGFX_CAPVERSION_10;
capsSet->flags = 0;
if (gfx->SmallCache)
capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE;
if (gfx->SmallCache)
capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE;
#ifdef WITH_GFX_H264
if (!gfx->AVC444)
capsSet->flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED;
if (!gfx->AVC444)
capsSet->flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED;
#else
capsSet->flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED;
capsSet->flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED;
#endif
capsSets[pdu.capsSetCount] = *capsSet;
capsSets[pdu.capsSetCount++].version = RDPGFX_CAPVERSION_102;
capsSets[pdu.capsSetCount] = *capsSet;
capsSets[pdu.capsSetCount++].version = RDPGFX_CAPVERSION_103;
capsSets[pdu.capsSetCount] = *capsSet;
capsSets[pdu.capsSetCount++].version = RDPGFX_CAPVERSION_102;
capsSets[pdu.capsSetCount] = *capsSet;
capsSets[pdu.capsSetCount++].version = RDPGFX_CAPVERSION_103;
}
header.pduLength = RDPGFX_HEADER_SIZE + 2 + (pdu.capsSetCount *
RDPGFX_CAPSET_SIZE);
header.pduLength = RDPGFX_HEADER_SIZE + 2 + (pdu.capsSetCount * RDPGFX_CAPSET_SIZE);
WLog_Print(gfx->log, WLOG_DEBUG, "SendCapsAdvertisePdu %"PRIu16"", pdu.capsSetCount);
s = Stream_New(NULL, header.pduLength);
@ -193,8 +198,8 @@ static UINT rdpgfx_send_frame_acknowledge_pdu(RDPGFX_CHANNEL_CALLBACK* callback,
header.cmdId = RDPGFX_CMDID_FRAMEACKNOWLEDGE;
header.pduLength = RDPGFX_HEADER_SIZE + 12;
WLog_Print(gfx->log, WLOG_DEBUG, "SendFrameAcknowledgePdu: %"PRIu32"", pdu->frameId);
s = Stream_New(NULL, header.pduLength);
s = Stream_New(NULL, header.pduLength);
if (!s)
{
WLog_ERR(TAG, "Stream_New failed!");
@ -228,8 +233,8 @@ static UINT rdpgfx_send_qoe_frame_acknowledge_pdu(RDPGFX_CHANNEL_CALLBACK* callb
header.cmdId = RDPGFX_CMDID_QOEFRAMEACKNOWLEDGE;
header.pduLength = RDPGFX_HEADER_SIZE + 12;
WLog_Print(gfx->log, WLOG_DEBUG, "SendQoeFrameAcknowledgePdu: %"PRIu32"", pdu->frameId);
s = Stream_New(NULL, header.pduLength);
s = Stream_New(NULL, header.pduLength);
if (!s)
{
WLog_ERR(TAG, "Stream_New failed!");
@ -267,6 +272,7 @@ static UINT rdpgfx_recv_reset_graphics_pdu(RDPGFX_CHANNEL_CALLBACK* callback,
RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin;
RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface;
UINT error = CHANNEL_RC_OK;
GraphicsResetEventArgs graphicsReset;
if (Stream_GetRemainingLength(s) < 12)
{
@ -284,9 +290,7 @@ static UINT rdpgfx_recv_reset_graphics_pdu(RDPGFX_CHANNEL_CALLBACK* callback,
return ERROR_INVALID_DATA;
}
pdu.monitorDefArray = (MONITOR_DEF*) calloc(pdu.monitorCount,
sizeof(MONITOR_DEF));
pdu.monitorDefArray = (MONITOR_DEF*) calloc(pdu.monitorCount, sizeof(MONITOR_DEF));
if (!pdu.monitorDefArray)
{
WLog_Print(gfx->log, WLOG_ERROR, "calloc failed!");
@ -332,6 +336,12 @@ static UINT rdpgfx_recv_reset_graphics_pdu(RDPGFX_CHANNEL_CALLBACK* callback,
WLog_Print(gfx->log, WLOG_ERROR, "context->ResetGraphics failed with error %"PRIu32"", error);
}
/* some listeners may be interested (namely the display channel) */
EventArgsInit(&graphicsReset, "xfreerdp");
graphicsReset.width = pdu.width;
graphicsReset.height = pdu.height;
PubSub_OnGraphicsReset(gfx->rdpcontext->pubSub, gfx->rdpcontext, &graphicsReset);
free(pdu.monitorDefArray);
return error;
}
@ -398,7 +408,6 @@ static UINT rdpgfx_recv_cache_import_reply_pdu(RDPGFX_CHANNEL_CALLBACK* callback
}
pdu.cacheSlots = (UINT16*) calloc(pdu.importedEntriesCount, sizeof(UINT16));
if (!pdu.cacheSlots)
{
WLog_Print(gfx->log, WLOG_ERROR, "calloc failed!");
@ -810,8 +819,7 @@ static UINT rdpgfx_recv_solid_fill_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStrea
Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */
if ((error = rdpgfx_read_color32(s,
&(pdu.fillPixel)))) /* fillPixel (4 bytes) */
if ((error = rdpgfx_read_color32(s, &(pdu.fillPixel)))) /* fillPixel (4 bytes) */
{
WLog_Print(gfx->log, WLOG_ERROR, "rdpgfx_read_color32 failed with error %"PRIu32"!", error);
return error;
@ -826,7 +834,6 @@ static UINT rdpgfx_recv_solid_fill_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStrea
}
pdu.fillRects = (RECTANGLE_16*) calloc(pdu.fillRectCount, sizeof(RECTANGLE_16));
if (!pdu.fillRects)
{
WLog_Print(gfx->log, WLOG_ERROR, "calloc failed!");
@ -898,9 +905,7 @@ static UINT rdpgfx_recv_surface_to_surface_pdu(RDPGFX_CHANNEL_CALLBACK*
return ERROR_INVALID_DATA;
}
pdu.destPts = (RDPGFX_POINT16*) calloc(pdu.destPtsCount,
sizeof(RDPGFX_POINT16));
pdu.destPts = (RDPGFX_POINT16*) calloc(pdu.destPtsCount, sizeof(RDPGFX_POINT16));
if (!pdu.destPts)
{
WLog_Print(gfx->log, WLOG_ERROR, "calloc failed!");
@ -1015,9 +1020,7 @@ static UINT rdpgfx_recv_cache_to_surface_pdu(RDPGFX_CHANNEL_CALLBACK* callback,
return ERROR_INVALID_DATA;
}
pdu.destPts = (RDPGFX_POINT16*) calloc(pdu.destPtsCount,
sizeof(RDPGFX_POINT16));
pdu.destPts = (RDPGFX_POINT16*) calloc(pdu.destPtsCount, sizeof(RDPGFX_POINT16));
if (!pdu.destPts)
{
WLog_Print(gfx->log, WLOG_ERROR, "calloc failed!");
@ -1135,7 +1138,7 @@ static UINT rdpgfx_recv_map_surface_to_window_pdu(RDPGFX_CHANNEL_CALLBACK* callb
*/
static UINT rdpgfx_recv_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s)
{
int beg, end;
size_t beg, end;
RDPGFX_HEADER header;
UINT error;
RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin;
@ -1148,11 +1151,9 @@ static UINT rdpgfx_recv_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s)
return error;
}
#if 1
WLog_Print(gfx->log, WLOG_DEBUG, "cmdId: %s (0x%04"PRIX16") flags: 0x%04"PRIX16" pduLength: %"PRIu32"",
rdpgfx_get_cmd_id_string(header.cmdId), header.cmdId, header.flags,
header.pduLength);
#endif
switch (header.cmdId)
{
@ -1305,8 +1306,8 @@ static UINT rdpgfx_on_data_received(IWTSVirtualChannelCallback*
RDPGFX_CHANNEL_CALLBACK* callback = (RDPGFX_CHANNEL_CALLBACK*) pChannelCallback;
RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin;
UINT error = CHANNEL_RC_OK;
status = zgfx_decompress(gfx->zgfx, Stream_Pointer(data),
Stream_GetRemainingLength(data), &pDstData, &DstSize, 0);
status = zgfx_decompress(gfx->zgfx, Stream_Pointer(data), Stream_GetRemainingLength(data),
&pDstData, &DstSize, 0);
if (status < 0)
{
@ -1315,7 +1316,6 @@ static UINT rdpgfx_on_data_received(IWTSVirtualChannelCallback*
}
s = Stream_New(pDstData, DstSize);
if (!s)
{
WLog_Print(gfx->log, WLOG_ERROR, "calloc failed!");
@ -1360,6 +1360,7 @@ static UINT rdpgfx_on_close(IWTSVirtualChannelCallback* pChannelCallback)
RDPGFX_CHANNEL_CALLBACK* callback = (RDPGFX_CHANNEL_CALLBACK*) pChannelCallback;
RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin;
RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface;
WLog_Print(gfx->log, WLOG_DEBUG, "OnClose");
free(callback);
gfx->UnacknowledgedFrames = 0;
@ -1419,11 +1420,9 @@ static UINT rdpgfx_on_new_channel_connection(IWTSListenerCallback*
IWTSVirtualChannelCallback** ppCallback)
{
RDPGFX_CHANNEL_CALLBACK* callback;
RDPGFX_LISTENER_CALLBACK* listener_callback = (RDPGFX_LISTENER_CALLBACK*)
pListenerCallback;
callback = (RDPGFX_CHANNEL_CALLBACK*) calloc(1,
sizeof(RDPGFX_CHANNEL_CALLBACK));
RDPGFX_LISTENER_CALLBACK* listener_callback = (RDPGFX_LISTENER_CALLBACK*)pListenerCallback;
callback = (RDPGFX_CHANNEL_CALLBACK*) calloc(1, sizeof(RDPGFX_CHANNEL_CALLBACK));
if (!callback)
{
WLog_ERR(TAG, "calloc failed!");
@ -1451,17 +1450,15 @@ static UINT rdpgfx_plugin_initialize(IWTSPlugin* pPlugin,
{
UINT error;
RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) pPlugin;
gfx->listener_callback = (RDPGFX_LISTENER_CALLBACK*) calloc(1,
sizeof(RDPGFX_LISTENER_CALLBACK));
gfx->listener_callback = (RDPGFX_LISTENER_CALLBACK*) calloc(1, sizeof(RDPGFX_LISTENER_CALLBACK));
if (!gfx->listener_callback)
{
WLog_Print(gfx->log, WLOG_ERROR, "calloc failed!");
return CHANNEL_RC_NO_MEMORY;
}
gfx->listener_callback->iface.OnNewChannelConnection =
rdpgfx_on_new_channel_connection;
gfx->listener_callback->iface.OnNewChannelConnection = rdpgfx_on_new_channel_connection;
gfx->listener_callback->plugin = pPlugin;
gfx->listener_callback->channel_mgr = pChannelMgr;
error = pChannelMgr->CreateListener(pChannelMgr, RDPGFX_DVC_CHANNEL_NAME, 0,
@ -1598,6 +1595,7 @@ static UINT rdpgfx_get_surface_ids(RdpgfxClientContext* context,
if (!pSurfaceIds)
{
WLog_Print(gfx->log, WLOG_ERROR, "calloc failed!");
free(pKeys);
return CHANNEL_RC_NO_MEMORY;
}
@ -1634,7 +1632,11 @@ static UINT rdpgfx_set_cache_slot_data(RdpgfxClientContext* context,
RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) context->handle;
if (cacheSlot >= gfx->MaxCacheSlot)
{
WLog_ERR(TAG, "%s: invalid cache slot %"PRIu16" maxAllowed=%"PRIu16"", __FUNCTION__,
cacheSlot, gfx->MaxCacheSlot);
return ERROR_INVALID_INDEX;
}
gfx->CacheSlots[cacheSlot] = pData;
return CHANNEL_RC_OK;
@ -1646,7 +1648,11 @@ static void* rdpgfx_get_cache_slot_data(RdpgfxClientContext* context, UINT16 cac
RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) context->handle;
if (cacheSlot >= gfx->MaxCacheSlot)
{
WLog_ERR(TAG, "%s: invalid cache slot %"PRIu16" maxAllowed=%"PRIu16"", __FUNCTION__,
cacheSlot, gfx->MaxCacheSlot);
return NULL;
}
pData = gfx->CacheSlots[cacheSlot];
return pData;
@ -1684,7 +1690,7 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
if (!gfx->log)
{
free(gfx);
WLog_ERR(TAG, "Failed to aquire reference to WLog %s", TAG);
WLog_ERR(TAG, "Failed to acquire reference to WLog %s", TAG);
return ERROR_INTERNAL_ERROR;
}
@ -1693,8 +1699,9 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
gfx->iface.Connected = NULL;
gfx->iface.Disconnected = NULL;
gfx->iface.Terminated = rdpgfx_plugin_terminated;
gfx->SurfaceTable = HashTable_New(TRUE);
gfx->rdpcontext = ((freerdp *)gfx->settings->instance)->context;
gfx->SurfaceTable = HashTable_New(TRUE);
if (!gfx->SurfaceTable)
{
free(gfx);
@ -1713,12 +1720,9 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
if (gfx->H264)
gfx->SmallCache = TRUE;
if (gfx->SmallCache)
gfx->ThinClient = FALSE;
gfx->MaxCacheSlot = (gfx->ThinClient) ? 4096 : 25600;
context = (RdpgfxClientContext*) calloc(1, sizeof(RdpgfxClientContext));
gfx->MaxCacheSlot = gfx->SmallCache ? 4096 : 25600;
context = (RdpgfxClientContext *)calloc(1, sizeof(RdpgfxClientContext));
if (!context)
{
free(gfx);

View File

@ -508,6 +508,10 @@ static UINT rdpgfx_write_h264_metablock(wStream* s, RDPGFX_H264_METABLOCK* meta)
RECTANGLE_16* regionRect;
RDPGFX_H264_QUANT_QUALITY* quantQualityVal;
UINT error = CHANNEL_RC_OK;
if (!Stream_EnsureRemainingCapacity(s, 4 + meta->numRegionRects * 10))
return ERROR_OUTOFMEMORY;
Stream_Write_UINT32(s, meta->numRegionRects); /* numRegionRects (4 bytes) */
for (index = 0; index < meta->numRegionRects; index++)
@ -552,6 +556,9 @@ static INLINE UINT rdpgfx_write_h264_avc420(wStream* s,
return error;
}
if (!Stream_EnsureRemainingCapacity(s, havc420->length))
return ERROR_OUTOFMEMORY;
Stream_Write(s, havc420->data, havc420->length);
return error;
}
@ -584,7 +591,7 @@ static UINT rdpgfx_write_surface_command(wStream* s,
break;
default:
WLog_ERR(TAG, "Format %s not supported!", GetColorFormatName(cmd->format));
WLog_ERR(TAG, "Format %s not supported!", FreeRDPGetColorFormatName(cmd->format));
return ERROR_INVALID_DATA;
}
@ -623,12 +630,11 @@ static UINT rdpgfx_write_surface_command(wStream* s,
return error;
}
}
else if (cmd->codecId == RDPGFX_CODECID_AVC444)
else if ((cmd->codecId == RDPGFX_CODECID_AVC444) || (cmd->codecId == RDPGFX_CODECID_AVC444v2))
{
havc444 = (RDPGFX_AVC444_BITMAP_STREAM*)cmd->extra;
havc420 = &(havc444->bitstream[0]);
/* avc420EncodedBitstreamInfo (4 bytes) */
Stream_Write_UINT32(s, havc420->length | (havc444->LC << 30UL));
havc420 = &(havc444->bitstream[0]); /* avc420EncodedBitstreamInfo (4 bytes) */
Stream_Write_UINT32(s, havc444->cbAvc420EncodedBitstream1 | (havc444->LC << 30UL));
/* avc420EncodedBitstream1 */
error = rdpgfx_write_h264_avc420(s, havc420);
@ -641,7 +647,7 @@ static UINT rdpgfx_write_surface_command(wStream* s,
/* avc420EncodedBitstream2 */
if (havc444->LC == 0)
{
havc420 = &(havc444->bitstream[0]);
havc420 = &(havc444->bitstream[1]);
error = rdpgfx_write_h264_avc420(s, havc420);
if (error != CHANNEL_RC_OK)
@ -656,7 +662,6 @@ static UINT rdpgfx_write_surface_command(wStream* s,
Stream_Write(s, cmd->data, cmd->length);
}
assert(Stream_GetPosition(s) <= Stream_Capacity(s));
/* Fill actual bitmap data length */
bitmapDataLength = Stream_GetPosition(s) - bitmapDataStart;
Stream_SetPosition(s, bitmapDataStart - sizeof(UINT32));
@ -1253,7 +1258,7 @@ static UINT rdpgfx_recv_qoe_frame_acknowledge_pdu(RdpgfxServerContext* context,
*/
static UINT rdpgfx_server_receive_pdu(RdpgfxServerContext* context, wStream* s)
{
int beg, end;
size_t beg, end;
RDPGFX_HEADER header;
UINT error = CHANNEL_RC_OK;
beg = Stream_GetPosition(s);
@ -1273,28 +1278,28 @@ static UINT rdpgfx_server_receive_pdu(RdpgfxServerContext* context, wStream* s)
case RDPGFX_CMDID_FRAMEACKNOWLEDGE:
if ((error = rdpgfx_recv_frame_acknowledge_pdu(context, s)))
WLog_ERR(TAG, "rdpgfx_recv_frame_acknowledge_pdu "
"failed with error %"PRIu32"!", error);
"failed with error %"PRIu32"!", error);
break;
case RDPGFX_CMDID_CACHEIMPORTOFFER:
if ((error = rdpgfx_recv_cache_import_offer_pdu(context, s)))
WLog_ERR(TAG, "rdpgfx_recv_cache_import_offer_pdu "
"failed with error %"PRIu32"!", error);
"failed with error %"PRIu32"!", error);
break;
case RDPGFX_CMDID_CAPSADVERTISE:
if ((error = rdpgfx_recv_caps_advertise_pdu(context, s)))
WLog_ERR(TAG, "rdpgfx_recv_caps_advertise_pdu "
"failed with error %"PRIu32"!", error);
"failed with error %"PRIu32"!", error);
break;
case RDPGFX_CMDID_QOEFRAMEACKNOWLEDGE:
if ((error = rdpgfx_recv_qoe_frame_acknowledge_pdu(context, s)))
WLog_ERR(TAG, "rdpgfx_recv_qoe_frame_acknowledge_pdu "
"failed with error %"PRIu32"!", error);
"failed with error %"PRIu32"!", error);
break;
@ -1322,7 +1327,7 @@ static UINT rdpgfx_server_receive_pdu(RdpgfxServerContext* context, wStream* s)
return error;
}
static void* rdpgfx_server_thread_func(void* arg)
static DWORD WINAPI rdpgfx_server_thread_func(LPVOID arg)
{
RdpgfxServerContext* context = (RdpgfxServerContext*) arg;
RdpgfxServerPrivate* priv = context->priv;
@ -1333,7 +1338,6 @@ static void* rdpgfx_server_thread_func(void* arg)
UINT error = CHANNEL_RC_OK;
buffer = NULL;
nCount = 0;
events[nCount++] = priv->stopEvent;
events[nCount++] = priv->channelEvent;
@ -1365,8 +1369,8 @@ static void* rdpgfx_server_thread_func(void* arg)
setChannelError(context->rdpcontext, error,
"rdpgfx_server_thread_func reported an error");
ExitThread((DWORD)error);
return NULL;
ExitThread(error);
return error;
}
static BOOL rdpgfx_server_open(RdpgfxServerContext* context)
@ -1433,7 +1437,6 @@ static BOOL rdpgfx_server_open(RdpgfxServerContext* context)
}
if (!(priv->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE)
rdpgfx_server_thread_func,
(void*) context, 0, NULL)))
{
@ -1654,7 +1657,7 @@ UINT rdpgfx_server_handle_messages(RdpgfxServerContext* context)
if ((ret = rdpgfx_server_receive_pdu(context, s)))
{
WLog_ERR(TAG, "rdpgfx_server_receive_pdu "
"failed with error %"PRIu32"!", ret);
"failed with error %"PRIu32"!", ret);
return ret;
}
}

View File

@ -54,7 +54,8 @@ struct rdpsnd_mac_plugin
UINT32 latency;
AUDIO_FORMAT format;
int audioBufferIndex;
size_t lastAudioBufferIndex;
size_t audioBufferIndex;
AudioQueueRef audioQueue;
AudioStreamBasicDescription audioFormat;
@ -70,7 +71,12 @@ typedef struct rdpsnd_mac_plugin rdpsndMacPlugin;
static void mac_audio_queue_output_cb(void* inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer)
{
rdpsndMacPlugin* mac = (rdpsndMacPlugin*)inUserData;
if (inBuffer == mac->audioBuffers[mac->lastAudioBufferIndex]) {
AudioQueuePause(mac->audioQueue);
mac->isPlaying = FALSE;
}
}
static BOOL rdpsnd_mac_set_format(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency)
@ -193,10 +199,16 @@ static void rdpsnd_mac_close(rdpsndDevicePlugin* device)
if (mac->isOpen)
{
size_t index;
mac->isOpen = FALSE;
AudioQueueStop(mac->audioQueue, true);
for (index = 0; index < MAC_AUDIO_QUEUE_NUM_BUFFERS; index++)
{
AudioQueueFreeBuffer(mac->audioQueue, mac->audioBuffers[index]);
}
AudioQueueDispose(mac->audioQueue, true);
mac->audioQueue = NULL;
@ -338,12 +350,9 @@ static void rdpsnd_mac_waveplay(rdpsndDevicePlugin* device, RDPSND_WAVE* wave)
wave->wTimeStampB = wave->wTimeStampA + wave->wLocalTimeB - wave->wLocalTimeA;
mac->lastStartTime = outActualStartTime.mSampleTime;
mac->lastAudioBufferIndex = mac->audioBufferIndex;
mac->audioBufferIndex++;
if (mac->audioBufferIndex >= MAC_AUDIO_QUEUE_NUM_BUFFERS)
{
mac->audioBufferIndex = 0;
}
mac->audioBufferIndex %= MAC_AUDIO_QUEUE_NUM_BUFFERS;
device->Start(device);
}

View File

@ -82,22 +82,25 @@ static int rdpsnd_oss_get_format(AUDIO_FORMAT* format)
switch (format->wFormatTag)
{
case WAVE_FORMAT_PCM:
switch (format->wBitsPerSample)
{
case 8:
return AFMT_S8;
case 16:
return AFMT_S16_LE;
}
break;
case WAVE_FORMAT_ALAW:
return AFMT_A_LAW;
#if 0 /* This does not work on my desktop. */
case WAVE_FORMAT_MULAW:
return AFMT_MU_LAW;
#endif
case WAVE_FORMAT_ADPCM:
case WAVE_FORMAT_DVI_ADPCM:
return AFMT_S16_LE;
@ -117,20 +120,19 @@ static BOOL rdpsnd_oss_format_supported(rdpsndDevicePlugin* device, AUDIO_FORMAT
switch (format->wFormatTag)
{
case WAVE_FORMAT_PCM:
if (format->cbSize != 0 ||
format->nSamplesPerSec > 48000 ||
(format->wBitsPerSample != 8 && format->wBitsPerSample != 16) ||
(format->nChannels != 1 && format->nChannels != 2))
format->nSamplesPerSec > 48000 ||
(format->wBitsPerSample != 8 && format->wBitsPerSample != 16) ||
(format->nChannels != 1 && format->nChannels != 2))
return FALSE;
break;
case WAVE_FORMAT_ADPCM:
case WAVE_FORMAT_DVI_ADPCM:
if (format->nSamplesPerSec > 48000 ||
format->wBitsPerSample != 4 ||
(format->nChannels != 1 && format->nChannels != 2))
format->wBitsPerSample != 4 ||
(format->nChannels != 1 && format->nChannels != 2))
return FALSE;
break;
@ -379,17 +381,19 @@ static BOOL rdpsnd_oss_wave_decode(rdpsndDevicePlugin* device, RDPSND_WAVE* wave
{
case WAVE_FORMAT_ADPCM:
oss->dsp_context->decode_ms_adpcm(oss->dsp_context,
wave->data, wave->length, oss->format.nChannels, oss->format.nBlockAlign);
wave->data, wave->length, oss->format.nChannels, oss->format.nBlockAlign);
wave->length = oss->dsp_context->adpcm_size;
wave->data = oss->dsp_context->adpcm_buffer;
break;
case WAVE_FORMAT_DVI_ADPCM:
oss->dsp_context->decode_ima_adpcm(oss->dsp_context,
wave->data, wave->length, oss->format.nChannels, oss->format.nBlockAlign);
wave->data, wave->length, oss->format.nChannels, oss->format.nBlockAlign);
wave->length = oss->dsp_context->adpcm_size;
wave->data = oss->dsp_context->adpcm_buffer;
break;
}
return TRUE;
}
@ -442,12 +446,14 @@ static int rdpsnd_oss_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV* a
COMMAND_LINE_ARGUMENT_A* arg;
rdpsndOssPlugin* oss = (rdpsndOssPlugin*)device;
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD;
status = CommandLineParseArgumentsA(args->argc, (const char**)args->argv, rdpsnd_oss_args, flags, oss, NULL, NULL);
status = CommandLineParseArgumentsA(args->argc, (const char**)args->argv, rdpsnd_oss_args, flags,
oss, NULL, NULL);
if (status < 0)
return status;
arg = rdpsnd_oss_args;
errno = 0;
do
{
@ -458,10 +464,21 @@ static int rdpsnd_oss_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV* a
CommandLineSwitchCase(arg, "dev")
{
str_num = _strdup(arg->Value);
if (!str_num)
return ERROR_OUTOFMEMORY;
oss->dev_unit = strtol(str_num, &eptr, 10);
{
long val = strtol(str_num, &eptr, 10);
if ((errno != 0) || (val < INT32_MIN) || (val > INT32_MAX))
{
free(str_num);
return CHANNEL_RC_NULL_DATA;
}
oss->dev_unit = val;
}
if (oss->dev_unit < 0 || *eptr != '\0')
oss->dev_unit = -1;
@ -491,8 +508,10 @@ UINT freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS p
ADDIN_ARGV* args;
rdpsndOssPlugin* oss;
oss = (rdpsndOssPlugin*)calloc(1, sizeof(rdpsndOssPlugin));
if (!oss)
return CHANNEL_RC_NO_MEMORY;
oss->device.Open = rdpsnd_oss_open;
oss->device.FormatSupported = rdpsnd_oss_format_supported;
oss->device.SetFormat = rdpsnd_oss_set_format;
@ -508,6 +527,7 @@ UINT freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS p
args = pEntryPoints->args;
rdpsnd_oss_parse_addin_args((rdpsndDevicePlugin*)oss, args);
oss->dsp_context = freerdp_dsp_context_new();
if (!oss->dsp_context)
{
free(oss);
@ -515,6 +535,5 @@ UINT freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS p
}
pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*)oss);
return CHANNEL_RC_OK;
}

View File

@ -191,6 +191,11 @@ static void rdpsnd_pulse_close(rdpsndDevicePlugin* device)
{
rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*) device;
#ifdef WITH_GSM
if (pulse->gsm_context)
gsm_destroy(pulse->gsm_context);
#endif
if (!pulse->context || !pulse->stream)
return;
@ -364,6 +369,10 @@ static void rdpsnd_pulse_free(rdpsndDevicePlugin* device)
pulse->mainloop = NULL;
}
#ifdef WITH_GSM
Stream_Free(pulse->gsmBuffer, TRUE);
#endif
free(pulse->device_name);
freerdp_dsp_context_free(pulse->dsp_context);
free(pulse);

View File

@ -34,6 +34,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <winpr/crt.h>
#include <winpr/wlog.h>
@ -102,7 +103,7 @@ struct rdpsnd_plugin
*/
static UINT rdpsnd_confirm_wave(rdpsndPlugin* rdpsnd, RDPSND_WAVE* wave);
static void* rdpsnd_schedule_thread(void* arg)
static DWORD WINAPI rdpsnd_schedule_thread(LPVOID arg)
{
wMessage message;
UINT16 wTimeDiff;
@ -182,8 +183,8 @@ static void* rdpsnd_schedule_thread(void* arg)
setChannelError(rdpsnd->rdpcontext, error,
"rdpsnd_schedule_thread reported an error");
ExitThread((DWORD)error);
return NULL;
ExitThread(error);
return error;
}
/**
@ -224,8 +225,8 @@ static void rdpsnd_select_supported_audio_formats(rdpsndPlugin* rdpsnd)
return;
rdpsnd->ClientFormats = (AUDIO_FORMAT*) calloc(
rdpsnd->NumberOfServerFormats,
sizeof(AUDIO_FORMAT));
rdpsnd->NumberOfServerFormats,
sizeof(AUDIO_FORMAT));
if (!rdpsnd->ClientFormats)
return;
@ -871,6 +872,7 @@ static UINT rdpsnd_process_addin_args(rdpsndPlugin* rdpsnd, ADDIN_ARGV* args)
return CHANNEL_RC_INITIALIZATION_ERROR;
arg = rdpsnd_args;
errno = 0;
do
{
@ -890,23 +892,43 @@ static UINT rdpsnd_process_addin_args(rdpsndPlugin* rdpsnd, ADDIN_ARGV* args)
}
CommandLineSwitchCase(arg, "format")
{
rdpsnd->fixedFormat = atoi(arg->Value);
unsigned long val = strtoul(arg->Value, NULL, 0);
if ((errno != 0) || (val > UINT16_MAX))
return CHANNEL_RC_INITIALIZATION_ERROR;
rdpsnd->fixedFormat = val;
}
CommandLineSwitchCase(arg, "rate")
{
rdpsnd->fixedRate = atoi(arg->Value);
unsigned long val = strtoul(arg->Value, NULL, 0);
if ((errno != 0) || (val > UINT32_MAX))
return CHANNEL_RC_INITIALIZATION_ERROR;
rdpsnd->fixedRate = val;
}
CommandLineSwitchCase(arg, "channel")
{
rdpsnd->fixedChannel = atoi(arg->Value);
unsigned long val = strtoul(arg->Value, NULL, 0);
if ((errno != 0) || (val > UINT16_MAX))
return CHANNEL_RC_INITIALIZATION_ERROR;
rdpsnd->fixedChannel = val;
}
CommandLineSwitchCase(arg, "latency")
{
rdpsnd->latency = atoi(arg->Value);
unsigned long val = strtoul(arg->Value, NULL, 0);
if ((errno != 0) || (val > INT32_MAX))
return CHANNEL_RC_INITIALIZATION_ERROR;
rdpsnd->latency = val;
}
CommandLineSwitchCase(arg, "quality")
{
int wQualityMode = DYNAMIC_QUALITY;
long wQualityMode = DYNAMIC_QUALITY;
if (_stricmp(arg->Value, "dynamic") == 0)
wQualityMode = DYNAMIC_QUALITY;
@ -915,7 +937,12 @@ static UINT rdpsnd_process_addin_args(rdpsndPlugin* rdpsnd, ADDIN_ARGV* args)
else if (_stricmp(arg->Value, "high") == 0)
wQualityMode = HIGH_QUALITY;
else
wQualityMode = atoi(arg->Value);
{
wQualityMode = strtol(arg->Value, NULL, 0);
if (errno != 0)
return CHANNEL_RC_INITIALIZATION_ERROR;
}
if ((wQualityMode < 0) || (wQualityMode > 2))
wQualityMode = DYNAMIC_QUALITY;
@ -1088,7 +1115,7 @@ static UINT rdpsnd_process_connect(rdpsndPlugin* rdpsnd)
}
rdpsnd->ScheduleThread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) rdpsnd_schedule_thread,
rdpsnd_schedule_thread,
(void*) rdpsnd, 0, NULL);
if (!rdpsnd->ScheduleThread)
@ -1244,7 +1271,7 @@ static VOID VCAPITYPE rdpsnd_virtual_channel_open_event_ex(LPVOID lpUserParam, D
"rdpsnd_virtual_channel_open_event_ex reported an error");
}
static void* rdpsnd_virtual_channel_client_thread(void* arg)
static DWORD WINAPI rdpsnd_virtual_channel_client_thread(LPVOID arg)
{
wStream* data;
wMessage message;
@ -1295,8 +1322,8 @@ out:
"rdpsnd_virtual_channel_client_thread reported an error");
rdpsnd_process_disconnect(rdpsnd);
ExitThread((DWORD)error);
return NULL;
ExitThread(error);
return error;
}
/**
@ -1328,7 +1355,7 @@ static UINT rdpsnd_virtual_channel_event_connected(rdpsndPlugin* rdpsnd,
}
rdpsnd->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) rdpsnd_virtual_channel_client_thread, (void*) rdpsnd,
rdpsnd_virtual_channel_client_thread, (void*) rdpsnd,
0, NULL);
if (!rdpsnd->thread)

View File

@ -42,7 +42,7 @@
*/
UINT rdpsnd_server_send_formats(RdpsndServerContext* context, wStream* s)
{
int pos;
size_t pos;
UINT16 i;
BOOL status;
ULONG written;
@ -239,7 +239,7 @@ out_free:
return error;
}
static void* rdpsnd_server_thread(void* arg)
static DWORD WINAPI rdpsnd_server_thread(LPVOID arg)
{
DWORD nCount, status;
HANDLE events[8];
@ -293,8 +293,8 @@ out:
setChannelError(context->rdpcontext, error,
"rdpsnd_server_thread reported an error");
ExitThread((DWORD)error);
return NULL;
ExitThread(error);
return error;
}
/**
@ -574,10 +574,11 @@ out:
static UINT rdpsnd_server_set_volume(RdpsndServerContext* context, int left,
int right)
{
int pos;
size_t pos;
BOOL status;
ULONG written;
wStream* s = context->priv->rdpsnd_pdu;
Stream_Write_UINT8(s, SNDC_SETVOLUME);
Stream_Write_UINT8(s, 0);
Stream_Seek_UINT16(s);
@ -600,7 +601,7 @@ static UINT rdpsnd_server_set_volume(RdpsndServerContext* context, int left,
*/
static UINT rdpsnd_server_close(RdpsndServerContext* context)
{
int pos;
size_t pos;
BOOL status;
ULONG written;
wStream* s = context->priv->rdpsnd_pdu;
@ -700,7 +701,7 @@ static UINT rdpsnd_server_start(RdpsndServerContext* context)
}
context->priv->Thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) rdpsnd_server_thread, (void*) context, 0, NULL);
rdpsnd_server_thread, (void*) context, 0, NULL);
if (!context->priv->Thread)
{

View File

@ -804,7 +804,7 @@ static VOID VCAPITYPE remdesk_virtual_channel_open_event_ex(LPVOID lpUserParam,
"remdesk_virtual_channel_open_event_ex reported an error");
}
static void* remdesk_virtual_channel_client_thread(void* arg)
static DWORD WINAPI remdesk_virtual_channel_client_thread(LPVOID arg)
{
wStream* data;
wMessage message;
@ -847,8 +847,8 @@ static void* remdesk_virtual_channel_client_thread(void* arg)
setChannelError(remdesk->rdpcontext, error,
"remdesk_virtual_channel_client_thread reported an error");
ExitThread((DWORD)error);
return NULL;
ExitThread(error);
return error;
}
/**
@ -882,7 +882,7 @@ static UINT remdesk_virtual_channel_event_connected(remdeskPlugin* remdesk,
}
remdesk->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) remdesk_virtual_channel_client_thread, (void*) remdesk,
remdesk_virtual_channel_client_thread, (void*) remdesk,
0, NULL);
if (!remdesk->thread)
@ -942,6 +942,7 @@ static UINT remdesk_virtual_channel_event_disconnected(remdeskPlugin* remdesk)
static void remdesk_virtual_channel_event_terminated(remdeskPlugin* remdesk)
{
remdesk->InitHandle = 0;
free(remdesk->context);
free(remdesk);
}

View File

@ -578,7 +578,7 @@ static UINT remdesk_server_receive_pdu(RemdeskServerContext* context,
return error;
}
static void* remdesk_server_thread(void* arg)
static DWORD WINAPI remdesk_server_thread(LPVOID arg)
{
wStream* s;
DWORD status;
@ -700,8 +700,8 @@ out:
setChannelError(context->rdpcontext, error,
"remdesk_server_thread reported an error");
ExitThread((DWORD)error);
return NULL;
ExitThread(error);
return error;
}
/**
@ -727,7 +727,7 @@ static UINT remdesk_server_start(RemdeskServerContext* context)
}
if (!(context->priv->Thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) remdesk_server_thread, (void*) context, 0, NULL)))
remdesk_server_thread, (void*) context, 0, NULL)))
{
WLog_ERR(TAG, "CreateThread failed!");
CloseHandle(context->priv->StopEvent);

View File

@ -124,20 +124,27 @@ static UINT32 _GetLastErrorToIoStatus(SERIAL_DEVICE* serial)
return STATUS_UNSUCCESSFUL;
}
static void serial_process_irp_create(SERIAL_DEVICE* serial, IRP* irp)
static UINT serial_process_irp_create(SERIAL_DEVICE* serial, IRP* irp)
{
DWORD DesiredAccess;
DWORD SharedAccess;
DWORD CreateDisposition;
UINT32 PathLength;
if (Stream_GetRemainingLength(irp->input) < 32)
return ERROR_INVALID_DATA;
Stream_Read_UINT32(irp->input, DesiredAccess); /* DesiredAccess (4 bytes) */
Stream_Seek_UINT64(irp->input); /* AllocationSize (8 bytes) */
Stream_Seek_UINT32(irp->input); /* FileAttributes (4 bytes) */
Stream_Read_UINT32(irp->input, SharedAccess); /* SharedAccess (4 bytes) */
Stream_Read_UINT32(irp->input,
CreateDisposition); /* CreateDisposition (4 bytes) */
Stream_Read_UINT32(irp->input, CreateDisposition); /* CreateDisposition (4 bytes) */
Stream_Seek_UINT32(irp->input); /* CreateOptions (4 bytes) */
Stream_Read_UINT32(irp->input, PathLength); /* PathLength (4 bytes) */
if (Stream_GetRemainingLength(irp->input) < PathLength)
return ERROR_INVALID_DATA;
Stream_Seek(irp->input, PathLength); /* Path (variable) */
assert(PathLength == 0); /* MS-RDPESP 2.2.2.2 */
#ifndef _WIN32
@ -191,18 +198,21 @@ static void serial_process_irp_create(SERIAL_DEVICE* serial, IRP* irp)
/* dcb.fBinary = TRUE; */
/* SetCommState(serial->hComm, &dcb); */
assert(irp->FileId == 0);
irp->FileId =
irp->devman->id_sequence++; /* FIXME: why not ((WINPR_COMM*)hComm)->fd? */
irp->FileId = irp->devman->id_sequence++; /* FIXME: why not ((WINPR_COMM*)hComm)->fd? */
irp->IoStatus = STATUS_SUCCESS;
WLog_Print(serial->log, WLOG_DEBUG, "%s (DeviceId: %"PRIu32", FileId: %"PRIu32") created.",
serial->device.name, irp->device->id, irp->FileId);
error_handle:
Stream_Write_UINT32(irp->output, irp->FileId); /* FileId (4 bytes) */
Stream_Write_UINT8(irp->output, 0); /* Information (1 byte) */
return CHANNEL_RC_OK;
}
static void serial_process_irp_close(SERIAL_DEVICE* serial, IRP* irp)
static UINT serial_process_irp_close(SERIAL_DEVICE* serial, IRP* irp)
{
if (Stream_GetRemainingLength(irp->input) < 32)
return ERROR_INVALID_DATA;
Stream_Seek(irp->input, 32); /* Padding (32 bytes) */
if (!CloseHandle(serial->hComm))
@ -219,6 +229,7 @@ static void serial_process_irp_close(SERIAL_DEVICE* serial, IRP* irp)
irp->IoStatus = STATUS_SUCCESS;
error_handle:
Stream_Zero(irp->output, 5); /* Padding (5 bytes) */
return CHANNEL_RC_OK;
}
/**
@ -232,6 +243,10 @@ static UINT serial_process_irp_read(SERIAL_DEVICE* serial, IRP* irp)
UINT64 Offset;
BYTE* buffer = NULL;
DWORD nbRead = 0;
if (Stream_GetRemainingLength(irp->input) < 32)
return ERROR_INVALID_DATA;
Stream_Read_UINT32(irp->input, Length); /* Length (4 bytes) */
Stream_Read_UINT64(irp->input, Offset); /* Offset (8 bytes) */
Stream_Seek(irp->input, 20); /* Padding (20 bytes) */
@ -283,11 +298,15 @@ error_handle:
return CHANNEL_RC_OK;
}
static void serial_process_irp_write(SERIAL_DEVICE* serial, IRP* irp)
static UINT serial_process_irp_write(SERIAL_DEVICE* serial, IRP* irp)
{
UINT32 Length;
UINT64 Offset;
DWORD nbWritten = 0;
if (Stream_GetRemainingLength(irp->input) < 32)
return ERROR_INVALID_DATA;
Stream_Read_UINT32(irp->input, Length); /* Length (4 bytes) */
Stream_Read_UINT64(irp->input, Offset); /* Offset (8 bytes) */
Stream_Seek(irp->input, 20); /* Padding (20 bytes) */
@ -318,6 +337,7 @@ static void serial_process_irp_write(SERIAL_DEVICE* serial, IRP* irp)
serial->device.name);
Stream_Write_UINT32(irp->output, nbWritten); /* Length (4 bytes) */
Stream_Write_UINT8(irp->output, 0); /* Padding (1 byte) */
return CHANNEL_RC_OK;
}
@ -334,12 +354,18 @@ static UINT serial_process_irp_device_control(SERIAL_DEVICE* serial, IRP* irp)
UINT32 OutputBufferLength;
BYTE* OutputBuffer = NULL;
DWORD BytesReturned = 0;
Stream_Read_UINT32(irp->input,
OutputBufferLength); /* OutputBufferLength (4 bytes) */
Stream_Read_UINT32(irp->input,
InputBufferLength); /* InputBufferLength (4 bytes) */
if (Stream_GetRemainingLength(irp->input) < 32)
return ERROR_INVALID_DATA;
Stream_Read_UINT32(irp->input, OutputBufferLength); /* OutputBufferLength (4 bytes) */
Stream_Read_UINT32(irp->input, InputBufferLength); /* InputBufferLength (4 bytes) */
Stream_Read_UINT32(irp->input, IoControlCode); /* IoControlCode (4 bytes) */
Stream_Seek(irp->input, 20); /* Padding (20 bytes) */
if (Stream_GetRemainingLength(irp->input) < InputBufferLength)
return ERROR_INVALID_DATA;
OutputBuffer = (BYTE*)calloc(OutputBufferLength, sizeof(BYTE));
if (OutputBuffer == NULL)
@ -381,8 +407,7 @@ error_handle:
* BytesReturned == OutputBufferLength when
* CommDeviceIoControl returns FALSE */
assert(OutputBufferLength == BytesReturned);
Stream_Write_UINT32(irp->output,
BytesReturned); /* OutputBufferLength (4 bytes) */
Stream_Write_UINT32(irp->output, BytesReturned); /* OutputBufferLength (4 bytes) */
if (BytesReturned > 0)
{
@ -425,11 +450,11 @@ static UINT serial_process_irp(SERIAL_DEVICE* serial, IRP* irp)
switch (irp->MajorFunction)
{
case IRP_MJ_CREATE:
serial_process_irp_create(serial, irp);
error = serial_process_irp_create(serial, irp);
break;
case IRP_MJ_CLOSE:
serial_process_irp_close(serial, irp);
error = serial_process_irp_close(serial, irp);
break;
case IRP_MJ_READ:
@ -439,7 +464,7 @@ static UINT serial_process_irp(SERIAL_DEVICE* serial, IRP* irp)
break;
case IRP_MJ_WRITE:
serial_process_irp_write(serial, irp);
error = serial_process_irp_write(serial, irp);
break;
case IRP_MJ_DEVICE_CONTROL:
@ -458,7 +483,7 @@ static UINT serial_process_irp(SERIAL_DEVICE* serial, IRP* irp)
}
static void* irp_thread_func(void* arg)
static DWORD WINAPI irp_thread_func(LPVOID arg)
{
IRP_THREAD_DATA* data = (IRP_THREAD_DATA*)arg;
UINT error;
@ -484,8 +509,8 @@ error_out:
* the CompletionId whereas the thread is not yet
* terminated */
free(data);
ExitThread((DWORD)error);
return NULL;
ExitThread(error);
return error;
}
@ -617,7 +642,7 @@ static void create_irp_thread(SERIAL_DEVICE* serial, IRP* irp)
/* data freed by irp_thread_func */
irpThread = CreateThread(NULL,
0,
(LPTHREAD_START_ROUTINE)irp_thread_func,
irp_thread_func,
(void*)data,
0,
NULL);
@ -672,7 +697,7 @@ static void terminate_pending_irp_threads(SERIAL_DEVICE* serial)
}
static void* serial_thread_func(void* arg)
static DWORD WINAPI serial_thread_func(LPVOID arg)
{
IRP* irp;
wMessage message;
@ -711,8 +736,8 @@ static void* serial_thread_func(void* arg)
setChannelError(serial->rdpcontext, error,
"serial_thread_func reported an error");
ExitThread((DWORD) error);
return NULL;
ExitThread(error);
return error;
}
@ -815,7 +840,6 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
if ((name && name[0]) && (path && path[0]))
{
wLog* log;
WLog_Init();
log = WLog_Get("com.freerdp.channel.serial.client");
WLog_Print(log, WLOG_DEBUG, "initializing");
#ifndef __linux__ /* to be removed */
@ -827,7 +851,8 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
if (!DefineCommDevice(name /* eg: COM1 */, path /* eg: /dev/ttyS0 */))
{
WLog_ERR(TAG, "DefineCommDevice failed!");
DWORD status = GetLastError();
WLog_ERR(TAG, "DefineCommDevice failed with %08"PRIx32, status);
return ERROR_INTERNAL_ERROR;
}
@ -927,7 +952,7 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
if (!(serial->MainThread = CreateThread(NULL,
0,
(LPTHREAD_START_ROUTINE) serial_thread_func,
serial_thread_func,
(void*) serial,
0,
NULL)))

View File

@ -34,8 +34,9 @@
#include "smartcard_main.h"
void* smartcard_context_thread(SMARTCARD_CONTEXT* pContext)
static DWORD WINAPI smartcard_context_thread(LPVOID arg)
{
SMARTCARD_CONTEXT* pContext = (SMARTCARD_CONTEXT*)arg;
DWORD nCount;
LONG status = 0;
DWORD waitStatus;
@ -107,8 +108,8 @@ void* smartcard_context_thread(SMARTCARD_CONTEXT* pContext)
setChannelError(smartcard->rdpcontext, error,
"smartcard_context_thread reported an error");
ExitThread((DWORD)status);
return NULL;
ExitThread(status);
return error;
}
SMARTCARD_CONTEXT* smartcard_context_new(SMARTCARD_DEVICE* smartcard,
@ -134,7 +135,7 @@ SMARTCARD_CONTEXT* smartcard_context_new(SMARTCARD_DEVICE* smartcard,
}
pContext->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) smartcard_context_thread,
smartcard_context_thread,
pContext, 0, NULL);
if (!pContext->thread)
@ -385,17 +386,17 @@ UINT smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp)
asyncIrp = TRUE;
/**
* The following matches mstsc's behavior of processing
* only certain requests asynchronously while processing
* those expected to return fast synchronously.
*/
switch (operation->ioControlCode)
{
case SCARD_IOCTL_ESTABLISHCONTEXT:
case SCARD_IOCTL_RELEASECONTEXT:
case SCARD_IOCTL_ISVALIDCONTEXT:
case SCARD_IOCTL_CANCEL:
case SCARD_IOCTL_ACCESSSTARTEDEVENT:
case SCARD_IOCTL_RELEASESTARTEDEVENT:
asyncIrp = FALSE;
break;
case SCARD_IOCTL_LISTREADERGROUPSA:
case SCARD_IOCTL_LISTREADERGROUPSW:
case SCARD_IOCTL_LISTREADERSA:
@ -416,21 +417,14 @@ UINT smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp)
case SCARD_IOCTL_LOCATECARDSW:
case SCARD_IOCTL_LOCATECARDSBYATRA:
case SCARD_IOCTL_LOCATECARDSBYATRW:
case SCARD_IOCTL_CANCEL:
case SCARD_IOCTL_READCACHEA:
case SCARD_IOCTL_READCACHEW:
case SCARD_IOCTL_WRITECACHEA:
case SCARD_IOCTL_WRITECACHEW:
case SCARD_IOCTL_GETREADERICON:
case SCARD_IOCTL_GETDEVICETYPEID:
asyncIrp = FALSE;
break;
case SCARD_IOCTL_GETSTATUSCHANGEA:
case SCARD_IOCTL_GETSTATUSCHANGEW:
asyncIrp = TRUE;
break;
case SCARD_IOCTL_CONNECTA:
case SCARD_IOCTL_CONNECTW:
case SCARD_IOCTL_RECONNECT:
@ -447,11 +441,6 @@ UINT smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp)
case SCARD_IOCTL_GETTRANSMITCOUNT:
asyncIrp = TRUE;
break;
case SCARD_IOCTL_ACCESSSTARTEDEVENT:
case SCARD_IOCTL_RELEASESTARTEDEVENT:
asyncIrp = FALSE;
break;
}
pContext = ListDictionary_GetItemValue(smartcard->rgSCardContextList,
@ -506,7 +495,7 @@ UINT smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp)
return CHANNEL_RC_OK;
}
static void* smartcard_thread_func(void* arg)
static DWORD WINAPI smartcard_thread_func(LPVOID arg)
{
IRP* irp;
DWORD nCount;
@ -657,8 +646,8 @@ out:
setChannelError(smartcard->rdpcontext, error,
"smartcard_thread_func reported an error");
ExitThread((DWORD)error);
return NULL;
ExitThread(error);
return error;
}
/**
@ -689,17 +678,9 @@ static UINT smartcard_irp_request(DEVICE* device, IRP* irp)
*/
UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
{
char* name;
char* path;
size_t length;
int ck;
RDPDR_SMARTCARD* device;
SMARTCARD_DEVICE* smartcard;
LONG status;
UINT error = CHANNEL_RC_NO_MEMORY;
device = (RDPDR_SMARTCARD*) pEntryPoints->device;
name = device->Name;
path = device->Path;
smartcard = (SMARTCARD_DEVICE*) calloc(1, sizeof(SMARTCARD_DEVICE));
if (!smartcard)
@ -724,30 +705,6 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
}
Stream_Write(smartcard->device.data, "SCARD", 6);
smartcard->name = NULL;
smartcard->path = NULL;
if (path)
{
smartcard->path = path;
smartcard->name = name;
}
else if (name)
{
if (1 == sscanf(name, "%d", &ck))
smartcard->path = name;
else
smartcard->name = name;
}
status = SCardAddReaderName(&smartcard->thread, (LPSTR) name);
if (status != SCARD_S_SUCCESS)
{
WLog_ERR(TAG, "Failed to add reader name!");
goto error_device_data;
}
smartcard->IrpQueue = MessageQueue_New(NULL);
if (!smartcard->IrpQueue)
@ -790,7 +747,7 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
}
smartcard->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) smartcard_thread_func,
smartcard_thread_func,
smartcard, CREATE_SUSPENDED, NULL);
if (!smartcard->thread)

View File

@ -110,9 +110,6 @@ struct _SMARTCARD_DEVICE
{
DEVICE device;
char* name;
char* path;
HANDLE thread;
HANDLE StartedEvent;
wMessageQueue* IrpQueue;

View File

@ -581,28 +581,23 @@ static LONG smartcard_GetStatusChangeA_Decode(SMARTCARD_DEVICE* smartcard,
static LONG smartcard_GetStatusChangeA_Call(SMARTCARD_DEVICE* smartcard,
SMARTCARD_OPERATION* operation)
{
LONG status;
UINT32 index;
GetStatusChange_Return ret;
LPSCARD_READERSTATEA rgReaderState = NULL;
IRP* irp = operation->irp;
GetStatusChangeA_Call* call = operation->call;
status = ret.ReturnCode = SCardGetStatusChangeA(operation->hContext,
call->dwTimeOut, call->rgReaderStates, call->cReaders);
if (status && (status != SCARD_E_TIMEOUT) && (status != SCARD_E_CANCELLED))
{
call->cReaders = 0;
}
ret.ReturnCode = SCardGetStatusChangeA(operation->hContext, call->dwTimeOut, call->rgReaderStates,
call->cReaders);
ret.cReaders = call->cReaders;
ret.rgReaderStates = NULL;
if (ret.cReaders > 0)
{
ret.rgReaderStates = (ReaderState_Return*) calloc(ret.cReaders, sizeof(ReaderState_Return));
if (!ret.rgReaderStates)
return STATUS_NO_MEMORY;
if (!ret.rgReaderStates)
return STATUS_NO_MEMORY;
}
for (index = 0; index < ret.cReaders; index++)
{
@ -613,12 +608,7 @@ static LONG smartcard_GetStatusChangeA_Call(SMARTCARD_DEVICE* smartcard,
}
smartcard_trace_get_status_change_return(smartcard, &ret, FALSE);
if ((status = smartcard_pack_get_status_change_return(smartcard, irp->output, &ret)))
{
WLog_ERR(TAG, "smartcard_pack_get_status_change_return failed with error %"PRId32"", status);
return status;
}
smartcard_pack_get_status_change_return(smartcard, irp->output, &ret);
if (call->rgReaderStates)
{
@ -657,28 +647,23 @@ static LONG smartcard_GetStatusChangeW_Decode(SMARTCARD_DEVICE* smartcard,
static LONG smartcard_GetStatusChangeW_Call(SMARTCARD_DEVICE* smartcard,
SMARTCARD_OPERATION* operation)
{
LONG status;
UINT32 index;
GetStatusChange_Return ret;
LPSCARD_READERSTATEW rgReaderState = NULL;
IRP* irp = operation->irp;
GetStatusChangeW_Call* call = operation->call;
status = ret.ReturnCode = SCardGetStatusChangeW(operation->hContext, call->dwTimeOut,
call->rgReaderStates, call->cReaders);
if (status && (status != SCARD_E_TIMEOUT) && (status != SCARD_E_CANCELLED))
{
call->cReaders = 0;
}
ret.ReturnCode = SCardGetStatusChangeW(operation->hContext, call->dwTimeOut,
call->rgReaderStates, call->cReaders);
ret.cReaders = call->cReaders;
ret.rgReaderStates = NULL;
if (ret.cReaders > 0)
{
ret.rgReaderStates = (ReaderState_Return*) calloc(ret.cReaders, sizeof(ReaderState_Return));
if (!ret.rgReaderStates)
return STATUS_NO_MEMORY;
if (!ret.rgReaderStates)
return STATUS_NO_MEMORY;
}
for (index = 0; index < ret.cReaders; index++)
{
@ -689,12 +674,7 @@ static LONG smartcard_GetStatusChangeW_Call(SMARTCARD_DEVICE* smartcard,
}
smartcard_trace_get_status_change_return(smartcard, &ret, TRUE);
if ((status = smartcard_pack_get_status_change_return(smartcard, irp->output, &ret)))
{
WLog_ERR(TAG, "smartcard_pack_get_status_change_return failed with error %"PRId32"", status);
return status;
}
smartcard_pack_get_status_change_return(smartcard, irp->output, &ret);
if (call->rgReaderStates)
{
@ -787,17 +767,19 @@ static LONG smartcard_ConnectA_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERA
if (status)
{
WLog_ERR(TAG, "SCardConnectA failed with error %"PRId32"", status);
return status;
goto out_fail;
}
if ((status = smartcard_pack_connect_return(smartcard, irp->output, &ret)))
{
WLog_ERR(TAG, "smartcard_pack_connect_return failed with error %"PRId32"", status);
return status;
goto out_fail;
}
status = ret.ReturnCode;
out_fail:
free(call->szReader);
return ret.ReturnCode;
return status;
}
static LONG smartcard_ConnectW_Decode(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation)
@ -843,17 +825,19 @@ static LONG smartcard_ConnectW_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERA
if (status)
{
WLog_ERR(TAG, "SCardConnectW failed with error %"PRId32"", status);
return status;
goto out_fail;
}
if ((status = smartcard_pack_connect_return(smartcard, irp->output, &ret)))
{
WLog_ERR(TAG, "smartcard_pack_connect_return failed with error %"PRId32"", status);
return status;
goto out_fail;
}
status = ret.ReturnCode;
out_fail:
free(call->szReader);
return ret.ReturnCode;
return status;
}
static LONG smartcard_Reconnect_Decode(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation)
@ -881,8 +865,8 @@ static LONG smartcard_Reconnect_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPER
Reconnect_Return ret;
IRP* irp = operation->irp;
Reconnect_Call* call = operation->call;
status = ret.ReturnCode = SCardReconnect(operation->hCard, call->dwShareMode,
call->dwPreferredProtocols, call->dwInitialization, &ret.dwActiveProtocol);
ret.ReturnCode = SCardReconnect(operation->hCard, call->dwShareMode,
call->dwPreferredProtocols, call->dwInitialization, &ret.dwActiveProtocol);
smartcard_trace_reconnect_return(smartcard, &ret);
if ((status = smartcard_pack_reconnect_return(smartcard, irp->output, &ret)))
@ -1064,23 +1048,34 @@ static LONG smartcard_StatusA_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERAT
LONG status;
Status_Return ret = { 0 };
DWORD cchReaderLen = 0;
DWORD cbAtrLen = 0;
LPSTR mszReaderNames = NULL;
IRP* irp = operation->irp;
Status_Call* call = operation->call;
if (call->cbAtrLen > 32)
call->cbAtrLen = 32;
ret.cbAtrLen = call->cbAtrLen;
ZeroMemory(ret.pbAtr, 32);
cchReaderLen = SCARD_AUTOALLOCATE;
status = ret.ReturnCode = SCardStatusA(operation->hCard, (LPSTR) &mszReaderNames, &cchReaderLen,
&ret.dwState, &ret.dwProtocol, (BYTE*) &ret.pbAtr, &ret.cbAtrLen);
call->cbAtrLen = 32;
cbAtrLen = call->cbAtrLen;
if (call->fmszReaderNamesIsNULL)
cchReaderLen = 0;
else
cchReaderLen = SCARD_AUTOALLOCATE;
status = ret.ReturnCode = SCardStatusA(operation->hCard,
call->fmszReaderNamesIsNULL ? NULL : (LPSTR) &mszReaderNames,
&cchReaderLen, &ret.dwState, &ret.dwProtocol,
cbAtrLen ? (BYTE*) &ret.pbAtr : NULL, &cbAtrLen);
if (status == SCARD_S_SUCCESS)
{
ret.mszReaderNames = (BYTE*) mszReaderNames;
if (!call->fmszReaderNamesIsNULL)
ret.mszReaderNames = (BYTE*) mszReaderNames;
ret.cBytes = cchReaderLen;
if (call->cbAtrLen)
ret.cbAtrLen = cbAtrLen;
}
smartcard_trace_status_return(smartcard, &ret, FALSE);
@ -1092,7 +1087,9 @@ static LONG smartcard_StatusA_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERAT
}
if (mszReaderNames)
{
SCardFreeMemory(operation->hContext, mszReaderNames);
}
return ret.ReturnCode;
}
@ -1124,17 +1121,33 @@ static LONG smartcard_StatusW_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERAT
LPWSTR mszReaderNames = NULL;
IRP* irp = operation->irp;
Status_Call* call = operation->call;
DWORD cbAtrLen;
if (call->cbAtrLen > 32)
call->cbAtrLen = 32;
ret.cbAtrLen = call->cbAtrLen;
if (call->fmszReaderNamesIsNULL)
cchReaderLen = 0;
else
cchReaderLen = SCARD_AUTOALLOCATE;
cbAtrLen = call->cbAtrLen;
ZeroMemory(ret.pbAtr, 32);
cchReaderLen = SCARD_AUTOALLOCATE;
status = ret.ReturnCode = SCardStatusW(operation->hCard, (LPWSTR) &mszReaderNames, &cchReaderLen,
&ret.dwState, &ret.dwProtocol, (BYTE*) &ret.pbAtr, &ret.cbAtrLen);
ret.mszReaderNames = (BYTE*) mszReaderNames;
ret.cBytes = cchReaderLen * 2;
status = ret.ReturnCode = SCardStatusW(operation->hCard,
call->fmszReaderNamesIsNULL ? NULL : (LPWSTR) &mszReaderNames,
&cchReaderLen, &ret.dwState, &ret.dwProtocol, (BYTE*) &ret.pbAtr, &cbAtrLen);
if (status == SCARD_S_SUCCESS)
{
if (!call->fmszReaderNamesIsNULL)
ret.mszReaderNames = (BYTE*) mszReaderNames;
ret.cBytes = cchReaderLen;
if (call->cbAtrLen)
ret.cbAtrLen = cbAtrLen;
}
smartcard_trace_status_return(smartcard, &ret, TRUE);
if ((status = smartcard_pack_status_return(smartcard, irp->output, &ret)))
@ -1190,8 +1203,8 @@ static LONG smartcard_Transmit_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERA
}
ret.pioRecvPci = call->pioRecvPci;
status = ret.ReturnCode = SCardTransmit(operation->hCard, call->pioSendPci, call->pbSendBuffer,
call->cbSendLength, ret.pioRecvPci, ret.pbRecvBuffer, &(ret.cbRecvLength));
ret.ReturnCode = SCardTransmit(operation->hCard, call->pioSendPci, call->pbSendBuffer,
call->cbSendLength, ret.pioRecvPci, ret.pbRecvBuffer, &(ret.cbRecvLength));
smartcard_trace_transmit_return(smartcard, &ret);
if ((status = smartcard_pack_transmit_return(smartcard, irp->output, &ret)))
@ -1238,9 +1251,9 @@ static LONG smartcard_Control_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERAT
if (!ret.pvOutBuffer)
return SCARD_E_NO_MEMORY;
status = ret.ReturnCode = SCardControl(operation->hCard,
call->dwControlCode, call->pvInBuffer, call->cbInBufferSize,
ret.pvOutBuffer, call->cbOutBufferSize, &ret.cbOutBufferSize);
ret.ReturnCode = SCardControl(operation->hCard,
call->dwControlCode, call->pvInBuffer, call->cbInBufferSize,
ret.pvOutBuffer, call->cbOutBufferSize, &ret.cbOutBufferSize);
smartcard_trace_control_return(smartcard, &ret);
if ((status = smartcard_pack_control_return(smartcard, irp->output, &ret)))
@ -1297,8 +1310,8 @@ static LONG smartcard_GetAttrib_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPER
}
cbAttrLen = call->cbAttrLen;
status = ret.ReturnCode = SCardGetAttrib(operation->hCard, call->dwAttrId,
autoAllocate ? (LPBYTE) & (ret.pbAttr) : ret.pbAttr, &cbAttrLen);
ret.ReturnCode = SCardGetAttrib(operation->hCard, call->dwAttrId,
autoAllocate ? (LPBYTE) & (ret.pbAttr) : ret.pbAttr, &cbAttrLen);
ret.cbAttrLen = cbAttrLen;
smartcard_trace_get_attrib_return(smartcard, &ret, call->dwAttrId);
@ -1379,7 +1392,6 @@ static LONG smartcard_LocateCardsByATRA_Call(SMARTCARD_DEVICE* smartcard,
SMARTCARD_OPERATION* operation)
{
LONG status;
BOOL equal;
DWORD i, j, k;
GetStatusChange_Return ret;
LPSCARD_READERSTATEA state = NULL;
@ -1412,21 +1424,15 @@ static LONG smartcard_LocateCardsByATRA_Call(SMARTCARD_DEVICE* smartcard,
{
for (j = 0; j < call->cReaders; j++)
{
equal = TRUE;
for (k = 0; k < call->rgAtrMasks[i].cbAtr; k++)
{
if ((call->rgAtrMasks[i].rgbAtr[k] & call->rgAtrMasks[i].rgbMask[k]) !=
(states[j].rgbAtr[k] & call->rgAtrMasks[i].rgbMask[k]))
{
equal = FALSE;
break;
}
if (equal)
{
states[j].dwEventState |= SCARD_STATE_ATRMATCH;
}
states[j].dwEventState |= SCARD_STATE_ATRMATCH;
}
}
}
@ -2022,13 +2028,12 @@ LONG smartcard_irp_device_control_call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OP
SCardGetErrorString(result), result);
}
irp->IoStatus = 0;
irp->IoStatus = STATUS_SUCCESS;
if ((result & 0xC0000000) == 0xC0000000)
{
/* NTSTATUS error */
irp->IoStatus = (UINT32)result;
Stream_SetPosition(irp->output, RDPDR_DEVICE_IO_RESPONSE_LENGTH);
WLog_WARN(TAG, "IRP failure: %s (0x%08"PRIX32"), ntstatus: 0x%08"PRIX32"",
smartcard_get_ioctl_string(ioControlCode, TRUE), ioControlCode, result);
}
@ -2039,21 +2044,9 @@ LONG smartcard_irp_device_control_call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OP
Stream_SetPosition(irp->output, RDPDR_DEVICE_IO_RESPONSE_LENGTH);
/* Device Control Response */
Stream_Write_UINT32(irp->output, outputBufferLength); /* OutputBufferLength (4 bytes) */
if ((result = smartcard_pack_common_type_header(smartcard,
irp->output))) /* CommonTypeHeader (8 bytes) */
{
WLog_ERR(TAG, "smartcard_pack_common_type_header failed with error %"PRId32"", result);
return result;
}
if ((result = smartcard_pack_private_type_header(smartcard, irp->output,
objectBufferLength))) /* PrivateTypeHeader (8 bytes) */
{
WLog_ERR(TAG, "smartcard_pack_private_type_header failed with error %"PRId32"", result);
return result;
}
smartcard_pack_common_type_header(smartcard, irp->output); /* CommonTypeHeader (8 bytes) */
smartcard_pack_private_type_header(smartcard, irp->output,
objectBufferLength); /* PrivateTypeHeader (8 bytes) */
Stream_Write_UINT32(irp->output, result); /* Result (4 bytes) */
Stream_SetPosition(irp->output, Stream_Length(irp->output));
return SCARD_S_SUCCESS;

View File

@ -75,13 +75,12 @@ LONG smartcard_unpack_common_type_header(SMARTCARD_DEVICE* smartcard, wStream* s
return SCARD_S_SUCCESS;
}
LONG smartcard_pack_common_type_header(SMARTCARD_DEVICE* smartcard, wStream* s)
void smartcard_pack_common_type_header(SMARTCARD_DEVICE* smartcard, wStream* s)
{
Stream_Write_UINT8(s, 1); /* Version (1 byte) */
Stream_Write_UINT8(s, 0x10); /* Endianness (1 byte) */
Stream_Write_UINT16(s, 8); /* CommonHeaderLength (2 bytes) */
Stream_Write_UINT32(s, 0xCCCCCCCC); /* Filler (4 bytes), should be 0xCCCCCCCC */
return SCARD_S_SUCCESS;
}
LONG smartcard_unpack_private_type_header(SMARTCARD_DEVICE* smartcard, wStream* s)
@ -116,12 +115,11 @@ LONG smartcard_unpack_private_type_header(SMARTCARD_DEVICE* smartcard, wStream*
return SCARD_S_SUCCESS;
}
LONG smartcard_pack_private_type_header(SMARTCARD_DEVICE* smartcard, wStream* s,
void smartcard_pack_private_type_header(SMARTCARD_DEVICE* smartcard, wStream* s,
UINT32 objectBufferLength)
{
Stream_Write_UINT32(s, objectBufferLength); /* ObjectBufferLength (4 bytes) */
Stream_Write_UINT32(s, 0x00000000); /* Filler (4 bytes), should be 0x00000000 */
return SCARD_S_SUCCESS;
}
LONG smartcard_unpack_read_size_align(SMARTCARD_DEVICE* smartcard, wStream* s, UINT32 size,
@ -850,7 +848,7 @@ void smartcard_trace_list_readers_return(SMARTCARD_DEVICE* smartcard, ListReader
CopyMemory(mszA, ret->msz, ret->cBytes);
}
for (index = 0; index < length - 2; index++)
for (index = 0; index < length - 1; index++)
{
if (mszA[index] == '\0')
mszA[index] = ',';
@ -1863,32 +1861,34 @@ void smartcard_trace_status_return(SMARTCARD_DEVICE* smartcard, Status_Return* r
if (!WLog_IsLevelActive(WLog_Get(TAG), WLOG_DEBUG))
return;
if (unicode)
if (ret->mszReaderNames)
{
length = ret->cBytes / 2;
if (ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) ret->mszReaderNames, (int)length,
&mszReaderNamesA, 0, NULL, NULL) < 1)
if (unicode)
{
WLog_ERR(TAG, "ConvertFromUnicode failed");
return;
length = ret->cBytes / 2;
if (ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) ret->mszReaderNames, (int) length,
&mszReaderNamesA, 0, NULL, NULL) < 1)
{
WLog_ERR(TAG, "ConvertFromUnicode failed");
return;
}
}
else
{
length = (int) ret->cBytes;
mszReaderNamesA = (char*) malloc(length);
if (!mszReaderNamesA)
{
WLog_ERR(TAG, "malloc failed!");
return;
}
CopyMemory(mszReaderNamesA, ret->mszReaderNames, ret->cBytes);
}
}
else
{
length = (int) ret->cBytes;
mszReaderNamesA = (char*) malloc(length);
if (!mszReaderNamesA)
{
WLog_ERR(TAG, "malloc failed!");
return;
}
CopyMemory(mszReaderNamesA, ret->mszReaderNames, ret->cBytes);
}
if (!mszReaderNamesA)
length = 0;
if (length > 2)
@ -2761,7 +2761,7 @@ LONG smartcard_unpack_locate_cards_by_atr_a_call(SMARTCARD_DEVICE* smartcard, wS
return STATUS_BUFFER_TOO_SMALL;
}
call->rgAtrMasks = (LocateCards_ATRMask*)calloc(call->cAtrs, sizeof(SCARD_ATRMASK));
call->rgAtrMasks = (LocateCards_ATRMask*)calloc(call->cAtrs, sizeof(LocateCards_ATRMask));
if (!call->rgAtrMasks)
{
@ -2789,7 +2789,7 @@ LONG smartcard_unpack_locate_cards_by_atr_a_call(SMARTCARD_DEVICE* smartcard, wS
if (call->cReaders > 0)
{
call->rgReaderStates = (ReaderStateA*)calloc(call->cReaders, sizeof(SCARD_READERSTATEA));
call->rgReaderStates = (ReaderStateA*)calloc(call->cReaders, sizeof(ReaderStateA));
if (!call->rgReaderStates)
{

View File

@ -452,10 +452,10 @@ void smartcard_scard_handle_native_to_redir(SMARTCARD_DEVICE* smartcard, REDIR_S
SCARDHANDLE hCard);
LONG smartcard_unpack_common_type_header(SMARTCARD_DEVICE* smartcard, wStream* s);
LONG smartcard_pack_common_type_header(SMARTCARD_DEVICE* smartcard, wStream* s);
void smartcard_pack_common_type_header(SMARTCARD_DEVICE* smartcard, wStream* s);
LONG smartcard_unpack_private_type_header(SMARTCARD_DEVICE* smartcard, wStream* s);
LONG smartcard_pack_private_type_header(SMARTCARD_DEVICE* smartcard, wStream* s,
void smartcard_pack_private_type_header(SMARTCARD_DEVICE* smartcard, wStream* s,
UINT32 objectBufferLength);
LONG smartcard_unpack_redir_scard_context(SMARTCARD_DEVICE* smartcard, wStream* s,

View File

@ -0,0 +1,27 @@
# FreeRDP: A Remote Desktop Protocol Implementation
# FreeRDP cmake build script
#
# Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
# Copyright 2017 Ben Cohen
#
# 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.
define_channel("sshagent")
if(WITH_CLIENT_CHANNELS)
add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME})
endif()
if(WITH_SERVER_CHANNELS)
add_channel_server(${MODULE_PREFIX} ${CHANNEL_NAME})
endif()

View File

@ -0,0 +1,13 @@
set(OPTION_DEFAULT OFF)
set(OPTION_CLIENT_DEFAULT OFF)
set(OPTION_SERVER_DEFAULT OFF)
define_channel_options(NAME "sshagent" TYPE "dynamic"
DESCRIPTION "SSH Agent Forwarding Extension"
SPECIFICATIONS ""
DEFAULT ${OPTION_DEFAULT})
define_channel_client_options(${OPTION_CLIENT_DEFAULT})
define_channel_server_options(${OPTION_SERVER_DEFAULT})

View File

@ -0,0 +1,34 @@
# FreeRDP: A Remote Desktop Protocol Implementation
# FreeRDP cmake build script
#
# Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
# Copyright 2017 Ben Cohen
#
# 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.
define_channel_client("sshagent")
set(${MODULE_PREFIX}_SRCS
sshagent_main.c
sshagent_main.h)
include_directories(..)
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE "DVCPluginEntry")
if (WITH_DEBUG_SYMBOLS AND MSVC AND NOT BUILTIN_CHANNELS AND BUILD_SHARED_LIBS)
install(FILES ${CMAKE_BINARY_DIR}/${MODULE_NAME}.pdb DESTINATION ${FREERDP_ADDIN_PATH} COMPONENT symbols)
endif()
target_link_libraries(${MODULE_NAME} winpr)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")

View File

@ -0,0 +1,408 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* SSH Agent Virtual Channel Extension
*
* Copyright 2013 Christian Hofstaedtler
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
* Copyright 2017 Ben Cohen
*
* 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.
*/
/*
* sshagent_main.c: DVC plugin to forward queries from RDP to the ssh-agent
*
* This relays data to and from an ssh-agent program equivalent running on the
* RDP server to an ssh-agent running locally. Unlike the normal ssh-agent,
* which sends data over an SSH channel, the data is send over an RDP dynamic
* virtual channel.
*
* protocol specification:
* Forward data verbatim over RDP dynamic virtual channel named "sshagent"
* between a ssh client on the xrdp server and the real ssh-agent where
* the RDP client is running. Each connection by a separate client to
* xrdp-ssh-agent gets a separate DVC invocation.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <pwd.h>
#include <unistd.h>
#include <errno.h>
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/thread.h>
#include <winpr/stream.h>
#include "sshagent_main.h"
#include <freerdp/channels/log.h>
#define TAG CHANNELS_TAG("sshagent.client")
typedef struct _SSHAGENT_LISTENER_CALLBACK SSHAGENT_LISTENER_CALLBACK;
struct _SSHAGENT_LISTENER_CALLBACK
{
IWTSListenerCallback iface;
IWTSPlugin* plugin;
IWTSVirtualChannelManager* channel_mgr;
rdpContext* rdpcontext;
const char* agent_uds_path;
};
typedef struct _SSHAGENT_CHANNEL_CALLBACK SSHAGENT_CHANNEL_CALLBACK;
struct _SSHAGENT_CHANNEL_CALLBACK
{
IWTSVirtualChannelCallback iface;
IWTSPlugin* plugin;
IWTSVirtualChannelManager* channel_mgr;
IWTSVirtualChannel* channel;
rdpContext* rdpcontext;
int agent_fd;
HANDLE thread;
CRITICAL_SECTION lock;
};
typedef struct _SSHAGENT_PLUGIN SSHAGENT_PLUGIN;
struct _SSHAGENT_PLUGIN
{
IWTSPlugin iface;
SSHAGENT_LISTENER_CALLBACK* listener_callback;
rdpContext* rdpcontext;
};
/**
* Function to open the connection to the sshagent
*
* @return The fd on success, otherwise -1
*/
static int connect_to_sshagent(const char* udspath)
{
int agent_fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (agent_fd == -1)
{
WLog_ERR(TAG, "Can't open Unix domain socket!");
return -1;
}
struct sockaddr_un addr;
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, udspath, sizeof(addr.sun_path) - 1);
int rc = connect(agent_fd, (struct sockaddr*)&addr, sizeof(addr));
if (rc != 0)
{
WLog_ERR(TAG, "Can't connect to Unix domain socket \"%s\"!",
udspath);
close(agent_fd);
return -1;
}
return agent_fd;
}
/**
* Entry point for thread to read from the ssh-agent socket and forward
* the data to RDP
*
* @return NULL
*/
static DWORD WINAPI sshagent_read_thread(LPVOID data)
{
SSHAGENT_CHANNEL_CALLBACK* callback = (SSHAGENT_CHANNEL_CALLBACK*)data;
BYTE buffer[4096];
int going = 1;
UINT status = CHANNEL_RC_OK;
while (going)
{
int bytes_read = read(callback->agent_fd,
buffer,
sizeof(buffer));
if (bytes_read == 0)
{
/* Socket closed cleanly at other end */
going = 0;
}
else if (bytes_read < 0)
{
if (errno != EINTR)
{
WLog_ERR(TAG,
"Error reading from sshagent, errno=%d",
errno);
status = ERROR_READ_FAULT;
going = 0;
}
}
else
{
/* Something read: forward to virtual channel */
status = callback->channel->Write(callback->channel,
bytes_read,
buffer,
NULL);
if (status != CHANNEL_RC_OK)
{
going = 0;
}
}
}
close(callback->agent_fd);
if (status != CHANNEL_RC_OK)
setChannelError(callback->rdpcontext, status,
"sshagent_read_thread reported an error");
ExitThread(status);
return status;
}
/**
* Callback for data received from the RDP server; forward this to ssh-agent
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT sshagent_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream* data)
{
SSHAGENT_CHANNEL_CALLBACK* callback = (SSHAGENT_CHANNEL_CALLBACK*) pChannelCallback;
BYTE* pBuffer = Stream_Pointer(data);
UINT32 cbSize = Stream_GetRemainingLength(data);
BYTE* pos = pBuffer;
/* Forward what we have received to the ssh agent */
UINT32 bytes_to_write = cbSize;
errno = 0;
while (bytes_to_write > 0)
{
int bytes_written = write(callback->agent_fd, pos,
bytes_to_write);
if (bytes_written < 0)
{
if (errno != EINTR)
{
WLog_ERR(TAG,
"Error writing to sshagent, errno=%d",
errno);
return ERROR_WRITE_FAULT;
}
}
else
{
bytes_to_write -= bytes_written;
pos += bytes_written;
}
}
/* Consume stream */
Stream_Seek(data, cbSize);
return CHANNEL_RC_OK;
}
/**
* Callback for when the virtual channel is closed
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT sshagent_on_close(IWTSVirtualChannelCallback* pChannelCallback)
{
SSHAGENT_CHANNEL_CALLBACK* callback = (SSHAGENT_CHANNEL_CALLBACK*) pChannelCallback;
/* Call shutdown() to wake up the read() in sshagent_read_thread(). */
shutdown(callback->agent_fd, SHUT_RDWR);
EnterCriticalSection(&callback->lock);
if (WaitForSingleObject(callback->thread, INFINITE) == WAIT_FAILED)
{
UINT error = GetLastError();
WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"!", error);
return error;
}
CloseHandle(callback->thread);
LeaveCriticalSection(&callback->lock);
DeleteCriticalSection(&callback->lock);
free(callback);
return CHANNEL_RC_OK;
}
/**
* Callback for when a new virtual channel is opened
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT sshagent_on_new_channel_connection(IWTSListenerCallback* pListenerCallback,
IWTSVirtualChannel* pChannel, BYTE* Data, BOOL* pbAccept,
IWTSVirtualChannelCallback** ppCallback)
{
SSHAGENT_CHANNEL_CALLBACK* callback;
SSHAGENT_LISTENER_CALLBACK* listener_callback = (SSHAGENT_LISTENER_CALLBACK*) pListenerCallback;
callback = (SSHAGENT_CHANNEL_CALLBACK*) calloc(1, sizeof(SSHAGENT_CHANNEL_CALLBACK));
if (!callback)
{
WLog_ERR(TAG, "calloc failed!");
return CHANNEL_RC_NO_MEMORY;
}
/* Now open a connection to the local ssh-agent. Do this for each
* connection to the plugin in case we mess up the agent session. */
callback->agent_fd
= connect_to_sshagent(listener_callback->agent_uds_path);
if (callback->agent_fd == -1)
{
free(callback);
return CHANNEL_RC_INITIALIZATION_ERROR;
}
InitializeCriticalSection(&callback->lock);
callback->iface.OnDataReceived = sshagent_on_data_received;
callback->iface.OnClose = sshagent_on_close;
callback->plugin = listener_callback->plugin;
callback->channel_mgr = listener_callback->channel_mgr;
callback->channel = pChannel;
callback->rdpcontext = listener_callback->rdpcontext;
callback->thread
= CreateThread(NULL,
0,
sshagent_read_thread,
(void*) callback,
0,
NULL);
if (!callback->thread)
{
WLog_ERR(TAG, "CreateThread failed!");
DeleteCriticalSection(&callback->lock);
free(callback);
return CHANNEL_RC_INITIALIZATION_ERROR;
}
*ppCallback = (IWTSVirtualChannelCallback*) callback;
return CHANNEL_RC_OK;
}
/**
* Callback for when the plugin is initialised
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT sshagent_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr)
{
SSHAGENT_PLUGIN* sshagent = (SSHAGENT_PLUGIN*) pPlugin;
sshagent->listener_callback = (SSHAGENT_LISTENER_CALLBACK*) calloc(1,
sizeof(SSHAGENT_LISTENER_CALLBACK));
if (!sshagent->listener_callback)
{
WLog_ERR(TAG, "calloc failed!");
return CHANNEL_RC_NO_MEMORY;
}
sshagent->listener_callback->rdpcontext = sshagent->rdpcontext;
sshagent->listener_callback->iface.OnNewChannelConnection = sshagent_on_new_channel_connection;
sshagent->listener_callback->plugin = pPlugin;
sshagent->listener_callback->channel_mgr = pChannelMgr;
sshagent->listener_callback->agent_uds_path = getenv("SSH_AUTH_SOCK");
if (sshagent->listener_callback->agent_uds_path == NULL)
{
WLog_ERR(TAG, "Environment variable $SSH_AUTH_SOCK undefined!");
free(sshagent->listener_callback);
sshagent->listener_callback = NULL;
return CHANNEL_RC_INITIALIZATION_ERROR;
}
return pChannelMgr->CreateListener(pChannelMgr, "SSHAGENT", 0,
(IWTSListenerCallback*) sshagent->listener_callback, NULL);
}
/**
* Callback for when the plugin is terminated
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT sshagent_plugin_terminated(IWTSPlugin* pPlugin)
{
SSHAGENT_PLUGIN* sshagent = (SSHAGENT_PLUGIN*) pPlugin;
free(sshagent);
return CHANNEL_RC_OK;
}
#ifdef BUILTIN_CHANNELS
#define DVCPluginEntry sshagent_DVCPluginEntry
#else
#define DVCPluginEntry FREERDP_API DVCPluginEntry
#endif
/**
* Main entry point for sshagent DVC plugin
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
{
UINT status = CHANNEL_RC_OK;
SSHAGENT_PLUGIN* sshagent;
sshagent = (SSHAGENT_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "sshagent");
if (!sshagent)
{
sshagent = (SSHAGENT_PLUGIN*) calloc(1, sizeof(SSHAGENT_PLUGIN));
if (!sshagent)
{
WLog_ERR(TAG, "calloc failed!");
return CHANNEL_RC_NO_MEMORY;
}
sshagent->iface.Initialize = sshagent_plugin_initialize;
sshagent->iface.Connected = NULL;
sshagent->iface.Disconnected = NULL;
sshagent->iface.Terminated = sshagent_plugin_terminated;
sshagent->rdpcontext = ((freerdp*)((rdpSettings*) pEntryPoints->GetRdpSettings(
pEntryPoints))->instance)->context;
status = pEntryPoints->RegisterPlugin(pEntryPoints, "sshagent", (IWTSPlugin*) sshagent);
}
return status;
}
/* vim: set sw=8:ts=8:noet: */

View File

@ -0,0 +1,42 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* SSH Agent Virtual Channel Extension
*
* Copyright 2013 Christian Hofstaedtler
* Copyright 2017 Ben Cohen
*
* 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 SSHAGENT_MAIN_H
#define SSHAGENT_MAIN_H
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <winpr/stream.h>
#include <freerdp/svc.h>
#include <freerdp/addin.h>
#include <freerdp/channels/log.h>
#define DVC_TAG CHANNELS_TAG("sshagent.client")
#ifdef WITH_DEBUG_SSHAGENT
#define DEBUG_SSHAGENT(...) WLog_DBG(DVC_TAG, __VA_ARGS__)
#else
#define DEBUG_SSHAGENT(...) do { } while (0)
#endif
#endif /* SSHAGENT_MAIN_H */

View File

@ -0,0 +1,31 @@
# FreeRDP: A Remote Desktop Protocol Implementation
# FreeRDP cmake build script
#
# Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
# Copyright 2017 Ben Cohen
#
# 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.
define_channel_server("sshagent")
set(${MODULE_PREFIX}_SRCS
sshagent_main.c)
add_channel_server_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "DVCPluginEntry")
target_link_libraries(${MODULE_NAME} freerdp)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Server")

View File

@ -0,0 +1,422 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* SSH Agent Virtual Channel Extension
*
* Copyright 2012-2013 Jay Sorg
* Copyright 2012-2013 Laxmikant Rashinkar
* Copyright 2017 Ben Cohen
*
* 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.
*/
/*
* Portions are from OpenSSH, under the following license:
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* The authentication agent program.
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* xrdp-ssh-agent.c: program to forward ssh-agent protocol from xrdp session
*
* This performs the equivalent function of ssh-agent on a server you connect
* to via ssh, but the ssh-agent protocol is over an RDP dynamic virtual
* channel and not an SSH channel.
*
* This will print out variables to set in your environment (specifically,
* $SSH_AUTH_SOCK) for ssh clients to find the agent's socket, then it will
* run in the background. This is suitable to run just as you would run the
* normal ssh-agent, e.g. in your Xsession or /etc/xrdp/startwm.sh.
*
* Your RDP client needs to be running a compatible client-side plugin
* that can see a local ssh-agent.
*
* usage (from within an xrdp session):
* xrdp-ssh-agent
*
* build instructions:
* gcc xrdp-ssh-agent.c -o xrdp-ssh-agent -L./.libs -lxrdpapi -Wall
*
* protocol specification:
* Forward data verbatim over RDP dynamic virtual channel named "sshagent"
* between a ssh client on the xrdp server and the real ssh-agent where
* the RDP client is running. Each connection by a separate client to
* xrdp-ssh-agent gets a separate DVC invocation.
*/
#if defined(HAVE_CONFIG_H)
#include <config.h>
#endif
#ifdef __WIN32__
#include <mstsapi.h>
#endif
#include <freerdp/channels/wtsvc.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/resource.h>
#define _PATH_DEVNULL "/dev/null"
char socket_name[PATH_MAX];
char socket_dir[PATH_MAX];
static int sa_uds_fd = -1;
static int is_going = 1;
/* Make a template filename for mk[sd]temp() */
/* This is from mktemp_proto() in misc.c from openssh */
void
mktemp_proto(char* s, size_t len)
{
const char* tmpdir;
int r;
if ((tmpdir = getenv("TMPDIR")) != NULL)
{
r = snprintf(s, len, "%s/ssh-XXXXXXXXXXXX", tmpdir);
if (r > 0 && (size_t)r < len)
return;
}
r = snprintf(s, len, "/tmp/ssh-XXXXXXXXXXXX");
if (r < 0 || (size_t)r >= len)
{
fprintf(stderr, "%s: template string too short", __func__);
exit(1);
}
}
/* This uses parts of main() in ssh-agent.c from openssh */
static void
setup_ssh_agent(struct sockaddr_un* addr)
{
int rc;
/* Create private directory for agent socket */
mktemp_proto(socket_dir, sizeof(socket_dir));
if (mkdtemp(socket_dir) == NULL)
{
perror("mkdtemp: private socket dir");
exit(1);
}
snprintf(socket_name, sizeof socket_name, "%s/agent.%ld", socket_dir,
(long)getpid());
/* Create unix domain socket */
unlink(socket_name);
sa_uds_fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (sa_uds_fd == -1)
{
fprintf(stderr, "sshagent: socket creation failed");
exit(2);
}
memset(addr, 0, sizeof(struct sockaddr_un));
addr->sun_family = AF_UNIX;
strncpy(addr->sun_path, socket_name, sizeof(addr->sun_path));
addr->sun_path[sizeof(addr->sun_path) - 1] = 0;
/* Create with privileges rw------- so other users can't access the UDS */
mode_t umask_sav = umask(0177);
rc = bind(sa_uds_fd, (struct sockaddr*)addr, sizeof(struct sockaddr_un));
if (rc != 0)
{
fprintf(stderr, "sshagent: bind failed");
close(sa_uds_fd);
unlink(socket_name);
exit(3);
}
umask(umask_sav);
rc = listen(sa_uds_fd, /* backlog = */ 5);
if (rc != 0)
{
fprintf(stderr, "listen failed\n");
close(sa_uds_fd);
unlink(socket_name);
exit(1);
}
/* Now fork: the child becomes the ssh-agent daemon and the parent prints
* out the pid and socket name. */
pid_t pid = fork();
if (pid == -1)
{
perror("fork");
exit(1);
}
else if (pid != 0)
{
/* Parent */
close(sa_uds_fd);
printf("SSH_AUTH_SOCK=%s; export SSH_AUTH_SOCK;\n", socket_name);
printf("SSH_AGENT_PID=%d; export SSH_AGENT_PID;\n", pid);
printf("echo Agent pid %d;\n", pid);
exit(0);
}
/* Child */
if (setsid() == -1)
{
fprintf(stderr, "setsid failed");
exit(1);
}
(void)chdir("/");
int devnullfd;
if ((devnullfd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1)
{
/* XXX might close listen socket */
(void)dup2(devnullfd, STDIN_FILENO);
(void)dup2(devnullfd, STDOUT_FILENO);
(void)dup2(devnullfd, STDERR_FILENO);
if (devnullfd > 2)
close(devnullfd);
}
/* deny core dumps, since memory contains unencrypted private keys */
struct rlimit rlim;
rlim.rlim_cur = rlim.rlim_max = 0;
if (setrlimit(RLIMIT_CORE, &rlim) < 0)
{
fprintf(stderr, "setrlimit RLIMIT_CORE: %s", strerror(errno));
exit(1);
}
}
static void
handle_connection(int client_fd)
{
int rdp_fd = -1;
int rc;
void* channel = WTSVirtualChannelOpenEx(WTS_CURRENT_SESSION,
"SSHAGENT",
WTS_CHANNEL_OPTION_DYNAMIC_PRI_MED);
if (channel == NULL)
{
fprintf(stderr, "WTSVirtualChannelOpenEx() failed\n");
}
unsigned int retlen;
int* retdata;
rc = WTSVirtualChannelQuery(channel,
WTSVirtualFileHandle,
(void**)&retdata,
&retlen);
if (!rc)
{
fprintf(stderr, "WTSVirtualChannelQuery() failed\n");
}
if (retlen != sizeof(rdp_fd))
{
fprintf(stderr, "WTSVirtualChannelQuery() returned wrong length %d\n",
retlen);
}
rdp_fd = *retdata;
int client_going = 1;
while (client_going)
{
/* Wait for data from RDP or the client */
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(client_fd, &readfds);
FD_SET(rdp_fd, &readfds);
select(FD_SETSIZE, &readfds, NULL, NULL, NULL);
if (FD_ISSET(rdp_fd, &readfds))
{
/* Read from RDP and write to the client */
char buffer[4096];
unsigned int bytes_to_write;
rc = WTSVirtualChannelRead(channel,
/* TimeOut = */ 5000,
buffer,
sizeof(buffer),
&bytes_to_write);
if (rc == 1)
{
char* pos = buffer;
errno = 0;
while (bytes_to_write > 0)
{
int bytes_written = send(client_fd, pos, bytes_to_write, 0);
if (bytes_written > 0)
{
bytes_to_write -= bytes_written;
pos += bytes_written;
}
else if (bytes_written == 0)
{
fprintf(stderr, "send() returned 0!\n");
}
else if (errno != EINTR)
{
/* Error */
fprintf(stderr, "Error %d on recv\n", errno);
client_going = 0;
}
}
}
else
{
/* Error */
fprintf(stderr, "WTSVirtualChannelRead() failed: %d\n", errno);
client_going = 0;
}
}
if (FD_ISSET(client_fd, &readfds))
{
/* Read from the client and write to RDP */
char buffer[4096];
ssize_t bytes_to_write = recv(client_fd, buffer, sizeof(buffer), 0);
if (bytes_to_write > 0)
{
char* pos = buffer;
while (bytes_to_write > 0)
{
unsigned int bytes_written;
int rc = WTSVirtualChannelWrite(channel,
pos,
bytes_to_write,
&bytes_written);
if (rc == 0)
{
fprintf(stderr, "WTSVirtualChannelWrite() failed: %d\n",
errno);
client_going = 0;
}
else
{
bytes_to_write -= bytes_written;
pos += bytes_written;
}
}
}
else if (bytes_to_write == 0)
{
/* Client has closed connection */
client_going = 0;
}
else
{
/* Error */
fprintf(stderr, "Error %d on recv\n", errno);
client_going = 0;
}
}
}
WTSVirtualChannelClose(channel);
}
int
main(int argc, char** argv)
{
/* Setup the Unix domain socket and daemon process */
struct sockaddr_un addr;
setup_ssh_agent(&addr);
/* Wait for a client to connect to the socket */
while (is_going)
{
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(sa_uds_fd, &readfds);
select(FD_SETSIZE, &readfds, NULL, NULL, NULL);
/* If something connected then get it...
* (You can test this using "socat - UNIX-CONNECT:<udspath>".) */
if (FD_ISSET(sa_uds_fd, &readfds))
{
socklen_t addrsize = sizeof(addr);
int client_fd = accept(sa_uds_fd,
(struct sockaddr*)&addr,
&addrsize);
handle_connection(client_fd);
close(client_fd);
}
}
close(sa_uds_fd);
unlink(socket_name);
return 0;
}
/* vim: set sw=4:ts=4:et: */

View File

@ -72,7 +72,7 @@ static BOOL tsmf_alsa_open(ITSMFAudioDevice *audio, const char *device)
}
else
{
strncpy(alsa->device, device, sizeof(alsa->device));
strncpy(alsa->device, device, sizeof(alsa->device) - 1);
}
return tsmf_alsa_open_device(alsa);
}

View File

@ -61,6 +61,11 @@
#define AV_CODEC_ID_AC3 CODEC_ID_AC3
#endif
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56, 34, 2)
#define AV_CODEC_CAP_TRUNCATED CODEC_CAP_TRUNCATED
#define AV_CODEC_FLAG_TRUNCATED CODEC_FLAG_TRUNCATED
#endif
#if LIBAVUTIL_VERSION_MAJOR < 52
#define AV_PIX_FMT_YUV420P PIX_FMT_YUV420P
#endif
@ -75,12 +80,12 @@ typedef struct _TSMFFFmpegDecoder
#else
enum AVCodecID codec_id;
#endif
AVCodecContext *codec_context;
AVCodec *codec;
AVFrame *frame;
AVCodecContext* codec_context;
AVCodec* codec;
AVFrame* frame;
int prepared;
BYTE *decoded_data;
BYTE* decoded_data;
UINT32 decoded_size;
UINT32 decoded_size_max;
} TSMFFFmpegDecoder;
@ -89,15 +94,17 @@ static BOOL tsmf_ffmpeg_init_context(ITSMFDecoder* decoder)
{
TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
mdecoder->codec_context = avcodec_alloc_context3(NULL);
if (!mdecoder->codec_context)
{
WLog_ERR(TAG, "avcodec_alloc_context failed.");
return FALSE;
}
return TRUE;
}
static BOOL tsmf_ffmpeg_init_video_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYPE *media_type)
static BOOL tsmf_ffmpeg_init_video_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYPE* media_type)
{
TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
mdecoder->codec_context->width = media_type->Width;
@ -113,7 +120,7 @@ static BOOL tsmf_ffmpeg_init_video_stream(ITSMFDecoder* decoder, const TS_AM_MED
return TRUE;
}
static BOOL tsmf_ffmpeg_init_audio_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYPE *media_type)
static BOOL tsmf_ffmpeg_init_audio_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYPE* media_type)
{
TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
mdecoder->codec_context->sample_rate = media_type->SamplesPerSecond.Numerator;
@ -140,14 +147,14 @@ static BOOL tsmf_ffmpeg_init_audio_stream(ITSMFDecoder* decoder, const TS_AM_MED
return TRUE;
}
static BOOL tsmf_ffmpeg_init_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYPE *media_type)
static BOOL tsmf_ffmpeg_init_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYPE* media_type)
{
BYTE *p;
BYTE* p;
UINT32 size;
const BYTE *s;
const BYTE* s;
TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
mdecoder->codec = avcodec_find_decoder(mdecoder->codec_id);
if (!mdecoder->codec)
{
WLog_ERR(TAG, "avcodec_find_decoder failed.");
@ -156,16 +163,21 @@ static BOOL tsmf_ffmpeg_init_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYP
mdecoder->codec_context->codec_id = mdecoder->codec_id;
mdecoder->codec_context->codec_type = mdecoder->media_type;
switch(mdecoder->media_type)
switch (mdecoder->media_type)
{
case AVMEDIA_TYPE_VIDEO:
if (!tsmf_ffmpeg_init_video_stream(decoder, media_type))
return FALSE;
break;
case AVMEDIA_TYPE_AUDIO:
if (!tsmf_ffmpeg_init_audio_stream(decoder, media_type))
return FALSE;
break;
default:
WLog_ERR(TAG, "unknown media_type %d", mdecoder->media_type);
break;
@ -176,11 +188,12 @@ static BOOL tsmf_ffmpeg_init_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYP
/* Add a padding to avoid invalid memory read in some codec */
mdecoder->codec_context->extradata_size = media_type->ExtraDataSize + 8;
mdecoder->codec_context->extradata = calloc(1, mdecoder->codec_context->extradata_size);
if (!mdecoder->codec_context->extradata)
return FALSE;
if (media_type->SubType == TSMF_SUB_TYPE_AVC1 &&
media_type->FormatType == TSMF_FORMAT_TYPE_MPEG2VIDEOINFO)
media_type->FormatType == TSMF_FORMAT_TYPE_MPEG2VIDEOINFO)
{
/* The extradata format that FFmpeg uses is following CodecPrivate in Matroska.
See http://haali.su/mkv/codecs.pdf */
@ -207,62 +220,77 @@ static BOOL tsmf_ffmpeg_init_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYP
}
}
if (mdecoder->codec->capabilities & CODEC_CAP_TRUNCATED)
mdecoder->codec_context->flags |= CODEC_FLAG_TRUNCATED;
if (mdecoder->codec->capabilities & AV_CODEC_CAP_TRUNCATED)
mdecoder->codec_context->flags |= AV_CODEC_FLAG_TRUNCATED;
return TRUE;
}
static BOOL tsmf_ffmpeg_prepare(ITSMFDecoder* decoder)
{
TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
if (avcodec_open2(mdecoder->codec_context, mdecoder->codec, NULL) < 0)
{
WLog_ERR(TAG, "avcodec_open2 failed.");
return FALSE;
}
mdecoder->prepared = 1;
return TRUE;
}
static BOOL tsmf_ffmpeg_set_format(ITSMFDecoder* decoder, TS_AM_MEDIA_TYPE *media_type)
static BOOL tsmf_ffmpeg_set_format(ITSMFDecoder* decoder, TS_AM_MEDIA_TYPE* media_type)
{
TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
switch(media_type->MajorType)
switch (media_type->MajorType)
{
case TSMF_MAJOR_TYPE_VIDEO:
mdecoder->media_type = AVMEDIA_TYPE_VIDEO;
break;
case TSMF_MAJOR_TYPE_AUDIO:
mdecoder->media_type = AVMEDIA_TYPE_AUDIO;
break;
default:
return FALSE;
}
switch(media_type->SubType)
switch (media_type->SubType)
{
case TSMF_SUB_TYPE_WVC1:
mdecoder->codec_id = AV_CODEC_ID_VC1;
break;
case TSMF_SUB_TYPE_WMA2:
mdecoder->codec_id = AV_CODEC_ID_WMAV2;
break;
case TSMF_SUB_TYPE_WMA9:
mdecoder->codec_id = AV_CODEC_ID_WMAPRO;
break;
case TSMF_SUB_TYPE_MP3:
mdecoder->codec_id = AV_CODEC_ID_MP3;
break;
case TSMF_SUB_TYPE_MP2A:
mdecoder->codec_id = AV_CODEC_ID_MP2;
break;
case TSMF_SUB_TYPE_MP2V:
mdecoder->codec_id = AV_CODEC_ID_MPEG2VIDEO;
break;
case TSMF_SUB_TYPE_WMV3:
mdecoder->codec_id = AV_CODEC_ID_WMV3;
break;
case TSMF_SUB_TYPE_AAC:
mdecoder->codec_id = AV_CODEC_ID_AAC;
/* For AAC the pFormat is a HEAACWAVEINFO struct, and the codec data
is at the end of it. See
http://msdn.microsoft.com/en-us/library/dd757806.aspx */
@ -271,32 +299,41 @@ static BOOL tsmf_ffmpeg_set_format(ITSMFDecoder* decoder, TS_AM_MEDIA_TYPE *medi
media_type->ExtraData += 12;
media_type->ExtraDataSize -= 12;
}
break;
case TSMF_SUB_TYPE_H264:
case TSMF_SUB_TYPE_AVC1:
mdecoder->codec_id = AV_CODEC_ID_H264;
break;
case TSMF_SUB_TYPE_AC3:
mdecoder->codec_id = AV_CODEC_ID_AC3;
break;
default:
return FALSE;
}
if (!tsmf_ffmpeg_init_context(decoder))
return FALSE;
if (!tsmf_ffmpeg_init_stream(decoder, media_type))
return FALSE;
if (!tsmf_ffmpeg_prepare(decoder))
return FALSE;
return TRUE;
}
static BOOL tsmf_ffmpeg_decode_video(ITSMFDecoder* decoder, const BYTE *data, UINT32 data_size, UINT32 extensions)
static BOOL tsmf_ffmpeg_decode_video(ITSMFDecoder* decoder, const BYTE* data, UINT32 data_size,
UINT32 extensions)
{
TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
int decoded;
int len;
AVFrame *frame;
AVFrame* frame;
BOOL ret = TRUE;
#if LIBAVCODEC_VERSION_MAJOR < 52 || (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR <= 20)
len = avcodec_decode_video(mdecoder->codec_context, mdecoder->frame, &decoded, data, data_size);
@ -304,13 +341,16 @@ static BOOL tsmf_ffmpeg_decode_video(ITSMFDecoder* decoder, const BYTE *data, UI
{
AVPacket pkt;
av_init_packet(&pkt);
pkt.data = (BYTE *) data;
pkt.data = (BYTE*) data;
pkt.size = data_size;
if (extensions & TSMM_SAMPLE_EXT_CLEANPOINT)
pkt.flags |= AV_PKT_FLAG_KEY;
len = avcodec_decode_video2(mdecoder->codec_context, mdecoder->frame, &decoded, &pkt);
}
#endif
if (len < 0)
{
WLog_ERR(TAG, "data_size %"PRIu32", avcodec_decode_video failed (%d)", data_size, len);
@ -324,14 +364,15 @@ static BOOL tsmf_ffmpeg_decode_video(ITSMFDecoder* decoder, const BYTE *data, UI
else
{
DEBUG_TSMF("linesize[0] %d linesize[1] %d linesize[2] %d linesize[3] %d "
"pix_fmt %d width %d height %d",
mdecoder->frame->linesize[0], mdecoder->frame->linesize[1],
mdecoder->frame->linesize[2], mdecoder->frame->linesize[3],
mdecoder->codec_context->pix_fmt,
mdecoder->codec_context->width, mdecoder->codec_context->height);
"pix_fmt %d width %d height %d",
mdecoder->frame->linesize[0], mdecoder->frame->linesize[1],
mdecoder->frame->linesize[2], mdecoder->frame->linesize[3],
mdecoder->codec_context->pix_fmt,
mdecoder->codec_context->width, mdecoder->codec_context->height);
mdecoder->decoded_size = avpicture_get_size(mdecoder->codec_context->pix_fmt,
mdecoder->codec_context->width, mdecoder->codec_context->height);
mdecoder->codec_context->width, mdecoder->codec_context->height);
mdecoder->decoded_data = calloc(1, mdecoder->decoded_size);
if (!mdecoder->decoded_data)
return FALSE;
@ -341,151 +382,172 @@ static BOOL tsmf_ffmpeg_decode_video(ITSMFDecoder* decoder, const BYTE *data, UI
frame = av_frame_alloc();
#endif
avpicture_fill((AVPicture*) frame, mdecoder->decoded_data,
mdecoder->codec_context->pix_fmt,
mdecoder->codec_context->width, mdecoder->codec_context->height);
mdecoder->codec_context->pix_fmt,
mdecoder->codec_context->width, mdecoder->codec_context->height);
av_picture_copy((AVPicture*) frame, (AVPicture*) mdecoder->frame,
mdecoder->codec_context->pix_fmt,
mdecoder->codec_context->width, mdecoder->codec_context->height);
mdecoder->codec_context->pix_fmt,
mdecoder->codec_context->width, mdecoder->codec_context->height);
av_free(frame);
}
return ret;
}
static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder* decoder, const BYTE *data, UINT32 data_size, UINT32 extensions)
static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder* decoder, const BYTE* data, UINT32 data_size,
UINT32 extensions)
{
TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
int len;
int frame_size;
UINT32 src_size;
const BYTE *src;
BYTE *dst;
const BYTE* src;
BYTE* dst;
int dst_offset;
#if 0
WLog_DBG(TAG, ("tsmf_ffmpeg_decode_audio: data_size %"PRIu32"", data_size));
int i;
for(i = 0; i < data_size; i++)
for (i = 0; i < data_size; i++)
{
WLog_DBG(TAG, ("%02"PRIX8"", data[i]));
if (i % 16 == 15)
WLog_DBG(TAG, ("\n"));
}
#endif
if (mdecoder->decoded_size_max == 0)
mdecoder->decoded_size_max = MAX_AUDIO_FRAME_SIZE + 16;
mdecoder->decoded_data = calloc(1, mdecoder->decoded_size_max);
if (!mdecoder->decoded_data)
return FALSE;
/* align the memory for SSE2 needs */
dst = (BYTE *)(((uintptr_t) mdecoder->decoded_data + 15) & ~ 0x0F);
dst = (BYTE*)(((uintptr_t) mdecoder->decoded_data + 15) & ~ 0x0F);
dst_offset = dst - mdecoder->decoded_data;
src = data;
src_size = data_size;
while(src_size > 0)
while (src_size > 0)
{
/* Ensure enough space for decoding */
if (mdecoder->decoded_size_max - mdecoder->decoded_size < MAX_AUDIO_FRAME_SIZE)
{
BYTE *tmp_data;
BYTE* tmp_data;
tmp_data = realloc(mdecoder->decoded_data, mdecoder->decoded_size_max * 2 + 16);
if (!tmp_data)
return FALSE;
mdecoder->decoded_size_max = mdecoder->decoded_size_max * 2 + 16;
mdecoder->decoded_data = tmp_data;
dst = (BYTE*)(((uintptr_t)mdecoder->decoded_data + 15) & ~ 0x0F);
dst = (BYTE *)(((uintptr_t)mdecoder->decoded_data + 15) & ~ 0x0F);
if (dst - mdecoder->decoded_data != dst_offset)
{
/* re-align the memory if the alignment has changed after realloc */
memmove(dst, mdecoder->decoded_data + dst_offset, mdecoder->decoded_size);
dst_offset = dst - mdecoder->decoded_data;
}
dst += mdecoder->decoded_size;
}
frame_size = mdecoder->decoded_size_max - mdecoder->decoded_size;
#if LIBAVCODEC_VERSION_MAJOR < 52 || (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR <= 20)
len = avcodec_decode_audio2(mdecoder->codec_context,
(int16_t *) dst, &frame_size, src, src_size);
(int16_t*) dst, &frame_size, src, src_size);
#else
{
#if LIBAVCODEC_VERSION_MAJOR < 55
AVFrame *decoded_frame = avcodec_alloc_frame();
AVFrame* decoded_frame = avcodec_alloc_frame();
#else
AVFrame *decoded_frame = av_frame_alloc();
AVFrame* decoded_frame = av_frame_alloc();
#endif
int got_frame = 0;
AVPacket pkt;
av_init_packet(&pkt);
pkt.data = (BYTE *) src;
pkt.data = (BYTE*) src;
pkt.size = src_size;
len = avcodec_decode_audio4(mdecoder->codec_context, decoded_frame, &got_frame, &pkt);
if (len >= 0 && got_frame)
{
frame_size = av_samples_get_buffer_size(NULL, mdecoder->codec_context->channels,
decoded_frame->nb_samples, mdecoder->codec_context->sample_fmt, 1);
decoded_frame->nb_samples, mdecoder->codec_context->sample_fmt, 1);
memcpy(dst, decoded_frame->data[0], frame_size);
}
else
{
frame_size = 0;
}
av_free(decoded_frame);
}
#endif
if (len > 0)
{
src += len;
src_size -= len;
}
if(frame_size > 0)
if (frame_size > 0)
{
mdecoder->decoded_size += frame_size;
dst += frame_size;
}
}
if (mdecoder->decoded_size == 0)
{
free(mdecoder->decoded_data);
mdecoder->decoded_data = NULL;
}
else
if (dst_offset)
{
/* move the aligned decoded data to original place */
memmove(mdecoder->decoded_data, mdecoder->decoded_data + dst_offset, mdecoder->decoded_size);
}
else if (dst_offset)
{
/* move the aligned decoded data to original place */
memmove(mdecoder->decoded_data, mdecoder->decoded_data + dst_offset, mdecoder->decoded_size);
}
DEBUG_TSMF("data_size %"PRIu32" decoded_size %"PRIu32"",
data_size, mdecoder->decoded_size);
data_size, mdecoder->decoded_size);
return TRUE;
}
static BOOL tsmf_ffmpeg_decode(ITSMFDecoder* decoder, const BYTE *data, UINT32 data_size, UINT32 extensions)
static BOOL tsmf_ffmpeg_decode(ITSMFDecoder* decoder, const BYTE* data, UINT32 data_size,
UINT32 extensions)
{
TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
if (mdecoder->decoded_data)
{
free(mdecoder->decoded_data);
mdecoder->decoded_data = NULL;
}
mdecoder->decoded_size = 0;
switch(mdecoder->media_type)
switch (mdecoder->media_type)
{
case AVMEDIA_TYPE_VIDEO:
return tsmf_ffmpeg_decode_video(decoder, data, data_size, extensions);
case AVMEDIA_TYPE_AUDIO:
return tsmf_ffmpeg_decode_audio(decoder, data, data_size, extensions);
default:
WLog_ERR(TAG, "unknown media type.");
return FALSE;
}
}
static BYTE *tsmf_ffmpeg_get_decoded_data(ITSMFDecoder* decoder, UINT32 *size)
static BYTE* tsmf_ffmpeg_get_decoded_data(ITSMFDecoder* decoder, UINT32* size)
{
BYTE *buf;
BYTE* buf;
TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
*size = mdecoder->decoded_size;
buf = mdecoder->decoded_data;
@ -502,14 +564,15 @@ static UINT32 tsmf_ffmpeg_get_decoded_format(ITSMFDecoder* decoder)
{
case AV_PIX_FMT_YUV420P:
return RDP_PIXFMT_I420;
default:
WLog_ERR(TAG, "unsupported pixel format %u",
mdecoder->codec_context->pix_fmt);
return (UINT32) -1;
mdecoder->codec_context->pix_fmt);
return (UINT32) - 1;
}
}
static BOOL tsmf_ffmpeg_get_decoded_dimension(ITSMFDecoder* decoder, UINT32 *width, UINT32 *height)
static BOOL tsmf_ffmpeg_get_decoded_dimension(ITSMFDecoder* decoder, UINT32* width, UINT32* height)
{
TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
@ -528,6 +591,7 @@ static BOOL tsmf_ffmpeg_get_decoded_dimension(ITSMFDecoder* decoder, UINT32 *wid
static void tsmf_ffmpeg_free(ITSMFDecoder* decoder)
{
TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
if (mdecoder->frame)
av_free(mdecoder->frame);
@ -541,10 +605,16 @@ static void tsmf_ffmpeg_free(ITSMFDecoder* decoder)
free(mdecoder->codec_context->extradata);
av_free(mdecoder->codec_context);
}
free(decoder);
}
static BOOL initialized = FALSE;
static INIT_ONCE g_Initialized = INIT_ONCE_STATIC_INIT;
static BOOL CALLBACK InitializeAvCodecs(PINIT_ONCE once, PVOID param, PVOID* context)
{
avcodec_register_all();
return TRUE;
}
#ifdef BUILTIN_CHANNELS
#define freerdp_tsmf_client_subsystem_entry ffmpeg_freerdp_tsmf_client_decoder_subsystem_entry
@ -555,15 +625,8 @@ static BOOL initialized = FALSE;
ITSMFDecoder* freerdp_tsmf_client_subsystem_entry(void)
{
TSMFFFmpegDecoder* decoder;
if (!initialized)
{
avcodec_register_all();
initialized = TRUE;
}
InitOnceExecuteOnce(&g_Initialized, InitializeAvCodecs, NULL, NULL);
WLog_DBG(TAG, "TSMFDecoderEntry FFMPEG");
decoder = (TSMFFFmpegDecoder*) calloc(1, sizeof(TSMFFFmpegDecoder));
if (!decoder)
@ -575,6 +638,5 @@ ITSMFDecoder* freerdp_tsmf_client_subsystem_entry(void)
decoder->iface.GetDecodedFormat = tsmf_ffmpeg_get_decoded_format;
decoder->iface.GetDecodedDimension = tsmf_ffmpeg_get_decoded_dimension;
decoder->iface.Free = tsmf_ffmpeg_free;
return (ITSMFDecoder*) decoder;
}

View File

@ -33,7 +33,15 @@
#include <winpr/thread.h>
#include <winpr/string.h>
#if __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wparentheses-equality"
#endif /* __clang__ */
#include <gst/gst.h>
#if __clang__
#pragma clang diagnostic pop
#endif /* __clang__ */
#if GST_VERSION_MAJOR > 0
#include <gst/video/videooverlay.h>
#else

View File

@ -33,7 +33,15 @@
#include <winpr/string.h>
#if __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wparentheses-equality"
#endif /* __clang__ */
#include <gst/gst.h>
#if __clang__
#pragma clang diagnostic pop
#endif /* __clang__ */
#include <gst/app/gstappsrc.h>
#include <gst/app/gstappsink.h>

View File

@ -81,7 +81,7 @@ static BOOL tsmf_oss_open(ITSMFAudioDevice* audio, const char* device)
}
else
{
strncpy(oss->dev_name, device, sizeof(oss->dev_name));
strncpy(oss->dev_name, device, sizeof(oss->dev_name) - 1);
}
if ((oss->pcm_handle = open(oss->dev_name, O_WRONLY)) < 0)

View File

@ -115,7 +115,7 @@ static BOOL tsmf_pulse_open(ITSMFAudioDevice *audio, const char *device)
TSMFPulseAudioDevice *pulse = (TSMFPulseAudioDevice *) audio;
if(device)
{
strcpy(pulse->device, device);
strncpy(pulse->device, device, sizeof(pulse->device) - 1);
}
pulse->mainloop = pa_threaded_mainloop_new();
if(!pulse->mainloop)

View File

@ -482,7 +482,7 @@ UINT tsmf_ifman_update_geometry_info(TSMF_IFMAN* ifman)
int num_rects = 0;
UINT error = CHANNEL_RC_OK;
int i;
int pos;
size_t pos;
if (Stream_GetRemainingLength(ifman->input) < GUID_SIZE + 32)
return ERROR_INVALID_DATA;

View File

@ -123,7 +123,7 @@ BOOL tsmf_playback_ack(IWTSVirtualChannelCallback *pChannelCallback,
*/
static UINT tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream *data)
{
int length;
size_t length;
wStream *input;
wStream *output;
UINT error = CHANNEL_RC_OK;

View File

@ -737,7 +737,7 @@ static BOOL tsmf_sample_playback(TSMF_SAMPLE* sample)
return ret;
}
static void* tsmf_stream_ack_func(void* arg)
static DWORD WINAPI tsmf_stream_ack_func(LPVOID arg)
{
HANDLE hdl[2];
TSMF_STREAM* stream = (TSMF_STREAM*) arg;
@ -817,11 +817,11 @@ static void* tsmf_stream_ack_func(void* arg)
"tsmf_stream_ack_func reported an error");
DEBUG_TSMF("out %"PRIu32"", stream->stream_id);
ExitThread(0);
return NULL;
ExitThread(error);
return error;
}
static void* tsmf_stream_playback_func(void* arg)
static DWORD WINAPI tsmf_stream_playback_func(LPVOID arg)
{
HANDLE hdl[2];
TSMF_SAMPLE* sample = NULL;
@ -907,8 +907,8 @@ static void* tsmf_stream_playback_func(void* arg)
"tsmf_stream_playback_func reported an error");
DEBUG_TSMF("out %"PRIu32"", stream->stream_id);
ExitThread(0);
return NULL;
ExitThread(error);
return error;
}
static BOOL tsmf_stream_start(TSMF_STREAM* stream)
@ -1259,13 +1259,13 @@ TSMF_STREAM* tsmf_stream_new(TSMF_PRESENTATION* presentation, UINT32 stream_id,
goto error_sample_ack_list;
stream->sample_ack_list->object.fnObjectFree = tsmf_sample_free;
stream->play_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) tsmf_stream_playback_func,
stream->play_thread = CreateThread(NULL, 0, tsmf_stream_playback_func,
stream, CREATE_SUSPENDED, NULL);
if (!stream->play_thread)
goto error_play_thread;
stream->ack_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)tsmf_stream_ack_func, stream,
stream->ack_thread = CreateThread(NULL, 0, tsmf_stream_ack_func, stream,
CREATE_SUSPENDED, NULL);
if (!stream->ack_thread)

File diff suppressed because it is too large Load Diff

View File

@ -35,16 +35,16 @@
int libusb_debug;
#define BASIC_STATE_FUNC_DEFINED(_arg, _type) \
static _type udevman_get_##_arg (IUDEVMAN* idevman) \
{ \
UDEVMAN * udevman = (UDEVMAN *) idevman; \
return udevman->_arg; \
} \
static void udevman_set_##_arg (IUDEVMAN* idevman, _type _t) \
{ \
UDEVMAN * udevman = (UDEVMAN *) idevman; \
udevman->_arg = _t; \
}
static _type udevman_get_##_arg (IUDEVMAN* idevman) \
{ \
UDEVMAN * udevman = (UDEVMAN *) idevman; \
return udevman->_arg; \
} \
static void udevman_set_##_arg (IUDEVMAN* idevman, _type _t) \
{ \
UDEVMAN * udevman = (UDEVMAN *) idevman; \
udevman->_arg = _t; \
}
#define BASIC_STATE_FUNC_REGISTER(_arg, _man) \
_man->iface.get_##_arg = udevman_get_##_arg; \
@ -90,17 +90,14 @@ static IUDEVICE* udevman_get_next(IUDEVMAN* idevman)
{
UDEVMAN* udevman = (UDEVMAN*) idevman;
IUDEVICE* pdev;
pdev = udevman->idev;
udevman->idev = (IUDEVICE*) ((UDEVICE*) udevman->idev)->next;
udevman->idev = (IUDEVICE*)((UDEVICE*) udevman->idev)->next;
return pdev;
}
static IUDEVICE* udevman_get_udevice_by_addr(IUDEVMAN* idevman, int bus_number, int dev_number)
{
IUDEVICE* pdev;
idevman->loading_lock(idevman);
idevman->rewind(idevman);
@ -117,23 +114,22 @@ static IUDEVICE* udevman_get_udevice_by_addr(IUDEVMAN* idevman, int bus_number,
idevman->loading_unlock(idevman);
WLog_WARN(TAG, "bus:%d dev:%d not exist in udevman",
bus_number, dev_number);
bus_number, dev_number);
return NULL;
}
static int udevman_register_udevice(IUDEVMAN* idevman, int bus_number, int dev_number,
int UsbDevice, UINT16 idVendor, UINT16 idProduct, int flag)
int UsbDevice, UINT16 idVendor, UINT16 idProduct, int flag)
{
UDEVMAN* udevman = (UDEVMAN*) idevman;
IUDEVICE* pdev = NULL;
IUDEVICE** devArray;
int i, num, addnum = 0;
pdev = (IUDEVICE*) udevman_get_udevice_by_addr(idevman, bus_number, dev_number);
if (pdev != NULL)
return 0;
if (flag == UDEVMAN_FLAG_ADD_BY_ADDR)
{
pdev = udev_new_by_addr(bus_number, dev_number);
@ -171,8 +167,8 @@ static int udevman_register_udevice(IUDEVMAN* idevman, int bus_number, int dev_n
{
pdev = devArray[i];
if (udevman_get_udevice_by_addr(idevman,
pdev->get_bus_number(pdev), pdev->get_dev_number(pdev)) != NULL)
if (udevman_get_udevice_by_addr(idevman,
pdev->get_bus_number(pdev), pdev->get_dev_number(pdev)) != NULL)
{
zfree(pdev);
continue;
@ -215,11 +211,9 @@ static int udevman_register_udevice(IUDEVMAN* idevman, int bus_number, int dev_n
static int udevman_unregister_udevice(IUDEVMAN* idevman, int bus_number, int dev_number)
{
UDEVMAN* udevman = (UDEVMAN*) idevman;
UDEVICE * pdev, * dev;
UDEVICE* pdev, * dev;
int ret = 0, err = 0;
dev = (UDEVICE*) udevman_get_udevice_by_addr(idevman, bus_number, dev_number);
idevman->loading_lock(idevman);
idevman->rewind(idevman);
@ -230,7 +224,6 @@ static int udevman_unregister_udevice(IUDEVMAN* idevman, int bus_number, int dev
if (pdev == dev) /* device exists */
{
/* set previous device to point to next device */
if (dev->prev != NULL)
{
/* unregistered device is not the head */
@ -248,7 +241,7 @@ static int udevman_unregister_udevice(IUDEVMAN* idevman, int bus_number, int dev
if (dev->next != NULL)
{
/* unregistered device is not the tail */
pdev = (UDEVICE *)dev->next;
pdev = (UDEVICE*)dev->next;
pdev->prev = dev->prev;
}
else
@ -256,11 +249,12 @@ static int udevman_unregister_udevice(IUDEVMAN* idevman, int bus_number, int dev
/* unregistered device is the tail, update tail */
udevman->tail = (IUDEVICE*)dev->prev;
}
udevman->device_num--;
break;
break;
}
}
idevman->loading_unlock(idevman);
if (dev)
@ -269,28 +263,31 @@ static int udevman_unregister_udevice(IUDEVMAN* idevman, int bus_number, int dev
if (err != LIBUSB_ERROR_NO_DEVICE)
{
ret = libusb_reset_device(dev->libusb_handle);
if (ret<0)
if (ret < 0)
{
WLog_ERR(TAG, "libusb_reset_device: ERROR!!ret:%d", ret);
}
}
/* release all interface and attach kernel driver */
dev->iface.attach_kernel_driver((IUDEVICE*)dev);
if(dev->request_queue) zfree(dev->request_queue);
dev->iface.attach_kernel_driver((IUDEVICE*)dev);
if (dev->request_queue) zfree(dev->request_queue);
/* free the config descriptor that send from windows */
msusb_msconfig_free(dev->MsConfig);
libusb_close (dev->libusb_handle);
libusb_close (dev->hub_handle);
libusb_close(dev->libusb_handle);
libusb_close(dev->hub_handle);
sem_destroy(&dev->sem_id);
/* free device info */
if (dev->devDescriptor)
zfree(dev->devDescriptor);
if (dev)
zfree(dev);
zfree(dev);
return 1; /* unregistration successful */
}
@ -302,28 +299,22 @@ static void udevman_parse_device_addr(char* str, int* id1, int* id2, char sign)
{
char s1[8];
char* s2;
ZeroMemory(s1, sizeof(s1));
s2 = (strchr(str, sign)) + 1;
s2 = (strchr(str, sign)) + 1;
strncpy(s1, str, strlen(str) - (strlen(s2) + 1));
*id1 = atoi(s1);
*id2 = atoi(s2);
*id1 = strtol(s1, NULL, 0);
*id2 = strtol(s2, NULL, 0);
}
static void udevman_parse_device_pid_vid(char* str, int* id1, int* id2, char sign)
{
char s1[8];
char* s2;
ZeroMemory(s1, sizeof(s1));
s2 = (strchr(str, sign)) + 1;
s2 = (strchr(str, sign)) + 1;
strncpy(s1, str, strlen(str) - (strlen(s2) + 1));
*id1 = (int) strtol(s1, NULL, 16);
*id2 = (int) strtol(s2, NULL, 16);
*id1 = strtol(s1, NULL, 16);
*id2 = strtol(s2, NULL, 16);
}
static int udevman_check_device_exist_by_id(IUDEVMAN* idevman, UINT16 idVendor, UINT16 idProduct)
@ -358,7 +349,6 @@ static IUDEVICE* udevman_get_udevice_by_UsbDevice_try_again(IUDEVMAN* idevman, U
}
idevman->loading_unlock(idevman);
return NULL;
}
@ -380,9 +370,7 @@ static IUDEVICE* udevman_get_udevice_by_UsbDevice(IUDEVMAN* idevman, UINT32 UsbD
}
idevman->loading_unlock(idevman);
/* try again */
pdev = (UDEVICE*) idevman->get_udevice_by_UsbDevice_try_again(idevman, UsbDevice);
if (pdev)
@ -425,10 +413,8 @@ BASIC_STATE_FUNC_DEFINED(sem_timeout, int)
static void udevman_free(IUDEVMAN* idevman)
{
UDEVMAN* udevman = (UDEVMAN*) idevman;
pthread_mutex_destroy(&udevman->devman_loading);
sem_destroy(&udevman->sem_urb_lock);
libusb_exit(NULL);
/* free udevman */
@ -437,11 +423,10 @@ static void udevman_free(IUDEVMAN* idevman)
zfree(udevman);
}
static void udevman_load_interface(UDEVMAN * udevman)
static void udevman_load_interface(UDEVMAN* udevman)
{
/* standard */
udevman->iface.free = udevman_free;
/* manage devices */
udevman->iface.rewind = udevman_rewind;
udevman->iface.get_next = udevman_get_next;
@ -449,18 +434,15 @@ static void udevman_load_interface(UDEVMAN * udevman)
udevman->iface.register_udevice = udevman_register_udevice;
udevman->iface.unregister_udevice = udevman_unregister_udevice;
udevman->iface.get_udevice_by_UsbDevice = udevman_get_udevice_by_UsbDevice;
udevman->iface.get_udevice_by_UsbDevice_try_again =
udevman_get_udevice_by_UsbDevice_try_again;
udevman->iface.get_udevice_by_UsbDevice_try_again =
udevman_get_udevice_by_UsbDevice_try_again;
/* Extension */
udevman->iface.check_device_exist_by_id = udevman_check_device_exist_by_id;
udevman->iface.isAutoAdd = udevman_is_auto_add;
/* Basic state */
BASIC_STATE_FUNC_REGISTER(defUsbDevice, udevman);
BASIC_STATE_FUNC_REGISTER(device_num, udevman);
BASIC_STATE_FUNC_REGISTER(sem_timeout, udevman);
/* control semaphore or mutex lock */
udevman->iface.loading_lock = udevman_loading_lock;
udevman->iface.loading_unlock = udevman_loading_unlock;
@ -502,7 +484,6 @@ static void urbdrc_udevman_register_devices(UDEVMAN* udevman, char* devices)
dev_number = 0;
idVendor = 0;
idProduct = 0;
strcpy(hardware_id, token);
token = strtok(NULL, "#");
@ -510,14 +491,13 @@ static void urbdrc_udevman_register_devices(UDEVMAN* udevman, char* devices)
{
udevman_parse_device_pid_vid(hardware_id, &idVendor, &idProduct, ':');
success = udevman->iface.register_udevice((IUDEVMAN*) udevman,
0, 0, UsbDevice, (UINT16) idVendor, (UINT16) idProduct, UDEVMAN_FLAG_ADD_BY_VID_PID);
0, 0, UsbDevice, (UINT16) idVendor, (UINT16) idProduct, UDEVMAN_FLAG_ADD_BY_VID_PID);
}
else if (udevman->flags & UDEVMAN_FLAG_ADD_BY_ADDR)
{
udevman_parse_device_addr(hardware_id, &bus_number, &dev_number, ':');
success = udevman->iface.register_udevice((IUDEVMAN*) udevman,
bus_number, dev_number, UsbDevice, 0, 0, UDEVMAN_FLAG_ADD_BY_ADDR);
bus_number, dev_number, UsbDevice, 0, 0, UDEVMAN_FLAG_ADD_BY_ADDR);
}
if (success)
@ -532,12 +512,9 @@ static void urbdrc_udevman_parse_addin_args(UDEVMAN* udevman, ADDIN_ARGV* args)
int status;
DWORD flags;
COMMAND_LINE_ARGUMENT_A* arg;
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON;
status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv,
urbdrc_udevman_args, flags, udevman, NULL, NULL);
urbdrc_udevman_args, flags, udevman, NULL, NULL);
arg = urbdrc_udevman_args;
do
@ -546,7 +523,6 @@ static void urbdrc_udevman_parse_addin_args(UDEVMAN* udevman, ADDIN_ARGV* args)
continue;
CommandLineSwitchStart(arg)
CommandLineSwitchCase(arg, "dbg")
{
WLog_SetLogLevel(WLog_Get(TAG), WLOG_TRACE);
@ -569,9 +545,7 @@ static void urbdrc_udevman_parse_addin_args(UDEVMAN* udevman, ADDIN_ARGV* args)
}
CommandLineSwitchDefault(arg)
{
}
CommandLineSwitchEnd(arg)
}
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
@ -587,34 +561,26 @@ int freerdp_urbdrc_client_subsystem_entry(PFREERDP_URBDRC_SERVICE_ENTRY_POINTS p
{
UDEVMAN* udevman;
ADDIN_ARGV* args = pEntryPoints->args;
libusb_init(NULL);
udevman = (PUDEVMAN) malloc(sizeof(UDEVMAN));
if (!udevman)
return -1;
udevman->device_num = 0;
udevman->idev = NULL;
udevman->head = NULL;
udevman->tail = NULL;
udevman->tail = NULL;
udevman->sem_timeout = 0;
udevman->flags = UDEVMAN_FLAG_ADD_BY_VID_PID;
pthread_mutex_init(&udevman->devman_loading, NULL);
sem_init(&udevman->sem_urb_lock, 0, MAX_URB_REQUSET_NUM);
/* load usb device service management */
udevman_load_interface(udevman);
/* set debug flag, to enable Debug message for usb data transfer */
libusb_debug = 10;
urbdrc_udevman_parse_addin_args(udevman, args);
pEntryPoints->pRegisterUDEVMAN(pEntryPoints->plugin, (IUDEVMAN*) udevman);
WLog_DBG(TAG, "UDEVMAN device registered.");
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,22 @@
# FreeRDP: A Remote Desktop Protocol Implementation
# FreeRDP cmake build script
#
# Copyright 2017 David Fort <contact@hardening-consulting.com>
#
# 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.
define_channel("video")
if(WITH_CLIENT_CHANNELS)
add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME})
endif()

View File

@ -0,0 +1,12 @@
set(OPTION_DEFAULT OFF)
set(OPTION_CLIENT_DEFAULT ON)
set(OPTION_SERVER_DEFAULT OFF)
define_channel_options(NAME "video" TYPE "dynamic"
DESCRIPTION "Video optimized remoting Virtual Channel Extension"
SPECIFICATIONS "[MS-RDPEVOR]"
DEFAULT ${OPTION_DEFAULT})
define_channel_client_options(${OPTION_CLIENT_DEFAULT})

View File

@ -0,0 +1,39 @@
# FreeRDP: A Remote Desktop Protocol Implementation
# FreeRDP cmake build script
#
# Copyright 2018 David Fort <contact@hardening-consulting.com>
#
# 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.
define_channel_client("video")
set(${MODULE_PREFIX}_SRCS
video_main.c
video_main.h)
include_directories(..)
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE "DVCPluginEntry")
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} winpr)
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
if (WITH_DEBUG_SYMBOLS AND MSVC AND NOT BUILTIN_CHANNELS AND BUILD_SHARED_LIBS)
install(FILES ${CMAKE_BINARY_DIR}/${MODULE_NAME}.pdb DESTINATION ${FREERDP_ADDIN_PATH} COMPONENT symbols)
endif()
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")

1168
channels/video/client/video_main.c Executable file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,35 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Video Optimized Remoting Virtual Channel Extension
*
* Copyright 2017 David Fort <contact@hardening-consulting.com>
*
* 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_VIDEO_CLIENT_MAIN_H
#define FREERDP_CHANNEL_VIDEO_CLIENT_MAIN_H
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <freerdp/dvc.h>
#include <freerdp/types.h>
#include <freerdp/addin.h>
#include <freerdp/channels/video.h>
#endif /* FREERDP_CHANNEL_GEOMETRY_CLIENT_MAIN_H */

View File

@ -1,5 +1,6 @@
message("PRELOADING android cache")
set(CMAKE_TOOLCHAIN_FILE "cmake/AndroidToolchain.cmake" CACHE PATH "ToolChain file")
set(WITH_SANITIZE_ADDRESS ON)
set(FREERDP_EXTERNAL_SSL_PATH $ENV{ANDROID_SSL_PATH} CACHE PATH "android ssl")
# ANDROID_NDK and ANDROID_SDK must be set as environment variable
#set(ANDROID_NDK $ENV{ANDROID_SDK} CACHE PATH "Android NDK")

View File

@ -2,9 +2,10 @@ message("PRELOADING cache")
set (WITH_MANPAGES OFF CACHE BOOL "man pages")
set (CMAKE_BUILD_TYPE "Debug" CACHE STRING "build type")
set (WITH_CUPS OFF CACHE BOOL "CUPS printing")
set (WITH_KRB5 ON CACHE BOOL "Kerberos support")
set (WITH_GSSAPI ON CACHE BOOL "Kerberos support")
set (WITH_ALSA OFF CACHE BOOL "alsa audio")
set (WITH_FFMPEG OFF CACHE BOOL "ffmepg support")
set (WITH_XV OFF CACHE BOOL "xvideo support")
set (BUILD_TESTING ON CACHE BOOL "build testing")
set (WITH_XSHM OFF CACHE BOOL "build with xshm support")
set (WITH_SANITIZE_ADDRESS ON)

View File

@ -1,5 +1,6 @@
message("PRELOADING android cache")
set(CMAKE_TOOLCHAIN_FILE "cmake/iOSToolchain.cmake" CACHE PATH "ToolChain file")
set(FREERDP_IOS_EXTERNAL_SSL_PATH $ENV{FREERDP_IOS_EXTERNAL_SSL_PATH} CACHE PATH "android ssl")
set (CMAKE_TOOLCHAIN_FILE "cmake/iOSToolchain.cmake" CACHE PATH "ToolChain file")
set (FREERDP_IOS_EXTERNAL_SSL_PATH $ENV{FREERDP_IOS_EXTERNAL_SSL_PATH} CACHE PATH "android ssl")
set (CMAKE_BUILD_TYPE "Debug" CACHE STRING "build type")
set(IOS_PLATFORM "SIMULATOR" CACHE STRING "iso platfrorm to build")
set (IOS_PLATFORM "SIMULATOR" CACHE STRING "iso platfrorm to build")
set (WITH_SANITIZE_ADDRESS ON)

View File

@ -7,7 +7,7 @@ set (WITH_PULSE ON CACHE BOOL "pulse")
set (WITH_CHANNELS ON CACHE BOOL "channels")
set (BUILTIN_CHANNELS ON CACHE BOOL "static channels")
set (WITH_CUPS ON CACHE BOOL "cups")
set (WITH_KRB5 ON CACHE BOOL "Kerberos support")
set (WITH_GSSAPI ON CACHE BOOL "Kerberos support")
set (WITH_PCSC ON CACHE BOOL "PCSC")
set (WITH_JPEG ON CACHE BOOL "jepg")
set (WITH_GSTREAMER_0_10 ON CACHE BOOL "gstreamer")
@ -47,3 +47,4 @@ set (WITH_DEBUG_X11_LOCAL_MOVESIZE OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_XV OFF CACHE BOOL "enable debug")
set (WITH_SAMPLE ON CACHE BOOL "samples")
set (WITH_NO_UNDEFINED ON CACHE BOOL "don't link with undefined symbols")
set (WITH_SANITIZE_ADDRESS ON)

View File

@ -4,3 +4,4 @@ set (CMAKE_BUILD_TYPE "Debug" CACHE STRING "build type")
set (WITH_CUPS ON CACHE BOOL "CUPS printing")
set (WITH_X11 ON CACHE BOOL "Enable X11")
set (BUILD_TESTING ON CACHE BOOL "build testing")
set (WITH_SANITIZE_ADDRESS ON)

View File

@ -2,9 +2,10 @@ message("PRELOADING cache")
set (WITH_MANPAGES OFF CACHE BOOL "man pages")
set (CMAKE_BUILD_TYPE "Debug" CACHE STRING "build type")
set (WITH_CUPS OFF CACHE BOOL "CUPS printing")
set (WITH_KRB5 ON CACHE BOOL "Kerberos support")
set (WITH_GSSAPI ON CACHE BOOL "Kerberos support")
set (WITH_ALSA OFF CACHE BOOL "alsa audio")
set (WITH_FFMPEG OFF CACHE BOOL "ffmepg support")
set (WITH_XV OFF CACHE BOOL "xvideo support")
set (BUILD_TESTING ON CACHE BOOL "build testing")
set (WITH_XSHM OFF CACHE BOOL "build with xshm support")
set (WITH_SANITIZE_ADDRESS ON)

View File

@ -1,4 +1,5 @@
message("PRELOADING windows cache")
set (CMAKE_BUILD_TYPE "Debug" CACHE STRING "build type")
set(WITH_SERVER "ON" CACHE BOOL "Build server binaries")
set (WITH_SERVER "ON" CACHE BOOL "Build server binaries")
set (BUILD_TESTING ON CACHE BOOL "build testing")
set (WITH_SANITIZE_ADDRESS ON)

View File

@ -220,7 +220,7 @@ BOOL df_verify_certificate(freerdp* instance, char* subject, char* issuer,
WLog_INFO(TAG,
"The above X.509 certificate could not be verified, possibly because you do not have "
"the CA certificate in your certificate store, or the certificate has expired. "
"Please look at the documentation on how to create local certificate store for a private CA.");
"Please look at the OpenSSL documentation on how to add a private CA to the store.");
while (1)
{
@ -422,7 +422,7 @@ int main(int argc, char* argv[])
if (!(g_sem = CreateSemaphore(NULL, 0, 1, NULL)))
{
WLog_ERR(TAG, "Failed to create semaphore");
exit(1);
return 1;
}
instance = freerdp_new();
@ -437,7 +437,7 @@ int main(int argc, char* argv[])
if (!freerdp_context_new(instance))
{
WLog_ERR(TAG, "Failed to create FreeRDP context");
exit(1);
return 1;
}
context = (dfContext*) instance->context;
@ -449,11 +449,11 @@ int main(int argc, char* argv[])
argv, FALSE);
if (status < 0)
exit(0);
return 0;
if (!freerdp_client_load_addins(instance->context->channels,
instance->settings))
exit(-1);
return -1;
data = (struct thread_data*) malloc(sizeof(struct thread_data));
ZeroMemory(data, sizeof(sizeof(struct thread_data)));

View File

@ -113,8 +113,9 @@ static BOOL tf_post_connect(freerdp* instance)
return TRUE;
}
static void* tf_client_thread_proc(freerdp* instance)
static DWORD WINAPI tf_client_thread_proc(LPVOID arg)
{
freerdp* instance = (freerdp*)arg;
DWORD nCount;
DWORD status;
HANDLE handles[64];
@ -122,7 +123,7 @@ static void* tf_client_thread_proc(freerdp* instance)
if (!freerdp_connect(instance))
{
WLog_ERR(TAG, "connection failure");
return NULL;
return 0;
}
while (!freerdp_shall_disconnect(instance))
@ -146,14 +147,16 @@ static void* tf_client_thread_proc(freerdp* instance)
if (!freerdp_check_event_handles(instance->context))
{
WLog_ERR(TAG, "Failed to check FreeRDP event handles");
if (freerdp_get_last_error(instance->context) == FREERDP_ERROR_SUCCESS)
WLog_ERR(TAG, "Failed to check FreeRDP event handles");
break;
}
}
freerdp_disconnect(instance);
ExitThread(0);
return NULL;
return 0;
}
int main(int argc, char* argv[])
@ -166,7 +169,7 @@ int main(int argc, char* argv[])
if (!instance)
{
WLog_ERR(TAG, "Couldn't create instance");
exit(1);
return 1;
}
instance->PreConnect = tf_pre_connect;
@ -174,13 +177,12 @@ int main(int argc, char* argv[])
instance->ContextSize = sizeof(tfContext);
instance->ContextNew = tf_context_new;
instance->ContextFree = tf_context_free;
freerdp_register_addin_provider(freerdp_channels_load_static_addin_entry, 0);
if (!freerdp_context_new(instance))
{
WLog_ERR(TAG, "Couldn't create context");
exit(1);
return 1;
}
status = freerdp_client_settings_parse_command_line(instance->settings, argc,
@ -188,16 +190,14 @@ int main(int argc, char* argv[])
if (status < 0)
{
exit(0);
return 0;
}
if (!freerdp_client_load_addins(instance->context->channels,
instance->settings))
exit(-1);
return -1;
if (!(thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)
tf_client_thread_proc, instance, 0, NULL)))
if (!(thread = CreateThread(NULL, 0, tf_client_thread_proc, instance, 0, NULL)))
{
WLog_ERR(TAG, "Failed to create client thread");
}

View File

@ -56,11 +56,11 @@ static void wlf_encomsp_uninit(wlfContext* wlf, EncomspClientContext* encomsp)
}
void wlf_OnChannelConnectedEventHandler(rdpContext* context,
void wlf_OnChannelConnectedEventHandler(void* context,
ChannelConnectedEventArgs* e)
{
wlfContext* wlf = (wlfContext*) context;
rdpSettings* settings = context->settings;
rdpSettings* settings = wlf->context.settings;
if (strcmp(e->name, RDPEI_DVC_CHANNEL_NAME) == 0)
{
@ -72,7 +72,7 @@ void wlf_OnChannelConnectedEventHandler(rdpContext* context,
else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0)
{
if (settings->SoftwareGdi)
gdi_graphics_pipeline_init(context->gdi, (RdpgfxClientContext*) e->pInterface);
gdi_graphics_pipeline_init(wlf->context.gdi, (RdpgfxClientContext*) e->pInterface);
}
else if (strcmp(e->name, RAIL_SVC_CHANNEL_NAME) == 0)
{
@ -86,11 +86,11 @@ void wlf_OnChannelConnectedEventHandler(rdpContext* context,
}
}
void wlf_OnChannelDisconnectedEventHandler(rdpContext* context,
void wlf_OnChannelDisconnectedEventHandler(void* context,
ChannelDisconnectedEventArgs* e)
{
wlfContext* wlf = (wlfContext*) context;
rdpSettings* settings = context->settings;
rdpSettings* settings = wlf->context.settings;
if (strcmp(e->name, RDPEI_DVC_CHANNEL_NAME) == 0)
{
@ -102,7 +102,7 @@ void wlf_OnChannelDisconnectedEventHandler(rdpContext* context,
else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0)
{
if (settings->SoftwareGdi)
gdi_graphics_pipeline_uninit(context->gdi,
gdi_graphics_pipeline_uninit(wlf->context.gdi,
(RdpgfxClientContext*) e->pInterface);
}
else if (strcmp(e->name, RAIL_SVC_CHANNEL_NAME) == 0)

View File

@ -34,9 +34,9 @@ int wlf_on_channel_connected(freerdp* instance, const char* name,
int wlf_on_channel_disconnected(freerdp* instance, const char* name,
void* pInterface);
void wlf_OnChannelConnectedEventHandler(rdpContext* context,
void wlf_OnChannelConnectedEventHandler(void* context,
ChannelConnectedEventArgs* e);
void wlf_OnChannelDisconnectedEventHandler(rdpContext* context,
void wlf_OnChannelDisconnectedEventHandler(void* context,
ChannelDisconnectedEventArgs* e);
#endif /* FREERDP_CLIENT_WAYLAND_CHANNELS_H */

View File

@ -92,7 +92,7 @@ BOOL wlf_handle_key(freerdp *instance, UwacKeyEvent *ev) {
rdpInput* input = instance->input;
DWORD rdp_scancode;
rdp_scancode = (DWORD) ev->raw_key;
rdp_scancode = freerdp_keyboard_get_rdp_scancode_from_x11_keycode(ev->raw_key + 8);
if (rdp_scancode == RDP_SCANCODE_UNKNOWN)
return TRUE;

View File

@ -1,7 +1,7 @@
.de URL
\\$2 \(laURL: \\$1 \(ra\\$3
..
.if \n[.g] .mso www.tmac))
.if \n[.g] .mso www.tmac
.TH wlfreerdp 1 2017-01-12 "@FREERDP_VERSION_FULL@" "FreeRDP"
.SH NAME
wlfreerdp \- FreeRDP wayland client

View File

@ -103,6 +103,8 @@ static BOOL wl_pre_connect(freerdp* instance)
{
rdpSettings* settings;
wlfContext* context;
UwacOutput* output;
UwacSize resolution;
if (!instance)
return FALSE;
@ -142,9 +144,25 @@ static BOOL wl_pre_connect(freerdp* instance)
settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE;
settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE;
PubSub_SubscribeChannelConnected(instance->context->pubSub,
(pChannelConnectedEventHandler) wlf_OnChannelConnectedEventHandler);
wlf_OnChannelConnectedEventHandler);
PubSub_SubscribeChannelDisconnected(instance->context->pubSub,
(pChannelDisconnectedEventHandler) wlf_OnChannelDisconnectedEventHandler);
wlf_OnChannelDisconnectedEventHandler);
if (settings->Fullscreen)
{
// Use the resolution of the first display output
output = UwacDisplayGetOutput(context->display, 1);
if (output != NULL && UwacOutputGetResolution(output, &resolution) == UWAC_SUCCESS)
{
settings->DesktopWidth = (UINT32) resolution.width;
settings->DesktopHeight = (UINT32) resolution.height;
}
else
{
WLog_WARN(TAG, "Failed to get output resolution! Check your display settings");
}
}
if (!freerdp_client_load_addins(instance->context->channels,
instance->settings))
@ -176,15 +194,14 @@ static BOOL wl_post_connect(freerdp* instance)
UwacWindowSetFullscreenState(window, NULL, instance->context->settings->Fullscreen);
UwacWindowSetTitle(window, "FreeRDP");
UwacWindowSetOpaqueRegion(context->window, 0, 0, gdi->width, gdi->height);
instance->update->BeginPaint = wl_begin_paint;
instance->update->EndPaint = wl_end_paint;
memcpy(UwacWindowGetDrawingBuffer(context->window), gdi->primary_buffer,
gdi->width * gdi->height * 4);
UwacWindowAddDamage(context->window, 0, 0, gdi->width, gdi->height);
context->haveDamage = TRUE;
freerdp_keyboard_init(instance->context->settings->KeyboardLayout);
return wl_update_content(context);
}
@ -328,7 +345,9 @@ static int wlfreerdp_run(freerdp* instance)
//if (WaitForMultipleObjects(count, &handles[1], FALSE, INFINITE)) {
if (freerdp_check_event_handles(instance->context) != TRUE)
{
printf("Failed to check FreeRDP file descriptor\n");
if (freerdp_get_last_error(instance->context) == FREERDP_ERROR_SUCCESS)
printf("Failed to check FreeRDP file descriptor\n");
break;
}

View File

@ -44,10 +44,14 @@ set(${MODULE_PREFIX}_SRCS
xf_cliprdr.h
xf_monitor.c
xf_monitor.h
xf_disp.c
xf_disp.h
xf_graphics.c
xf_graphics.h
xf_keyboard.c
xf_keyboard.h
xf_video.c
xf_video.h
xf_window.c
xf_window.h
xf_client.c
@ -86,13 +90,19 @@ if(WITH_MANPAGES)
configure_file(xfreerdp.1.xml.in xfreerdp.1.xml @ONLY IMMEDIATE)
add_executable(generate_argument_docbook generate_argument_docbook.c)
set(GAD_LIBS freerdp-client)
target_link_libraries(generate_argument_docbook ${GAD_LIBS} freerdp winpr)
# Compile the helper tool with default compiler settings.
# We need the include paths though.
get_property(dirs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES)
set(GENERATE_INCLUDES "")
foreach(dir ${dirs})
set(GENERATE_INCLUDES ${GENERATE_INCLUDES} -I${dir})
endforeach(dir)
add_custom_command(OUTPUT xfreerdp.1
COMMAND generate_argument_docbook
COMMAND ${CMAKE_C_COMPILER} ${GENERATE_INCLUDES}
${CMAKE_CURRENT_SOURCE_DIR}/generate_argument_docbook.c
-o ${CMAKE_CURRENT_BINARY_DIR}/generate_argument_docbook
COMMAND ${CMAKE_CURRENT_BINARY_DIR}/generate_argument_docbook
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_SOURCE_DIR}/xfreerdp-channels.1.xml ${CMAKE_CURRENT_BINARY_DIR}
COMMAND ${CMAKE_COMMAND} -E copy
@ -101,12 +111,11 @@ if(WITH_MANPAGES)
${CMAKE_CURRENT_SOURCE_DIR}/xfreerdp-envvar.1.xml ${CMAKE_CURRENT_BINARY_DIR}
COMMAND ${XSLTPROC_EXECUTABLE} ${DOCBOOKXSL_DIR}/manpages/docbook.xsl xfreerdp.1.xml
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
DEPENDS
${CMAKE_CURRENT_BINARY_DIR}/xfreerdp.1.xml
${CMAKE_CURRENT_SOURCE_DIR}/xfreerdp-examples.1.xml
${CMAKE_CURRENT_SOURCE_DIR}/xfreerdp-channels.1.xml
${CMAKE_CURRENT_SOURCE_DIR}/xfreerdp-envvar.1.xml
generate_argument_docbook)
DEPENDS
${CMAKE_CURRENT_BINARY_DIR}/xfreerdp.1.xml
${CMAKE_CURRENT_SOURCE_DIR}/xfreerdp-examples.1.xml
${CMAKE_CURRENT_SOURCE_DIR}/xfreerdp-channels.1.xml
${CMAKE_CURRENT_SOURCE_DIR}/xfreerdp-envvar.1.xml)
add_custom_target(xfreerdp.manpage ALL
DEPENDS xfreerdp.1)
@ -145,6 +154,10 @@ set(XRENDER_FEATURE_TYPE "RECOMMENDED")
set(XRENDER_FEATURE_PURPOSE "rendering")
set(XRENDER_FEATURE_DESCRIPTION "X11 render extension")
set(XRANDR_FEATURE_TYPE "RECOMMENDED")
set(XRANDR_FEATURE_PURPOSE "tracking output configuration")
set(XRANDR_FEATURE_DESCRIPTION "X11 randr extension")
set(XFIXES_FEATURE_TYPE "RECOMMENDED")
set(XFIXES_FEATURE_PURPOSE "X11 xfixes extension")
set(XFIXES_FEATURE_DESCRIPTION "Useful additions to the X11 core protocol")
@ -156,6 +169,7 @@ find_feature(Xcursor ${XCURSOR_FEATURE_TYPE} ${XCURSOR_FEATURE_PURPOSE} ${XCURSO
find_feature(Xv ${XV_FEATURE_TYPE} ${XV_FEATURE_PURPOSE} ${XV_FEATURE_DESCRIPTION})
find_feature(Xi ${XI_FEATURE_TYPE} ${XI_FEATURE_PURPOSE} ${XI_FEATURE_DESCRIPTION})
find_feature(Xrender ${XRENDER_FEATURE_TYPE} ${XRENDER_FEATURE_PURPOSE} ${XRENDER_FEATURE_DESCRIPTION})
find_feature(XRandR ${XRANDR_FEATURE_TYPE} ${XRANDR_FEATURE_PURPOSE} ${XRANDR_FEATURE_DESCRIPTION})
find_feature(Xfixes ${XFIXES_FEATURE_TYPE} ${XFIXES_FEATURE_PURPOSE} ${XFIXES_FEATURE_DESCRIPTION})
if(WITH_XINERAMA)
@ -194,6 +208,12 @@ if(WITH_XRENDER)
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${XRENDER_LIBRARIES})
endif()
if(WITH_XRANDR)
add_definitions(-DWITH_XRANDR)
include_directories(${XRANDR_INCLUDE_DIRS})
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${XRANDR_LIBRARIES})
endif()
if(WITH_XFIXES)
add_definitions(-DWITH_XFIXES)
include_directories(${XFIXES_INCLUDE_DIRS})

View File

@ -1,18 +1,15 @@
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <winpr/cmdline.h>
#include "../common/cmdline.h"
/* We need to include the command line c file to get access to
* the argument struct. */
#include "../common/cmdline.c"
LPSTR tr_esc_str(LPCSTR arg)
#define TAG FREERDP_TAG("generate_argument_docbook")
LPSTR tr_esc_str(LPCSTR arg, bool format)
{
LPSTR tmp = NULL;
size_t cs = 0, x, ds;
size_t cs = 0, x, ds, len;
size_t s;
if(NULL == arg)
return NULL;
@ -26,7 +23,7 @@ LPSTR tr_esc_str(LPCSTR arg)
tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
if(NULL == tmp)
{
WLog_ERR(TAG, "Could not allocate string buffer.");
fprintf(stderr, "Could not allocate string buffer.\n");
exit(-2);
}
/* Copy character for character and check, if it is necessary to escape. */
@ -36,37 +33,41 @@ LPSTR tr_esc_str(LPCSTR arg)
switch(arg[x])
{
case '<':
ds += 3;
len = format ? 13 : 4;
ds += len - 1;
tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
if(NULL == tmp)
{
WLog_ERR(TAG, "Could not reallocate string buffer.");
fprintf(stderr, "Could not reallocate string buffer.\n");
exit(-3);
}
tmp[cs++] = '&';
tmp[cs++] = 'l';
tmp[cs++] = 't';
tmp[cs++] = ';';
if (format)
strncpy (&tmp[cs], "<replaceable>", len);
else
strncpy (&tmp[cs], "&lt;", len);
cs += len;
break;
case '>':
ds += 3;
len = format ? 14 : 4;
ds += len - 1;
tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
if(NULL == tmp)
{
WLog_ERR(TAG, "Could not reallocate string buffer.");
fprintf(stderr, "Could not reallocate string buffer.\n");
exit(-4);
}
tmp[cs++] = '&';
tmp[cs++] = 'g';
tmp[cs++] = 't';
tmp[cs++] = ';';
if (format)
strncpy (&tmp[cs], "</replaceable>", len);
else
strncpy (&tmp[cs], "&lt;", len);
cs += len;
break;
case '\'':
ds += 5;
tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
if(NULL == tmp)
{
WLog_ERR(TAG, "Could not reallocate string buffer.");
fprintf(stderr, "Could not reallocate string buffer.\n");
exit(-5);
}
tmp[cs++] = '&';
@ -81,7 +82,7 @@ LPSTR tr_esc_str(LPCSTR arg)
tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
if(NULL == tmp)
{
WLog_ERR(TAG, "Could not reallocate string buffer.");
fprintf(stderr, "Could not reallocate string buffer.\n");
exit(-6);
}
tmp[cs++] = '&';
@ -96,7 +97,7 @@ LPSTR tr_esc_str(LPCSTR arg)
tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
if(NULL == tmp)
{
WLog_ERR(TAG, "Could not reallocate string buffer.");
fprintf(stderr, "Could not reallocate string buffer.\n");
exit(-7);
}
tmp[cs++] = '&';
@ -125,7 +126,7 @@ int main(int argc, char *argv[])
fp = fopen(fname, "w");
if(NULL == fp)
{
WLog_ERR(TAG, "Could not open '%s' for writing.", fname);
fprintf(stderr, "Could not open '%s' for writing.\n", fname);
return -1;
}
/* The tag used as header in the manpage */
@ -136,39 +137,71 @@ int main(int argc, char *argv[])
* compatible XML */
if(elements < 2)
{
WLog_ERR(TAG, "The argument array 'args' is empty, writing an empty file.");
fprintf(stderr, "The argument array 'args' is empty, writing an empty file.\n");
elements = 1;
}
for(x=0; x<elements - 1; x++)
{
const COMMAND_LINE_ARGUMENT_A *arg = &args[x];
const char *name = tr_esc_str((LPSTR) arg->Name);
const char *format = tr_esc_str(arg->Format);
const char *text = tr_esc_str((LPSTR) arg->Text);
char *name = tr_esc_str((LPSTR) arg->Name, FALSE);
char *alias = tr_esc_str((LPSTR) arg->Alias, FALSE);
char *format = tr_esc_str(arg->Format, TRUE);
char *text = tr_esc_str((LPSTR) arg->Text, FALSE);
fprintf(fp, "\t\t\t<varlistentry>\n");
fprintf(fp, "\t\t\t\t<term><option>/%s</option>", name);
if ((arg->Flags == COMMAND_LINE_VALUE_REQUIRED) && format)
fprintf(fp, " <replaceable>%s</replaceable>\n", format);
fprintf(fp, "</term>\n");
do
{
fprintf(fp, "\t\t\t\t<term><option>");
if (arg->Flags == COMMAND_LINE_VALUE_BOOL)
fprintf(fp, "%s", arg->Default ? "-" : "+");
else
fprintf(fp, "/");
fprintf(fp, "%s</option>", name);
if (format || text)
if (format)
{
if (arg->Flags == COMMAND_LINE_VALUE_OPTIONAL)
fprintf(fp, "[");
fprintf(fp, ":%s", format);
if (arg->Flags == COMMAND_LINE_VALUE_OPTIONAL)
fprintf(fp, "]");
}
fprintf(fp, "</term>\n");
if (alias == name)
break;
free (name);
name = alias;
}
while (alias);
if (text)
{
fprintf(fp, "\t\t\t\t<listitem>\n");
fprintf(fp, "\t\t\t\t\t<para>%s\n", format ? format : "");
fprintf(fp, "\t\t\t\t\t<para>");
if (text)
{
if (format)
fprintf(fp, " - ");
fprintf(fp, "%s", text);
if (arg->Flags == COMMAND_LINE_VALUE_BOOL)
fprintf(fp, " (default:%s)", arg->Default ? "on" : "off");
else if (arg->Default)
{
char *value = tr_esc_str((LPSTR) arg->Default, FALSE);
fprintf(fp, " (default:%s)", value);
free (value);
}
fprintf(fp, "</para>\n");
fprintf(fp, "\t\t\t\t</listitem>\n");
}
fprintf(fp, "\t\t\t</varlistentry>\n");
free((void*) name);
free((void*) format);
free((void*) text);
free(name);
free(format);
free(text);
}
fprintf(fp, "\t\t</variablelist>\n");
fprintf(fp, "\t</refsect1>\n");

View File

@ -21,6 +21,7 @@
#include "config.h"
#endif
#include <freerdp/gdi/video.h>
#include "xf_channels.h"
#include "xf_client.h"
@ -30,11 +31,13 @@
#include "xf_tsmf.h"
#include "xf_rail.h"
#include "xf_cliprdr.h"
#include "xf_disp.h"
#include "xf_video.h"
void xf_OnChannelConnectedEventHandler(rdpContext* context, ChannelConnectedEventArgs* e)
void xf_OnChannelConnectedEventHandler(void* context, ChannelConnectedEventArgs* e)
{
xfContext* xfc = (xfContext*) context;
rdpSettings* settings = context->settings;
rdpSettings* settings = xfc->context.settings;
if (strcmp(e->name, RDPEI_DVC_CHANNEL_NAME) == 0)
{
@ -47,7 +50,7 @@ void xf_OnChannelConnectedEventHandler(rdpContext* context, ChannelConnectedEven
else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0)
{
if (settings->SoftwareGdi)
gdi_graphics_pipeline_init(context->gdi, (RdpgfxClientContext*) e->pInterface);
gdi_graphics_pipeline_init(xfc->context.gdi, (RdpgfxClientContext*) e->pInterface);
else
xf_graphics_pipeline_init(xfc, (RdpgfxClientContext*) e->pInterface);
}
@ -63,12 +66,31 @@ void xf_OnChannelConnectedEventHandler(rdpContext* context, ChannelConnectedEven
{
xf_encomsp_init(xfc, (EncomspClientContext*) e->pInterface);
}
else if (strcmp(e->name, DISP_DVC_CHANNEL_NAME) == 0)
{
xf_disp_init(xfc, (DispClientContext*)e->pInterface);
}
else if (strcmp(e->name, GEOMETRY_DVC_CHANNEL_NAME) == 0)
{
gdi_video_geometry_init(xfc->context.gdi, (GeometryClientContext*)e->pInterface);
}
else if (strcmp(e->name, VIDEO_CONTROL_DVC_CHANNEL_NAME) == 0)
{
if (settings->SoftwareGdi)
gdi_video_control_init(xfc->context.gdi, (VideoClientContext*)e->pInterface);
else
xf_video_control_init(xfc, (VideoClientContext*)e->pInterface);
}
else if (strcmp(e->name, VIDEO_DATA_DVC_CHANNEL_NAME) == 0)
{
gdi_video_data_init(xfc->context.gdi, (VideoClientContext*)e->pInterface);
}
}
void xf_OnChannelDisconnectedEventHandler(rdpContext* context, ChannelDisconnectedEventArgs* e)
void xf_OnChannelDisconnectedEventHandler(void* context, ChannelDisconnectedEventArgs* e)
{
xfContext* xfc = (xfContext*) context;
rdpSettings* settings = context->settings;
rdpSettings* settings = xfc->context.settings;
if (strcmp(e->name, RDPEI_DVC_CHANNEL_NAME) == 0)
{
@ -81,7 +103,7 @@ void xf_OnChannelDisconnectedEventHandler(rdpContext* context, ChannelDisconnect
else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0)
{
if (settings->SoftwareGdi)
gdi_graphics_pipeline_uninit(context->gdi, (RdpgfxClientContext*) e->pInterface);
gdi_graphics_pipeline_uninit(xfc->context.gdi, (RdpgfxClientContext*) e->pInterface);
else
xf_graphics_pipeline_uninit(xfc, (RdpgfxClientContext*) e->pInterface);
}
@ -97,4 +119,19 @@ void xf_OnChannelDisconnectedEventHandler(rdpContext* context, ChannelDisconnect
{
xf_encomsp_uninit(xfc, (EncomspClientContext*) e->pInterface);
}
else if (strcmp(e->name, GEOMETRY_DVC_CHANNEL_NAME) == 0)
{
gdi_video_geometry_uninit(xfc->context.gdi, (GeometryClientContext*)e->pInterface);
}
else if (strcmp(e->name, VIDEO_CONTROL_DVC_CHANNEL_NAME) == 0)
{
if (settings->SoftwareGdi)
gdi_video_control_uninit(xfc->context.gdi, (VideoClientContext*)e->pInterface);
else
xf_video_control_uninit(xfc, (VideoClientContext*)e->pInterface);
}
else if (strcmp(e->name, VIDEO_DATA_DVC_CHANNEL_NAME) == 0)
{
gdi_video_data_uninit(xfc->context.gdi, (VideoClientContext*)e->pInterface);
}
}

View File

@ -28,11 +28,14 @@
#include <freerdp/client/cliprdr.h>
#include <freerdp/client/rdpgfx.h>
#include <freerdp/client/encomsp.h>
#include <freerdp/client/disp.h>
#include <freerdp/client/geometry.h>
#include <freerdp/client/video.h>
int xf_on_channel_connected(freerdp* instance, const char* name, void* pInterface);
int xf_on_channel_disconnected(freerdp* instance, const char* name, void* pInterface);
void xf_OnChannelConnectedEventHandler(rdpContext* context, ChannelConnectedEventArgs* e);
void xf_OnChannelDisconnectedEventHandler(rdpContext* context, ChannelDisconnectedEventArgs* e);
void xf_OnChannelConnectedEventHandler(void* context, ChannelConnectedEventArgs* e);
void xf_OnChannelDisconnectedEventHandler(void* context, ChannelDisconnectedEventArgs* e);
#endif /* FREERDP_CLIENT_X11_CHANNELS_H */

View File

@ -30,6 +30,7 @@
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#ifdef WITH_XRENDER
#include <X11/extensions/Xrender.h>
@ -86,6 +87,7 @@
#include <winpr/synch.h>
#include <winpr/file.h>
#include <winpr/print.h>
#include <winpr/sysinfo.h>
#include <X11/XKBlib.h>
#include "xf_gdi.h"
@ -94,6 +96,8 @@
#include "xf_event.h"
#include "xf_input.h"
#include "xf_cliprdr.h"
#include "xf_disp.h"
#include "xf_video.h"
#include "xf_monitor.h"
#include "xf_graphics.h"
#include "xf_keyboard.h"
@ -222,8 +226,7 @@ void xf_draw_screen(xfContext* xfc, int x, int y, int w, int h)
}
#endif
XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc, x, y, w, h,
x, y);
XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc, x, y, w, h, x, y);
}
static BOOL xf_desktop_resize(rdpContext* context)
@ -259,8 +262,7 @@ static BOOL xf_desktop_resize(rdpContext* context)
if (!xfc->fullscreen)
{
xf_ResizeDesktopWindow(xfc, xfc->window, settings->DesktopWidth,
settings->DesktopHeight);
xf_ResizeDesktopWindow(xfc, xfc->window, settings->DesktopWidth, settings->DesktopHeight);
}
else
{
@ -287,9 +289,6 @@ static BOOL xf_desktop_resize(rdpContext* context)
static BOOL xf_sw_begin_paint(rdpContext* context)
{
rdpGdi* gdi = context->gdi;
gdi->primary->hdc->hwnd->invalid->null = TRUE;
gdi->primary->hdc->hwnd->ninvalid = 0;
return TRUE;
}
@ -302,6 +301,10 @@ static BOOL xf_sw_end_paint(rdpContext* context)
HGDI_RGN cinvalid;
xfContext* xfc = (xfContext*) context;
rdpGdi* gdi = context->gdi;
if (gdi->suppressOutput)
return TRUE;
x = gdi->primary->hdc->hwnd->invalid->x;
y = gdi->primary->hdc->hwnd->invalid->y;
w = gdi->primary->hdc->hwnd->invalid->w;
@ -354,6 +357,8 @@ static BOOL xf_sw_end_paint(rdpContext* context)
xf_unlock_x11(xfc, FALSE);
}
gdi->primary->hdc->hwnd->invalid->null = TRUE;
gdi->primary->hdc->hwnd->ninvalid = 0;
return TRUE;
}
@ -381,6 +386,8 @@ static BOOL xf_sw_desktop_resize(rdpContext* context)
goto out;
}
xfc->image->byte_order = LSBFirst;
xfc->image->bitmap_bit_order = LSBFirst;
ret = xf_desktop_resize(context);
out:
xf_unlock_x11(xfc, TRUE);
@ -389,9 +396,6 @@ out:
static BOOL xf_hw_begin_paint(rdpContext* context)
{
xfContext* xfc = (xfContext*) context;
xfc->hdc->hwnd->invalid->null = TRUE;
xfc->hdc->hwnd->ninvalid = 0;
return TRUE;
}
@ -401,6 +405,9 @@ static BOOL xf_hw_end_paint(rdpContext* context)
UINT32 w, h;
xfContext* xfc = (xfContext*) context;
if (xfc->context.gdi->suppressOutput)
return TRUE;
if (!xfc->remote_app)
{
if (!xfc->complex_regions)
@ -456,6 +463,8 @@ static BOOL xf_hw_end_paint(rdpContext* context)
xf_unlock_x11(xfc, FALSE);
}
xfc->hdc->hwnd->invalid->null = TRUE;
xfc->hdc->hwnd->ninvalid = 0;
return TRUE;
}
@ -628,6 +637,8 @@ BOOL xf_create_window(xfContext* xfc)
ZPixmap, 0, (char*) gdi->primary_buffer,
settings->DesktopWidth, settings->DesktopHeight,
xfc->scanline_pad, gdi->stride);
xfc->image->byte_order = LSBFirst;
xfc->image->bitmap_bit_order = LSBFirst;
}
return TRUE;
@ -635,12 +646,6 @@ BOOL xf_create_window(xfContext* xfc)
static void xf_window_free(xfContext* xfc)
{
if (xfc->gc_mono)
{
XFreeGC(xfc->display, xfc->gc_mono);
xfc->gc_mono = 0;
}
if (xfc->window)
{
xf_DestroyDesktopWindow(xfc, xfc->window);
@ -672,6 +677,12 @@ static void xf_window_free(xfContext* xfc)
xfc->bitmap_mono = 0;
}
if (xfc->gc_mono)
{
XFreeGC(xfc->display, xfc->gc_mono);
xfc->gc_mono = 0;
}
if (xfc->primary)
{
XFreePixmap(xfc->display, xfc->primary);
@ -772,15 +783,6 @@ void xf_unlock_x11(xfContext* xfc, BOOL display)
}
}
static void xf_calculate_color_shifts(UINT32 mask, UINT8* rsh, UINT8* lsh)
{
for (*lsh = 0; !(mask & 1); mask >>= 1)
(*lsh)++;
for (*rsh = 8; mask; mask >>= 1)
(*rsh)--;
}
static BOOL xf_get_pixmap_info(xfContext* xfc)
{
int i;
@ -849,20 +851,13 @@ static BOOL xf_get_pixmap_info(xfContext* xfc)
if (xfc->visual)
{
/*
* Detect if the server visual has an inverted colormap
* (BGR vs RGB, or red being the least significant byte)
*/
* Detect if the server visual has an inverted colormap
* (BGR vs RGB, or red being the least significant byte)
*/
if (vi->red_mask & 0xFF)
{
xfc->invert = TRUE;
xfc->invert = FALSE;
}
/* calculate color shifts required for rdp order color conversion */
xf_calculate_color_shifts(vi->red_mask, &xfc->red_shift_r, &xfc->red_shift_l);
xf_calculate_color_shifts(vi->green_mask, &xfc->green_shift_r,
&xfc->green_shift_l);
xf_calculate_color_shifts(vi->blue_mask, &xfc->blue_shift_r,
&xfc->blue_shift_l);
}
XFree(vis);
@ -1124,9 +1119,9 @@ static BOOL xf_pre_connect(freerdp* instance)
settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE;
settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE;
PubSub_SubscribeChannelConnected(instance->context->pubSub,
(pChannelConnectedEventHandler) xf_OnChannelConnectedEventHandler);
xf_OnChannelConnectedEventHandler);
PubSub_SubscribeChannelDisconnected(instance->context->pubSub,
(pChannelDisconnectedEventHandler) xf_OnChannelDisconnectedEventHandler);
xf_OnChannelDisconnectedEventHandler);
if (!freerdp_client_load_addins(channels, instance->settings))
return FALSE;
@ -1278,15 +1273,19 @@ static BOOL xf_post_connect(freerdp* instance)
update->SetKeyboardIndicators = xf_keyboard_set_indicators;
update->SetKeyboardImeStatus = xf_keyboard_set_ime_status;
if (!(xfc->clipboard = xf_clipboard_new(xfc)))
return FALSE;
if (!(xfc->xfDisp = xf_disp_new(xfc)))
{
xf_clipboard_free(xfc->clipboard);
return FALSE;
}
EventArgsInit(&e, "xfreerdp");
e.width = settings->DesktopWidth;
e.height = settings->DesktopHeight;
PubSub_OnResizeWindow(context->pubSub, xfc, &e);
return TRUE;
}
@ -1308,6 +1307,17 @@ static void xf_post_disconnect(freerdp* instance)
xfc->clipboard = NULL;
}
if (xfc->xfDisp)
{
xf_disp_free(xfc->xfDisp);
xfc->xfDisp = NULL;
}
if ((xfc->window != NULL) && (xfc->drawable == xfc->window->handle))
xfc->drawable = 0;
else
xf_DestroyDummyWindow(xfc, xfc->drawable);
xf_window_free(xfc);
xf_keyboard_free(xfc);
}
@ -1315,15 +1325,14 @@ static void xf_post_disconnect(freerdp* instance)
static int xf_logon_error_info(freerdp* instance, UINT32 data, UINT32 type)
{
xfContext* xfc = (xfContext*) instance->context;
const char *str_data = freerdp_get_logon_error_info_data(data);
const char *str_type = freerdp_get_logon_error_info_type(type);
const char* str_data = freerdp_get_logon_error_info_data(data);
const char* str_type = freerdp_get_logon_error_info_type(type);
WLog_INFO(TAG, "Logon Error Info %s [%s]", str_data, str_type);
xf_rail_disable_remoteapp_mode(xfc);
return 1;
}
static void* xf_input_thread(void* arg)
static DWORD WINAPI xf_input_thread(LPVOID arg)
{
BOOL running = TRUE;
DWORD status;
@ -1402,7 +1411,7 @@ static void* xf_input_thread(void* arg)
MessageQueue_PostQuit(queue, 0);
ExitThread(0);
return NULL;
return 0;
}
static BOOL xf_auto_reconnect(freerdp* instance)
@ -1454,10 +1463,10 @@ static BOOL xf_auto_reconnect(freerdp* instance)
* @param instance - pointer to the rdp_freerdp structure that contains the session's settings
* @return A code from the enum XF_EXIT_CODE (0 if successful)
*/
static void* xf_client_thread(void* param)
static DWORD WINAPI xf_client_thread(LPVOID param)
{
BOOL status;
int exit_code;
DWORD exit_code = 0;
DWORD nCount;
DWORD waitStatus;
HANDLE handles[64];
@ -1466,29 +1475,34 @@ static void* xf_client_thread(void* param)
rdpContext* context;
HANDLE inputEvent = NULL;
HANDLE inputThread = NULL;
HANDLE timer = NULL;
LARGE_INTEGER due;
rdpSettings* settings;
exit_code = 0;
TimerEventArgs timerEvent;
EventArgsInit(&timerEvent, "xfreerdp");
instance = (freerdp*) param;
context = instance->context;
status = freerdp_connect(instance);
xfc = (xfContext*) instance->context;
if (!status)
{
if (freerdp_get_last_error(instance->context) ==
FREERDP_ERROR_AUTHENTICATION_FAILED)
exit_code = XF_EXIT_AUTH_FAILURE;
else
exit_code = XF_EXIT_CONN_FAILED;
}
else
exit_code = XF_EXIT_SUCCESS;
if (!status)
goto end;
/* --authonly ? */
if (instance->settings->AuthenticationOnly)
{
WLog_ERR(TAG, "Authentication only, exit status %"PRId32"", !status);
if (!status)
{
if (freerdp_get_last_error(instance->context) ==
FREERDP_ERROR_AUTHENTICATION_FAILED)
exit_code = XF_EXIT_AUTH_FAILURE;
else
exit_code = XF_EXIT_CONN_FAILED;
}
else
exit_code = XF_EXIT_SUCCESS;
goto disconnect;
}
@ -1507,16 +1521,31 @@ static void* xf_client_thread(void* param)
}
settings = context->settings;
timer = CreateWaitableTimerA(NULL, FALSE, "mainloop-periodic-timer");
if (!timer)
{
WLog_ERR(TAG, "failed to create timer");
goto disconnect;
}
due.QuadPart = 0;
if (!SetWaitableTimer(timer, &due, 20, NULL, NULL, FALSE))
{
goto disconnect;
}
handles[0] = timer;
if (!settings->AsyncInput)
{
inputEvent = xfc->x11event;
handles[0] = inputEvent;
handles[1] = inputEvent;
}
else
{
if (!(inputThread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) xf_input_thread, instance, 0, NULL)))
if (!(inputThread = CreateThread(NULL, 0, xf_input_thread, instance, 0, NULL)))
{
WLog_ERR(TAG, "async input: failed to create input thread");
exit_code = XF_EXIT_UNKNOWN;
@ -1527,17 +1556,17 @@ static void* xf_client_thread(void* param)
while (!freerdp_shall_disconnect(instance))
{
/*
* win8 and server 2k12 seem to have some timing issue/race condition
* when a initial sync request is send to sync the keyboard indicators
* sending the sync event twice fixed this problem
*/
* win8 and server 2k12 seem to have some timing issue/race condition
* when a initial sync request is send to sync the keyboard indicators
* sending the sync event twice fixed this problem
*/
if (freerdp_focus_required(instance))
{
xf_keyboard_focus_in(xfc);
xf_keyboard_focus_in(xfc);
}
nCount = (settings->AsyncInput) ? 0 : 1;
nCount = (settings->AsyncInput) ? 1 : 2;
if (!settings->AsyncTransport)
{
@ -1552,7 +1581,7 @@ static void* xf_client_thread(void* param)
nCount += tmp;
}
waitStatus = WaitForMultipleObjects(nCount, handles, FALSE, 100);
waitStatus = WaitForMultipleObjects(nCount, handles, FALSE, INFINITE);
if (waitStatus == WAIT_FAILED)
break;
@ -1564,7 +1593,9 @@ static void* xf_client_thread(void* param)
if (xf_auto_reconnect(instance))
continue;
WLog_ERR(TAG, "Failed to check FreeRDP file descriptor");
if (freerdp_get_last_error(context) == FREERDP_ERROR_SUCCESS)
WLog_ERR(TAG, "Failed to check FreeRDP file descriptor");
break;
}
}
@ -1577,6 +1608,12 @@ static void* xf_client_thread(void* param)
break;
}
}
if ((status != WAIT_TIMEOUT) && (waitStatus == WAIT_OBJECT_0))
{
timerEvent.now = GetTickCount64();
PubSub_OnTimer(context->pubSub, context, &timerEvent);
}
}
if (settings->AsyncInput)
@ -1589,9 +1626,14 @@ static void* xf_client_thread(void* param)
exit_code = freerdp_error_info(instance);
disconnect:
if (timer)
CloseHandle(timer);
freerdp_disconnect(instance);
end:
ExitThread(exit_code);
return NULL;
return exit_code;
}
DWORD xf_exit_code_from_disconnect_reason(DWORD reason)
@ -1612,17 +1654,18 @@ DWORD xf_exit_code_from_disconnect_reason(DWORD reason)
return reason;
}
static void xf_TerminateEventHandler(rdpContext* context, TerminateEventArgs* e)
static void xf_TerminateEventHandler(void* context, TerminateEventArgs* e)
{
freerdp_abort_connect(context->instance);
rdpContext* ctx = (rdpContext*)context;
freerdp_abort_connect(ctx->instance);
}
#ifdef WITH_XRENDER
static void xf_ZoomingChangeEventHandler(rdpContext* context,
static void xf_ZoomingChangeEventHandler(void* context,
ZoomingChangeEventArgs* e)
{
xfContext* xfc = (xfContext*) context;
rdpSettings* settings = context->settings;
rdpSettings* settings = xfc->context.settings;
int w = xfc->scaledWidth + e->dx;
int h = xfc->scaledHeight + e->dy;
@ -1643,11 +1686,11 @@ static void xf_ZoomingChangeEventHandler(rdpContext* context,
xf_draw_screen(xfc, 0, 0, settings->DesktopWidth, settings->DesktopHeight);
}
static void xf_PanningChangeEventHandler(rdpContext* context,
static void xf_PanningChangeEventHandler(void* context,
PanningChangeEventArgs* e)
{
xfContext* xfc = (xfContext*) context;
rdpSettings* settings = context->settings;
rdpSettings* settings = xfc->context.settings;
if (e->dx == 0 && e->dy == 0)
return;
@ -1688,8 +1731,7 @@ static int xfreerdp_client_start(rdpContext* context)
return -1;
}
if (!(xfc->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) xf_client_thread,
if (!(xfc->thread = CreateThread(NULL, 0, xf_client_thread,
context->instance, 0, NULL)))
{
WLog_ERR(TAG, "failed to create client thread");
@ -1714,6 +1756,19 @@ static int xfreerdp_client_stop(rdpContext* context)
return 0;
}
static Atom get_supported_atom(xfContext* xfc, const char* atomName)
{
unsigned long i;
const Atom atom = XInternAtom(xfc->display, atomName, False);
for (i = 0; i < xfc->supportedAtomCount; i++)
{
if (xfc->supportedAtoms[i] == atom)
return atom;
}
return None;
}
static BOOL xfreerdp_client_new(freerdp* instance, rdpContext* context)
{
xfContext* xfc = (xfContext*) instance->context;
@ -1731,12 +1786,12 @@ static BOOL xfreerdp_client_new(freerdp* instance, rdpContext* context)
instance->VerifyChangedCertificate = client_cli_verify_changed_certificate;
instance->LogonErrorInfo = xf_logon_error_info;
PubSub_SubscribeTerminate(context->pubSub,
(pTerminateEventHandler) xf_TerminateEventHandler);
xf_TerminateEventHandler);
#ifdef WITH_XRENDER
PubSub_SubscribeZoomingChange(context->pubSub,
(pZoomingChangeEventHandler) xf_ZoomingChangeEventHandler);
xf_ZoomingChangeEventHandler);
PubSub_SubscribePanningChange(context->pubSub,
(pPanningChangeEventHandler) xf_PanningChangeEventHandler);
xf_PanningChangeEventHandler);
#endif
xfc->UseXThreads = TRUE;
//xfc->debug = TRUE;
@ -1768,20 +1823,49 @@ static BOOL xfreerdp_client_new(freerdp* instance, rdpContext* context)
goto fail_create_mutex;
}
xfc->xfds = ConnectionNumber(xfc->display);
xfc->screen_number = DefaultScreen(xfc->display);
xfc->screen = ScreenOfDisplay(xfc->display, xfc->screen_number);
xfc->depth = DefaultDepthOfScreen(xfc->screen);
xfc->big_endian = (ImageByteOrder(xfc->display) == MSBFirst);
xfc->invert = TRUE;
xfc->complex_regions = TRUE;
xfc->_NET_SUPPORTED = XInternAtom(xfc->display, "_NET_SUPPORTED", True);
xfc->_NET_SUPPORTING_WM_CHECK = XInternAtom(xfc->display, "_NET_SUPPORTING_WM_CHECK", True);
if ((xfc->_NET_SUPPORTED != None) && (xfc->_NET_SUPPORTING_WM_CHECK != None))
{
Atom actual_type;
int actual_format;
unsigned long nitems, after;
unsigned char* data = NULL;
int status = XGetWindowProperty(xfc->display, RootWindowOfScreen(xfc->screen),
xfc->_NET_SUPPORTED, 0, 1024, False, XA_ATOM,
&actual_type, &actual_format, &nitems, &after, &data);
if ((status == Success) && (actual_type == XA_ATOM) && (actual_format == 32))
{
xfc->supportedAtomCount = nitems;
xfc->supportedAtoms = calloc(nitems, sizeof(Atom));
memcpy(xfc->supportedAtoms, data, nitems * sizeof(Atom));
}
if (data)
XFree(data);
}
xfc->_NET_WM_ICON = XInternAtom(xfc->display, "_NET_WM_ICON", False);
xfc->_MOTIF_WM_HINTS = XInternAtom(xfc->display, "_MOTIF_WM_HINTS", False);
xfc->_NET_CURRENT_DESKTOP = XInternAtom(xfc->display, "_NET_CURRENT_DESKTOP",
False);
xfc->_NET_WORKAREA = XInternAtom(xfc->display, "_NET_WORKAREA", False);
xfc->_NET_WM_STATE = XInternAtom(xfc->display, "_NET_WM_STATE", False);
xfc->_NET_WM_STATE_FULLSCREEN = XInternAtom(xfc->display,
"_NET_WM_STATE_FULLSCREEN", False);
xfc->_NET_WM_STATE = get_supported_atom(xfc, "_NET_WM_STATE");
xfc->_NET_WM_STATE_FULLSCREEN = get_supported_atom(xfc, "_NET_WM_STATE_FULLSCREEN");
xfc->_NET_WM_STATE_MAXIMIZED_HORZ = XInternAtom(xfc->display,
"_NET_WM_STATE_MAXIMIZED_HORZ", False);
xfc->_NET_WM_STATE_MAXIMIZED_VERT = XInternAtom(xfc->display,
"_NET_WM_STATE_MAXIMIZED_VERT", False);
xfc->_NET_WM_FULLSCREEN_MONITORS = XInternAtom(xfc->display,
"_NET_WM_FULLSCREEN_MONITORS", False);
xfc->_NET_WM_FULLSCREEN_MONITORS = get_supported_atom(xfc, "_NET_WM_FULLSCREEN_MONITORS");
xfc->_NET_WM_NAME = XInternAtom(xfc->display, "_NET_WM_NAME", False);
xfc->_NET_WM_PID = XInternAtom(xfc->display, "_NET_WM_PID", False);
xfc->_NET_WM_WINDOW_TYPE = XInternAtom(xfc->display, "_NET_WM_WINDOW_TYPE",
@ -1808,13 +1892,6 @@ static BOOL xfreerdp_client_new(freerdp* instance, rdpContext* context)
xfc->WM_PROTOCOLS = XInternAtom(xfc->display, "WM_PROTOCOLS", False);
xfc->WM_DELETE_WINDOW = XInternAtom(xfc->display, "WM_DELETE_WINDOW", False);
xfc->WM_STATE = XInternAtom(xfc->display, "WM_STATE", False);
xfc->xfds = ConnectionNumber(xfc->display);
xfc->screen_number = DefaultScreen(xfc->display);
xfc->screen = ScreenOfDisplay(xfc->display, xfc->screen_number);
xfc->depth = DefaultDepthOfScreen(xfc->screen);
xfc->big_endian = (ImageByteOrder(xfc->display) == MSBFirst);
xfc->invert = (ImageByteOrder(xfc->display) == MSBFirst) ? FALSE : TRUE;
xfc->complex_regions = TRUE;
xfc->x11event = CreateFileDescriptorEvent(NULL, FALSE, FALSE, xfc->xfds,
WINPR_FD_READ);
@ -1891,6 +1968,8 @@ static void xfreerdp_client_free(freerdp* instance, rdpContext* context)
free(xfc->vscreen.monitors);
xfc->vscreen.monitors = NULL;
}
free(xfc->supportedAtoms);
}
int RdpClientEntry(RDP_CLIENT_ENTRY_POINTS* pEntryPoints)

View File

@ -320,7 +320,10 @@ static wStream* xf_cliprdr_serialize_server_format_list(xfClipboard* clipboard)
}
Stream_Write_UINT32(s, format->formatId);
Stream_Write(s, format->formatName, name_length);
if (format->formatName)
Stream_Write(s, format->formatName, name_length);
Stream_Write_UINT8(s, '\0');
}
@ -436,7 +439,8 @@ static CLIPRDR_FORMAT* xf_cliprdr_get_raw_server_formats(xfClipboard* clipboard,
{
WLog_ERR(TAG,
"failed to retrieve raw format list: data=%p, length=%lu, format=%d, type=%lu (expected=%lu)",
(void*) data, length, format, (unsigned long) type, (unsigned long) clipboard->raw_format_list_atom);
(void*) data, length, format, (unsigned long) type,
(unsigned long) clipboard->raw_format_list_atom);
}
if (data)
@ -630,15 +634,13 @@ static void xf_cliprdr_process_requested_data(xfClipboard* clipboard,
* to not process CF_RAW as a file list in case WinPR does not support file transfers.
*/
if (dstFormatId &&
(dstFormatId == ClipboardGetFormatId(clipboard->system, "FileGroupDescriptorW")))
(dstFormatId == ClipboardGetFormatId(clipboard->system, "FileGroupDescriptorW")))
{
UINT error = NO_ERROR;
FILEDESCRIPTOR* file_array = (FILEDESCRIPTOR*) pDstData;
UINT32 file_count = DstSize / sizeof(FILEDESCRIPTOR);
pDstData = NULL;
DstSize = 0;
error = cliprdr_serialize_file_list(file_array, file_count, &pDstData, &DstSize);
if (error)
@ -817,6 +819,7 @@ static void xf_cliprdr_clear_cached_data(xfClipboard* clipboard)
free(clipboard->data);
clipboard->data = NULL;
}
clipboard->data_length = 0;
if (clipboard->data_raw)
@ -824,6 +827,7 @@ static void xf_cliprdr_clear_cached_data(xfClipboard* clipboard)
free(clipboard->data_raw);
clipboard->data_raw = NULL;
}
clipboard->data_raw_length = 0;
}
@ -904,7 +908,7 @@ static BOOL xf_cliprdr_process_selection_request(xfClipboard* clipboard,
/* We can compare format names by pointer value here as they are both
* taken from the same clipboard->serverFormats array */
matchingFormat = (formatId == clipboard->data_format_id)
&& (formatName == clipboard->data_format_name);
&& (formatName == clipboard->data_format_name);
if (matchingFormat && (clipboard->data != 0) && !rawTransfer)
{
@ -930,7 +934,6 @@ static BOOL xf_cliprdr_process_selection_request(xfClipboard* clipboard,
* Response will be postponed after receiving the data
*/
xf_cliprdr_clear_cached_data(clipboard);
respond->xselection.property = xevent->xselectionrequest.property;
clipboard->respond = respond;
clipboard->data_format_id = formatId;
@ -1078,7 +1081,7 @@ static UINT xf_cliprdr_send_client_capabilities(xfClipboard* clipboard)
if (clipboard->streams_supported && clipboard->file_formats_registered)
generalCapabilitySet.generalFlags |=
CB_STREAM_FILECLIP_ENABLED | CB_FILECLIP_NO_FILE_PATHS;
CB_STREAM_FILECLIP_ENABLED | CB_FILECLIP_NO_FILE_PATHS;
return clipboard->context->ClientCapabilities(clipboard->context,
&capabilities);
@ -1180,7 +1183,6 @@ static UINT xf_cliprdr_server_capabilities(CliprdrClientContext* context,
const CLIPRDR_GENERAL_CAPABILITY_SET* generalCaps;
const BYTE* capsPtr = (const BYTE*) capabilities->capabilitySets;
xfClipboard* clipboard = (xfClipboard*) context->custom;
clipboard->streams_supported = FALSE;
for (i = 0; i < capabilities->cCapabilitiesSets; i++)
@ -1211,21 +1213,19 @@ static UINT xf_cliprdr_server_capabilities(CliprdrClientContext* context,
static UINT xf_cliprdr_server_format_list(CliprdrClientContext* context,
CLIPRDR_FORMAT_LIST* formatList)
{
int i, j;
CLIPRDR_FORMAT* format;
UINT32 i;
int j;
xfClipboard* clipboard = (xfClipboard*) context->custom;
xfContext* xfc = clipboard->xfc;
UINT ret;
xf_cliprdr_clear_cached_data(clipboard);
clipboard->data_format_id = -1;
clipboard->data_format_name = NULL;
if (clipboard->serverFormats)
{
for (i = 0; i < clipboard->numServerFormats; i++)
free(clipboard->serverFormats[i].formatName);
for (j = 0; j < clipboard->numServerFormats; j++)
free(clipboard->serverFormats[j].formatName);
free(clipboard->serverFormats);
clipboard->serverFormats = NULL;
@ -1244,7 +1244,7 @@ static UINT xf_cliprdr_server_format_list(CliprdrClientContext* context,
for (i = 0; i < formatList->numFormats; i++)
{
format = &formatList->formats[i];
CLIPRDR_FORMAT* format = &formatList->formats[i];
clipboard->serverFormats[i].formatId = format->formatId;
if (format->formatName)
@ -1253,8 +1253,10 @@ static UINT xf_cliprdr_server_format_list(CliprdrClientContext* context,
if (!clipboard->serverFormats[i].formatName)
{
for (--i; i >= 0; --i)
free(clipboard->serverFormats[i].formatName);
UINT32 k;
for (k = 0; k < i; k++)
free(clipboard->serverFormats[k].formatName);
clipboard->numServerFormats = 0;
free(clipboard->serverFormats);
@ -1265,15 +1267,17 @@ static UINT xf_cliprdr_server_format_list(CliprdrClientContext* context,
}
/* CF_RAW is always implicitly supported by the server */
format = &clipboard->serverFormats[formatList->numFormats];
format->formatId = CF_RAW;
format->formatName = NULL;
{
CLIPRDR_FORMAT* format = &clipboard->serverFormats[formatList->numFormats];
format->formatId = CF_RAW;
format->formatName = NULL;
}
xf_cliprdr_provide_server_format_list(clipboard);
clipboard->numTargets = 2;
for (i = 0; i < formatList->numFormats; i++)
{
format = &formatList->formats[i];
CLIPRDR_FORMAT* format = &formatList->formats[i];
for (j = 0; j < clipboard->numClientFormats; j++)
{
@ -1362,7 +1366,6 @@ static UINT xf_cliprdr_server_format_data_response(CliprdrClientContext*
return CHANNEL_RC_OK;
xf_cliprdr_clear_cached_data(clipboard);
pDstData = NULL;
DstSize = 0;
srcFormatId = 0;
@ -1430,11 +1433,11 @@ static UINT xf_cliprdr_server_format_data_response(CliprdrClientContext*
* conversion again on subsequent requests */
clipboard->data = pDstData;
clipboard->data_length = DstSize;
/* We have to copy the original data again, as pSrcData is now owned
* by clipboard->system. Memory allocation failure is not fatal here
* as this is only a cached value. */
clipboard->data_raw = (BYTE*) malloc(size);
if (clipboard->data_raw)
{
CopyMemory(clipboard->data_raw, data, size);
@ -1455,56 +1458,48 @@ static UINT xf_cliprdr_server_format_data_response(CliprdrClientContext*
}
static UINT xf_cliprdr_server_file_size_request(xfClipboard* clipboard,
const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
{
wClipboardFileSizeRequest request;
ZeroMemory(&request, sizeof(request));
request.streamId = fileContentsRequest->streamId;
request.listIndex = fileContentsRequest->listIndex;
if (fileContentsRequest->cbRequested != sizeof(UINT64))
{
WLog_WARN(TAG, "unexpected FILECONTENTS_SIZE request: %"PRIu32" bytes",
fileContentsRequest->cbRequested);
fileContentsRequest->cbRequested);
}
return clipboard->delegate->ClientRequestFileSize(clipboard->delegate, &request);
}
static UINT xf_cliprdr_server_file_range_request(xfClipboard* clipboard,
const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
{
wClipboardFileRangeRequest request;
ZeroMemory(&request, sizeof(request));
request.streamId = fileContentsRequest->streamId;
request.listIndex = fileContentsRequest->listIndex;
request.nPositionLow = fileContentsRequest->nPositionLow;
request.nPositionHigh = fileContentsRequest->nPositionHigh;
request.cbRequested = fileContentsRequest->cbRequested;
return clipboard->delegate->ClientRequestFileRange(clipboard->delegate, &request);
}
static UINT xf_cliprdr_send_file_contents_failure(CliprdrClientContext* context,
const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
{
CLIPRDR_FILE_CONTENTS_RESPONSE response;
ZeroMemory(&response, sizeof(response));
response.msgFlags = CB_RESPONSE_FAIL;
response.streamId = fileContentsRequest->streamId;
response.dwFlags = fileContentsRequest->dwFlags;
return context->ClientFileContentsResponse(context, &response);
}
static UINT xf_cliprdr_server_file_contents_request(CliprdrClientContext* context,
CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
{
UINT error = NO_ERROR;
xfClipboard* clipboard = context->custom;
@ -1514,10 +1509,9 @@ static UINT xf_cliprdr_server_file_contents_request(CliprdrClientContext* contex
* The FILECONTENTS_SIZE and FILECONTENTS_RANGE flags MUST NOT be set at the same time.
*/
if ((fileContentsRequest->dwFlags & (FILECONTENTS_SIZE | FILECONTENTS_RANGE)) ==
(FILECONTENTS_SIZE | FILECONTENTS_RANGE))
(FILECONTENTS_SIZE | FILECONTENTS_RANGE))
{
WLog_ERR(TAG, "invalid CLIPRDR_FILECONTENTS_REQUEST.dwFlags");
return xf_cliprdr_send_file_contents_failure(context, fileContentsRequest);
}
@ -1530,7 +1524,6 @@ static UINT xf_cliprdr_server_file_contents_request(CliprdrClientContext* contex
if (error)
{
WLog_ERR(TAG, "failed to handle CLIPRDR_FILECONTENTS_REQUEST: 0x%08X", error);
return xf_cliprdr_send_file_contents_failure(context, fileContentsRequest);
}
@ -1538,66 +1531,54 @@ static UINT xf_cliprdr_server_file_contents_request(CliprdrClientContext* contex
}
static UINT xf_cliprdr_clipboard_file_size_success(wClipboardDelegate* delegate,
const wClipboardFileSizeRequest* request, UINT64 fileSize)
const wClipboardFileSizeRequest* request, UINT64 fileSize)
{
CLIPRDR_FILE_CONTENTS_RESPONSE response;
xfClipboard* clipboard = delegate->custom;
ZeroMemory(&response, sizeof(response));
response.msgFlags = CB_RESPONSE_OK;
response.streamId = request->streamId;
response.dwFlags = FILECONTENTS_SIZE;
response.cbRequested = sizeof(UINT64);
response.requestedData = (BYTE*) &fileSize;
return clipboard->context->ClientFileContentsResponse(clipboard->context, &response);
}
static UINT xf_cliprdr_clipboard_file_size_failure(wClipboardDelegate* delegate,
const wClipboardFileSizeRequest* request, UINT errorCode)
const wClipboardFileSizeRequest* request, UINT errorCode)
{
CLIPRDR_FILE_CONTENTS_RESPONSE response;
xfClipboard* clipboard = delegate->custom;
ZeroMemory(&response, sizeof(response));
response.msgFlags = CB_RESPONSE_FAIL;
response.streamId = request->streamId;
response.dwFlags = FILECONTENTS_SIZE;
return clipboard->context->ClientFileContentsResponse(clipboard->context, &response);
}
static UINT xf_cliprdr_clipboard_file_range_success(wClipboardDelegate* delegate,
const wClipboardFileRangeRequest* request, const BYTE* data, UINT32 size)
const wClipboardFileRangeRequest* request, const BYTE* data, UINT32 size)
{
CLIPRDR_FILE_CONTENTS_RESPONSE response;
xfClipboard* clipboard = delegate->custom;
ZeroMemory(&response, sizeof(response));
response.msgFlags = CB_RESPONSE_OK;
response.streamId = request->streamId;
response.dwFlags = FILECONTENTS_RANGE;
response.cbRequested = size;
response.requestedData = (BYTE*) data;
return clipboard->context->ClientFileContentsResponse(clipboard->context, &response);
}
static UINT xf_cliprdr_clipboard_file_range_failure(wClipboardDelegate* delegate,
const wClipboardFileRangeRequest* request, UINT errorCode)
const wClipboardFileRangeRequest* request, UINT errorCode)
{
CLIPRDR_FILE_CONTENTS_RESPONSE response;
xfClipboard* clipboard = delegate->custom;
ZeroMemory(&response, sizeof(response));
response.msgFlags = CB_RESPONSE_FAIL;
response.streamId = request->streamId;
response.dwFlags = FILECONTENTS_RANGE;
return clipboard->context->ClientFileContentsResponse(clipboard->context, &response);
}
@ -1631,12 +1612,11 @@ xfClipboard* xf_clipboard_new(xfContext* xfc)
clipboard->property_atom = XInternAtom(xfc->display, "_FREERDP_CLIPRDR", FALSE);
clipboard->raw_transfer_atom = XInternAtom(xfc->display, "_FREERDP_CLIPRDR_RAW", FALSE);
clipboard->raw_format_list_atom =
XInternAtom(xfc->display, "_FREERDP_CLIPRDR_FORMATS", FALSE);
XInternAtom(xfc->display, "_FREERDP_CLIPRDR_FORMATS", FALSE);
xf_cliprdr_set_raw_transfer_enabled(clipboard, TRUE);
XSelectInput(xfc->display, clipboard->root_window, PropertyChangeMask);
#ifdef WITH_XFIXES
if (XFixesQueryExtension(xfc->display, &clipboard->xfixes_event_base,
&clipboard->xfixes_error_base))
{
@ -1662,40 +1642,34 @@ xfClipboard* xf_clipboard_new(xfContext* xfc)
WLog_ERR(TAG,
"Warning: Using clipboard redirection without XFIXES extension is strongly discouraged!");
#endif
clipboard->clientFormats[n].atom = XInternAtom(xfc->display, "_FREERDP_RAW", False);
clipboard->clientFormats[n].formatId = CF_RAW;
n++;
clipboard->clientFormats[n].atom = XInternAtom(xfc->display, "UTF8_STRING", False);
clipboard->clientFormats[n].formatId = CF_UNICODETEXT;
n++;
clipboard->clientFormats[n].atom = XA_STRING;
clipboard->clientFormats[n].formatId = CF_TEXT;
n++;
clipboard->clientFormats[n].atom = XInternAtom(xfc->display, "image/png", False);
clipboard->clientFormats[n].formatId = CB_FORMAT_PNG;
n++;
clipboard->clientFormats[n].atom = XInternAtom(xfc->display, "image/jpeg", False);
clipboard->clientFormats[n].formatId = CB_FORMAT_JPEG;
n++;
clipboard->clientFormats[n].atom = XInternAtom(xfc->display, "image/gif", False);
clipboard->clientFormats[n].formatId = CB_FORMAT_GIF;
n++;
clipboard->clientFormats[n].atom = XInternAtom(xfc->display, "image/bmp", False);
clipboard->clientFormats[n].formatId = CF_DIB;
n++;
clipboard->clientFormats[n].atom = XInternAtom(xfc->display, "text/html", False);
clipboard->clientFormats[n].formatId = CB_FORMAT_HTML;
clipboard->clientFormats[n].formatName = _strdup("HTML Format");
if (!clipboard->clientFormats[n].formatName)
goto error;
n++;
/*
@ -1710,8 +1684,10 @@ xfClipboard* xf_clipboard_new(xfContext* xfc)
clipboard->clientFormats[n].atom = XInternAtom(xfc->display, "text/uri-list", False);
clipboard->clientFormats[n].formatId = CB_FORMAT_TEXTURILIST;
clipboard->clientFormats[n].formatName = _strdup("FileGroupDescriptorW");
if (!clipboard->clientFormats[n].formatName)
goto error;
n++;
}
@ -1720,24 +1696,20 @@ xfClipboard* xf_clipboard_new(xfContext* xfc)
clipboard->targets[1] = XInternAtom(xfc->display, "TARGETS", FALSE);
clipboard->numTargets = 2;
clipboard->incr_atom = XInternAtom(xfc->display, "INCR", FALSE);
clipboard->delegate = ClipboardGetDelegate(clipboard->system);
clipboard->delegate->custom = clipboard;
clipboard->delegate->ClipboardFileSizeSuccess = xf_cliprdr_clipboard_file_size_success;
clipboard->delegate->ClipboardFileSizeFailure = xf_cliprdr_clipboard_file_size_failure;
clipboard->delegate->ClipboardFileRangeSuccess = xf_cliprdr_clipboard_file_range_success;
clipboard->delegate->ClipboardFileRangeFailure = xf_cliprdr_clipboard_file_range_failure;
return clipboard;
error:
for (i = 0; i < n; i++)
free(clipboard->clientFormats[i].formatName);
ClipboardDestroy(clipboard->system);
free(clipboard);
return NULL;
}

333
client/X11/xf_disp.c Normal file
View File

@ -0,0 +1,333 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* X11 Display Control channel
*
* Copyright 2017 David Fort <contact@hardening-consulting.com>
*
* 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.
*/
#include <winpr/sysinfo.h>
#include <X11/Xutil.h>
#ifdef WITH_XRANDR
#include <X11/extensions/Xrandr.h>
#include <X11/extensions/randr.h>
#if (RANDR_MAJOR * 100 + RANDR_MINOR) >= 105
# define USABLE_XRANDR
#endif
#endif
#include "xf_disp.h"
#include "xf_monitor.h"
#define TAG CLIENT_TAG("x11disp")
#define RESIZE_MIN_DELAY 200 /* minimum delay in ms between two resizes */
struct _xfDispContext
{
xfContext *xfc;
BOOL haveXRandr;
int eventBase, errorBase;
int lastSentWidth, lastSentHeight;
UINT64 lastSentDate;
int targetWidth, targetHeight;
BOOL activated;
BOOL waitingResize;
};
static BOOL xf_disp_sendResize(xfDispContext *xfDisp, int width, int height)
{
DISPLAY_CONTROL_MONITOR_LAYOUT layout;
xfContext *xfc = xfDisp->xfc;
rdpSettings *settings = xfc->context.settings;
xfDisp->lastSentDate = GetTickCount64();
xfDisp->lastSentWidth = width;
xfDisp->lastSentHeight = height;
xfDisp->waitingResize = TRUE;
layout.Flags = DISPLAY_CONTROL_MONITOR_PRIMARY;
layout.Top = layout.Left = 0;
layout.Width = width;
layout.Height = height;
layout.Orientation = ORIENTATION_LANDSCAPE;
layout.DesktopScaleFactor = settings->DesktopScaleFactor;
layout.DeviceScaleFactor = settings->DeviceScaleFactor;
layout.PhysicalWidth = width;
layout.PhysicalHeight = height;
return xfc->disp->SendMonitorLayout(xfc->disp, 1, &layout) == CHANNEL_RC_OK;
}
static BOOL xf_disp_set_window_resizable(xfDispContext *xfDisp)
{
XSizeHints *size_hints;
if (!(size_hints = XAllocSizeHints()))
return FALSE;
size_hints->flags = PMinSize | PMaxSize | PWinGravity;
size_hints->win_gravity = NorthWestGravity;
size_hints->min_width = size_hints->min_height = 320;
size_hints->max_width = size_hints->max_height = 8192;
if (xfDisp->xfc->window)
XSetWMNormalHints(xfDisp->xfc->display, xfDisp->xfc->window->handle, size_hints);
XFree(size_hints);
return TRUE;
}
static void xf_disp_OnActivated(void* context, ActivatedEventArgs* e)
{
xfContext *xfc = (xfContext *)context;
xfDispContext *xfDisp = xfc->xfDisp;
rdpSettings *settings = xfc->context.settings;
xfDisp->waitingResize = FALSE;
if (xfDisp->activated && !settings->Fullscreen)
{
xf_disp_set_window_resizable(xfDisp);
if (e->firstActivation)
return;
/* if a resize has been done recently don't do anything and let the timer
* perform the resize */
if (GetTickCount64() - xfDisp->lastSentDate < RESIZE_MIN_DELAY)
return;
if ((xfDisp->lastSentWidth != xfDisp->targetWidth) || (xfDisp->lastSentHeight != xfDisp->targetHeight))
{
WLog_DBG(TAG, "performing delayed resize to %dx%d", xfDisp->targetWidth, xfDisp->targetHeight);
xf_disp_sendResize(xfDisp, xfDisp->targetWidth, xfDisp->targetHeight);
}
}
}
static void xf_disp_OnGraphicsReset(void* context, GraphicsResetEventArgs* e)
{
xfContext *xfc = (xfContext *)context;
xfDispContext *xfDisp = xfc->xfDisp;
rdpSettings *settings = xfc->context.settings;
xfDisp->waitingResize = FALSE;
if (xfDisp->activated && !settings->Fullscreen)
{
xf_disp_set_window_resizable(xfDisp);
/* if a resize has been done recently don't do anything and let the timer
* perform the resize */
if (GetTickCount64() - xfDisp->lastSentDate < RESIZE_MIN_DELAY)
return;
if ((xfDisp->lastSentWidth != xfDisp->targetWidth) || (xfDisp->lastSentHeight != xfDisp->targetHeight))
{
WLog_DBG(TAG, "performing delayed resize to %dx%d", xfDisp->targetWidth, xfDisp->targetHeight);
xf_disp_sendResize(xfDisp, xfDisp->targetWidth, xfDisp->targetHeight);
}
}
}
static void xf_disp_OnTimer(void* context, TimerEventArgs* e)
{
xfContext *xfc = (xfContext *)context;
xfDispContext *xfDisp = xfc->xfDisp;
rdpSettings *settings = xfc->context.settings;
if (!xfDisp->activated || settings->Fullscreen)
return;
if (e->now - xfDisp->lastSentDate < RESIZE_MIN_DELAY)
return;
if ((xfDisp->lastSentWidth != xfDisp->targetWidth) || (xfDisp->lastSentHeight != xfDisp->targetHeight))
{
WLog_DBG(TAG, "timer performing delayed resize to %dx%d", xfDisp->targetWidth, xfDisp->targetHeight);
xf_disp_sendResize(xfDisp, xfDisp->targetWidth, xfDisp->targetHeight);
}
}
xfDispContext *xf_disp_new(xfContext* xfc)
{
xfDispContext *ret = calloc(1, sizeof(xfDispContext));
if (!ret)
return NULL;
ret->xfc = xfc;
#ifdef USABLE_XRANDR
if (XRRQueryExtension(xfc->display, &ret->eventBase, &ret->errorBase))
{
ret->haveXRandr = TRUE;
}
#endif
ret->lastSentWidth = ret->targetWidth = xfc->context.settings->DesktopWidth;
ret->lastSentHeight = ret->targetHeight = xfc->context.settings->DesktopHeight;
PubSub_SubscribeActivated(xfc->context.pubSub, xf_disp_OnActivated);
PubSub_SubscribeGraphicsReset(xfc->context.pubSub, xf_disp_OnGraphicsReset);
PubSub_SubscribeTimer(xfc->context.pubSub, xf_disp_OnTimer);
return ret;
}
void xf_disp_free(xfDispContext *disp)
{
PubSub_UnsubscribeActivated(disp->xfc->context.pubSub, xf_disp_OnActivated);
PubSub_UnsubscribeTimer(disp->xfc->context.pubSub, xf_disp_OnTimer);
free(disp);
}
static UINT xf_disp_sendLayout(DispClientContext *disp, rdpMonitor *monitors, int nmonitors)
{
UINT ret = CHANNEL_RC_OK;
DISPLAY_CONTROL_MONITOR_LAYOUT *layouts;
int i;
xfDispContext *xfDisp = (xfDispContext *)disp->custom;
rdpSettings *settings = xfDisp->xfc->context.settings;
layouts = calloc(nmonitors, sizeof(DISPLAY_CONTROL_MONITOR_LAYOUT));
if (!layouts)
return CHANNEL_RC_NO_MEMORY;
for (i = 0; i < nmonitors; i++)
{
layouts[i].Flags = (monitors[i].is_primary ? DISPLAY_CONTROL_MONITOR_PRIMARY : 0);
layouts[i].Left = monitors[i].x;
layouts[i].Top = monitors[i].y;
layouts[i].Width = monitors[i].width;
layouts[i].Height = monitors[i].height;
layouts[i].Orientation = ORIENTATION_LANDSCAPE;
layouts[i].PhysicalWidth = monitors[i].attributes.physicalWidth;
layouts[i].PhysicalHeight = monitors[i].attributes.physicalHeight;
switch(monitors[i].attributes.orientation)
{
case 90:
layouts[i].Orientation = ORIENTATION_PORTRAIT;
break;
case 180:
layouts[i].Orientation = ORIENTATION_LANDSCAPE_FLIPPED;
break;
case 270:
layouts[i].Orientation = ORIENTATION_PORTRAIT_FLIPPED;
break;
case 0:
default:
/* MS-RDPEDISP - 2.2.2.2.1:
* Orientation (4 bytes): A 32-bit unsigned integer that specifies the
* orientation of the monitor in degrees. Valid values are 0, 90, 180
* or 270
*
* So we default to ORIENTATION_LANDSCAPE
*/
layouts[i].Orientation = ORIENTATION_LANDSCAPE;
break;
}
layouts[i].DesktopScaleFactor = settings->DesktopScaleFactor;
layouts[i].DeviceScaleFactor = settings->DeviceScaleFactor;
}
ret = disp->SendMonitorLayout(disp, nmonitors, layouts);
free(layouts);
return ret;
}
BOOL xf_disp_handle_xevent(xfContext *xfc, XEvent *event)
{
xfDispContext *xfDisp = xfc->xfDisp;
rdpSettings *settings = xfc->context.settings;
UINT32 maxWidth, maxHeight;
if (!xfDisp->haveXRandr)
return TRUE;
#ifdef USABLE_XRANDR
if (event->type != xfDisp->eventBase + RRScreenChangeNotify)
return TRUE;
#endif
xf_detect_monitors(xfc, &maxWidth, &maxHeight);
return xf_disp_sendLayout(xfc->disp, settings->MonitorDefArray, settings->MonitorCount) == CHANNEL_RC_OK;
}
BOOL xf_disp_handle_configureNotify(xfContext *xfc, int width, int height)
{
xfDispContext *xfDisp = xfc->xfDisp;
if (xfDisp->lastSentWidth == width && xfDisp->lastSentHeight == height)
return TRUE;
if (xfDisp->waitingResize || !xfDisp->activated ||
(GetTickCount64() - xfDisp->lastSentDate < RESIZE_MIN_DELAY))
{
WLog_DBG(TAG, "delaying resize to %dx%d", width, height);
xfDisp->targetWidth = width;
xfDisp->targetHeight = height;
return TRUE;
}
WLog_DBG(TAG, "resizing on ConfigureNotify to %dx%d", width, height);
return xf_disp_sendResize(xfDisp, width, height);
}
UINT xf_DisplayControlCaps(DispClientContext *disp, UINT32 maxNumMonitors, UINT32 maxMonitorAreaFactorA, UINT32 maxMonitorAreaFactorB)
{
/* we're called only if dynamic resolution update is activated */
xfDispContext *xfDisp = (xfDispContext *)disp->custom;
rdpSettings *settings = xfDisp->xfc->context.settings;
WLog_DBG(TAG, "DisplayControlCapsPdu: MaxNumMonitors: %"PRIu32" MaxMonitorAreaFactorA: %"PRIu32" MaxMonitorAreaFactorB: %"PRIu32"",
maxNumMonitors, maxMonitorAreaFactorA, maxMonitorAreaFactorB);
xfDisp->activated = TRUE;
if (settings->Fullscreen)
return CHANNEL_RC_OK;
WLog_DBG(TAG, "DisplayControlCapsPdu: setting the window as resizeable");
return xf_disp_set_window_resizable(xfDisp) ? CHANNEL_RC_OK : CHANNEL_RC_NO_MEMORY;
}
BOOL xf_disp_init(xfContext* xfc, DispClientContext *disp)
{
rdpSettings *settings = xfc->context.settings;
xfc->disp = disp;
disp->custom = (void*) xfc->xfDisp;
if (settings->DynamicResolutionUpdate)
{
disp->DisplayControlCaps = xf_DisplayControlCaps;
#ifdef USABLE_XRANDR
if (settings->Fullscreen)
{
/* ask X11 to notify us of screen changes */
XRRSelectInput(xfc->display, DefaultRootWindow(xfc->display), RRScreenChangeNotifyMask);
}
#endif
}
return TRUE;
}

36
client/X11/xf_disp.h Normal file
View File

@ -0,0 +1,36 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* X11 Display Control channel
*
* Copyright 2017 David Fort <contact@hardening-consulting.com>
*
* 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_CLIENT_X11_DISP_H
#define FREERDP_CLIENT_X11_DISP_H
#include <freerdp/types.h>
#include <freerdp/client/disp.h>
#include "xf_client.h"
#include "xfreerdp.h"
FREERDP_API BOOL xf_disp_init(xfContext* xfc, DispClientContext *disp);
xfDispContext *xf_disp_new(xfContext* xfc);
void xf_disp_free(xfDispContext *disp);
BOOL xf_disp_handle_xevent(xfContext *xfc, XEvent *event);
BOOL xf_disp_handle_configureNotify(xfContext *xfc, int width, int height);
void xf_disp_resized(xfDispContext *disp);
#endif /* FREERDP_CLIENT_X11_DISP_H */

Some files were not shown because too many files have changed in this diff Show More