New upstream version 2.0.0~gite60d0d5
This commit is contained in:
parent
9aa47e3624
commit
4e8ad76edb
164
CMakeLists.txt
164
CMakeLists.txt
@ -41,6 +41,12 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
# Include our extra modules
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/)
|
||||
|
||||
if((CMAKE_SYSTEM_NAME MATCHES "WindowsStore") AND (CMAKE_SYSTEM_VERSION MATCHES "10.0"))
|
||||
set(UWP 1)
|
||||
add_definitions("-D_UWP")
|
||||
set(CMAKE_WINDOWS_VERSION "WIN10")
|
||||
endif()
|
||||
|
||||
# Check for cmake compatibility (enable/disable features)
|
||||
include(CheckCmakeCompat)
|
||||
|
||||
@ -65,7 +71,7 @@ include(CMakePackageConfigHelpers)
|
||||
# Soname versioning
|
||||
set(BUILD_NUMBER 0)
|
||||
if ($ENV{BUILD_NUMBER})
|
||||
set(BUILD_NUMBER $ENV{BUILD_NUMBER})
|
||||
set(BUILD_NUMBER $ENV{BUILD_NUMBER})
|
||||
endif()
|
||||
set(WITH_LIBRARY_VERSIONING "ON")
|
||||
set(FREERDP_VERSION_MAJOR "2")
|
||||
@ -81,6 +87,12 @@ else()
|
||||
endif()
|
||||
set(FREERDP_INCLUDE_DIR "include/freerdp${FREERDP_VERSION_MAJOR}/")
|
||||
|
||||
# Compatibility options
|
||||
if(DEFINED STATIC_CHANNELS)
|
||||
message(WARNING "STATIC_CHANNELS is obsolete, please use BUILTIN_CHANNELS instead")
|
||||
set(BUILTIN_CHANNELS ${STATIC_CHANNELS} CACHE BOOL "" FORCE)
|
||||
endif()
|
||||
|
||||
# Make paths absolute
|
||||
if (CMAKE_INSTALL_PREFIX)
|
||||
get_filename_component(CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}" ABSOLUTE)
|
||||
@ -90,9 +102,9 @@ if (FREERDP_EXTERNAL_PATH)
|
||||
endif()
|
||||
|
||||
# Allow to search the host machine for git
|
||||
if(ANDROID OR IOS)
|
||||
if(CMAKE_CROSSCOMPILING)
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH)
|
||||
endif(ANDROID OR IOS)
|
||||
endif(CMAKE_CROSSCOMPILING)
|
||||
|
||||
include(GetGitRevisionDescription)
|
||||
git_get_exact_tag(GIT_REVISION --tags --always)
|
||||
@ -100,9 +112,9 @@ git_get_exact_tag(GIT_REVISION --tags --always)
|
||||
if (${GIT_REVISION} STREQUAL "n/a")
|
||||
git_rev_parse (GIT_REVISION --short)
|
||||
endif()
|
||||
if(ANDROID OR IOS)
|
||||
if(CMAKE_CROSSCOMPILING)
|
||||
SET (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY)
|
||||
endif(ANDROID OR IOS)
|
||||
endif(CMAKE_CROSSCOMPILING)
|
||||
|
||||
message(STATUS "Git Revision ${GIT_REVISION}")
|
||||
|
||||
@ -123,11 +135,16 @@ if(NOT DEFINED BUILD_SHARED_LIBS)
|
||||
endif()
|
||||
|
||||
if(BUILD_TESTING)
|
||||
set(EXPORT_ALL_SYMBOLS TRUE)
|
||||
set(EXPORT_ALL_SYMBOLS TRUE)
|
||||
elseif(NOT DEFINED EXPORT_ALL_SYMBOLS)
|
||||
set(EXPORT_ALL_SYMBOLS FALSE)
|
||||
set(EXPORT_ALL_SYMBOLS FALSE)
|
||||
endif()
|
||||
|
||||
if (EXPORT_ALL_SYMBOLS)
|
||||
# set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
|
||||
add_definitions(-DFREERDP_TEST_EXPORTS -DBUILD_TESTING)
|
||||
endif(EXPORT_ALL_SYMBOLS)
|
||||
|
||||
# BSD
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "BSD")
|
||||
set(BSD TRUE)
|
||||
@ -145,7 +162,10 @@ if(MSVC)
|
||||
if(NOT DEFINED MSVC_RUNTIME)
|
||||
set(MSVC_RUNTIME "dynamic")
|
||||
endif()
|
||||
if(${MSVC_RUNTIME} STREQUAL "static")
|
||||
if(MSVC_RUNTIME STREQUAL "static")
|
||||
if(BUILD_SHARED_LIBS)
|
||||
message(FATAL_ERROR "Static CRT is only supported in a fully static build")
|
||||
endif()
|
||||
message(STATUS "Use the MSVC static runtime option carefully!")
|
||||
message(STATUS "OpenSSL uses /MD by default, and is very picky")
|
||||
message(STATUS "Random freeing errors are a common sign of runtime issues")
|
||||
@ -215,20 +235,7 @@ if(CMAKE_COMPILER_IS_GNUCC)
|
||||
endif()
|
||||
endif()
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||
set(CMAKE_C_FLAGS_RELEASE "-DNDEBUG")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG")
|
||||
|
||||
CHECK_C_COMPILER_FLAG (-Wno-builtin-macro-redefined Wno-builtin-macro-redefined)
|
||||
if(Wno-builtin-macro-redefined)
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Wno-builtin-macro-redefined")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -D__FILE__='\"$(subst ${CMAKE_BINARY_DIR}/,,$(subst ${CMAKE_SOURCE_DIR}/,,$(abspath $<)))\"'")
|
||||
endif()
|
||||
|
||||
CHECK_CXX_COMPILER_FLAG (-Wno-builtin-macro-redefined Wno-builtin-macro-redefinedCXX)
|
||||
if(Wno-builtin-macro-redefinedCXX)
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wno-builtin-macro-redefined")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -D__FILE__='\"$(subst ${CMAKE_BINARY_DIR}/,,$(subst ${CMAKE_SOURCE_DIR}/,,$(abspath $<)))\"'")
|
||||
endif()
|
||||
add_definitions(-DNDEBUG)
|
||||
else()
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")
|
||||
@ -238,6 +245,23 @@ if(CMAKE_COMPILER_IS_GNUCC)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# When building with Unix Makefiles and doing any release builds
|
||||
# try to set __FILE__ to relative paths via a make specific macro
|
||||
if (CMAKE_GENERATOR MATCHES "Unix Makefile*")
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
|
||||
string(TOUPPER ${CMAKE_BUILD_TYPE} UPPER_BUILD_TYPE)
|
||||
CHECK_C_COMPILER_FLAG (-Wno-builtin-macro-redefined Wno-builtin-macro-redefined)
|
||||
if(Wno-builtin-macro-redefined)
|
||||
set(CMAKE_C_FLAGS_${UPPER_BUILD_TYPE} "${CMAKE_C_FLAGS_${UPPER_BUILD_TYPE}} -Wno-builtin-macro-redefined -D__FILE__='\"$(subst ${CMAKE_BINARY_DIR}/,,$(subst ${CMAKE_SOURCE_DIR}/,,$(abspath $<)))\"'")
|
||||
endif()
|
||||
|
||||
CHECK_CXX_COMPILER_FLAG (-Wno-builtin-macro-redefined Wno-builtin-macro-redefinedCXX)
|
||||
if(Wno-builtin-macro-redefinedCXX)
|
||||
set(CMAKE_CXX_FLAGS_${UPPER_BUILD_TYPE} "${CMAKE_CXX_FLAGS_${UPPER_BUILD_TYPE}} -Wno-builtin-macro-redefined -D__FILE__='\"$(subst ${CMAKE_BINARY_DIR}/,,$(subst ${CMAKE_SOURCE_DIR}/,,$(abspath $<)))\"'")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
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")
|
||||
@ -272,11 +296,31 @@ if(${CMAKE_C_COMPILER_ID} STREQUAL "Clang" OR CMAKE_COMPILER_IS_GNUCC)
|
||||
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_LEAK)
|
||||
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")
|
||||
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()
|
||||
endif()
|
||||
|
||||
if (WITH_NO_UNDEFINED)
|
||||
if (DEFINED CMAKE_REQUIRED_FLAGS)
|
||||
set(SAVE_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
|
||||
@ -315,9 +359,9 @@ if(MSVC)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W3")
|
||||
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_AMD64_")
|
||||
add_definitions(-D_AMD64_)
|
||||
else()
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_X86_")
|
||||
add_definitions(-D_X86_)
|
||||
endif()
|
||||
|
||||
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR})
|
||||
@ -332,9 +376,10 @@ if(MSVC)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUNICODE -D_UNICODE")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CRT_SECURE_NO_WARNINGS")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWIN32_LEAN_AND_MEAN")
|
||||
add_definitions(-DUNICODE -D_UNICODE)
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||
add_definitions(-DWIN32_LEAN_AND_MEAN)
|
||||
add_definitions(-D_WINSOCK_DEPRECATED_NO_WARNINGS)
|
||||
|
||||
set(CMAKE_USE_RELATIVE_PATH ON)
|
||||
if (${CMAKE_GENERATOR} MATCHES "NMake Makefile*")
|
||||
@ -358,14 +403,13 @@ if(WIN32)
|
||||
endif()
|
||||
|
||||
if(CMAKE_WINDOWS_VERSION STREQUAL "WINXP")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWINVER=0x0501 -DWIN32_WINNT=0x0501")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DWINVER=0x0501 -DWIN32_WINNT=0x0501")
|
||||
add_definitions(-DWINVER=0x0501 -D_WIN32_WINNT=0x0501)
|
||||
elseif(CMAKE_WINDOWS_VERSION STREQUAL "WIN7")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWINVER=0x0601 -DWIN32_WINNT=0x0601")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DWINVER=0x0601 -DWIN32_WINNT=0x0601")
|
||||
add_definitions(-DWINVER=0x0601 -D_WIN32_WINNT=0x0601)
|
||||
elseif(CMAKE_WINDOWS_VERSION STREQUAL "WIN8")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWINVER=0x0602 -DWIN32_WINNT=0x0602")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DWINVER=0x0602 -DWIN32_WINNT=0x0602")
|
||||
add_definitions(-DWINVER=0x0602 -D_WIN32_WINNT=0x0602)
|
||||
elseif(CMAKE_WINDOWS_VERSION STREQUAL "WIN10")
|
||||
add_definitions(-DWINVER=0x0A00 -D_WIN32_WINNT=0x0A00)
|
||||
endif()
|
||||
|
||||
if (FREERDP_EXTERNAL_SSL_PATH)
|
||||
@ -377,8 +421,7 @@ if(IOS)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -isysroot ${CMAKE_IOS_SDK_ROOT} -g")
|
||||
endif()
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWINPR_EXPORTS -DFREERDP_EXPORTS")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DWINPR_EXPORTS -DFREERDP_EXPORTS")
|
||||
add_definitions(-DWINPR_EXPORTS -DFREERDP_EXPORTS)
|
||||
|
||||
# Include files
|
||||
if(NOT IOS)
|
||||
@ -449,6 +492,8 @@ endif()
|
||||
if(ANDROID)
|
||||
set(WITH_LIBRARY_VERSIONING "OFF")
|
||||
|
||||
set_property( GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS ${ANDROID_LIBRARY_USE_LIB64_PATHS} )
|
||||
|
||||
if (${ANDROID_ABI} STREQUAL "armeabi")
|
||||
set (WITH_NEON OFF)
|
||||
endif()
|
||||
@ -484,12 +529,22 @@ endif()
|
||||
|
||||
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
|
||||
|
||||
if(NOT IOS AND NOT ANDROID)
|
||||
if(NOT IOS)
|
||||
find_package(Threads REQUIRED)
|
||||
endif()
|
||||
|
||||
if(NOT WIN32)
|
||||
check_library_exists(pthread pthread_mutex_timedlock "" HAVE_PTHREAD_MUTEX_TIMEDLOCK)
|
||||
CHECK_SYMBOL_EXISTS(pthread_mutex_timedlock pthread.h HAVE_PTHREAD_MUTEX_TIMEDLOCK_SYMBOL)
|
||||
if (NOT HAVE_PTHREAD_MUTEX_TIMEDLOCK_SYMBOL)
|
||||
CHECK_LIBRARY_EXISTS(pthread pthread_mutex_timedlock "" HAVE_PTHREAD_MUTEX_TIMEDLOCK_LIB)
|
||||
endif (NOT HAVE_PTHREAD_MUTEX_TIMEDLOCK_SYMBOL)
|
||||
if (NOT HAVE_PTHREAD_MUTEX_TIMEDLOCK_LIB)
|
||||
CHECK_LIBRARY_EXISTS(pthreads pthread_mutex_timedlock "" HAVE_PTHREAD_MUTEX_TIMEDLOCK_LIBS)
|
||||
endif (NOT HAVE_PTHREAD_MUTEX_TIMEDLOCK_LIB)
|
||||
|
||||
if (HAVE_PTHREAD_MUTEX_TIMEDLOCK_SYMBOL OR HAVE_PTHREAD_MUTEX_TIMEDLOCK_LIB OR HAVE_PTHREAD_MUTEX_TIMEDLOCK_LIBS)
|
||||
set(HAVE_PTHREAD_MUTEX_TIMEDLOCK ON)
|
||||
endif (HAVE_PTHREAD_MUTEX_TIMEDLOCK_SYMBOL OR HAVE_PTHREAD_MUTEX_TIMEDLOCK_LIB OR HAVE_PTHREAD_MUTEX_TIMEDLOCK_LIBS)
|
||||
endif()
|
||||
|
||||
if(WITH_VALGRIND_MEMCHECK)
|
||||
@ -701,6 +756,7 @@ endif()
|
||||
|
||||
if(OPENSSL_FOUND)
|
||||
add_definitions("-DWITH_OPENSSL")
|
||||
message(STATUS "Using OpenSSL Version: ${OPENSSL_VERSION}")
|
||||
endif()
|
||||
|
||||
if(MBEDTLS_FOUND)
|
||||
@ -711,15 +767,21 @@ if (TARGET_ARCH MATCHES "sparc")
|
||||
set(HAVE_ALIGNED_REQUIRED 1)
|
||||
endif()
|
||||
|
||||
# Path to put FreeRDP data
|
||||
set(FREERDP_DATA_PATH "${CMAKE_INSTALL_PREFIX}/share/freerdp${FREERDP_VERSION_MAJOR}")
|
||||
|
||||
# Path to put plugins
|
||||
|
||||
set(FREERDP_LIBRARY_PATH "${CMAKE_INSTALL_LIBDIR}")
|
||||
|
||||
set(FREERDP_PLUGIN_PATH "${CMAKE_INSTALL_LIBDIR}/freerdp${FREERDP_VERSION_MAJOR}")
|
||||
set(FREERDP_ADDIN_PATH "${FREERDP_PLUGIN_PATH}")
|
||||
# Android expects all libraries to be loadable
|
||||
# without paths.
|
||||
if (ANDROID)
|
||||
set(FREERDP_DATA_PATH "share")
|
||||
set(FREERDP_INSTALL_PREFIX ".")
|
||||
set(FREERDP_LIBRARY_PATH ".")
|
||||
set(FREERDP_PLUGIN_PATH ".")
|
||||
set(FREERDP_ADDIN_PATH ".")
|
||||
else (ANDROID)
|
||||
set(FREERDP_DATA_PATH "${CMAKE_INSTALL_PREFIX}/share/freerdp${FREERDP_VERSION_MAJOR}")
|
||||
set(FREERDP_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
|
||||
set(FREERDP_LIBRARY_PATH "${CMAKE_INSTALL_LIBDIR}")
|
||||
set(FREERDP_PLUGIN_PATH "${CMAKE_INSTALL_LIBDIR}/freerdp${FREERDP_VERSION_MAJOR}")
|
||||
set(FREERDP_ADDIN_PATH "${FREERDP_PLUGIN_PATH}")
|
||||
endif(ANDROID)
|
||||
|
||||
# Path to put extensions
|
||||
set(FREERDP_EXTENSION_PATH "${CMAKE_INSTALL_FULL_LIBDIR}/freerdp${FREERDP_VERSION_MAJOR}/extensions")
|
||||
@ -758,8 +820,6 @@ endif()
|
||||
include(CTest)
|
||||
|
||||
if(BUILD_TESTING)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DFREERDP_TEST_EXPORTS")
|
||||
|
||||
enable_testing()
|
||||
|
||||
if(MSVC)
|
||||
@ -812,7 +872,7 @@ include_directories("${CMAKE_BINARY_DIR}/rdtk/include")
|
||||
add_subdirectory(rdtk)
|
||||
|
||||
if(WAYLAND_FOUND)
|
||||
add_subdirectory(uwac)
|
||||
add_subdirectory(uwac)
|
||||
endif()
|
||||
|
||||
if(BSD)
|
||||
@ -858,9 +918,9 @@ include(${CMAKE_CPACK_INCLUDE_FILE})
|
||||
set(FREERDP_BUILD_CONFIG_LIST "")
|
||||
GET_CMAKE_PROPERTY(res VARIABLES)
|
||||
FOREACH(var ${res})
|
||||
IF (var MATCHES "^WITH_*|^BUILD_TESTING|^STATIC_CHANNELS|^HAVE_*")
|
||||
LIST(APPEND FREERDP_BUILD_CONFIG_LIST "${var}=${${var}}")
|
||||
ENDIF()
|
||||
IF (var MATCHES "^WITH_*|^BUILD_TESTING|^BUILTIN_CHANNELS|^HAVE_*")
|
||||
LIST(APPEND FREERDP_BUILD_CONFIG_LIST "${var}=${${var}}")
|
||||
ENDIF()
|
||||
ENDFOREACH()
|
||||
string(REPLACE ";" " " FREERDP_BUILD_CONFIG "${FREERDP_BUILD_CONFIG_LIST}")
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/buildflags.h.in ${CMAKE_CURRENT_BINARY_DIR}/buildflags.h)
|
||||
|
||||
@ -167,7 +167,7 @@ macro(client_channel_install _targets _destination)
|
||||
endmacro(client_channel_install)
|
||||
|
||||
macro(add_channel_client_library _module_prefix _module_name _channel_name _dynamic _entry)
|
||||
if(${_dynamic} AND (NOT STATIC_CHANNELS))
|
||||
if(${_dynamic} AND (NOT BUILTIN_CHANNELS))
|
||||
# On windows create dll version information.
|
||||
# Vendor, product and year are already set in top level CMakeLists.txt
|
||||
if (WIN32)
|
||||
@ -193,14 +193,14 @@ macro(add_channel_client_library _module_prefix _module_name _channel_name _dyna
|
||||
set(${_module_prefix}_CHANNEL ${_channel_name} PARENT_SCOPE)
|
||||
set(${_module_prefix}_ENTRY ${_entry} PARENT_SCOPE)
|
||||
add_library(${_module_name} STATIC ${${_module_prefix}_SRCS})
|
||||
if (${CMAKE_VERSION} VERSION_LESS 2.8.12)
|
||||
if (${CMAKE_VERSION} VERSION_LESS 2.8.12 OR NOT BUILD_SHARED_LIBS)
|
||||
client_channel_install(${_module_name} ${FREERDP_ADDIN_PATH})
|
||||
endif()
|
||||
endif()
|
||||
endmacro(add_channel_client_library)
|
||||
|
||||
macro(add_channel_client_subsystem_library _module_prefix _module_name _channel_name _type _dynamic _entry)
|
||||
if(${_dynamic} AND (NOT STATIC_CHANNELS))
|
||||
if(${_dynamic} AND (NOT BUILTIN_CHANNELS))
|
||||
# On windows create dll version information.
|
||||
# Vendor, product and year are already set in top level CMakeLists.txt
|
||||
if (WIN32)
|
||||
@ -225,14 +225,14 @@ macro(add_channel_client_subsystem_library _module_prefix _module_name _channel_
|
||||
set(${_module_prefix}_NAME ${_module_name} PARENT_SCOPE)
|
||||
set(${_module_prefix}_TYPE ${_type} PARENT_SCOPE)
|
||||
add_library(${_module_name} STATIC ${${_module_prefix}_SRCS})
|
||||
if (${CMAKE_VERSION} VERSION_LESS 2.8.12)
|
||||
if (${CMAKE_VERSION} VERSION_LESS 2.8.12 OR NOT BUILD_SHARED_LIBS)
|
||||
client_channel_install(${_module_name} ${FREERDP_ADDIN_PATH})
|
||||
endif()
|
||||
endif()
|
||||
endmacro(add_channel_client_subsystem_library)
|
||||
|
||||
macro(add_channel_server_library _module_prefix _module_name _channel_name _dynamic _entry)
|
||||
if(${_dynamic} AND (NOT STATIC_CHANNELS))
|
||||
if(${_dynamic} AND (NOT BUILTIN_CHANNELS))
|
||||
# On windows create dll version information.
|
||||
# Vendor, product and year are already set in top level CMakeLists.txt
|
||||
if (WIN32)
|
||||
@ -257,7 +257,7 @@ macro(add_channel_server_library _module_prefix _module_name _channel_name _dyna
|
||||
set(${_module_prefix}_CHANNEL ${_channel_name} PARENT_SCOPE)
|
||||
set(${_module_prefix}_ENTRY ${_entry} PARENT_SCOPE)
|
||||
add_library(${_module_name} STATIC ${${_module_prefix}_SRCS})
|
||||
if (${CMAKE_VERSION} VERSION_LESS 2.8.12)
|
||||
if (${CMAKE_VERSION} VERSION_LESS 2.8.12 OR NOT BUILD_SHARED_LIBS)
|
||||
server_channel_install(${_module_name} ${FREERDP_ADDIN_PATH})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@ -27,7 +27,7 @@ add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE
|
||||
|
||||
target_link_libraries(${MODULE_NAME} freerdp winpr)
|
||||
|
||||
if (WITH_DEBUG_SYMBOLS AND MSVC AND NOT STATIC_CHANNELS AND BUILD_SHARED_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()
|
||||
|
||||
|
||||
@ -69,7 +69,8 @@ typedef struct _AudinALSADevice
|
||||
rdpContext* rdpcontext;
|
||||
} AudinALSADevice;
|
||||
|
||||
static BOOL audin_alsa_set_params(AudinALSADevice* alsa, snd_pcm_t* capture_handle)
|
||||
static BOOL audin_alsa_set_params(AudinALSADevice* alsa,
|
||||
snd_pcm_t* capture_handle)
|
||||
{
|
||||
int error;
|
||||
snd_pcm_hw_params_t* hw_params;
|
||||
@ -77,26 +78,29 @@ static BOOL audin_alsa_set_params(AudinALSADevice* alsa, snd_pcm_t* capture_hand
|
||||
if ((error = snd_pcm_hw_params_malloc(&hw_params)) < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "snd_pcm_hw_params_malloc (%s)",
|
||||
snd_strerror(error));
|
||||
snd_strerror(error));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
snd_pcm_hw_params_any(capture_handle, hw_params);
|
||||
snd_pcm_hw_params_set_access(capture_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
|
||||
snd_pcm_hw_params_set_access(capture_handle, hw_params,
|
||||
SND_PCM_ACCESS_RW_INTERLEAVED);
|
||||
snd_pcm_hw_params_set_format(capture_handle, hw_params, alsa->format);
|
||||
snd_pcm_hw_params_set_rate_near(capture_handle, hw_params, &alsa->actual_rate, NULL);
|
||||
snd_pcm_hw_params_set_channels_near(capture_handle, hw_params, &alsa->actual_channels);
|
||||
snd_pcm_hw_params_set_rate_near(capture_handle, hw_params, &alsa->actual_rate,
|
||||
NULL);
|
||||
snd_pcm_hw_params_set_channels_near(capture_handle, hw_params,
|
||||
&alsa->actual_channels);
|
||||
snd_pcm_hw_params(capture_handle, hw_params);
|
||||
snd_pcm_hw_params_free(hw_params);
|
||||
snd_pcm_prepare(capture_handle);
|
||||
|
||||
if ((alsa->actual_rate != alsa->target_rate) ||
|
||||
(alsa->actual_channels != alsa->target_channels))
|
||||
(alsa->actual_channels != alsa->target_channels))
|
||||
{
|
||||
DEBUG_DVC("actual rate %d / channel %d is "
|
||||
"different from target rate %d / channel %d, resampling required.",
|
||||
alsa->actual_rate, alsa->actual_channels,
|
||||
alsa->target_rate, alsa->target_channels);
|
||||
"different from target rate %d / channel %d, resampling required.",
|
||||
alsa->actual_rate, alsa->actual_channels,
|
||||
alsa->target_rate, alsa->target_channels);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
@ -107,7 +111,8 @@ static BOOL audin_alsa_set_params(AudinALSADevice* alsa, snd_pcm_t* capture_hand
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT audin_alsa_thread_receive(AudinALSADevice* alsa, BYTE* src, int size)
|
||||
static UINT audin_alsa_thread_receive(AudinALSADevice* alsa, BYTE* src,
|
||||
int size)
|
||||
{
|
||||
int frames;
|
||||
int cframes;
|
||||
@ -116,38 +121,37 @@ static UINT audin_alsa_thread_receive(AudinALSADevice* alsa, BYTE* src, int size
|
||||
BYTE* encoded_data;
|
||||
int rbytes_per_frame;
|
||||
int tbytes_per_frame;
|
||||
int status;
|
||||
|
||||
int status;
|
||||
rbytes_per_frame = alsa->actual_channels * alsa->bytes_per_channel;
|
||||
tbytes_per_frame = alsa->target_channels * alsa->bytes_per_channel;
|
||||
|
||||
if ((alsa->target_rate == alsa->actual_rate) &&
|
||||
(alsa->target_channels == alsa->actual_channels))
|
||||
(alsa->target_channels == alsa->actual_channels))
|
||||
{
|
||||
frames = size / rbytes_per_frame;
|
||||
}
|
||||
else
|
||||
{
|
||||
alsa->dsp_context->resample(alsa->dsp_context, src, alsa->bytes_per_channel,
|
||||
alsa->actual_channels, alsa->actual_rate, size / rbytes_per_frame,
|
||||
alsa->target_channels, alsa->target_rate);
|
||||
alsa->actual_channels, alsa->actual_rate, size / rbytes_per_frame,
|
||||
alsa->target_channels, alsa->target_rate);
|
||||
frames = alsa->dsp_context->resampled_frames;
|
||||
DEBUG_DVC("resampled %d frames at %d to %d frames at %d",
|
||||
size / rbytes_per_frame, alsa->actual_rate, frames, alsa->target_rate);
|
||||
size / rbytes_per_frame, alsa->actual_rate, frames, alsa->target_rate);
|
||||
size = frames * tbytes_per_frame;
|
||||
src = alsa->dsp_context->resampled_buffer;
|
||||
}
|
||||
|
||||
while (frames > 0)
|
||||
{
|
||||
status = WaitForSingleObject(alsa->stopEvent, 0);
|
||||
status = WaitForSingleObject(alsa->stopEvent, 0);
|
||||
|
||||
if (status == WAIT_FAILED)
|
||||
{
|
||||
ret = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", ret);
|
||||
break;
|
||||
}
|
||||
if (status == WAIT_FAILED)
|
||||
{
|
||||
ret = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %u!", ret);
|
||||
break;
|
||||
}
|
||||
|
||||
if (status == WAIT_OBJECT_0)
|
||||
break;
|
||||
@ -157,8 +161,8 @@ static UINT audin_alsa_thread_receive(AudinALSADevice* alsa, BYTE* src, int size
|
||||
if (cframes > frames)
|
||||
cframes = frames;
|
||||
|
||||
CopyMemory(alsa->buffer + alsa->buffer_frames * tbytes_per_frame, src, cframes * tbytes_per_frame);
|
||||
|
||||
CopyMemory(alsa->buffer + alsa->buffer_frames * tbytes_per_frame, src,
|
||||
cframes * tbytes_per_frame);
|
||||
alsa->buffer_frames += cframes;
|
||||
|
||||
if (alsa->buffer_frames >= alsa->frames_per_packet)
|
||||
@ -166,8 +170,8 @@ static UINT audin_alsa_thread_receive(AudinALSADevice* alsa, BYTE* src, int size
|
||||
if (alsa->wformat == WAVE_FORMAT_DVI_ADPCM)
|
||||
{
|
||||
if (!alsa->dsp_context->encode_ima_adpcm(alsa->dsp_context,
|
||||
alsa->buffer, alsa->buffer_frames * tbytes_per_frame,
|
||||
alsa->target_channels, alsa->block_size))
|
||||
alsa->buffer, alsa->buffer_frames * tbytes_per_frame,
|
||||
alsa->target_channels, alsa->block_size))
|
||||
{
|
||||
ret = ERROR_INTERNAL_ERROR;
|
||||
break;
|
||||
@ -175,9 +179,8 @@ static UINT audin_alsa_thread_receive(AudinALSADevice* alsa, BYTE* src, int size
|
||||
|
||||
encoded_data = alsa->dsp_context->adpcm_buffer;
|
||||
encoded_size = alsa->dsp_context->adpcm_size;
|
||||
|
||||
DEBUG_DVC("encoded %d to %d",
|
||||
alsa->buffer_frames * tbytes_per_frame, encoded_size);
|
||||
alsa->buffer_frames * tbytes_per_frame, encoded_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -185,22 +188,22 @@ static UINT audin_alsa_thread_receive(AudinALSADevice* alsa, BYTE* src, int size
|
||||
encoded_size = alsa->buffer_frames * tbytes_per_frame;
|
||||
}
|
||||
|
||||
status = WaitForSingleObject(alsa->stopEvent, 0);
|
||||
status = WaitForSingleObject(alsa->stopEvent, 0);
|
||||
|
||||
if (status == WAIT_FAILED)
|
||||
{
|
||||
ret = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", ret);
|
||||
break;
|
||||
}
|
||||
if (status == WAIT_FAILED)
|
||||
{
|
||||
ret = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %u!", ret);
|
||||
break;
|
||||
}
|
||||
|
||||
if (status == WAIT_OBJECT_0)
|
||||
if (status == WAIT_OBJECT_0)
|
||||
break;
|
||||
else
|
||||
{
|
||||
DEBUG_DVC("encoded %d [%d] to %d [%X]", alsa->buffer_frames,
|
||||
tbytes_per_frame, encoded_size,
|
||||
alsa->wformat);
|
||||
tbytes_per_frame, encoded_size,
|
||||
alsa->wformat);
|
||||
ret = alsa->receive(encoded_data, encoded_size, alsa->user_data);
|
||||
}
|
||||
|
||||
@ -225,81 +228,83 @@ static void* audin_alsa_thread_func(void* arg)
|
||||
int tbytes_per_frame;
|
||||
snd_pcm_t* capture_handle = NULL;
|
||||
AudinALSADevice* alsa = (AudinALSADevice*) arg;
|
||||
DWORD status;
|
||||
|
||||
DWORD status;
|
||||
DEBUG_DVC("in");
|
||||
|
||||
rbytes_per_frame = alsa->actual_channels * alsa->bytes_per_channel;
|
||||
tbytes_per_frame = alsa->target_channels * alsa->bytes_per_channel;
|
||||
buffer = (BYTE*) calloc(1, rbytes_per_frame * alsa->frames_per_packet);
|
||||
|
||||
if (!buffer)
|
||||
{
|
||||
WLog_ERR(TAG, "calloc failed!");
|
||||
error = CHANNEL_RC_NO_MEMORY;
|
||||
if (alsa->rdpcontext)
|
||||
setChannelError(alsa->rdpcontext, error, "calloc failed!");
|
||||
goto out;
|
||||
error = CHANNEL_RC_NO_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
freerdp_dsp_context_reset_adpcm(alsa->dsp_context);
|
||||
|
||||
if ((error = snd_pcm_open(&capture_handle, alsa->device_name, SND_PCM_STREAM_CAPTURE, 0)) < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "snd_pcm_open (%s)", snd_strerror(error));
|
||||
goto out;
|
||||
}
|
||||
if ((error = snd_pcm_open(&capture_handle, alsa->device_name,
|
||||
SND_PCM_STREAM_CAPTURE, 0)) < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "snd_pcm_open (%s)", snd_strerror(error));
|
||||
error = CHANNEL_RC_INITIALIZATION_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!audin_alsa_set_params(alsa, capture_handle))
|
||||
{
|
||||
WLog_ERR(TAG, "audin_alsa_set_params failed");
|
||||
goto out;
|
||||
}
|
||||
if (!audin_alsa_set_params(alsa, capture_handle))
|
||||
{
|
||||
WLog_ERR(TAG, "audin_alsa_set_params failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
while(1)
|
||||
{
|
||||
status = WaitForSingleObject(alsa->stopEvent, 0);
|
||||
while (1)
|
||||
{
|
||||
status = WaitForSingleObject(alsa->stopEvent, 0);
|
||||
|
||||
if (status == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
|
||||
break;
|
||||
}
|
||||
if (status == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %ld!", error);
|
||||
break;
|
||||
}
|
||||
|
||||
if (status == WAIT_OBJECT_0)
|
||||
break;
|
||||
if (status == WAIT_OBJECT_0)
|
||||
break;
|
||||
|
||||
error = snd_pcm_readi(capture_handle, buffer, alsa->frames_per_packet);
|
||||
error = snd_pcm_readi(capture_handle, buffer, alsa->frames_per_packet);
|
||||
|
||||
if (error == -EPIPE)
|
||||
{
|
||||
snd_pcm_recover(capture_handle, error, 0);
|
||||
continue;
|
||||
}
|
||||
else if (error < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "snd_pcm_readi (%s)", snd_strerror(error));
|
||||
break;
|
||||
}
|
||||
if (error == -EPIPE)
|
||||
{
|
||||
snd_pcm_recover(capture_handle, error, 0);
|
||||
continue;
|
||||
}
|
||||
else if (error < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "snd_pcm_readi (%s)", snd_strerror(error));
|
||||
break;
|
||||
}
|
||||
|
||||
if ((error = audin_alsa_thread_receive(alsa, buffer, error * rbytes_per_frame)))
|
||||
{
|
||||
WLog_ERR(TAG, "audin_alsa_thread_receive failed with error %lu", error);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
if ((error = audin_alsa_thread_receive(alsa, buffer, error * rbytes_per_frame)))
|
||||
{
|
||||
WLog_ERR(TAG, "audin_alsa_thread_receive failed with error %ld", error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
|
||||
if (capture_handle)
|
||||
snd_pcm_close(capture_handle);
|
||||
|
||||
out:
|
||||
DEBUG_DVC("out");
|
||||
if (error && alsa->rdpcontext)
|
||||
setChannelError(alsa->rdpcontext, error, "audin_alsa_thread_func reported an error");
|
||||
ExitThread((DWORD)error);
|
||||
|
||||
if (error && alsa->rdpcontext)
|
||||
setChannelError(alsa->rdpcontext, error,
|
||||
"audin_alsa_thread_func reported an error");
|
||||
|
||||
ExitThread((DWORD)error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -311,36 +316,36 @@ out:
|
||||
static UINT audin_alsa_free(IAudinDevice* device)
|
||||
{
|
||||
AudinALSADevice* alsa = (AudinALSADevice*) device;
|
||||
|
||||
freerdp_dsp_context_free(alsa->dsp_context);
|
||||
|
||||
free(alsa->device_name);
|
||||
|
||||
free(alsa);
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
static BOOL audin_alsa_format_supported(IAudinDevice* device, audinFormat* format)
|
||||
static BOOL audin_alsa_format_supported(IAudinDevice* device,
|
||||
audinFormat* 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 TRUE;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
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 TRUE;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@ -352,11 +357,11 @@ static BOOL audin_alsa_format_supported(IAudinDevice* device, audinFormat* forma
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT audin_alsa_set_format(IAudinDevice* device, audinFormat* format, UINT32 FramesPerPacket)
|
||||
static UINT audin_alsa_set_format(IAudinDevice* device, audinFormat* format,
|
||||
UINT32 FramesPerPacket)
|
||||
{
|
||||
int bs;
|
||||
AudinALSADevice* alsa = (AudinALSADevice*) device;
|
||||
|
||||
alsa->target_rate = format->nSamplesPerSec;
|
||||
alsa->actual_rate = format->nSamplesPerSec;
|
||||
alsa->target_channels = format->nChannels;
|
||||
@ -371,11 +376,13 @@ static UINT audin_alsa_set_format(IAudinDevice* device, audinFormat* format, UIN
|
||||
alsa->format = SND_PCM_FORMAT_S8;
|
||||
alsa->bytes_per_channel = 1;
|
||||
break;
|
||||
|
||||
case 16:
|
||||
alsa->format = SND_PCM_FORMAT_S16_LE;
|
||||
alsa->bytes_per_channel = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case WAVE_FORMAT_DVI_ADPCM:
|
||||
@ -383,9 +390,9 @@ static UINT audin_alsa_set_format(IAudinDevice* device, audinFormat* format, UIN
|
||||
alsa->bytes_per_channel = 2;
|
||||
bs = (format->nBlockAlign - 4 * format->nChannels) * 4;
|
||||
alsa->frames_per_packet = (alsa->frames_per_packet * format->nChannels * 2 /
|
||||
bs + 1) * bs / (format->nChannels * 2);
|
||||
bs + 1) * bs / (format->nChannels * 2);
|
||||
DEBUG_DVC("aligned FramesPerPacket=%d",
|
||||
alsa->frames_per_packet);
|
||||
alsa->frames_per_packet);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -399,34 +406,37 @@ static UINT audin_alsa_set_format(IAudinDevice* device, audinFormat* format, UIN
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT audin_alsa_open(IAudinDevice* device, AudinReceive receive, void* user_data)
|
||||
static UINT audin_alsa_open(IAudinDevice* device, AudinReceive receive,
|
||||
void* user_data)
|
||||
{
|
||||
int tbytes_per_frame;
|
||||
AudinALSADevice* alsa = (AudinALSADevice*) device;
|
||||
|
||||
alsa->receive = receive;
|
||||
alsa->user_data = user_data;
|
||||
|
||||
tbytes_per_frame = alsa->target_channels * alsa->bytes_per_channel;
|
||||
alsa->buffer = (BYTE*) calloc(1, tbytes_per_frame * alsa->frames_per_packet);
|
||||
|
||||
if (!alsa->buffer)
|
||||
{
|
||||
WLog_ERR(TAG, "calloc failed!");
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
alsa->buffer_frames = 0;
|
||||
|
||||
|
||||
if (!(alsa->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
|
||||
{
|
||||
WLog_ERR(TAG, "CreateEvent failed!");
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
if (!(alsa->thread = CreateThread(NULL, 0,
|
||||
(LPTHREAD_START_ROUTINE) audin_alsa_thread_func, alsa, 0, NULL)))
|
||||
(LPTHREAD_START_ROUTINE) audin_alsa_thread_func, alsa, 0, NULL)))
|
||||
{
|
||||
WLog_ERR(TAG, "CreateThread failed!");
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
error_out:
|
||||
free(alsa->buffer);
|
||||
@ -443,32 +453,30 @@ error_out:
|
||||
*/
|
||||
static UINT audin_alsa_close(IAudinDevice* device)
|
||||
{
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
AudinALSADevice* alsa = (AudinALSADevice*) device;
|
||||
|
||||
if (alsa->stopEvent)
|
||||
{
|
||||
SetEvent(alsa->stopEvent);
|
||||
|
||||
if (WaitForSingleObject(alsa->thread, INFINITE) == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", error);
|
||||
return error;
|
||||
}
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %u", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
CloseHandle(alsa->stopEvent);
|
||||
alsa->stopEvent = NULL;
|
||||
|
||||
CloseHandle(alsa->thread);
|
||||
alsa->thread = NULL;
|
||||
}
|
||||
|
||||
free(alsa->buffer);
|
||||
alsa->buffer = NULL;
|
||||
|
||||
alsa->receive = NULL;
|
||||
alsa->user_data = NULL;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -483,17 +491,17 @@ COMMAND_LINE_ARGUMENT_A audin_alsa_args[] =
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT audin_alsa_parse_addin_args(AudinALSADevice* device, ADDIN_ARGV* args)
|
||||
static UINT audin_alsa_parse_addin_args(AudinALSADevice* device,
|
||||
ADDIN_ARGV* args)
|
||||
{
|
||||
int status;
|
||||
DWORD flags;
|
||||
COMMAND_LINE_ARGUMENT_A* arg;
|
||||
AudinALSADevice* alsa = (AudinALSADevice*) device;
|
||||
|
||||
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD;
|
||||
|
||||
status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv, audin_alsa_args, flags, alsa, NULL, NULL);
|
||||
|
||||
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON |
|
||||
COMMAND_LINE_IGN_UNKNOWN_KEYWORD;
|
||||
status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv,
|
||||
audin_alsa_args, flags, alsa, NULL, NULL);
|
||||
arg = audin_alsa_args;
|
||||
|
||||
do
|
||||
@ -502,17 +510,16 @@ static UINT audin_alsa_parse_addin_args(AudinALSADevice* device, ADDIN_ARGV* arg
|
||||
continue;
|
||||
|
||||
CommandLineSwitchStart(arg)
|
||||
|
||||
CommandLineSwitchCase(arg, "dev")
|
||||
{
|
||||
alsa->device_name = _strdup(arg->Value);
|
||||
if(!alsa->device_name)
|
||||
|
||||
if (!alsa->device_name)
|
||||
{
|
||||
WLog_ERR(TAG, "_strdup failed!");
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
CommandLineSwitchEnd(arg)
|
||||
}
|
||||
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
|
||||
@ -520,7 +527,7 @@ static UINT audin_alsa_parse_addin_args(AudinALSADevice* device, ADDIN_ARGV* arg
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#ifdef BUILTIN_CHANNELS
|
||||
#define freerdp_audin_client_subsystem_entry alsa_freerdp_audin_client_subsystem_entry
|
||||
#else
|
||||
#define freerdp_audin_client_subsystem_entry FREERDP_API freerdp_audin_client_subsystem_entry
|
||||
@ -531,13 +538,14 @@ static UINT audin_alsa_parse_addin_args(AudinALSADevice* device, ADDIN_ARGV* arg
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints)
|
||||
UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS
|
||||
pEntryPoints)
|
||||
{
|
||||
ADDIN_ARGV* args;
|
||||
AudinALSADevice* alsa;
|
||||
UINT error;
|
||||
|
||||
alsa = (AudinALSADevice*) calloc(1, sizeof(AudinALSADevice));
|
||||
|
||||
if (!alsa)
|
||||
{
|
||||
WLog_ERR(TAG, "calloc failed!");
|
||||
@ -550,18 +558,18 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEn
|
||||
alsa->iface.Close = audin_alsa_close;
|
||||
alsa->iface.Free = audin_alsa_free;
|
||||
alsa->rdpcontext = pEntryPoints->rdpcontext;
|
||||
|
||||
args = pEntryPoints->args;
|
||||
|
||||
if ((error = audin_alsa_parse_addin_args(alsa, args)))
|
||||
{
|
||||
WLog_ERR(TAG, "audin_alsa_parse_addin_args failed with errorcode %lu!", error);
|
||||
WLog_ERR(TAG, "audin_alsa_parse_addin_args failed with errorcode %u!", error);
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
if (!alsa->device_name)
|
||||
{
|
||||
alsa->device_name = _strdup("default");
|
||||
|
||||
if (!alsa->device_name)
|
||||
{
|
||||
WLog_ERR(TAG, "_strdup failed!");
|
||||
@ -577,8 +585,8 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEn
|
||||
alsa->target_channels = 2;
|
||||
alsa->actual_channels = 2;
|
||||
alsa->bytes_per_channel = 2;
|
||||
|
||||
alsa->dsp_context = freerdp_dsp_context_new();
|
||||
|
||||
if (!alsa->dsp_context)
|
||||
{
|
||||
WLog_ERR(TAG, "freerdp_dsp_context_new failed!");
|
||||
@ -586,9 +594,10 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEn
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
if ((error = pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, (IAudinDevice*) alsa)))
|
||||
if ((error = pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin,
|
||||
(IAudinDevice*) alsa)))
|
||||
{
|
||||
WLog_ERR(TAG, "RegisterAudinDevice failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "RegisterAudinDevice failed with error %u!", error);
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
|
||||
@ -374,13 +374,13 @@ static UINT audin_process_open(IWTSVirtualChannelCallback* pChannelCallback, wSt
|
||||
IFCALLRET(audin->device->SetFormat, error, audin->device, format, FramesPerPacket);
|
||||
if (error != CHANNEL_RC_OK)
|
||||
{
|
||||
WLog_ERR(TAG, "SetFormat failed with errorcode %lu", error);
|
||||
WLog_ERR(TAG, "SetFormat failed with errorcode %u", error);
|
||||
return error;
|
||||
}
|
||||
IFCALLRET(audin->device->Open, error, audin->device, audin_receive_wave_data, callback);
|
||||
if (error != CHANNEL_RC_OK)
|
||||
{
|
||||
WLog_ERR(TAG, "Open failed with errorcode %lu", error);
|
||||
WLog_ERR(TAG, "Open failed with errorcode %u", error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
@ -428,19 +428,19 @@ static UINT audin_process_format_change(IWTSVirtualChannelCallback* pChannelCall
|
||||
IFCALLRET(audin->device->Close, error, audin->device);
|
||||
if (error != CHANNEL_RC_OK)
|
||||
{
|
||||
WLog_ERR(TAG, "Close failed with errorcode %lu", error);
|
||||
WLog_ERR(TAG, "Close failed with errorcode %u", error);
|
||||
return error;
|
||||
}
|
||||
IFCALLRET(audin->device->SetFormat, error, audin->device, format, 0);
|
||||
if (error != CHANNEL_RC_OK)
|
||||
{
|
||||
WLog_ERR(TAG, "SetFormat failed with errorcode %lu", error);
|
||||
WLog_ERR(TAG, "SetFormat failed with errorcode %u", error);
|
||||
return error;
|
||||
}
|
||||
IFCALLRET(audin->device->Open, error, audin->device, audin_receive_wave_data, callback);
|
||||
if (error != CHANNEL_RC_OK)
|
||||
{
|
||||
WLog_ERR(TAG, "Open failed with errorcode %lu", error);
|
||||
WLog_ERR(TAG, "Open failed with errorcode %u", error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
@ -509,7 +509,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 %lu", error);
|
||||
WLog_ERR(TAG, "Close failed with errorcode %u", error);
|
||||
}
|
||||
|
||||
free(callback->formats);
|
||||
@ -593,7 +593,7 @@ static UINT audin_plugin_terminated(IWTSPlugin* pPlugin)
|
||||
IFCALLRET(audin->device->Free, error, audin->device);
|
||||
if (error != CHANNEL_RC_OK)
|
||||
{
|
||||
WLog_ERR(TAG, "Free failed with errorcode %lu", error);
|
||||
WLog_ERR(TAG, "Free failed with errorcode %u", error);
|
||||
// dont stop on error
|
||||
}
|
||||
audin->device = NULL;
|
||||
@ -662,7 +662,7 @@ static UINT audin_load_device_plugin(IWTSPlugin* pPlugin, const char* name, ADDI
|
||||
|
||||
if ((error = entry(&entryPoints)))
|
||||
{
|
||||
WLog_ERR(TAG, "%s entry returned error %lu.", name, error);
|
||||
WLog_ERR(TAG, "%s entry returned error %u.", name, error);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -721,10 +721,8 @@ BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, ADDIN_ARGV* args)
|
||||
COMMAND_LINE_ARGUMENT_A* arg;
|
||||
UINT error;
|
||||
|
||||
if (args->argc == 1)
|
||||
{
|
||||
if (!args || args->argc == 1)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD;
|
||||
|
||||
@ -746,7 +744,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 %lu!", error);
|
||||
WLog_ERR(TAG, "audin_set_subsystem failed with error %u!", error);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
@ -754,7 +752,7 @@ 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 %lu!", error);
|
||||
WLog_ERR(TAG, "audin_set_device_name failed with error %u!", error);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
@ -782,7 +780,7 @@ BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, ADDIN_ARGV* args)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#ifdef BUILTIN_CHANNELS
|
||||
#define DVCPluginEntry audin_DVCPluginEntry
|
||||
#else
|
||||
#define DVCPluginEntry FREERDP_API DVCPluginEntry
|
||||
@ -860,7 +858,7 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
|
||||
{
|
||||
if ((error = audin_load_device_plugin((IWTSPlugin*) audin, audin->subsystem, args)))
|
||||
{
|
||||
WLog_ERR(TAG, "audin_load_device_plugin %s failed with error %lu!",
|
||||
WLog_ERR(TAG, "audin_load_device_plugin %s failed with error %u!",
|
||||
audin->subsystem, error);
|
||||
goto out;
|
||||
}
|
||||
@ -871,17 +869,17 @@ 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 %lu!",
|
||||
WLog_ERR(TAG, "audin_set_subsystem for %s failed with error %u!",
|
||||
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 %lu!",
|
||||
WLog_ERR(TAG, "audin_set_device_name for %s failed with error %u!",
|
||||
entry->subsystem, error);
|
||||
}
|
||||
else if ((error = audin_load_device_plugin((IWTSPlugin*) audin, audin->subsystem, args)))
|
||||
{
|
||||
WLog_ERR(TAG, "audin_load_device_plugin %s failed with error %lu!",
|
||||
WLog_ERR(TAG, "audin_load_device_plugin %s failed with error %u!",
|
||||
entry->subsystem, error);
|
||||
}
|
||||
|
||||
|
||||
@ -33,9 +33,9 @@
|
||||
#define TAG CHANNELS_TAG("audin.client")
|
||||
|
||||
#ifdef WITH_DEBUG_DVC
|
||||
#define DEBUG_DVC(fmt, ...) WLog_DBG(TAG, fmt, ## __VA_ARGS__)
|
||||
#define DEBUG_DVC(...) WLog_DBG(TAG, __VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG_DVC(fmt, ...) do { } while (0)
|
||||
#define DEBUG_DVC(...) do { } while (0)
|
||||
#endif
|
||||
|
||||
#endif /* FREERDP_AUDIN_CLIENT_MAIN_H */
|
||||
|
||||
@ -33,6 +33,9 @@
|
||||
#include <winpr/debug.h>
|
||||
#include <winpr/cmdline.h>
|
||||
|
||||
#define __COREFOUNDATION_CFPLUGINCOM__ 1
|
||||
#define IUNKNOWN_C_GUTS void *_reserved; void* QueryInterface; void* AddRef; void* Release
|
||||
|
||||
#include <CoreAudio/CoreAudioTypes.h>
|
||||
#include <CoreAudio/CoreAudio.h>
|
||||
#include <AudioToolbox/AudioToolbox.h>
|
||||
@ -171,7 +174,7 @@ static void mac_audio_queue_input_cb(void *aqData,
|
||||
{
|
||||
AudinMacDevice* mac = (AudinMacDevice*)aqData;
|
||||
UINT error;
|
||||
int encoded_size;
|
||||
int encoded_size = 0;
|
||||
const BYTE *encoded_data;
|
||||
BYTE *buffer = inBuffer->mAudioData;
|
||||
int buffer_size = inBuffer->mAudioDataByteSize;
|
||||
@ -212,7 +215,7 @@ static void mac_audio_queue_input_cb(void *aqData,
|
||||
|
||||
if ((error = mac->receive(encoded_data, encoded_size, mac->user_data)))
|
||||
{
|
||||
WLog_ERR(TAG, "mac->receive failed with error %lu", error);
|
||||
WLog_ERR(TAG, "mac->receive failed with error %u", error);
|
||||
SetLastError(ERROR_INTERNAL_ERROR);
|
||||
return;
|
||||
}
|
||||
@ -400,7 +403,7 @@ static UINT audin_mac_parse_addin_args(AudinMacDevice *device, ADDIN_ARGV *args)
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#ifdef BUILTIN_CHANNELS
|
||||
#define freerdp_audin_client_subsystem_entry mac_freerdp_audin_client_subsystem_entry
|
||||
#else
|
||||
#define freerdp_audin_client_subsystem_entry FREERDP_API freerdp_audin_client_subsystem_entry
|
||||
@ -435,7 +438,7 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEn
|
||||
|
||||
if ((error = audin_mac_parse_addin_args(mac, args)))
|
||||
{
|
||||
WLog_ERR(TAG, "audin_mac_parse_addin_args failed with %lu!", error);
|
||||
WLog_ERR(TAG, "audin_mac_parse_addin_args failed with %u!", error);
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
@ -449,7 +452,7 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEn
|
||||
|
||||
if ((error = pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, (IAudinDevice*) mac)))
|
||||
{
|
||||
WLog_ERR(TAG, "RegisterAudinDevice failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "RegisterAudinDevice failed with error %u!", error);
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
|
||||
@ -112,7 +112,7 @@ static void* audin_opensles_thread_func(void* arg)
|
||||
if (status == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %u!", error);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -125,7 +125,7 @@ static void* audin_opensles_thread_func(void* arg)
|
||||
rc = android_RecIn(opensles->stream, buffer.s, raw_size);
|
||||
if (rc < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "android_RecIn %lu", rc);
|
||||
WLog_ERR(TAG, "android_RecIn %d", rc);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -401,7 +401,7 @@ static UINT audin_opensles_close(IAudinDevice* device)
|
||||
if (WaitForSingleObject(opensles->thread, INFINITE) == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", error);
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %u", error);
|
||||
return error;
|
||||
}
|
||||
CloseHandle(opensles->stopEvent);
|
||||
@ -473,7 +473,7 @@ static UINT audin_opensles_parse_addin_args(AudinOpenSLESDevice* device,
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#ifdef BUILTIN_CHANNELS
|
||||
#define freerdp_audin_client_subsystem_entry \
|
||||
opensles_freerdp_audin_client_subsystem_entry
|
||||
#else
|
||||
|
||||
@ -6,14 +6,14 @@ All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* 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.
|
||||
* Neither the name of the <organization> nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* 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.
|
||||
* Neither the name of the <organization> nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
@ -34,114 +34,132 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#define CONV16BIT 32768
|
||||
#define CONVMYFLT (1./32768.)
|
||||
|
||||
static void bqRecorderCallback(SLAndroidSimpleBufferQueueItf bq, void *context);
|
||||
static void bqRecorderCallback(SLAndroidSimpleBufferQueueItf bq, void* context);
|
||||
|
||||
// creates the OpenSL ES audio engine
|
||||
static SLresult openSLCreateEngine(OPENSL_STREAM *p)
|
||||
static SLresult openSLCreateEngine(OPENSL_STREAM* p)
|
||||
{
|
||||
SLresult result;
|
||||
// create engine
|
||||
result = slCreateEngine(&(p->engineObject), 0, NULL, 0, NULL, NULL);
|
||||
SLresult result;
|
||||
// create engine
|
||||
result = slCreateEngine(&(p->engineObject), 0, NULL, 0, NULL, NULL);
|
||||
DEBUG_DVC("engineObject=%p", p->engineObject);
|
||||
if(result != SL_RESULT_SUCCESS) goto engine_end;
|
||||
|
||||
// realize the engine
|
||||
result = (*p->engineObject)->Realize(p->engineObject, SL_BOOLEAN_FALSE);
|
||||
if (result != SL_RESULT_SUCCESS) goto engine_end;
|
||||
|
||||
// realize the engine
|
||||
result = (*p->engineObject)->Realize(p->engineObject, SL_BOOLEAN_FALSE);
|
||||
DEBUG_DVC("Realize=%d", result);
|
||||
if(result != SL_RESULT_SUCCESS) goto engine_end;
|
||||
|
||||
// get the engine interface, which is needed in order to create other objects
|
||||
result = (*p->engineObject)->GetInterface(p->engineObject, SL_IID_ENGINE, &(p->engineEngine));
|
||||
if (result != SL_RESULT_SUCCESS) goto engine_end;
|
||||
|
||||
// get the engine interface, which is needed in order to create other objects
|
||||
result = (*p->engineObject)->GetInterface(p->engineObject, SL_IID_ENGINE,
|
||||
&(p->engineEngine));
|
||||
DEBUG_DVC("engineEngine=%p", p->engineEngine);
|
||||
if(result != SL_RESULT_SUCCESS) goto engine_end;
|
||||
|
||||
// get the volume interface - important, this is optional!
|
||||
result = (*p->engineObject)->GetInterface(p->engineObject, SL_IID_DEVICEVOLUME, &(p->deviceVolume));
|
||||
if (result != SL_RESULT_SUCCESS) goto engine_end;
|
||||
|
||||
// get the volume interface - important, this is optional!
|
||||
result = (*p->engineObject)->GetInterface(p->engineObject, SL_IID_DEVICEVOLUME,
|
||||
&(p->deviceVolume));
|
||||
DEBUG_DVC("deviceVolume=%p", p->deviceVolume);
|
||||
if(result != SL_RESULT_SUCCESS)
|
||||
|
||||
if (result != SL_RESULT_SUCCESS)
|
||||
{
|
||||
p->deviceVolume = NULL;
|
||||
result = SL_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
engine_end:
|
||||
engine_end:
|
||||
assert(SL_RESULT_SUCCESS == result);
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Open the OpenSL ES device for input
|
||||
static SLresult openSLRecOpen(OPENSL_STREAM *p){
|
||||
|
||||
SLresult result;
|
||||
SLuint32 sr = p->sr;
|
||||
SLuint32 channels = p->inchannels;
|
||||
|
||||
static SLresult openSLRecOpen(OPENSL_STREAM* p)
|
||||
{
|
||||
SLresult result;
|
||||
SLuint32 sr = p->sr;
|
||||
SLuint32 channels = p->inchannels;
|
||||
assert(!p->recorderObject);
|
||||
|
||||
if(channels){
|
||||
if (channels)
|
||||
{
|
||||
switch (sr)
|
||||
{
|
||||
case 8000:
|
||||
sr = SL_SAMPLINGRATE_8;
|
||||
break;
|
||||
|
||||
switch(sr){
|
||||
case 11025:
|
||||
sr = SL_SAMPLINGRATE_11_025;
|
||||
break;
|
||||
|
||||
case 8000:
|
||||
sr = SL_SAMPLINGRATE_8;
|
||||
break;
|
||||
case 11025:
|
||||
sr = SL_SAMPLINGRATE_11_025;
|
||||
break;
|
||||
case 16000:
|
||||
sr = SL_SAMPLINGRATE_16;
|
||||
break;
|
||||
case 22050:
|
||||
sr = SL_SAMPLINGRATE_22_05;
|
||||
break;
|
||||
case 24000:
|
||||
sr = SL_SAMPLINGRATE_24;
|
||||
break;
|
||||
case 32000:
|
||||
sr = SL_SAMPLINGRATE_32;
|
||||
break;
|
||||
case 44100:
|
||||
sr = SL_SAMPLINGRATE_44_1;
|
||||
break;
|
||||
case 48000:
|
||||
sr = SL_SAMPLINGRATE_48;
|
||||
break;
|
||||
case 64000:
|
||||
sr = SL_SAMPLINGRATE_64;
|
||||
break;
|
||||
case 88200:
|
||||
sr = SL_SAMPLINGRATE_88_2;
|
||||
break;
|
||||
case 96000:
|
||||
sr = SL_SAMPLINGRATE_96;
|
||||
break;
|
||||
case 192000:
|
||||
sr = SL_SAMPLINGRATE_192;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
// configure audio source
|
||||
SLDataLocator_IODevice loc_dev = {SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT,
|
||||
SL_DEFAULTDEVICEID_AUDIOINPUT, NULL};
|
||||
SLDataSource audioSrc = {&loc_dev, NULL};
|
||||
case 16000:
|
||||
sr = SL_SAMPLINGRATE_16;
|
||||
break;
|
||||
|
||||
// configure audio sink
|
||||
int speakers;
|
||||
if(channels > 1)
|
||||
speakers = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
|
||||
else
|
||||
case 22050:
|
||||
sr = SL_SAMPLINGRATE_22_05;
|
||||
break;
|
||||
|
||||
case 24000:
|
||||
sr = SL_SAMPLINGRATE_24;
|
||||
break;
|
||||
|
||||
case 32000:
|
||||
sr = SL_SAMPLINGRATE_32;
|
||||
break;
|
||||
|
||||
case 44100:
|
||||
sr = SL_SAMPLINGRATE_44_1;
|
||||
break;
|
||||
|
||||
case 48000:
|
||||
sr = SL_SAMPLINGRATE_48;
|
||||
break;
|
||||
|
||||
case 64000:
|
||||
sr = SL_SAMPLINGRATE_64;
|
||||
break;
|
||||
|
||||
case 88200:
|
||||
sr = SL_SAMPLINGRATE_88_2;
|
||||
break;
|
||||
|
||||
case 96000:
|
||||
sr = SL_SAMPLINGRATE_96;
|
||||
break;
|
||||
|
||||
case 192000:
|
||||
sr = SL_SAMPLINGRATE_192;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
// configure audio source
|
||||
SLDataLocator_IODevice loc_dev = {SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT,
|
||||
SL_DEFAULTDEVICEID_AUDIOINPUT, NULL
|
||||
};
|
||||
SLDataSource audioSrc = {&loc_dev, NULL};
|
||||
// configure audio sink
|
||||
int speakers;
|
||||
|
||||
if (channels > 1)
|
||||
speakers = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
|
||||
else
|
||||
speakers = SL_SPEAKER_FRONT_CENTER;
|
||||
SLDataLocator_AndroidSimpleBufferQueue loc_bq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};
|
||||
SLDataFormat_PCM format_pcm;
|
||||
|
||||
|
||||
SLDataLocator_AndroidSimpleBufferQueue loc_bq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};
|
||||
SLDataFormat_PCM format_pcm;
|
||||
format_pcm.formatType = SL_DATAFORMAT_PCM;
|
||||
format_pcm.numChannels = channels;
|
||||
format_pcm.samplesPerSec = sr;
|
||||
format_pcm.channelMask = speakers;
|
||||
format_pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
|
||||
|
||||
format_pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
|
||||
|
||||
if (16 == p->bits_per_sample)
|
||||
{
|
||||
format_pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16;
|
||||
@ -155,131 +173,135 @@ static SLresult openSLRecOpen(OPENSL_STREAM *p){
|
||||
else
|
||||
assert(0);
|
||||
|
||||
SLDataSink audioSnk = {&loc_bq, &format_pcm};
|
||||
|
||||
// create audio recorder
|
||||
// (requires the RECORD_AUDIO permission)
|
||||
const SLInterfaceID id[] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE};
|
||||
const SLboolean req[] = {SL_BOOLEAN_TRUE};
|
||||
result = (*p->engineEngine)->CreateAudioRecorder(p->engineEngine,
|
||||
&(p->recorderObject), &audioSrc, &audioSnk, 1, id, req);
|
||||
SLDataSink audioSnk = {&loc_bq, &format_pcm};
|
||||
// create audio recorder
|
||||
// (requires the RECORD_AUDIO permission)
|
||||
const SLInterfaceID id[] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE};
|
||||
const SLboolean req[] = {SL_BOOLEAN_TRUE};
|
||||
result = (*p->engineEngine)->CreateAudioRecorder(p->engineEngine,
|
||||
&(p->recorderObject), &audioSrc, &audioSnk, 1, id, req);
|
||||
DEBUG_DVC("p->recorderObject=%p", p->recorderObject);
|
||||
assert(!result);
|
||||
if (SL_RESULT_SUCCESS != result) goto end_recopen;
|
||||
|
||||
// realize the audio recorder
|
||||
result = (*p->recorderObject)->Realize(p->recorderObject, SL_BOOLEAN_FALSE);
|
||||
if (SL_RESULT_SUCCESS != result) goto end_recopen;
|
||||
|
||||
// realize the audio recorder
|
||||
result = (*p->recorderObject)->Realize(p->recorderObject, SL_BOOLEAN_FALSE);
|
||||
DEBUG_DVC("Realize=%d", result);
|
||||
assert(!result);
|
||||
if (SL_RESULT_SUCCESS != result) goto end_recopen;
|
||||
|
||||
// get the record interface
|
||||
result = (*p->recorderObject)->GetInterface(p->recorderObject,
|
||||
SL_IID_RECORD, &(p->recorderRecord));
|
||||
if (SL_RESULT_SUCCESS != result) goto end_recopen;
|
||||
|
||||
// get the record interface
|
||||
result = (*p->recorderObject)->GetInterface(p->recorderObject,
|
||||
SL_IID_RECORD, &(p->recorderRecord));
|
||||
DEBUG_DVC("p->recorderRecord=%p", p->recorderRecord);
|
||||
assert(!result);
|
||||
if (SL_RESULT_SUCCESS != result) goto end_recopen;
|
||||
|
||||
// get the buffer queue interface
|
||||
result = (*p->recorderObject)->GetInterface(p->recorderObject,
|
||||
SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
|
||||
&(p->recorderBufferQueue));
|
||||
DEBUG_DVC("p->recorderBufferQueue=%p", p->recorderBufferQueue);
|
||||
assert(!result);
|
||||
if (SL_RESULT_SUCCESS != result) goto end_recopen;
|
||||
|
||||
// register callback on the buffer queue
|
||||
result = (*p->recorderBufferQueue)->RegisterCallback(p->recorderBufferQueue,
|
||||
bqRecorderCallback, p);
|
||||
if (SL_RESULT_SUCCESS != result) goto end_recopen;
|
||||
|
||||
// get the buffer queue interface
|
||||
result = (*p->recorderObject)->GetInterface(p->recorderObject,
|
||||
SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
|
||||
&(p->recorderBufferQueue));
|
||||
DEBUG_DVC("p->recorderBufferQueue=%p", p->recorderBufferQueue);
|
||||
assert(!result);
|
||||
if (SL_RESULT_SUCCESS != result)
|
||||
|
||||
if (SL_RESULT_SUCCESS != result) goto end_recopen;
|
||||
|
||||
// register callback on the buffer queue
|
||||
result = (*p->recorderBufferQueue)->RegisterCallback(p->recorderBufferQueue,
|
||||
bqRecorderCallback, p);
|
||||
DEBUG_DVC("p->recorderBufferQueue=%p", p->recorderBufferQueue);
|
||||
assert(!result);
|
||||
|
||||
if (SL_RESULT_SUCCESS != result)
|
||||
goto end_recopen;
|
||||
|
||||
end_recopen:
|
||||
return result;
|
||||
}
|
||||
else return SL_RESULT_SUCCESS;
|
||||
|
||||
|
||||
end_recopen:
|
||||
return result;
|
||||
}
|
||||
else return SL_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
// close the OpenSL IO and destroy the audio engine
|
||||
static void openSLDestroyEngine(OPENSL_STREAM *p)
|
||||
static void openSLDestroyEngine(OPENSL_STREAM* p)
|
||||
{
|
||||
DEBUG_DVC("p=%p", p);
|
||||
|
||||
// destroy audio recorder object, and invalidate all associated interfaces
|
||||
if (p->recorderObject != NULL) {
|
||||
(*p->recorderObject)->Destroy(p->recorderObject);
|
||||
p->recorderObject = NULL;
|
||||
p->recorderRecord = NULL;
|
||||
p->recorderBufferQueue = NULL;
|
||||
}
|
||||
|
||||
// destroy engine object, and invalidate all associated interfaces
|
||||
if (p->engineObject != NULL) {
|
||||
(*p->engineObject)->Destroy(p->engineObject);
|
||||
p->engineObject = NULL;
|
||||
p->engineEngine = NULL;
|
||||
}
|
||||
// destroy audio recorder object, and invalidate all associated interfaces
|
||||
if (p->recorderObject != NULL)
|
||||
{
|
||||
(*p->recorderObject)->Destroy(p->recorderObject);
|
||||
p->recorderObject = NULL;
|
||||
p->recorderRecord = NULL;
|
||||
p->recorderBufferQueue = NULL;
|
||||
}
|
||||
|
||||
// destroy engine object, and invalidate all associated interfaces
|
||||
if (p->engineObject != NULL)
|
||||
{
|
||||
(*p->engineObject)->Destroy(p->engineObject);
|
||||
p->engineObject = NULL;
|
||||
p->engineEngine = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// open the android audio device for input
|
||||
OPENSL_STREAM *android_OpenRecDevice(char *name, int sr, int inchannels,
|
||||
int bufferframes, int bits_per_sample)
|
||||
// open the android audio device for input
|
||||
OPENSL_STREAM* android_OpenRecDevice(char* name, int sr, int inchannels,
|
||||
int bufferframes, int bits_per_sample)
|
||||
{
|
||||
|
||||
OPENSL_STREAM *p;
|
||||
p = (OPENSL_STREAM *) calloc(sizeof(OPENSL_STREAM),1);
|
||||
if (!p)
|
||||
return NULL;
|
||||
OPENSL_STREAM* p;
|
||||
p = (OPENSL_STREAM*) calloc(sizeof(OPENSL_STREAM), 1);
|
||||
|
||||
p->inchannels = inchannels;
|
||||
p->sr = sr;
|
||||
if (!p)
|
||||
return NULL;
|
||||
|
||||
p->inchannels = inchannels;
|
||||
p->sr = sr;
|
||||
p->queue = Queue_New(TRUE, -1, -1);
|
||||
p->buffersize = bufferframes;
|
||||
p->bits_per_sample = bits_per_sample;
|
||||
|
||||
if ((p->bits_per_sample != 8) && (p->bits_per_sample != 16))
|
||||
{
|
||||
android_CloseRecDevice(p);
|
||||
android_CloseRecDevice(p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(openSLCreateEngine(p) != SL_RESULT_SUCCESS)
|
||||
{
|
||||
android_CloseRecDevice(p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(openSLRecOpen(p) != SL_RESULT_SUCCESS)
|
||||
if (openSLCreateEngine(p) != SL_RESULT_SUCCESS)
|
||||
{
|
||||
android_CloseRecDevice(p);
|
||||
return NULL;
|
||||
}
|
||||
android_CloseRecDevice(p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return p;
|
||||
if (openSLRecOpen(p) != SL_RESULT_SUCCESS)
|
||||
{
|
||||
android_CloseRecDevice(p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
// close the android audio device
|
||||
void android_CloseRecDevice(OPENSL_STREAM *p)
|
||||
void android_CloseRecDevice(OPENSL_STREAM* p)
|
||||
{
|
||||
DEBUG_DVC("p=%p", p);
|
||||
|
||||
if (p == NULL)
|
||||
return;
|
||||
if (p == NULL)
|
||||
return;
|
||||
|
||||
if (p->queue)
|
||||
{
|
||||
while (Queue_Count(p->queue) > 0)
|
||||
{
|
||||
queue_element *e = Queue_Dequeue(p->queue);
|
||||
queue_element* e = Queue_Dequeue(p->queue);
|
||||
free(e->data);
|
||||
free(e);
|
||||
}
|
||||
|
||||
Queue_Free(p->queue);
|
||||
}
|
||||
|
||||
@ -295,52 +317,47 @@ void android_CloseRecDevice(OPENSL_STREAM *p)
|
||||
free(p->prep);
|
||||
}
|
||||
|
||||
openSLDestroyEngine(p);
|
||||
|
||||
free(p);
|
||||
openSLDestroyEngine(p);
|
||||
free(p);
|
||||
}
|
||||
|
||||
// this callback handler is called every time a buffer finishes recording
|
||||
void bqRecorderCallback(SLAndroidSimpleBufferQueueItf bq, void *context)
|
||||
static void bqRecorderCallback(SLAndroidSimpleBufferQueueItf bq, void* context)
|
||||
{
|
||||
queue_element *e;
|
||||
|
||||
OPENSL_STREAM *p = (OPENSL_STREAM *) context;
|
||||
|
||||
queue_element* e;
|
||||
OPENSL_STREAM* p = (OPENSL_STREAM*) context;
|
||||
DEBUG_DVC("p=%p", p);
|
||||
|
||||
assert(p);
|
||||
assert(p->next);
|
||||
assert(p->prep);
|
||||
assert(p->queue);
|
||||
|
||||
e = calloc(1, sizeof(queue_element));
|
||||
|
||||
if (!e)
|
||||
return;
|
||||
|
||||
e->data = calloc(p->buffersize, p->bits_per_sample / 8);
|
||||
|
||||
if (!e->data)
|
||||
{
|
||||
free(e);
|
||||
return;
|
||||
}
|
||||
e->size = p->buffersize * p->bits_per_sample / 8;
|
||||
|
||||
e->size = p->buffersize * p->bits_per_sample / 8;
|
||||
Queue_Enqueue(p->queue, p->next);
|
||||
p->next = p->prep;
|
||||
p->prep = e;
|
||||
|
||||
(*p->recorderBufferQueue)->Enqueue(p->recorderBufferQueue,
|
||||
e->data, e->size);
|
||||
|
||||
(*p->recorderBufferQueue)->Enqueue(p->recorderBufferQueue,
|
||||
e->data, e->size);
|
||||
}
|
||||
|
||||
// gets a buffer of size samples from the device
|
||||
int android_RecIn(OPENSL_STREAM *p,short *buffer,int size)
|
||||
{
|
||||
queue_element *e;
|
||||
int rc;
|
||||
DWORD status;
|
||||
|
||||
// gets a buffer of size samples from the device
|
||||
int android_RecIn(OPENSL_STREAM* p, short* buffer, int size)
|
||||
{
|
||||
queue_element* e;
|
||||
int rc;
|
||||
DWORD status;
|
||||
assert(p);
|
||||
assert(buffer);
|
||||
assert(size > 0);
|
||||
@ -349,35 +366,33 @@ int android_RecIn(OPENSL_STREAM *p,short *buffer,int size)
|
||||
if (!p->prep)
|
||||
{
|
||||
p->prep = calloc(1, sizeof(queue_element));
|
||||
|
||||
p->prep->data = calloc(p->buffersize, p->bits_per_sample / 8);
|
||||
p->prep->size = p->buffersize * p->bits_per_sample / 8;
|
||||
|
||||
p->next = calloc(1, sizeof(queue_element));
|
||||
p->next->data = calloc(p->buffersize, p->bits_per_sample / 8);
|
||||
p->next->size = p->buffersize * p->bits_per_sample / 8;
|
||||
|
||||
(*p->recorderBufferQueue)->Enqueue(p->recorderBufferQueue,
|
||||
p->next->data, p->next->size);
|
||||
(*p->recorderBufferQueue)->Enqueue(p->recorderBufferQueue,
|
||||
p->prep->data, p->prep->size);
|
||||
|
||||
(*p->recorderRecord)->SetRecordState(p->recorderRecord, SL_RECORDSTATE_RECORDING);
|
||||
(*p->recorderBufferQueue)->Enqueue(p->recorderBufferQueue,
|
||||
p->next->data, p->next->size);
|
||||
(*p->recorderBufferQueue)->Enqueue(p->recorderBufferQueue,
|
||||
p->prep->data, p->prep->size);
|
||||
(*p->recorderRecord)->SetRecordState(p->recorderRecord,
|
||||
SL_RECORDSTATE_RECORDING);
|
||||
}
|
||||
|
||||
/* Wait for queue to be filled... */
|
||||
if (!Queue_Count(p->queue))
|
||||
{
|
||||
status = WaitForSingleObject(p->queue->event, INFINITE);
|
||||
if (status == WAIT_FAILED)
|
||||
{
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", GetLastError());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
{
|
||||
status = WaitForSingleObject(p->queue->event, INFINITE);
|
||||
|
||||
if (status == WAIT_FAILED)
|
||||
{
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", (unsigned long)GetLastError());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
e = Queue_Dequeue(p->queue);
|
||||
|
||||
if (!e)
|
||||
{
|
||||
WLog_ERR(TAG, "[ERROR] got e=%p from queue", e);
|
||||
@ -387,11 +402,9 @@ int android_RecIn(OPENSL_STREAM *p,short *buffer,int size)
|
||||
rc = (e->size < size) ? e->size : size;
|
||||
assert(size == e->size);
|
||||
assert(p->buffersize * p->bits_per_sample / 8 == size);
|
||||
|
||||
memcpy(buffer, e->data, rc);
|
||||
free(e->data);
|
||||
free(e);
|
||||
|
||||
return rc;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
@ -6,14 +6,14 @@ All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* 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.
|
||||
* Neither the name of the <organization> nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* 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.
|
||||
* Neither the name of the <organization> nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
@ -36,6 +36,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <winpr/synch.h>
|
||||
#include <winpr/collections.h>
|
||||
|
||||
#include <freerdp/api.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
@ -45,46 +47,48 @@ extern "C" {
|
||||
typedef struct
|
||||
{
|
||||
size_t size;
|
||||
void *data;
|
||||
void* data;
|
||||
} queue_element;
|
||||
|
||||
typedef struct opensl_stream {
|
||||
// engine interfaces
|
||||
SLObjectItf engineObject;
|
||||
SLEngineItf engineEngine;
|
||||
typedef struct opensl_stream
|
||||
{
|
||||
// engine interfaces
|
||||
SLObjectItf engineObject;
|
||||
SLEngineItf engineEngine;
|
||||
|
||||
// device interfaces
|
||||
SLDeviceVolumeItf deviceVolume;
|
||||
|
||||
// recorder interfaces
|
||||
SLObjectItf recorderObject;
|
||||
SLRecordItf recorderRecord;
|
||||
SLAndroidSimpleBufferQueueItf recorderBufferQueue;
|
||||
// recorder interfaces
|
||||
SLObjectItf recorderObject;
|
||||
SLRecordItf recorderRecord;
|
||||
SLAndroidSimpleBufferQueueItf recorderBufferQueue;
|
||||
|
||||
unsigned int inchannels;
|
||||
unsigned int sr;
|
||||
unsigned int inchannels;
|
||||
unsigned int sr;
|
||||
unsigned int buffersize;
|
||||
unsigned int bits_per_sample;
|
||||
|
||||
wQueue *queue;
|
||||
queue_element *prep;
|
||||
queue_element *next;
|
||||
wQueue* queue;
|
||||
queue_element* prep;
|
||||
queue_element* next;
|
||||
} OPENSL_STREAM;
|
||||
|
||||
/*
|
||||
Open the audio device with a given sampling rate (sr), input and output channels and IO buffer size
|
||||
in frames. Returns a handle to the OpenSL stream
|
||||
*/
|
||||
OPENSL_STREAM* android_OpenRecDevice(char *name, int sr, int inchannels,
|
||||
int bufferframes, int bits_per_sample);
|
||||
/*
|
||||
Close the audio device
|
||||
*/
|
||||
void android_CloseRecDevice(OPENSL_STREAM *p);
|
||||
/*
|
||||
Read a buffer from the OpenSL stream *p, of size samples. Returns the number of samples read.
|
||||
*/
|
||||
int android_RecIn(OPENSL_STREAM *p, short *buffer,int size);
|
||||
/*
|
||||
Open the audio device with a given sampling rate (sr), input and output channels and IO buffer size
|
||||
in frames. Returns a handle to the OpenSL stream
|
||||
*/
|
||||
FREERDP_LOCAL OPENSL_STREAM* android_OpenRecDevice(char* name, int sr,
|
||||
int inchannels,
|
||||
int bufferframes, int bits_per_sample);
|
||||
/*
|
||||
Close the audio device
|
||||
*/
|
||||
FREERDP_LOCAL void android_CloseRecDevice(OPENSL_STREAM* p);
|
||||
/*
|
||||
Read a buffer from the OpenSL stream *p, of size samples. Returns the number of samples read.
|
||||
*/
|
||||
FREERDP_LOCAL int android_RecIn(OPENSL_STREAM* p, short* buffer, int size);
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -81,22 +81,25 @@ static int audin_oss_get_format(audinFormat* 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;
|
||||
@ -105,7 +108,8 @@ static int audin_oss_get_format(audinFormat* format)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL audin_oss_format_supported(IAudinDevice* device, audinFormat* format)
|
||||
static BOOL audin_oss_format_supported(IAudinDevice* device,
|
||||
audinFormat* format)
|
||||
{
|
||||
int req_fmt = 0;
|
||||
|
||||
@ -115,20 +119,19 @@ static BOOL audin_oss_format_supported(IAudinDevice* device, audinFormat* 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;
|
||||
@ -147,7 +150,8 @@ static BOOL audin_oss_format_supported(IAudinDevice* device, audinFormat* format
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT audin_oss_set_format(IAudinDevice* device, audinFormat* format, UINT32 FramesPerPacket)
|
||||
static UINT audin_oss_set_format(IAudinDevice* device, audinFormat* format,
|
||||
UINT32 FramesPerPacket)
|
||||
{
|
||||
AudinOSSDevice* oss = (AudinOSSDevice*)device;
|
||||
|
||||
@ -165,6 +169,7 @@ static UINT audin_oss_set_format(IAudinDevice* device, audinFormat* format, UINT
|
||||
oss->format.wBitsPerSample *= 4;
|
||||
break;
|
||||
}
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
@ -255,7 +260,8 @@ static void* audin_oss_thread_func(void* arg)
|
||||
if (ioctl(pcm_handle, SNDCTL_DSP_SETFRAGMENT, &tmp) == -1)
|
||||
OSS_LOG_ERR("SNDCTL_DSP_SETFRAGMENT failed", errno);
|
||||
|
||||
buffer_size = (oss->FramesPerPacket * oss->format.nChannels * (oss->format.wBitsPerSample / 8));
|
||||
buffer_size = (oss->FramesPerPacket * oss->format.nChannels *
|
||||
(oss->format.wBitsPerSample / 8));
|
||||
buffer = (BYTE*)calloc((buffer_size + sizeof(void*)), sizeof(BYTE));
|
||||
|
||||
if (NULL == buffer)
|
||||
@ -274,7 +280,7 @@ static void* audin_oss_thread_func(void* arg)
|
||||
if (status == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", error);
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %u", error);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
@ -294,44 +300,50 @@ static void* audin_oss_thread_func(void* arg)
|
||||
continue;
|
||||
|
||||
/* Process. */
|
||||
switch (oss->format.wFormatTag) {
|
||||
case WAVE_FORMAT_ADPCM:
|
||||
if (!oss->dsp_context->encode_ms_adpcm(oss->dsp_context,
|
||||
buffer, buffer_size, oss->format.nChannels, oss->format.nBlockAlign))
|
||||
{
|
||||
error = ERROR_INTERNAL_ERROR;
|
||||
goto err_out;
|
||||
}
|
||||
encoded_data = oss->dsp_context->adpcm_buffer;
|
||||
encoded_size = oss->dsp_context->adpcm_size;
|
||||
break;
|
||||
case WAVE_FORMAT_DVI_ADPCM:
|
||||
if (!oss->dsp_context->encode_ima_adpcm(oss->dsp_context,
|
||||
buffer, buffer_size, oss->format.nChannels, oss->format.nBlockAlign))
|
||||
{
|
||||
error = ERROR_INTERNAL_ERROR;
|
||||
goto err_out;
|
||||
}
|
||||
encoded_data = oss->dsp_context->adpcm_buffer;
|
||||
encoded_size = oss->dsp_context->adpcm_size;
|
||||
break;
|
||||
default:
|
||||
encoded_data = buffer;
|
||||
encoded_size = buffer_size;
|
||||
break;
|
||||
}
|
||||
if ((error = oss->receive(encoded_data, encoded_size, oss->user_data)))
|
||||
switch (oss->format.wFormatTag)
|
||||
{
|
||||
WLog_ERR(TAG, "oss->receive failed with error %lu", error);
|
||||
break;
|
||||
case WAVE_FORMAT_ADPCM:
|
||||
if (!oss->dsp_context->encode_ms_adpcm(oss->dsp_context,
|
||||
buffer, buffer_size, oss->format.nChannels, oss->format.nBlockAlign))
|
||||
{
|
||||
error = ERROR_INTERNAL_ERROR;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
encoded_data = oss->dsp_context->adpcm_buffer;
|
||||
encoded_size = oss->dsp_context->adpcm_size;
|
||||
break;
|
||||
|
||||
case WAVE_FORMAT_DVI_ADPCM:
|
||||
if (!oss->dsp_context->encode_ima_adpcm(oss->dsp_context,
|
||||
buffer, buffer_size, oss->format.nChannels, oss->format.nBlockAlign))
|
||||
{
|
||||
error = ERROR_INTERNAL_ERROR;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
encoded_data = oss->dsp_context->adpcm_buffer;
|
||||
encoded_size = oss->dsp_context->adpcm_size;
|
||||
break;
|
||||
|
||||
default:
|
||||
encoded_data = buffer;
|
||||
encoded_size = buffer_size;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((error = oss->receive(encoded_data, encoded_size, oss->user_data)))
|
||||
{
|
||||
WLog_ERR(TAG, "oss->receive failed with error %u", error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
err_out:
|
||||
|
||||
if (error && oss->rdpcontext)
|
||||
setChannelError(oss->rdpcontext, error, "audin_oss_thread_func reported an error");
|
||||
setChannelError(oss->rdpcontext, error,
|
||||
"audin_oss_thread_func reported an error");
|
||||
|
||||
if (pcm_handle != -1)
|
||||
{
|
||||
@ -349,9 +361,10 @@ err_out:
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT audin_oss_open(IAudinDevice *device, AudinReceive receive, void *user_data) {
|
||||
AudinOSSDevice *oss = (AudinOSSDevice*)device;
|
||||
|
||||
static UINT audin_oss_open(IAudinDevice* device, AudinReceive receive,
|
||||
void* user_data)
|
||||
{
|
||||
AudinOSSDevice* oss = (AudinOSSDevice*)device;
|
||||
oss->receive = receive;
|
||||
oss->user_data = user_data;
|
||||
|
||||
@ -360,8 +373,9 @@ static UINT audin_oss_open(IAudinDevice *device, AudinReceive receive, void *use
|
||||
WLog_ERR(TAG, "CreateEvent failed!");
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
if (!(oss->thread = CreateThread(NULL, 0,
|
||||
(LPTHREAD_START_ROUTINE)audin_oss_thread_func, oss, 0, NULL)))
|
||||
(LPTHREAD_START_ROUTINE)audin_oss_thread_func, oss, 0, NULL)))
|
||||
{
|
||||
WLog_ERR(TAG, "CreateThread failed!");
|
||||
CloseHandle(oss->stopEvent);
|
||||
@ -377,10 +391,10 @@ static UINT audin_oss_open(IAudinDevice *device, AudinReceive receive, void *use
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT audin_oss_close(IAudinDevice *device)
|
||||
static UINT audin_oss_close(IAudinDevice* device)
|
||||
{
|
||||
UINT error;
|
||||
AudinOSSDevice *oss = (AudinOSSDevice*)device;
|
||||
AudinOSSDevice* oss = (AudinOSSDevice*)device;
|
||||
|
||||
if (device == NULL)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
@ -388,12 +402,14 @@ static UINT audin_oss_close(IAudinDevice *device)
|
||||
if (oss->stopEvent != NULL)
|
||||
{
|
||||
SetEvent(oss->stopEvent);
|
||||
|
||||
if (WaitForSingleObject(oss->thread, INFINITE) == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", error);
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %u", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
CloseHandle(oss->stopEvent);
|
||||
oss->stopEvent = NULL;
|
||||
CloseHandle(oss->thread);
|
||||
@ -402,7 +418,6 @@ static UINT audin_oss_close(IAudinDevice *device)
|
||||
|
||||
oss->receive = NULL;
|
||||
oss->user_data = NULL;
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
@ -413,8 +428,7 @@ static UINT audin_oss_close(IAudinDevice *device)
|
||||
*/
|
||||
static UINT audin_oss_free(IAudinDevice* device)
|
||||
{
|
||||
AudinOSSDevice *oss = (AudinOSSDevice*)device;
|
||||
|
||||
AudinOSSDevice* oss = (AudinOSSDevice*)device;
|
||||
int error;
|
||||
|
||||
if (device == NULL)
|
||||
@ -424,9 +438,9 @@ static UINT audin_oss_free(IAudinDevice* device)
|
||||
{
|
||||
WLog_ERR(TAG, "audin_oss_close failed with error code %d!", error);
|
||||
}
|
||||
|
||||
freerdp_dsp_context_free(oss->dsp_context);
|
||||
free(oss);
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
@ -441,15 +455,17 @@ COMMAND_LINE_ARGUMENT_A audin_oss_args[] =
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT audin_oss_parse_addin_args(AudinOSSDevice *device, ADDIN_ARGV *args)
|
||||
static UINT audin_oss_parse_addin_args(AudinOSSDevice* device, ADDIN_ARGV* args)
|
||||
{
|
||||
int status;
|
||||
char* str_num, *eptr;
|
||||
DWORD flags;
|
||||
COMMAND_LINE_ARGUMENT_A* arg;
|
||||
AudinOSSDevice* oss = (AudinOSSDevice*)device;
|
||||
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD;
|
||||
status = CommandLineParseArgumentsA(args->argc, (const char**)args->argv, audin_oss_args, flags, oss, NULL, NULL);
|
||||
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON |
|
||||
COMMAND_LINE_IGN_UNKNOWN_KEYWORD;
|
||||
status = CommandLineParseArgumentsA(args->argc, (const char**)args->argv,
|
||||
audin_oss_args, flags, oss, NULL, NULL);
|
||||
|
||||
if (status < 0)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
@ -465,11 +481,13 @@ static UINT audin_oss_parse_addin_args(AudinOSSDevice *device, ADDIN_ARGV *args)
|
||||
CommandLineSwitchCase(arg, "dev")
|
||||
{
|
||||
str_num = _strdup(arg->Value);
|
||||
|
||||
if (!str_num)
|
||||
{
|
||||
WLog_ERR(TAG, "_strdup failed!");
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
}
|
||||
|
||||
oss->dev_unit = strtol(str_num, &eptr, 10);
|
||||
|
||||
if (oss->dev_unit < 0 || *eptr != '\0')
|
||||
@ -480,10 +498,11 @@ static UINT audin_oss_parse_addin_args(AudinOSSDevice *device, ADDIN_ARGV *args)
|
||||
CommandLineSwitchEnd(arg)
|
||||
}
|
||||
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#ifdef BUILTIN_CHANNELS
|
||||
#define freerdp_audin_client_subsystem_entry oss_freerdp_audin_client_subsystem_entry
|
||||
#else
|
||||
#define freerdp_audin_client_subsystem_entry FREERDP_API freerdp_audin_client_subsystem_entry
|
||||
@ -494,13 +513,14 @@ static UINT audin_oss_parse_addin_args(AudinOSSDevice *device, ADDIN_ARGV *args)
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints)
|
||||
UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS
|
||||
pEntryPoints)
|
||||
{
|
||||
ADDIN_ARGV *args;
|
||||
AudinOSSDevice *oss;
|
||||
ADDIN_ARGV* args;
|
||||
AudinOSSDevice* oss;
|
||||
UINT error;
|
||||
|
||||
oss = (AudinOSSDevice*)calloc(1, sizeof(AudinOSSDevice));
|
||||
|
||||
if (!oss)
|
||||
{
|
||||
WLog_ERR(TAG, "calloc failed!");
|
||||
@ -513,17 +533,17 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEn
|
||||
oss->iface.Close = audin_oss_close;
|
||||
oss->iface.Free = audin_oss_free;
|
||||
oss->rdpcontext = pEntryPoints->rdpcontext;
|
||||
|
||||
oss->dev_unit = -1;
|
||||
args = pEntryPoints->args;
|
||||
|
||||
if ((error = audin_oss_parse_addin_args(oss, args)))
|
||||
{
|
||||
WLog_ERR(TAG, "audin_oss_parse_addin_args failed with errorcode %lu!", error);
|
||||
WLog_ERR(TAG, "audin_oss_parse_addin_args failed with errorcode %u!", error);
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
oss->dsp_context = freerdp_dsp_context_new();
|
||||
|
||||
if (!oss->dsp_context)
|
||||
{
|
||||
WLog_ERR(TAG, "freerdp_dsp_context_new failed!");
|
||||
@ -531,9 +551,10 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEn
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
if ((error = pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, (IAudinDevice*) oss)))
|
||||
if ((error = pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin,
|
||||
(IAudinDevice*) oss)))
|
||||
{
|
||||
WLog_ERR(TAG, "RegisterAudinDevice failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "RegisterAudinDevice failed with error %u!", error);
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
@ -542,5 +563,4 @@ error_out:
|
||||
freerdp_dsp_context_free(oss->dsp_context);
|
||||
free(oss);
|
||||
return error;
|
||||
|
||||
}
|
||||
|
||||
@ -523,7 +523,7 @@ static UINT audin_pulse_parse_addin_args(AudinPulseDevice* device, ADDIN_ARGV* a
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#ifdef BUILTIN_CHANNELS
|
||||
#define freerdp_audin_client_subsystem_entry pulse_freerdp_audin_client_subsystem_entry
|
||||
#else
|
||||
#define freerdp_audin_client_subsystem_entry FREERDP_API freerdp_audin_client_subsystem_entry
|
||||
@ -558,7 +558,7 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEn
|
||||
|
||||
if ((error = audin_pulse_parse_addin_args(pulse, args)))
|
||||
{
|
||||
WLog_ERR(TAG, "audin_pulse_parse_addin_args failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "audin_pulse_parse_addin_args failed with error %u!", error);
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
@ -598,7 +598,7 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEn
|
||||
|
||||
if ((error = pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, (IAudinDevice*) pulse)))
|
||||
{
|
||||
WLog_ERR(TAG, "RegisterAudinDevice failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "RegisterAudinDevice failed with error %u!", error);
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
|
||||
@ -26,12 +26,12 @@ add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_N
|
||||
|
||||
|
||||
|
||||
set(${MODULE_PREFIX}_LIBS freerdp winmm.lib)
|
||||
set(${MODULE_PREFIX}_LIBS freerdp winpr winmm.lib)
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
|
||||
if (WITH_DEBUG_SYMBOLS AND MSVC AND NOT STATIC_CHANNELS AND BUILD_SHARED_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()
|
||||
|
||||
|
||||
@ -230,7 +230,7 @@ static UINT audin_winmm_close(IAudinDevice* device)
|
||||
if (status == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -391,7 +391,7 @@ static UINT audin_winmm_parse_addin_args(AudinWinmmDevice* device, ADDIN_ARGV* a
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#ifdef BUILTIN_CHANNELS
|
||||
#define freerdp_audin_client_subsystem_entry winmm_freerdp_audin_client_subsystem_entry
|
||||
#else
|
||||
#define freerdp_audin_client_subsystem_entry FREERDP_API freerdp_audin_client_subsystem_entry
|
||||
|
||||
@ -69,13 +69,15 @@ typedef struct _audin_server
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT audin_server_select_format(audin_server_context* context, int client_format_index)
|
||||
static UINT audin_server_select_format(audin_server_context* context,
|
||||
int client_format_index)
|
||||
{
|
||||
audin_server* audin = (audin_server*) context;
|
||||
|
||||
if (client_format_index >= context->num_client_formats)
|
||||
{
|
||||
WLog_ERR(TAG, "error in protocol: client_format_index >= context->num_client_formats!");
|
||||
WLog_ERR(TAG,
|
||||
"error in protocol: client_format_index >= context->num_client_formats!");
|
||||
return ERROR_INVALID_DATA;
|
||||
}
|
||||
|
||||
@ -85,6 +87,7 @@ static UINT audin_server_select_format(audin_server_context* context, int client
|
||||
{
|
||||
/* TODO: send MSG_SNDIN_FORMATCHANGE */
|
||||
}
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
@ -96,14 +99,16 @@ static UINT audin_server_select_format(audin_server_context* context, int client
|
||||
static UINT audin_server_send_version(audin_server* audin, wStream* s)
|
||||
{
|
||||
ULONG written;
|
||||
|
||||
Stream_Write_UINT8(s, MSG_SNDIN_VERSION);
|
||||
Stream_Write_UINT32(s, 1); /* Version (4 bytes) */
|
||||
if (!WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written))
|
||||
|
||||
if (!WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s),
|
||||
Stream_GetPosition(s), &written))
|
||||
{
|
||||
WLog_ERR(TAG, "WTSVirtualChannelWrite failed!");
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
@ -112,13 +117,15 @@ static UINT audin_server_send_version(audin_server* audin, wStream* s)
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT audin_server_recv_version(audin_server* audin, wStream* s, UINT32 length)
|
||||
static UINT audin_server_recv_version(audin_server* audin, wStream* s,
|
||||
UINT32 length)
|
||||
{
|
||||
UINT32 Version;
|
||||
|
||||
if (length < 4)
|
||||
{
|
||||
WLog_ERR(TAG, "error parsing version info: expected at least 4 bytes, got %d", length);
|
||||
WLog_ERR(TAG, "error parsing version info: expected at least 4 bytes, got %d",
|
||||
length);
|
||||
return ERROR_INVALID_DATA;
|
||||
}
|
||||
|
||||
@ -143,17 +150,18 @@ static UINT audin_server_send_formats(audin_server* audin, wStream* s)
|
||||
int i;
|
||||
UINT32 nAvgBytesPerSec;
|
||||
ULONG written;
|
||||
|
||||
Stream_SetPosition(s, 0);
|
||||
Stream_Write_UINT8(s, MSG_SNDIN_FORMATS);
|
||||
Stream_Write_UINT32(s, audin->context.num_server_formats); /* NumFormats (4 bytes) */
|
||||
Stream_Write_UINT32(s, 0); /* cbSizeFormatsPacket (4 bytes), client-to-server only */
|
||||
Stream_Write_UINT32(s,
|
||||
audin->context.num_server_formats); /* NumFormats (4 bytes) */
|
||||
Stream_Write_UINT32(s,
|
||||
0); /* cbSizeFormatsPacket (4 bytes), client-to-server only */
|
||||
|
||||
for (i = 0; i < audin->context.num_server_formats; i++)
|
||||
{
|
||||
nAvgBytesPerSec = audin->context.server_formats[i].nSamplesPerSec *
|
||||
audin->context.server_formats[i].nChannels *
|
||||
audin->context.server_formats[i].wBitsPerSample / 8;
|
||||
audin->context.server_formats[i].nChannels *
|
||||
audin->context.server_formats[i].wBitsPerSample / 8;
|
||||
|
||||
if (!Stream_EnsureRemainingCapacity(s, 18))
|
||||
{
|
||||
@ -178,11 +186,12 @@ static UINT audin_server_send_formats(audin_server* audin, wStream* s)
|
||||
}
|
||||
|
||||
Stream_Write(s, audin->context.server_formats[i].data,
|
||||
audin->context.server_formats[i].cbSize);
|
||||
audin->context.server_formats[i].cbSize);
|
||||
}
|
||||
}
|
||||
|
||||
return WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written) ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
|
||||
return WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s),
|
||||
Stream_GetPosition(s), &written) ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -190,29 +199,36 @@ static UINT audin_server_send_formats(audin_server* audin, wStream* s)
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT audin_server_recv_formats(audin_server* audin, wStream* s, UINT32 length)
|
||||
static UINT audin_server_recv_formats(audin_server* audin, wStream* s,
|
||||
UINT32 length)
|
||||
{
|
||||
int i;
|
||||
UINT success = CHANNEL_RC_OK;
|
||||
|
||||
if (length < 8)
|
||||
{
|
||||
WLog_ERR(TAG, "error parsing rec formats: expected at least 8 bytes, got %d", length);
|
||||
WLog_ERR(TAG, "error parsing rec formats: expected at least 8 bytes, got %d",
|
||||
length);
|
||||
return ERROR_INVALID_DATA;
|
||||
}
|
||||
|
||||
Stream_Read_UINT32(s, audin->context.num_client_formats); /* NumFormats (4 bytes) */
|
||||
Stream_Read_UINT32(s,
|
||||
audin->context.num_client_formats); /* NumFormats (4 bytes) */
|
||||
Stream_Seek_UINT32(s); /* cbSizeFormatsPacket (4 bytes) */
|
||||
length -= 8;
|
||||
|
||||
if (audin->context.num_client_formats <= 0)
|
||||
{
|
||||
WLog_ERR(TAG, "num_client_formats expected > 0 but got %d", audin->context.num_client_formats);
|
||||
WLog_ERR(TAG, "num_client_formats expected > 0 but got %d",
|
||||
audin->context.num_client_formats);
|
||||
return ERROR_INVALID_DATA;
|
||||
}
|
||||
|
||||
audin->context.client_formats = malloc(audin->context.num_client_formats * sizeof(AUDIO_FORMAT));
|
||||
ZeroMemory(audin->context.client_formats, audin->context.num_client_formats * sizeof(AUDIO_FORMAT));
|
||||
audin->context.client_formats = calloc(audin->context.num_client_formats,
|
||||
sizeof(AUDIO_FORMAT));
|
||||
|
||||
if (!audin->context.client_formats)
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
|
||||
for (i = 0; i < audin->context.num_client_formats; i++)
|
||||
{
|
||||
@ -239,8 +255,10 @@ static UINT audin_server_recv_formats(audin_server* audin, wStream* s, UINT32 le
|
||||
}
|
||||
|
||||
IFCALLRET(audin->context.Opening, success, &audin->context);
|
||||
if (success)
|
||||
WLog_ERR(TAG, "context.Opening failed with error %lu", success);
|
||||
|
||||
if (success)
|
||||
WLog_ERR(TAG, "context.Opening failed with error %u", success);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
@ -256,16 +274,17 @@ static UINT audin_server_send_open(audin_server* audin, wStream* s)
|
||||
if (audin->context.selected_client_format < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "audin->context.selected_client_format = %d",
|
||||
audin->context.selected_client_format);
|
||||
audin->context.selected_client_format);
|
||||
return ERROR_INVALID_DATA;
|
||||
}
|
||||
|
||||
audin->opened = TRUE;
|
||||
|
||||
Stream_SetPosition(s, 0);
|
||||
Stream_Write_UINT8(s, MSG_SNDIN_OPEN);
|
||||
Stream_Write_UINT32(s, audin->context.frames_per_packet); /* FramesPerPacket (4 bytes) */
|
||||
Stream_Write_UINT32(s, audin->context.selected_client_format); /* initialFormat (4 bytes) */
|
||||
Stream_Write_UINT32(s,
|
||||
audin->context.frames_per_packet); /* FramesPerPacket (4 bytes) */
|
||||
Stream_Write_UINT32(s,
|
||||
audin->context.selected_client_format); /* initialFormat (4 bytes) */
|
||||
/*
|
||||
* [MS-RDPEAI] 3.2.5.1.6
|
||||
* The second format specify the format that SHOULD be used to capture data from
|
||||
@ -278,8 +297,8 @@ static UINT audin_server_send_open(audin_server* audin, wStream* s)
|
||||
Stream_Write_UINT16(s, 4); /* nBlockAlign */
|
||||
Stream_Write_UINT16(s, 16); /* wBitsPerSample */
|
||||
Stream_Write_UINT16(s, 0); /* cbSize */
|
||||
|
||||
return WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written) ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
|
||||
return WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s),
|
||||
Stream_GetPosition(s), &written) ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -287,24 +306,24 @@ static UINT audin_server_send_open(audin_server* audin, wStream* s)
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT audin_server_recv_open_reply(audin_server* audin, wStream* s, UINT32 length)
|
||||
static UINT audin_server_recv_open_reply(audin_server* audin, wStream* s,
|
||||
UINT32 length)
|
||||
{
|
||||
|
||||
UINT32 Result;
|
||||
UINT success = CHANNEL_RC_OK;
|
||||
|
||||
if (length < 4)
|
||||
{
|
||||
WLog_ERR(TAG, "error parsing version info: expected at least 4 bytes, got %d", length);
|
||||
WLog_ERR(TAG, "error parsing version info: expected at least 4 bytes, got %d",
|
||||
length);
|
||||
return ERROR_INVALID_DATA;
|
||||
}
|
||||
|
||||
Stream_Read_UINT32(s, Result);
|
||||
|
||||
IFCALLRET(audin->context.OpenResult, success, &audin->context, Result);
|
||||
|
||||
if (success)
|
||||
WLog_ERR(TAG, "context.OpenResult failed with error %lu", success);
|
||||
if (success)
|
||||
WLog_ERR(TAG, "context.OpenResult failed with error %u", success);
|
||||
|
||||
return success;
|
||||
}
|
||||
@ -314,7 +333,8 @@ static UINT audin_server_recv_open_reply(audin_server* audin, wStream* s, UINT32
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT audin_server_recv_data(audin_server* audin, wStream* s, UINT32 length)
|
||||
static UINT audin_server_recv_data(audin_server* audin, wStream* s,
|
||||
UINT32 length)
|
||||
{
|
||||
AUDIO_FORMAT* format;
|
||||
int sbytes_per_sample;
|
||||
@ -327,7 +347,7 @@ static UINT audin_server_recv_data(audin_server* audin, wStream* s, UINT32 lengt
|
||||
if (audin->context.selected_client_format < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "audin->context.selected_client_format = %d",
|
||||
audin->context.selected_client_format);
|
||||
audin->context.selected_client_format);
|
||||
return ERROR_INVALID_DATA;
|
||||
}
|
||||
|
||||
@ -336,7 +356,7 @@ static UINT audin_server_recv_data(audin_server* audin, wStream* s, UINT32 lengt
|
||||
if (format->wFormatTag == WAVE_FORMAT_ADPCM)
|
||||
{
|
||||
audin->dsp_context->decode_ms_adpcm(audin->dsp_context,
|
||||
Stream_Pointer(s), length, format->nChannels, format->nBlockAlign);
|
||||
Stream_Pointer(s), length, format->nChannels, format->nBlockAlign);
|
||||
size = audin->dsp_context->adpcm_size;
|
||||
src = audin->dsp_context->adpcm_buffer;
|
||||
sbytes_per_sample = 2;
|
||||
@ -345,7 +365,7 @@ static UINT audin_server_recv_data(audin_server* audin, wStream* s, UINT32 lengt
|
||||
else if (format->wFormatTag == WAVE_FORMAT_DVI_ADPCM)
|
||||
{
|
||||
audin->dsp_context->decode_ima_adpcm(audin->dsp_context,
|
||||
Stream_Pointer(s), length, format->nChannels, format->nBlockAlign);
|
||||
Stream_Pointer(s), length, format->nChannels, format->nBlockAlign);
|
||||
size = audin->dsp_context->adpcm_size;
|
||||
src = audin->dsp_context->adpcm_buffer;
|
||||
sbytes_per_sample = 2;
|
||||
@ -359,25 +379,26 @@ static UINT audin_server_recv_data(audin_server* audin, wStream* s, UINT32 lengt
|
||||
sbytes_per_frame = format->nChannels * sbytes_per_sample;
|
||||
}
|
||||
|
||||
if (format->nSamplesPerSec == audin->context.dst_format.nSamplesPerSec && format->nChannels == audin->context.dst_format.nChannels)
|
||||
if (format->nSamplesPerSec == audin->context.dst_format.nSamplesPerSec
|
||||
&& format->nChannels == audin->context.dst_format.nChannels)
|
||||
{
|
||||
frames = size / sbytes_per_frame;
|
||||
}
|
||||
else
|
||||
{
|
||||
audin->dsp_context->resample(audin->dsp_context, src, sbytes_per_sample,
|
||||
format->nChannels, format->nSamplesPerSec, size / sbytes_per_frame,
|
||||
audin->context.dst_format.nChannels, audin->context.dst_format.nSamplesPerSec);
|
||||
format->nChannels, format->nSamplesPerSec, size / sbytes_per_frame,
|
||||
audin->context.dst_format.nChannels, audin->context.dst_format.nSamplesPerSec);
|
||||
frames = audin->dsp_context->resampled_frames;
|
||||
src = audin->dsp_context->resampled_buffer;
|
||||
}
|
||||
|
||||
IFCALLRET(audin->context.ReceiveSamples, success, &audin->context, src, frames);
|
||||
|
||||
if (success)
|
||||
WLog_ERR(TAG, "context.ReceiveSamples failed with error %lu", success);
|
||||
if (success)
|
||||
WLog_ERR(TAG, "context.ReceiveSamples failed with error %u", success);
|
||||
|
||||
return success;
|
||||
return success;
|
||||
}
|
||||
|
||||
static void* audin_server_thread_func(void* arg)
|
||||
@ -393,12 +414,12 @@ static void* audin_server_thread_func(void* arg)
|
||||
audin_server* audin = (audin_server*) arg;
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
DWORD status;
|
||||
|
||||
buffer = NULL;
|
||||
BytesReturned = 0;
|
||||
ChannelEvent = NULL;
|
||||
|
||||
if (WTSVirtualChannelQuery(audin->audin_channel, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE)
|
||||
if (WTSVirtualChannelQuery(audin->audin_channel, WTSVirtualEventHandle, &buffer,
|
||||
&BytesReturned) == TRUE)
|
||||
{
|
||||
if (BytesReturned == sizeof(HANDLE))
|
||||
CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE));
|
||||
@ -420,17 +441,19 @@ static void* audin_server_thread_func(void* arg)
|
||||
|
||||
while (1)
|
||||
{
|
||||
if ((status = WaitForMultipleObjects(nCount, events, FALSE, 100)) == WAIT_OBJECT_0)
|
||||
if ((status = WaitForMultipleObjects(nCount, events, FALSE,
|
||||
100)) == WAIT_OBJECT_0)
|
||||
goto out;
|
||||
|
||||
if (status == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu", error);
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForMultipleObjects failed with error %u", error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (WTSVirtualChannelQuery(audin->audin_channel, WTSVirtualChannelReady, &buffer, &BytesReturned) == FALSE)
|
||||
if (WTSVirtualChannelQuery(audin->audin_channel, WTSVirtualChannelReady,
|
||||
&buffer, &BytesReturned) == FALSE)
|
||||
{
|
||||
WLog_ERR(TAG, "WTSVirtualChannelQuery failed");
|
||||
error = ERROR_INTERNAL_ERROR;
|
||||
@ -438,7 +461,6 @@ static void* audin_server_thread_func(void* arg)
|
||||
}
|
||||
|
||||
ready = *((BOOL*) buffer);
|
||||
|
||||
WTSFreeMemory(buffer);
|
||||
|
||||
if (ready)
|
||||
@ -446,6 +468,7 @@ static void* audin_server_thread_func(void* arg)
|
||||
}
|
||||
|
||||
s = Stream_New(NULL, 4096);
|
||||
|
||||
if (!s)
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_New failed!");
|
||||
@ -453,26 +476,26 @@ static void* audin_server_thread_func(void* arg)
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
if (ready)
|
||||
{
|
||||
if ((error = audin_server_send_version(audin, s)))
|
||||
{
|
||||
WLog_ERR(TAG, "audin_server_send_version failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "audin_server_send_version failed with error %u!", error);
|
||||
goto out_capacity;
|
||||
}
|
||||
}
|
||||
|
||||
while (ready)
|
||||
{
|
||||
if ((status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE)) == WAIT_OBJECT_0)
|
||||
if ((status = WaitForMultipleObjects(nCount, events, FALSE,
|
||||
INFINITE)) == WAIT_OBJECT_0)
|
||||
break;
|
||||
|
||||
if (status == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu", error);
|
||||
goto out;
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForMultipleObjects failed with error %u", error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
Stream_SetPosition(s, 0);
|
||||
@ -483,12 +506,15 @@ static void* audin_server_thread_func(void* arg)
|
||||
error = ERROR_INTERNAL_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (BytesReturned < 1)
|
||||
continue;
|
||||
|
||||
if (!Stream_EnsureRemainingCapacity(s, BytesReturned))
|
||||
break;
|
||||
|
||||
if (WTSVirtualChannelRead(audin->audin_channel, 0, (PCHAR) Stream_Buffer(s),
|
||||
Stream_Capacity(s), &BytesReturned) == FALSE)
|
||||
Stream_Capacity(s), &BytesReturned) == FALSE)
|
||||
{
|
||||
WLog_ERR(TAG, "WTSVirtualChannelRead failed!");
|
||||
error = ERROR_INTERNAL_ERROR;
|
||||
@ -503,35 +529,40 @@ static void* audin_server_thread_func(void* arg)
|
||||
case MSG_SNDIN_VERSION:
|
||||
if ((error = audin_server_recv_version(audin, s, BytesReturned)))
|
||||
{
|
||||
WLog_ERR(TAG, "audin_server_recv_version failed with error %lu!", error);
|
||||
goto out_capacity;
|
||||
}
|
||||
if ((error = audin_server_send_formats(audin, s)))
|
||||
{
|
||||
WLog_ERR(TAG, "audin_server_send_formats failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "audin_server_recv_version failed with error %u!", error);
|
||||
goto out_capacity;
|
||||
}
|
||||
|
||||
if ((error = audin_server_send_formats(audin, s)))
|
||||
{
|
||||
WLog_ERR(TAG, "audin_server_send_formats failed with error %u!", error);
|
||||
goto out_capacity;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MSG_SNDIN_FORMATS:
|
||||
if ((error = audin_server_recv_formats(audin, s, BytesReturned)))
|
||||
{
|
||||
WLog_ERR(TAG, "audin_server_recv_formats failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "audin_server_recv_formats failed with error %u!", error);
|
||||
goto out_capacity;
|
||||
}
|
||||
|
||||
if ((error = audin_server_send_open(audin, s)))
|
||||
{
|
||||
WLog_ERR(TAG, "audin_server_send_open failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "audin_server_send_open failed with error %u!", error);
|
||||
goto out_capacity;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MSG_SNDIN_OPEN_REPLY:
|
||||
if ((error = audin_server_recv_open_reply(audin, s, BytesReturned)))
|
||||
{
|
||||
WLog_ERR(TAG, "audin_server_recv_open_reply failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "audin_server_recv_open_reply failed with error %u!", error);
|
||||
goto out_capacity;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MSG_SNDIN_DATA_INCOMING:
|
||||
@ -540,9 +571,10 @@ static void* audin_server_thread_func(void* arg)
|
||||
case MSG_SNDIN_DATA:
|
||||
if ((error = audin_server_recv_data(audin, s, BytesReturned)))
|
||||
{
|
||||
WLog_ERR(TAG, "audin_server_recv_data failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "audin_server_recv_data failed with error %u!", error);
|
||||
goto out_capacity;
|
||||
};
|
||||
|
||||
break;
|
||||
|
||||
case MSG_SNDIN_FORMATCHANGE:
|
||||
@ -559,8 +591,10 @@ out_capacity:
|
||||
out:
|
||||
WTSVirtualChannelClose(audin->audin_channel);
|
||||
audin->audin_channel = NULL;
|
||||
|
||||
if (error && audin->context.rdpcontext)
|
||||
setChannelError(audin->context.rdpcontext, error, "audin_server_thread_func reported an error");
|
||||
setChannelError(audin->context.rdpcontext, error,
|
||||
"audin_server_thread_func reported an error");
|
||||
|
||||
ExitThread((DWORD)error);
|
||||
return NULL;
|
||||
@ -574,18 +608,17 @@ static BOOL audin_server_open(audin_server_context* context)
|
||||
{
|
||||
PULONG pSessionId = NULL;
|
||||
DWORD BytesReturned = 0;
|
||||
|
||||
audin->SessionId = WTS_CURRENT_SESSION;
|
||||
|
||||
if (WTSQuerySessionInformationA(context->vcm, WTS_CURRENT_SESSION,
|
||||
WTSSessionId, (LPSTR*) &pSessionId, &BytesReturned))
|
||||
WTSSessionId, (LPSTR*) &pSessionId, &BytesReturned))
|
||||
{
|
||||
audin->SessionId = (DWORD) *pSessionId;
|
||||
audin->SessionId = (DWORD) * pSessionId;
|
||||
WTSFreeMemory(pSessionId);
|
||||
}
|
||||
|
||||
audin->audin_channel = WTSVirtualChannelOpenEx(audin->SessionId,
|
||||
"AUDIO_INPUT", WTS_CHANNEL_OPTION_DYNAMIC);
|
||||
"AUDIO_INPUT", WTS_CHANNEL_OPTION_DYNAMIC);
|
||||
|
||||
if (!audin->audin_channel)
|
||||
{
|
||||
@ -600,7 +633,7 @@ static BOOL audin_server_open(audin_server_context* context)
|
||||
}
|
||||
|
||||
if (!(audin->thread = CreateThread(NULL, 0,
|
||||
(LPTHREAD_START_ROUTINE) audin_server_thread_func, (void*) audin, 0, NULL)))
|
||||
(LPTHREAD_START_ROUTINE) audin_server_thread_func, (void*) audin, 0, NULL)))
|
||||
{
|
||||
WLog_ERR(TAG, "CreateThread failed!");
|
||||
CloseHandle(audin->stopEvent);
|
||||
@ -610,6 +643,7 @@ static BOOL audin_server_open(audin_server_context* context)
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
WLog_ERR(TAG, "thread already running!");
|
||||
return FALSE;
|
||||
}
|
||||
@ -621,11 +655,12 @@ static BOOL audin_server_close(audin_server_context* context)
|
||||
if (audin->thread)
|
||||
{
|
||||
SetEvent(audin->stopEvent);
|
||||
|
||||
if (WaitForSingleObject(audin->thread, INFINITE) == WAIT_FAILED)
|
||||
{
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
{
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", (unsigned long)GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
CloseHandle(audin->thread);
|
||||
CloseHandle(audin->stopEvent);
|
||||
@ -640,15 +675,14 @@ static BOOL audin_server_close(audin_server_context* context)
|
||||
}
|
||||
|
||||
audin->context.selected_client_format = -1;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
audin_server_context* audin_server_context_new(HANDLE vcm)
|
||||
{
|
||||
audin_server* audin;
|
||||
audin = (audin_server*)calloc(1, sizeof(audin_server));
|
||||
|
||||
audin = (audin_server *)calloc(1, sizeof(audin_server));
|
||||
if (!audin)
|
||||
{
|
||||
WLog_ERR(TAG, "calloc failed!");
|
||||
@ -661,7 +695,6 @@ audin_server_context* audin_server_context_new(HANDLE vcm)
|
||||
audin->context.SelectFormat = audin_server_select_format;
|
||||
audin->context.Open = audin_server_open;
|
||||
audin->context.Close = audin_server_close;
|
||||
|
||||
audin->dsp_context = freerdp_dsp_context_new();
|
||||
|
||||
if (!audin->dsp_context)
|
||||
@ -677,7 +710,6 @@ audin_server_context* audin_server_context_new(HANDLE vcm)
|
||||
void audin_server_context_free(audin_server_context* context)
|
||||
{
|
||||
audin_server* audin = (audin_server*) context;
|
||||
|
||||
audin_server_close(context);
|
||||
|
||||
if (audin->dsp_context)
|
||||
|
||||
@ -25,7 +25,7 @@ set(${MODULE_PREFIX}_SRCS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/addin.h)
|
||||
|
||||
if(CHANNEL_STATIC_CLIENT_ENTRIES)
|
||||
list(REMOVE_DUPLICATES CHANNEL_STATIC_CLIENT_ENTRIES)
|
||||
list(REMOVE_DUPLICATES CHANNEL_STATIC_CLIENT_ENTRIES)
|
||||
endif()
|
||||
|
||||
foreach(STATIC_ENTRY ${CHANNEL_STATIC_CLIENT_ENTRIES})
|
||||
@ -38,6 +38,8 @@ foreach(STATIC_ENTRY ${CHANNEL_STATIC_CLIENT_ENTRIES})
|
||||
set(ENTRY_POINT_NAME "${STATIC_MODULE_CHANNEL}_${${STATIC_MODULE}_CLIENT_ENTRY}")
|
||||
if(${${STATIC_MODULE}_CLIENT_ENTRY} STREQUAL "VirtualChannelEntry")
|
||||
set(ENTRY_POINT_IMPORT "extern BOOL VCAPITYPE ${ENTRY_POINT_NAME}(PCHANNEL_ENTRY_POINTS);")
|
||||
elseif(${${STATIC_MODULE}_CLIENT_ENTRY} STREQUAL "VirtualChannelEntryEx")
|
||||
set(ENTRY_POINT_IMPORT "extern BOOL VCAPITYPE ${ENTRY_POINT_NAME}(PCHANNEL_ENTRY_POINTS,PVOID);")
|
||||
else()
|
||||
set(ENTRY_POINT_IMPORT "extern UINT ${ENTRY_POINT_NAME}();")
|
||||
endif()
|
||||
|
||||
@ -349,6 +349,24 @@ void freerdp_channels_addin_list_free(FREERDP_ADDIN** ppAddins)
|
||||
free(ppAddins);
|
||||
}
|
||||
|
||||
extern const STATIC_ENTRY CLIENT_VirtualChannelEntryEx_TABLE[];
|
||||
|
||||
BOOL freerdp_channels_is_virtual_channel_entry_ex(LPCSTR pszName)
|
||||
{
|
||||
int i;
|
||||
STATIC_ENTRY* entry;
|
||||
|
||||
for (i = 0; CLIENT_VirtualChannelEntryEx_TABLE[i].name != NULL; i++)
|
||||
{
|
||||
entry = (STATIC_ENTRY*) &CLIENT_VirtualChannelEntryEx_TABLE[i];
|
||||
|
||||
if (!strcmp(entry->name, pszName))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void* freerdp_channels_load_static_addin_entry(LPCSTR pszName, LPSTR pszSubsystem, LPSTR pszType, DWORD dwFlags)
|
||||
{
|
||||
int i, j;
|
||||
@ -380,6 +398,12 @@ void* freerdp_channels_load_static_addin_entry(LPCSTR pszName, LPSTR pszSubsyste
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dwFlags & FREERDP_ADDIN_CHANNEL_ENTRYEX)
|
||||
{
|
||||
if (!freerdp_channels_is_virtual_channel_entry_ex(pszName))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (void*) CLIENT_STATIC_ADDIN_TABLE[i].entry;
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,7 +23,7 @@ set(${MODULE_PREFIX}_SRCS
|
||||
cliprdr_main.c
|
||||
cliprdr_main.h)
|
||||
|
||||
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntry")
|
||||
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntryEx")
|
||||
|
||||
set(${MODULE_PREFIX}_LIBS freerdp winpr)
|
||||
|
||||
|
||||
@ -265,7 +265,7 @@ UINT cliprdr_process_format_list_response(cliprdrPlugin* cliprdr, wStream* s, UI
|
||||
|
||||
IFCALLRET(context->ServerFormatListResponse, error, context, &formatListResponse);
|
||||
if (error)
|
||||
WLog_ERR(TAG, "ServerFormatListResponse failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "ServerFormatListResponse failed with error %u!", error);
|
||||
|
||||
return error;
|
||||
}
|
||||
@ -298,7 +298,7 @@ UINT cliprdr_process_format_data_request(cliprdrPlugin* cliprdr, wStream* s, UIN
|
||||
|
||||
IFCALLRET(context->ServerFormatDataRequest, error, context, &formatDataRequest);
|
||||
if (error)
|
||||
WLog_ERR(TAG, "ServerFormatDataRequest failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "ServerFormatDataRequest failed with error %u!", error);
|
||||
|
||||
return error;
|
||||
}
|
||||
@ -332,7 +332,7 @@ UINT cliprdr_process_format_data_response(cliprdrPlugin* cliprdr, wStream* s, UI
|
||||
|
||||
IFCALLRET(context->ServerFormatDataResponse, error, context, &formatDataResponse);
|
||||
if (error)
|
||||
WLog_ERR(TAG, "ServerFormatDataResponse failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "ServerFormatDataResponse failed with error %u!", error);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -33,7 +33,7 @@
|
||||
struct cliprdr_plugin
|
||||
{
|
||||
CHANNEL_DEF channelDef;
|
||||
CHANNEL_ENTRY_POINTS_FREERDP channelEntryPoints;
|
||||
CHANNEL_ENTRY_POINTS_FREERDP_EX channelEntryPoints;
|
||||
|
||||
CliprdrClientContext* context;
|
||||
|
||||
@ -52,15 +52,12 @@ struct cliprdr_plugin
|
||||
};
|
||||
typedef struct cliprdr_plugin cliprdrPlugin;
|
||||
|
||||
wStream* cliprdr_packet_new(UINT16 msgType, UINT16 msgFlags, UINT32 dataLen);
|
||||
UINT cliprdr_packet_send(cliprdrPlugin* cliprdr, wStream* data_out);
|
||||
|
||||
CliprdrClientContext* cliprdr_get_client_interface(cliprdrPlugin* cliprdr);
|
||||
|
||||
#ifdef WITH_DEBUG_CLIPRDR
|
||||
#define DEBUG_CLIPRDR(fmt, ...) WLog_DBG(TAG, fmt, ## __VA_ARGS__)
|
||||
#define DEBUG_CLIPRDR(...) WLog_DBG(TAG, __VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG_CLIPRDR(fmt, ...) do { } while (0)
|
||||
#define DEBUG_CLIPRDR(...) do { } while (0)
|
||||
#endif
|
||||
|
||||
#endif /* __CLIPRDR_MAIN_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -32,7 +32,7 @@ set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} winpr)
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
|
||||
if (WITH_DEBUG_SYMBOLS AND MSVC AND NOT STATIC_CHANNELS AND BUILD_SHARED_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()
|
||||
|
||||
|
||||
6
channels/disp/client/disp_main.c
Normal file → Executable file
6
channels/disp/client/disp_main.c
Normal file → Executable file
@ -5,6 +5,7 @@
|
||||
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2015 Thincast Technologies GmbH
|
||||
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
|
||||
* Copyright 2016 David PHAM-VAN <d.phamvan@inuvika.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -317,6 +318,9 @@ static UINT disp_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManage
|
||||
*/
|
||||
static UINT disp_plugin_terminated(IWTSPlugin* pPlugin)
|
||||
{
|
||||
DISP_PLUGIN* disp = (DISP_PLUGIN*) pPlugin;
|
||||
free(disp->listener_callback);
|
||||
free(disp->iface.pInterface);
|
||||
free(pPlugin);
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
@ -338,7 +342,7 @@ UINT disp_send_monitor_layout(DispClientContext* context, UINT32 NumMonitors, DI
|
||||
return disp_send_display_control_monitor_layout_pdu(callback, NumMonitors, Monitors);
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#ifdef BUILTIN_CHANNELS
|
||||
#define DVCPluginEntry disp_DVCPluginEntry
|
||||
#else
|
||||
#define DVCPluginEntry FREERDP_API DVCPluginEntry
|
||||
|
||||
@ -21,7 +21,7 @@ set(${MODULE_PREFIX}_SRCS
|
||||
drdynvc_main.c
|
||||
drdynvc_main.h)
|
||||
|
||||
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntry")
|
||||
|
||||
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntryEx")
|
||||
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -115,7 +115,7 @@ typedef enum _DRDYNVC_STATE DRDYNVC_STATE;
|
||||
struct drdynvc_plugin
|
||||
{
|
||||
CHANNEL_DEF channelDef;
|
||||
CHANNEL_ENTRY_POINTS_FREERDP channelEntryPoints;
|
||||
CHANNEL_ENTRY_POINTS_FREERDP_EX channelEntryPoints;
|
||||
|
||||
wLog* log;
|
||||
HANDLE thread;
|
||||
@ -134,7 +134,6 @@ struct drdynvc_plugin
|
||||
int PriorityCharge3;
|
||||
rdpContext* rdpcontext;
|
||||
|
||||
|
||||
IWTSVirtualChannelManager* channel_mgr;
|
||||
};
|
||||
|
||||
|
||||
@ -45,14 +45,13 @@ static void* drdynvc_server_thread(void* arg)
|
||||
DWORD BytesReturned;
|
||||
DrdynvcServerContext* context;
|
||||
UINT error = ERROR_INTERNAL_ERROR;
|
||||
|
||||
context = (DrdynvcServerContext*) arg;
|
||||
|
||||
buffer = NULL;
|
||||
BytesReturned = 0;
|
||||
ChannelEvent = NULL;
|
||||
|
||||
s = Stream_New(NULL, 4096);
|
||||
|
||||
if (!s)
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_New failed!");
|
||||
@ -60,7 +59,8 @@ static void* drdynvc_server_thread(void* arg)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE)
|
||||
if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle,
|
||||
&buffer, &BytesReturned) == TRUE)
|
||||
{
|
||||
if (BytesReturned == sizeof(HANDLE))
|
||||
CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE));
|
||||
@ -82,13 +82,16 @@ static void* drdynvc_server_thread(void* arg)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0, NULL, 0, &BytesReturned))
|
||||
if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0, NULL, 0,
|
||||
&BytesReturned))
|
||||
{
|
||||
WLog_ERR(TAG, "WTSVirtualChannelRead failed!");
|
||||
break;
|
||||
}
|
||||
|
||||
if (BytesReturned < 1)
|
||||
continue;
|
||||
|
||||
if (!Stream_EnsureRemainingCapacity(s, BytesReturned))
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
|
||||
@ -96,7 +99,7 @@ static void* drdynvc_server_thread(void* arg)
|
||||
}
|
||||
|
||||
if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0,
|
||||
(PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned))
|
||||
(PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned))
|
||||
{
|
||||
WLog_ERR(TAG, "WTSVirtualChannelRead failed!");
|
||||
break;
|
||||
@ -118,7 +121,8 @@ static void* drdynvc_server_thread(void* arg)
|
||||
*/
|
||||
static UINT drdynvc_server_start(DrdynvcServerContext* context)
|
||||
{
|
||||
context->priv->ChannelHandle = WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, "drdynvc");
|
||||
context->priv->ChannelHandle = WTSVirtualChannelOpen(context->vcm,
|
||||
WTS_CURRENT_SESSION, "drdynvc");
|
||||
|
||||
if (!context->priv->ChannelHandle)
|
||||
{
|
||||
@ -131,8 +135,9 @@ static UINT drdynvc_server_start(DrdynvcServerContext* context)
|
||||
WLog_ERR(TAG, "CreateEvent failed!");
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
if (!(context->priv->Thread = CreateThread(NULL, 0,
|
||||
(LPTHREAD_START_ROUTINE) drdynvc_server_thread, (void*) context, 0, NULL)))
|
||||
(LPTHREAD_START_ROUTINE) drdynvc_server_thread, (void*) context, 0, NULL)))
|
||||
{
|
||||
WLog_ERR(TAG, "CreateThread failed!");
|
||||
CloseHandle(context->priv->StopEvent);
|
||||
@ -150,34 +155,32 @@ static UINT drdynvc_server_start(DrdynvcServerContext* context)
|
||||
*/
|
||||
static UINT drdynvc_server_stop(DrdynvcServerContext* context)
|
||||
{
|
||||
UINT error;
|
||||
UINT error;
|
||||
SetEvent(context->priv->StopEvent);
|
||||
|
||||
if (WaitForSingleObject(context->priv->Thread, INFINITE) == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
|
||||
return error;
|
||||
}
|
||||
CloseHandle(context->priv->Thread);
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
CloseHandle(context->priv->Thread);
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
DrdynvcServerContext* drdynvc_server_context_new(HANDLE vcm)
|
||||
{
|
||||
DrdynvcServerContext* context;
|
||||
|
||||
context = (DrdynvcServerContext*) calloc(1, sizeof(DrdynvcServerContext));
|
||||
|
||||
if (context)
|
||||
{
|
||||
context->vcm = vcm;
|
||||
|
||||
context->Start = drdynvc_server_start;
|
||||
context->Stop = drdynvc_server_stop;
|
||||
|
||||
context->priv = (DrdynvcServerPrivate*) calloc(1, sizeof(DrdynvcServerPrivate));
|
||||
|
||||
if (!context->priv)
|
||||
{
|
||||
WLog_ERR(TAG, "calloc failed!");
|
||||
|
||||
@ -36,7 +36,7 @@ add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE
|
||||
target_link_libraries(${MODULE_NAME} winpr freerdp)
|
||||
|
||||
|
||||
if (WITH_DEBUG_SYMBOLS AND MSVC AND NOT STATIC_CHANNELS AND BUILD_SHARED_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()
|
||||
|
||||
|
||||
@ -222,7 +222,7 @@ static DIR *opendir(const char *dirname)
|
||||
* allows rewinddir() to function correctly when the current working
|
||||
* directory is changed between opendir() and rewinddir().
|
||||
*/
|
||||
if (GetFullPathNameA (dirname, MAX_PATH, dirp->patt, NULL)) {
|
||||
if (GetFullPathNameA(dirname, MAX_PATH, dirp->patt, NULL)) {
|
||||
char *p;
|
||||
|
||||
/* append the search pattern "\\*\0" to the directory name */
|
||||
@ -234,7 +234,7 @@ static DIR *opendir(const char *dirname)
|
||||
*p = '\0';
|
||||
|
||||
/* open directory stream and retrieve the first entry */
|
||||
dirp->search_handle = FindFirstFileA (dirp->patt, &dirp->find_data);
|
||||
dirp->search_handle = FindFirstFileA(dirp->patt, &dirp->find_data);
|
||||
if (dirp->search_handle != INVALID_HANDLE_VALUE) {
|
||||
/* a directory entry is now waiting in memory */
|
||||
dirp->cached = 1;
|
||||
|
||||
@ -43,6 +43,7 @@
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/path.h>
|
||||
#include <winpr/file.h>
|
||||
#include <winpr/stream.h>
|
||||
|
||||
@ -546,7 +547,7 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN
|
||||
hFd = CreateFileA(file->fullpath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (hFd == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
WLog_ERR(TAG, "Unable to set file time %s to %d", file->fullpath);
|
||||
WLog_ERR(TAG, "Unable to create file %s", file->fullpath);
|
||||
return FALSE;
|
||||
}
|
||||
if (liCreationTime.QuadPart != 0)
|
||||
@ -575,7 +576,7 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN
|
||||
}
|
||||
if (!SetFileTime(hFd, pftCreationTime, pftLastAccessTime, pftLastWriteTime))
|
||||
{
|
||||
WLog_ERR(TAG, "Unable to set file time %s to %d", file->fullpath);
|
||||
WLog_ERR(TAG, "Unable to set file time on %s", file->fullpath);
|
||||
CloseHandle(hFd);
|
||||
return FALSE;
|
||||
}
|
||||
@ -591,13 +592,13 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN
|
||||
hFd = CreateFileA(file->fullpath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (hFd == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
WLog_ERR(TAG, "Unable to truncate %s to %d", file->fullpath, size);
|
||||
WLog_ERR(TAG, "Unable to truncate %s to %lld", file->fullpath, (long long) size);
|
||||
return FALSE;
|
||||
}
|
||||
liSize.QuadPart = size;
|
||||
if (SetFilePointer(hFd, liSize.LowPart, &liSize.HighPart, FILE_BEGIN) == 0)
|
||||
{
|
||||
WLog_ERR(TAG, "Unable to truncate %s to %d", file->fullpath, size);
|
||||
WLog_ERR(TAG, "Unable to truncate %s to %lld", file->fullpath, (long long) size);
|
||||
CloseHandle(hFd);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -38,10 +38,12 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/path.h>
|
||||
#include <winpr/string.h>
|
||||
#include <winpr/synch.h>
|
||||
#include <winpr/thread.h>
|
||||
#include <winpr/stream.h>
|
||||
#include <winpr/environment.h>
|
||||
#include <winpr/interlocked.h>
|
||||
#include <winpr/collections.h>
|
||||
|
||||
@ -78,15 +80,19 @@ static UINT32 drive_map_posix_err(int fs_errno)
|
||||
case EACCES:
|
||||
rc = STATUS_ACCESS_DENIED;
|
||||
break;
|
||||
|
||||
case ENOENT:
|
||||
rc = STATUS_NO_SUCH_FILE;
|
||||
break;
|
||||
|
||||
case EBUSY:
|
||||
rc = STATUS_DEVICE_BUSY;
|
||||
break;
|
||||
|
||||
case EEXIST:
|
||||
rc = STATUS_OBJECT_NAME_COLLISION;
|
||||
break;
|
||||
|
||||
case EISDIR:
|
||||
rc = STATUS_FILE_IS_A_DIRECTORY;
|
||||
break;
|
||||
@ -102,10 +108,8 @@ static UINT32 drive_map_posix_err(int fs_errno)
|
||||
static DRIVE_FILE* drive_get_file_by_id(DRIVE_DEVICE* drive, UINT32 id)
|
||||
{
|
||||
DRIVE_FILE* file = NULL;
|
||||
void* key = (void*) (size_t) id;
|
||||
|
||||
void* key = (void*)(size_t) id;
|
||||
file = (DRIVE_FILE*) ListDictionary_GetItemValue(drive->files, key);
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
@ -126,19 +130,19 @@ static UINT drive_process_irp_create(DRIVE_DEVICE* drive, IRP* irp)
|
||||
UINT32 CreateOptions;
|
||||
UINT32 PathLength;
|
||||
char* path = NULL;
|
||||
|
||||
Stream_Read_UINT32(irp->input, DesiredAccess);
|
||||
Stream_Seek(irp->input, 16); /* AllocationSize(8), FileAttributes(4), SharedAccess(4) */
|
||||
Stream_Seek(irp->input,
|
||||
16); /* AllocationSize(8), FileAttributes(4), SharedAccess(4) */
|
||||
Stream_Read_UINT32(irp->input, CreateDisposition);
|
||||
Stream_Read_UINT32(irp->input, CreateOptions);
|
||||
Stream_Read_UINT32(irp->input, PathLength);
|
||||
|
||||
status = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(irp->input),
|
||||
PathLength / 2, &path, 0, NULL, NULL);
|
||||
PathLength / 2, &path, 0, NULL, NULL);
|
||||
|
||||
if (status < 1)
|
||||
{
|
||||
path = (char*) calloc(1, 1);
|
||||
|
||||
if (!path)
|
||||
{
|
||||
WLog_ERR(TAG, "calloc failed!");
|
||||
@ -146,11 +150,9 @@ static UINT drive_process_irp_create(DRIVE_DEVICE* drive, IRP* irp)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FileId = irp->devman->id_sequence++;
|
||||
|
||||
file = drive_file_new(drive->path, path, FileId,
|
||||
DesiredAccess, CreateDisposition, CreateOptions);
|
||||
DesiredAccess, CreateDisposition, CreateOptions);
|
||||
|
||||
if (!file)
|
||||
{
|
||||
@ -162,14 +164,14 @@ static UINT drive_process_irp_create(DRIVE_DEVICE* drive, IRP* irp)
|
||||
{
|
||||
FileId = 0;
|
||||
Information = 0;
|
||||
|
||||
/* map errno to windows result */
|
||||
irp->IoStatus = drive_map_posix_err(file->err);
|
||||
drive_file_free(file);
|
||||
}
|
||||
else
|
||||
{
|
||||
key = (void*) (size_t) file->id;
|
||||
key = (void*)(size_t) file->id;
|
||||
|
||||
if (!ListDictionary_Add(drive->files, key, file))
|
||||
{
|
||||
WLog_ERR(TAG, "ListDictionary_Add failed!");
|
||||
@ -185,12 +187,15 @@ static UINT drive_process_irp_create(DRIVE_DEVICE* drive, IRP* irp)
|
||||
case FILE_OVERWRITE:
|
||||
Information = FILE_SUPERSEDED;
|
||||
break;
|
||||
|
||||
case FILE_OPEN_IF:
|
||||
Information = FILE_OPENED;
|
||||
break;
|
||||
|
||||
case FILE_OVERWRITE_IF:
|
||||
Information = FILE_OVERWRITTEN;
|
||||
break;
|
||||
|
||||
default:
|
||||
Information = 0;
|
||||
break;
|
||||
@ -199,9 +204,7 @@ static UINT drive_process_irp_create(DRIVE_DEVICE* drive, IRP* irp)
|
||||
|
||||
Stream_Write_UINT32(irp->output, FileId);
|
||||
Stream_Write_UINT8(irp->output, Information);
|
||||
|
||||
free(path);
|
||||
|
||||
return irp->Complete(irp);
|
||||
}
|
||||
|
||||
@ -214,10 +217,8 @@ static UINT drive_process_irp_close(DRIVE_DEVICE* drive, IRP* irp)
|
||||
{
|
||||
void* key;
|
||||
DRIVE_FILE* file;
|
||||
|
||||
file = drive_get_file_by_id(drive, irp->FileId);
|
||||
|
||||
key = (void*) (size_t) irp->FileId;
|
||||
key = (void*)(size_t) irp->FileId;
|
||||
|
||||
if (!file)
|
||||
{
|
||||
@ -230,7 +231,6 @@ static UINT drive_process_irp_close(DRIVE_DEVICE* drive, IRP* irp)
|
||||
}
|
||||
|
||||
Stream_Zero(irp->output, 5); /* Padding(5) */
|
||||
|
||||
return irp->Complete(irp);
|
||||
}
|
||||
|
||||
@ -245,10 +245,8 @@ static UINT drive_process_irp_read(DRIVE_DEVICE* drive, IRP* irp)
|
||||
UINT32 Length;
|
||||
UINT64 Offset;
|
||||
BYTE* buffer = NULL;
|
||||
|
||||
Stream_Read_UINT32(irp->input, Length);
|
||||
Stream_Read_UINT64(irp->input, Offset);
|
||||
|
||||
file = drive_get_file_by_id(drive, irp->FileId);
|
||||
|
||||
if (!file)
|
||||
@ -264,6 +262,7 @@ static UINT drive_process_irp_read(DRIVE_DEVICE* drive, IRP* irp)
|
||||
else
|
||||
{
|
||||
buffer = (BYTE*) malloc(Length);
|
||||
|
||||
if (!buffer)
|
||||
{
|
||||
WLog_ERR(TAG, "malloc failed!");
|
||||
@ -288,11 +287,11 @@ static UINT drive_process_irp_read(DRIVE_DEVICE* drive, IRP* irp)
|
||||
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
Stream_Write(irp->output, buffer, Length);
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
|
||||
return irp->Complete(irp);
|
||||
}
|
||||
|
||||
@ -306,11 +305,9 @@ static UINT drive_process_irp_write(DRIVE_DEVICE* drive, IRP* irp)
|
||||
DRIVE_FILE* file;
|
||||
UINT32 Length;
|
||||
UINT64 Offset;
|
||||
|
||||
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);
|
||||
|
||||
if (!file)
|
||||
@ -331,7 +328,6 @@ static UINT drive_process_irp_write(DRIVE_DEVICE* drive, IRP* irp)
|
||||
|
||||
Stream_Write_UINT32(irp->output, Length);
|
||||
Stream_Write_UINT8(irp->output, 0); /* Padding */
|
||||
|
||||
return irp->Complete(irp);
|
||||
}
|
||||
|
||||
@ -344,9 +340,7 @@ 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 (!file)
|
||||
@ -371,18 +365,17 @@ static UINT drive_process_irp_set_information(DRIVE_DEVICE* drive, IRP* irp)
|
||||
DRIVE_FILE* file;
|
||||
UINT32 FsInformationClass;
|
||||
UINT32 Length;
|
||||
|
||||
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);
|
||||
|
||||
if (!file)
|
||||
{
|
||||
irp->IoStatus = STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
else if (!drive_file_set_information(file, FsInformationClass, Length, irp->input))
|
||||
else if (!drive_file_set_information(file, FsInformationClass, Length,
|
||||
irp->input))
|
||||
{
|
||||
irp->IoStatus = STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
@ -391,7 +384,6 @@ static UINT drive_process_irp_set_information(DRIVE_DEVICE* drive, IRP* irp)
|
||||
irp->IoStatus = STATUS_DIRECTORY_NOT_EMPTY;
|
||||
|
||||
Stream_Write_UINT32(irp->output, Length);
|
||||
|
||||
return irp->Complete(irp);
|
||||
}
|
||||
|
||||
@ -400,7 +392,8 @@ static UINT drive_process_irp_set_information(DRIVE_DEVICE* drive, IRP* irp)
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive, IRP* irp)
|
||||
static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive,
|
||||
IRP* irp)
|
||||
{
|
||||
UINT32 FsInformationClass;
|
||||
wStream* output = irp->output;
|
||||
@ -410,9 +403,7 @@ static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive, IRP*
|
||||
char* diskType = {"FAT32"};
|
||||
WCHAR* outStr = NULL;
|
||||
int length;
|
||||
|
||||
Stream_Read_UINT32(irp->input, FsInformationClass);
|
||||
|
||||
STATVFS(drive->path, &svfst);
|
||||
STAT(drive->path, &st);
|
||||
|
||||
@ -422,6 +413,7 @@ static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive, IRP*
|
||||
/* http://msdn.microsoft.com/en-us/library/cc232108.aspx */
|
||||
length = ConvertToUnicode(sys_code_page, 0, volumeLabel, -1, &outStr, 0) * 2;
|
||||
Stream_Write_UINT32(output, 17 + length); /* Length */
|
||||
|
||||
if (!Stream_EnsureRemainingCapacity(output, 17 + length))
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
|
||||
@ -429,7 +421,8 @@ static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive, IRP*
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
}
|
||||
|
||||
Stream_Write_UINT64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_ctime)); /* VolumeCreationTime */
|
||||
Stream_Write_UINT64(output,
|
||||
FILE_TIME_SYSTEM_TO_RDP(st.st_ctime)); /* VolumeCreationTime */
|
||||
#ifdef ANDROID
|
||||
Stream_Write_UINT32(output, svfst.f_fsid.__val[0]); /* VolumeSerialNumber */
|
||||
#else
|
||||
@ -445,11 +438,13 @@ static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive, IRP*
|
||||
case FileFsSizeInformation:
|
||||
/* http://msdn.microsoft.com/en-us/library/cc232107.aspx */
|
||||
Stream_Write_UINT32(output, 24); /* Length */
|
||||
|
||||
if (!Stream_EnsureRemainingCapacity(output, 24))
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
}
|
||||
|
||||
Stream_Write_UINT64(output, svfst.f_blocks); /* TotalAllocationUnits */
|
||||
Stream_Write_UINT64(output, svfst.f_bavail); /* AvailableAllocationUnits */
|
||||
Stream_Write_UINT32(output, 1); /* SectorsPerAllocationUnit */
|
||||
@ -460,19 +455,22 @@ static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive, IRP*
|
||||
/* http://msdn.microsoft.com/en-us/library/cc232101.aspx */
|
||||
length = ConvertToUnicode(sys_code_page, 0, diskType, -1, &outStr, 0) * 2;
|
||||
Stream_Write_UINT32(output, 12 + length); /* Length */
|
||||
|
||||
if (!Stream_EnsureRemainingCapacity(output, 12 + length))
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
}
|
||||
|
||||
Stream_Write_UINT32(output,
|
||||
FILE_CASE_SENSITIVE_SEARCH |
|
||||
FILE_CASE_PRESERVED_NAMES |
|
||||
FILE_UNICODE_ON_DISK); /* FileSystemAttributes */
|
||||
FILE_CASE_SENSITIVE_SEARCH |
|
||||
FILE_CASE_PRESERVED_NAMES |
|
||||
FILE_UNICODE_ON_DISK); /* FileSystemAttributes */
|
||||
#ifdef ANDROID
|
||||
Stream_Write_UINT32(output, 255); /* MaximumComponentNameLength */
|
||||
#else
|
||||
Stream_Write_UINT32(output, svfst.f_namemax/*510*/); /* MaximumComponentNameLength */
|
||||
Stream_Write_UINT32(output,
|
||||
svfst.f_namemax/*510*/); /* MaximumComponentNameLength */
|
||||
#endif
|
||||
Stream_Write_UINT32(output, length); /* FileSystemNameLength */
|
||||
Stream_Write(output, outStr, length); /* FileSystemName (Unicode) */
|
||||
@ -482,13 +480,16 @@ static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive, IRP*
|
||||
case FileFsFullSizeInformation:
|
||||
/* http://msdn.microsoft.com/en-us/library/cc232104.aspx */
|
||||
Stream_Write_UINT32(output, 32); /* Length */
|
||||
|
||||
if (!Stream_EnsureRemainingCapacity(output, 32))
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
}
|
||||
|
||||
Stream_Write_UINT64(output, svfst.f_blocks); /* TotalAllocationUnits */
|
||||
Stream_Write_UINT64(output, svfst.f_bavail); /* CallerAvailableAllocationUnits */
|
||||
Stream_Write_UINT64(output,
|
||||
svfst.f_bavail); /* CallerAvailableAllocationUnits */
|
||||
Stream_Write_UINT64(output, svfst.f_bfree); /* AvailableAllocationUnits */
|
||||
Stream_Write_UINT32(output, 1); /* SectorsPerAllocationUnit */
|
||||
Stream_Write_UINT32(output, svfst.f_bsize); /* BytesPerSector */
|
||||
@ -497,11 +498,13 @@ static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive, IRP*
|
||||
case FileFsDeviceInformation:
|
||||
/* http://msdn.microsoft.com/en-us/library/cc232109.aspx */
|
||||
Stream_Write_UINT32(output, 8); /* Length */
|
||||
|
||||
if (!Stream_EnsureRemainingCapacity(output, 8))
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
}
|
||||
|
||||
Stream_Write_UINT32(output, FILE_DEVICE_DISK); /* DeviceType */
|
||||
Stream_Write_UINT32(output, 0); /* Characteristics */
|
||||
break;
|
||||
@ -526,11 +529,8 @@ static UINT drive_process_irp_silent_ignore(DRIVE_DEVICE* drive, IRP* irp)
|
||||
{
|
||||
UINT32 FsInformationClass;
|
||||
wStream* output = irp->output;
|
||||
|
||||
Stream_Read_UINT32(irp->input, FsInformationClass);
|
||||
|
||||
Stream_Write_UINT32(output, 0); /* Length */
|
||||
|
||||
return irp->Complete(irp);
|
||||
}
|
||||
|
||||
@ -547,14 +547,12 @@ static UINT drive_process_irp_query_directory(DRIVE_DEVICE* drive, IRP* irp)
|
||||
BYTE InitialQuery;
|
||||
UINT32 PathLength;
|
||||
UINT32 FsInformationClass;
|
||||
|
||||
Stream_Read_UINT32(irp->input, FsInformationClass);
|
||||
Stream_Read_UINT8(irp->input, InitialQuery);
|
||||
Stream_Read_UINT32(irp->input, PathLength);
|
||||
Stream_Seek(irp->input, 23); /* Padding */
|
||||
|
||||
status = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(irp->input),
|
||||
PathLength / 2, &path, 0, NULL, NULL);
|
||||
PathLength / 2, &path, 0, NULL, NULL);
|
||||
|
||||
if (status < 1)
|
||||
if (!(path = (char*) calloc(1, 1)))
|
||||
@ -570,13 +568,13 @@ static UINT drive_process_irp_query_directory(DRIVE_DEVICE* drive, IRP* irp)
|
||||
irp->IoStatus = STATUS_UNSUCCESSFUL;
|
||||
Stream_Write_UINT32(irp->output, 0); /* Length */
|
||||
}
|
||||
else if (!drive_file_query_directory(file, FsInformationClass, InitialQuery, path, irp->output))
|
||||
else if (!drive_file_query_directory(file, FsInformationClass, InitialQuery,
|
||||
path, irp->output))
|
||||
{
|
||||
irp->IoStatus = STATUS_NO_MORE_FILES;
|
||||
}
|
||||
|
||||
free(path);
|
||||
|
||||
return irp->Complete(irp);
|
||||
}
|
||||
|
||||
@ -603,6 +601,7 @@ static UINT drive_process_irp_directory_control(DRIVE_DEVICE* drive, IRP* irp)
|
||||
return irp->Complete(irp);
|
||||
break;
|
||||
}
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
@ -625,7 +624,6 @@ static UINT drive_process_irp_device_control(DRIVE_DEVICE* drive, IRP* irp)
|
||||
static UINT drive_process_irp(DRIVE_DEVICE* drive, IRP* irp)
|
||||
{
|
||||
UINT error;
|
||||
|
||||
irp->IoStatus = STATUS_SUCCESS;
|
||||
|
||||
switch (irp->MajorFunction)
|
||||
@ -675,6 +673,7 @@ static UINT drive_process_irp(DRIVE_DEVICE* drive, IRP* irp)
|
||||
error = irp->Complete(irp);
|
||||
break;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -709,13 +708,15 @@ static void* drive_thread_func(void* arg)
|
||||
if (irp)
|
||||
if ((error = drive_process_irp(drive, irp)))
|
||||
{
|
||||
WLog_ERR(TAG, "drive_process_irp failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "drive_process_irp failed with error %u!", error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (error && drive->rdpcontext)
|
||||
setChannelError(drive->rdpcontext, error, "drive_thread_func reported an error");
|
||||
setChannelError(drive->rdpcontext, error,
|
||||
"drive_thread_func reported an error");
|
||||
|
||||
ExitThread((DWORD)error);
|
||||
return NULL;
|
||||
}
|
||||
@ -728,11 +729,13 @@ static void* drive_thread_func(void* arg)
|
||||
static UINT drive_irp_request(DEVICE* device, IRP* irp)
|
||||
{
|
||||
DRIVE_DEVICE* drive = (DRIVE_DEVICE*) device;
|
||||
|
||||
if (!MessageQueue_Post(drive->IrpQueue, NULL, 0, (void*) irp, NULL))
|
||||
{
|
||||
WLog_ERR(TAG, "MessageQueue_Post failed!");
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
@ -744,24 +747,22 @@ static UINT drive_irp_request(DEVICE* device, IRP* irp)
|
||||
static UINT drive_free(DEVICE* device)
|
||||
{
|
||||
DRIVE_DEVICE* drive = (DRIVE_DEVICE*) device;
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
|
||||
if (MessageQueue_PostQuit(drive->IrpQueue, 0) && (WaitForSingleObject(drive->thread, INFINITE) == WAIT_FAILED))
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", error);
|
||||
return error;
|
||||
}
|
||||
if (MessageQueue_PostQuit(drive->IrpQueue, 0)
|
||||
&& (WaitForSingleObject(drive->thread, INFINITE) == WAIT_FAILED))
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %u", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
CloseHandle(drive->thread);
|
||||
|
||||
ListDictionary_Free(drive->files);
|
||||
MessageQueue_Free(drive->IrpQueue);
|
||||
|
||||
Stream_Free(drive->device.data, TRUE);
|
||||
|
||||
free(drive);
|
||||
return error;
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -769,29 +770,32 @@ 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, char* name, char* path)
|
||||
UINT drive_register_drive_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints,
|
||||
char* name, char* path)
|
||||
{
|
||||
int i, length;
|
||||
DRIVE_DEVICE* drive;
|
||||
UINT error;
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
/*
|
||||
* We cannot enter paths like c:\ because : is an arg separator
|
||||
* thus, paths are entered as c+\ and the + is substituted here
|
||||
*/
|
||||
if (path[1] == '+')
|
||||
{
|
||||
if ((path[0]>='a' && path[0]<='z') || (path[0]>='A' && path[0]<='Z'))
|
||||
if ((path[0] >= 'a' && path[0] <= 'z') || (path[0] >= 'A' && path[0] <= 'Z'))
|
||||
{
|
||||
path[1] = ':';
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (name[0] && path[0])
|
||||
{
|
||||
drive = (DRIVE_DEVICE*) calloc(1, sizeof(DRIVE_DEVICE));
|
||||
|
||||
if (!drive)
|
||||
{
|
||||
WLog_ERR(TAG, "calloc failed!");
|
||||
@ -803,9 +807,9 @@ UINT drive_register_drive_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, char*
|
||||
drive->device.IRPRequest = drive_irp_request;
|
||||
drive->device.Free = drive_free;
|
||||
drive->rdpcontext = pEntryPoints->rdpcontext;
|
||||
|
||||
length = (int) strlen(name);
|
||||
drive->device.data = Stream_New(NULL, length + 1);
|
||||
|
||||
if (!drive->device.data)
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_New failed!");
|
||||
@ -817,17 +821,19 @@ UINT drive_register_drive_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, char*
|
||||
Stream_Write_UINT8(drive->device.data, name[i] < 0 ? '_' : name[i]);
|
||||
|
||||
drive->path = path;
|
||||
|
||||
drive->files = ListDictionary_New(TRUE);
|
||||
|
||||
if (!drive->files)
|
||||
{
|
||||
WLog_ERR(TAG, "ListDictionary_New failed!");
|
||||
error = CHANNEL_RC_NO_MEMORY;
|
||||
goto out_error;
|
||||
}
|
||||
ListDictionary_ValueObject(drive->files)->fnObjectFree = (OBJECT_FREE_FN) drive_file_free;
|
||||
|
||||
ListDictionary_ValueObject(drive->files)->fnObjectFree =
|
||||
(OBJECT_FREE_FN) drive_file_free;
|
||||
drive->IrpQueue = MessageQueue_New(NULL);
|
||||
|
||||
if (!drive->IrpQueue)
|
||||
{
|
||||
WLog_ERR(TAG, "ListDictionary_New failed!");
|
||||
@ -835,13 +841,15 @@ UINT drive_register_drive_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, char*
|
||||
goto out_error;
|
||||
}
|
||||
|
||||
if ((error = pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*) drive)))
|
||||
if ((error = pEntryPoints->RegisterDevice(pEntryPoints->devman,
|
||||
(DEVICE*) drive)))
|
||||
{
|
||||
WLog_ERR(TAG, "RegisterDevice failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "RegisterDevice failed with error %u!", error);
|
||||
goto out_error;
|
||||
}
|
||||
|
||||
if (!(drive->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) drive_thread_func, drive, CREATE_SUSPENDED, NULL)))
|
||||
if (!(drive->thread = CreateThread(NULL, 0,
|
||||
(LPTHREAD_START_ROUTINE) drive_thread_func, drive, CREATE_SUSPENDED, NULL)))
|
||||
{
|
||||
WLog_ERR(TAG, "CreateThread failed!");
|
||||
goto out_error;
|
||||
@ -849,6 +857,7 @@ UINT drive_register_drive_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, char*
|
||||
|
||||
ResumeThread(drive->thread);
|
||||
}
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
out_error:
|
||||
MessageQueue_Free(drive->IrpQueue);
|
||||
@ -857,7 +866,7 @@ out_error:
|
||||
return error;
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#ifdef BUILTIN_CHANNELS
|
||||
#define DeviceServiceEntry drive_DeviceServiceEntry
|
||||
#else
|
||||
#define DeviceServiceEntry FREERDP_API DeviceServiceEntry
|
||||
@ -878,21 +887,19 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
char* dev;
|
||||
int len;
|
||||
char devlist[512], buf[512];
|
||||
char *bufdup;
|
||||
char *devdup;
|
||||
char* bufdup;
|
||||
char* devdup;
|
||||
#endif
|
||||
|
||||
drive = (RDPDR_DRIVE*) pEntryPoints->device;
|
||||
|
||||
#ifndef WIN32
|
||||
|
||||
sys_code_page = CP_UTF8;
|
||||
|
||||
if (strcmp(drive->Path, "*") == 0)
|
||||
{
|
||||
/* all drives */
|
||||
|
||||
free(drive->Path);
|
||||
drive->Path = _strdup("/");
|
||||
|
||||
if (!drive->Path)
|
||||
{
|
||||
WLog_ERR(TAG, "_strdup failed!");
|
||||
@ -902,15 +909,14 @@ 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);
|
||||
|
||||
if (home_env)
|
||||
{
|
||||
drive->Path = _strdup(home_env);
|
||||
|
||||
if (!drive->Path)
|
||||
{
|
||||
WLog_ERR(TAG, "_strdup failed!");
|
||||
@ -920,6 +926,7 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
else
|
||||
{
|
||||
drive->Path = _strdup("/");
|
||||
|
||||
if (!drive->Path)
|
||||
{
|
||||
WLog_ERR(TAG, "_strdup failed!");
|
||||
@ -929,27 +936,29 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
}
|
||||
|
||||
error = drive_register_drive_path(pEntryPoints, drive->Name, drive->Path);
|
||||
|
||||
#else
|
||||
sys_code_page = GetACP();
|
||||
|
||||
/* Special case: path[0] == '*' -> export all drives */
|
||||
/* Special case: path[0] == '%' -> user home dir */
|
||||
if (strcmp(drive->Path, "%") == 0)
|
||||
{
|
||||
sprintf_s(buf, sizeof(buf), "%s\\", getenv("USERPROFILE"));
|
||||
GetEnvironmentVariableA("USERPROFILE", buf, sizeof(buf));
|
||||
PathCchAddBackslashA(buf, sizeof(buf));
|
||||
free(drive->Path);
|
||||
drive->Path = _strdup(buf);
|
||||
|
||||
if (!drive->Path)
|
||||
{
|
||||
WLog_ERR(TAG, "_strdup failed!");
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
}
|
||||
|
||||
error = drive_register_drive_path(pEntryPoints, drive->Name, drive->Path);
|
||||
}
|
||||
else if (strcmp(drive->Path, "*") == 0)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Enumerate all devices: */
|
||||
GetLogicalDriveStringsA(sizeof(devlist) - 1, devlist);
|
||||
|
||||
@ -963,11 +972,13 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
buf[len + 1] = dev[0];
|
||||
buf[len + 2] = 0;
|
||||
buf[len + 3] = 0;
|
||||
|
||||
if (!(bufdup = _strdup(buf)))
|
||||
{
|
||||
WLog_ERR(TAG, "_strdup failed!");
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
}
|
||||
|
||||
if (!(devdup = _strdup(dev)))
|
||||
{
|
||||
WLog_ERR(TAG, "_strdup failed!");
|
||||
@ -985,7 +996,7 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
{
|
||||
error = drive_register_drive_path(pEntryPoints, drive->Name, drive->Path);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -25,7 +25,7 @@ include_directories(..)
|
||||
|
||||
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE "DVCPluginEntry")
|
||||
|
||||
if (WITH_DEBUG_SYMBOLS AND MSVC AND NOT STATIC_CHANNELS AND BUILD_SHARED_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()
|
||||
|
||||
|
||||
@ -160,7 +160,7 @@ static UINT echo_plugin_terminated(IWTSPlugin* pPlugin)
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#ifdef BUILTIN_CHANNELS
|
||||
#define DVCPluginEntry echo_DVCPluginEntry
|
||||
#else
|
||||
#define DVCPluginEntry FREERDP_API DVCPluginEntry
|
||||
|
||||
@ -31,9 +31,9 @@
|
||||
|
||||
#define DVC_TAG CHANNELS_TAG("echo.client")
|
||||
#ifdef WITH_DEBUG_DVC
|
||||
#define DEBUG_DVC(fmt, ...) WLog_DBG(DVC_TAG, fmt, ## __VA_ARGS__)
|
||||
#define DEBUG_DVC(...) WLog_DBG(DVC_TAG, __VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG_DVC(fmt, ...) do { } while (0)
|
||||
#define DEBUG_DVC(...) do { } while (0)
|
||||
#endif
|
||||
|
||||
#endif /* __ECHO_MAIN_H */
|
||||
|
||||
@ -67,34 +67,34 @@ static UINT echo_server_open_channel(echo_server* echo)
|
||||
PULONG pSessionId = NULL;
|
||||
|
||||
if (WTSQuerySessionInformationA(echo->context.vcm, WTS_CURRENT_SESSION,
|
||||
WTSSessionId, (LPSTR*) &pSessionId, &BytesReturned) == FALSE)
|
||||
WTSSessionId, (LPSTR*) &pSessionId, &BytesReturned) == FALSE)
|
||||
{
|
||||
WLog_ERR(TAG, "WTSQuerySessionInformationA failed!");
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
echo->SessionId = (DWORD) *pSessionId;
|
||||
echo->SessionId = (DWORD) * pSessionId;
|
||||
WTSFreeMemory(pSessionId);
|
||||
|
||||
hEvent = WTSVirtualChannelManagerGetEventHandle(echo->context.vcm);
|
||||
StartTick = GetTickCount();
|
||||
|
||||
while (echo->echo_channel == NULL)
|
||||
{
|
||||
if (WaitForSingleObject(hEvent, 1000) == WAIT_FAILED)
|
||||
{
|
||||
Error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", Error);
|
||||
return Error;
|
||||
}
|
||||
{
|
||||
Error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", (unsigned long)Error);
|
||||
return Error;
|
||||
}
|
||||
|
||||
echo->echo_channel = WTSVirtualChannelOpenEx(echo->SessionId,
|
||||
"ECHO", WTS_CHANNEL_OPTION_DYNAMIC);
|
||||
"ECHO", WTS_CHANNEL_OPTION_DYNAMIC);
|
||||
|
||||
if (echo->echo_channel)
|
||||
break;
|
||||
|
||||
Error = GetLastError();
|
||||
|
||||
if (Error == ERROR_NOT_FOUND)
|
||||
break;
|
||||
|
||||
@ -121,10 +121,14 @@ static void* echo_server_thread_func(void* arg)
|
||||
if ((error = echo_server_open_channel(echo)))
|
||||
{
|
||||
UINT error2 = 0;
|
||||
WLog_ERR(TAG, "echo_server_open_channel failed with error %lu!", error);
|
||||
IFCALLRET(echo->context.OpenResult, error2, &echo->context, ECHO_SERVER_OPEN_RESULT_NOTSUPPORTED);
|
||||
WLog_ERR(TAG, "echo_server_open_channel failed with error %u!", error);
|
||||
IFCALLRET(echo->context.OpenResult, error2, &echo->context,
|
||||
ECHO_SERVER_OPEN_RESULT_NOTSUPPORTED);
|
||||
|
||||
if (error2)
|
||||
WLog_ERR(TAG, "echo server's OpenResult callback failed with error %lu", error2);
|
||||
WLog_ERR(TAG, "echo server's OpenResult callback failed with error %u",
|
||||
error2);
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -132,7 +136,8 @@ static void* echo_server_thread_func(void* arg)
|
||||
BytesReturned = 0;
|
||||
ChannelEvent = NULL;
|
||||
|
||||
if (WTSVirtualChannelQuery(echo->echo_channel, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE)
|
||||
if (WTSVirtualChannelQuery(echo->echo_channel, WTSVirtualEventHandle, &buffer,
|
||||
&BytesReturned) == TRUE)
|
||||
{
|
||||
if (BytesReturned == sizeof(HANDLE))
|
||||
CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE));
|
||||
@ -153,40 +158,50 @@ static void* echo_server_thread_func(void* arg)
|
||||
if (status == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu", error);
|
||||
WLog_ERR(TAG, "WaitForMultipleObjects failed with error %u", error);
|
||||
break;
|
||||
}
|
||||
|
||||
if (status == WAIT_OBJECT_0)
|
||||
{
|
||||
IFCALLRET(echo->context.OpenResult, error, &echo->context, ECHO_SERVER_OPEN_RESULT_CLOSED);
|
||||
IFCALLRET(echo->context.OpenResult, error, &echo->context,
|
||||
ECHO_SERVER_OPEN_RESULT_CLOSED);
|
||||
|
||||
if (error)
|
||||
WLog_ERR(TAG, "OpenResult failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "OpenResult failed with error %u!", error);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (WTSVirtualChannelQuery(echo->echo_channel, WTSVirtualChannelReady, &buffer, &BytesReturned) == FALSE)
|
||||
if (WTSVirtualChannelQuery(echo->echo_channel, WTSVirtualChannelReady, &buffer,
|
||||
&BytesReturned) == FALSE)
|
||||
{
|
||||
IFCALLRET(echo->context.OpenResult, error, &echo->context, ECHO_SERVER_OPEN_RESULT_ERROR);
|
||||
IFCALLRET(echo->context.OpenResult, error, &echo->context,
|
||||
ECHO_SERVER_OPEN_RESULT_ERROR);
|
||||
|
||||
if (error)
|
||||
WLog_ERR(TAG, "OpenResult failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "OpenResult failed with error %u!", error);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
ready = *((BOOL*) buffer);
|
||||
|
||||
WTSFreeMemory(buffer);
|
||||
|
||||
if (ready)
|
||||
{
|
||||
IFCALLRET(echo->context.OpenResult, error, &echo->context, ECHO_SERVER_OPEN_RESULT_OK);
|
||||
IFCALLRET(echo->context.OpenResult, error, &echo->context,
|
||||
ECHO_SERVER_OPEN_RESULT_OK);
|
||||
|
||||
if (error)
|
||||
WLog_ERR(TAG, "OpenResult failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "OpenResult failed with error %u!", error);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
s = Stream_New(NULL, 4096);
|
||||
|
||||
if (!s)
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_New failed!");
|
||||
@ -197,23 +212,24 @@ static void* echo_server_thread_func(void* arg)
|
||||
|
||||
while (ready)
|
||||
{
|
||||
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
|
||||
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
|
||||
|
||||
if (status == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu", error);
|
||||
break;
|
||||
}
|
||||
if (status == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForMultipleObjects failed with error %u", error);
|
||||
break;
|
||||
}
|
||||
|
||||
if (status == WAIT_OBJECT_0)
|
||||
if (status == WAIT_OBJECT_0)
|
||||
break;
|
||||
|
||||
Stream_SetPosition(s, 0);
|
||||
|
||||
WTSVirtualChannelRead(echo->echo_channel, 0, NULL, 0, &BytesReturned);
|
||||
|
||||
if (BytesReturned < 1)
|
||||
continue;
|
||||
|
||||
if (!Stream_EnsureRemainingCapacity(s, BytesReturned))
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
|
||||
@ -222,26 +238,31 @@ static void* echo_server_thread_func(void* arg)
|
||||
}
|
||||
|
||||
if (WTSVirtualChannelRead(echo->echo_channel, 0, (PCHAR) Stream_Buffer(s),
|
||||
(ULONG) Stream_Capacity(s), &BytesReturned) == FALSE)
|
||||
(ULONG) Stream_Capacity(s), &BytesReturned) == FALSE)
|
||||
{
|
||||
WLog_ERR(TAG, "WTSVirtualChannelRead failed!");
|
||||
error = ERROR_INTERNAL_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
IFCALLRET(echo->context.Response, error, &echo->context, (BYTE *) Stream_Buffer(s), BytesReturned);
|
||||
IFCALLRET(echo->context.Response, error, &echo->context,
|
||||
(BYTE*) Stream_Buffer(s), BytesReturned);
|
||||
|
||||
if (error)
|
||||
{
|
||||
WLog_ERR(TAG, "Response failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "Response failed with error %u!", error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Stream_Free(s, TRUE);
|
||||
WTSVirtualChannelClose(echo->echo_channel);
|
||||
echo->echo_channel = NULL;
|
||||
out:
|
||||
|
||||
if (error && echo->context.rdpcontext)
|
||||
setChannelError(echo->context.rdpcontext, error, "echo_server_thread_func reported an error");
|
||||
setChannelError(echo->context.rdpcontext, error,
|
||||
"echo_server_thread_func reported an error");
|
||||
|
||||
ExitThread((DWORD)error);
|
||||
return NULL;
|
||||
@ -264,7 +285,8 @@ 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,
|
||||
(LPTHREAD_START_ROUTINE) echo_server_thread_func, (void*) echo, 0, NULL)))
|
||||
{
|
||||
WLog_ERR(TAG, "CreateEvent failed!");
|
||||
CloseHandle(echo->stopEvent);
|
||||
@ -272,6 +294,7 @@ static UINT echo_server_open(echo_server_context* context)
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
@ -282,7 +305,7 @@ static UINT echo_server_open(echo_server_context* context)
|
||||
*/
|
||||
static UINT echo_server_close(echo_server_context* context)
|
||||
{
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
echo_server* echo = (echo_server*) context;
|
||||
|
||||
if (echo->thread)
|
||||
@ -290,31 +313,31 @@ static UINT echo_server_close(echo_server_context* context)
|
||||
SetEvent(echo->stopEvent);
|
||||
|
||||
if (WaitForSingleObject(echo->thread, INFINITE) == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", error);
|
||||
return error;
|
||||
}
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %u", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
CloseHandle(echo->thread);
|
||||
CloseHandle(echo->stopEvent);
|
||||
echo->thread = NULL;
|
||||
echo->stopEvent = NULL;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static BOOL echo_server_request(echo_server_context* context, const BYTE* buffer, UINT32 length)
|
||||
static BOOL echo_server_request(echo_server_context* context,
|
||||
const BYTE* buffer, UINT32 length)
|
||||
{
|
||||
echo_server* echo = (echo_server*) context;
|
||||
|
||||
return WTSVirtualChannelWrite(echo->echo_channel, (PCHAR) buffer, length, NULL);
|
||||
}
|
||||
|
||||
echo_server_context* echo_server_context_new(HANDLE vcm)
|
||||
{
|
||||
echo_server* echo;
|
||||
|
||||
echo = (echo_server*) calloc(1, sizeof(echo_server));
|
||||
|
||||
if (echo)
|
||||
@ -333,8 +356,6 @@ echo_server_context* echo_server_context_new(HANDLE vcm)
|
||||
void echo_server_context_free(echo_server_context* context)
|
||||
{
|
||||
echo_server* echo = (echo_server*) context;
|
||||
|
||||
echo_server_close(context);
|
||||
|
||||
free(echo);
|
||||
}
|
||||
|
||||
@ -23,7 +23,7 @@ set(${MODULE_PREFIX}_SRCS
|
||||
encomsp_main.c
|
||||
encomsp_main.h)
|
||||
|
||||
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntry")
|
||||
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntryEx")
|
||||
|
||||
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -40,7 +40,7 @@
|
||||
struct encomsp_plugin
|
||||
{
|
||||
CHANNEL_DEF channelDef;
|
||||
CHANNEL_ENTRY_POINTS_FREERDP channelEntryPoints;
|
||||
CHANNEL_ENTRY_POINTS_FREERDP_EX channelEntryPoints;
|
||||
|
||||
EncomspClientContext* context;
|
||||
|
||||
|
||||
@ -45,7 +45,6 @@ static UINT encomsp_read_header(wStream* s, ENCOMSP_ORDER_HEADER* header)
|
||||
|
||||
Stream_Read_UINT16(s, header->Type); /* Type (2 bytes) */
|
||||
Stream_Read_UINT16(s, header->Length); /* Length (2 bytes) */
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
@ -55,7 +54,6 @@ static int encomsp_write_header(wStream* s, ENCOMSP_ORDER_HEADER* header)
|
||||
{
|
||||
Stream_Write_UINT16(s, header->Type); /* Type (2 bytes) */
|
||||
Stream_Write_UINT16(s, header->Length); /* Length (2 bytes) */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -75,7 +73,6 @@ static int encomsp_read_unicode_string(wStream* s, ENCOMSP_UNICODE_STRING* str)
|
||||
return -1;
|
||||
|
||||
Stream_Read(s, &(str->wString), (str->cchString * 2)); /* String (variable) */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -86,14 +83,13 @@ static int encomsp_read_unicode_string(wStream* s, ENCOMSP_UNICODE_STRING* str)
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT encomsp_recv_change_participant_control_level_pdu(EncomspServerContext* context, wStream* s, ENCOMSP_ORDER_HEADER* header)
|
||||
static UINT encomsp_recv_change_participant_control_level_pdu(
|
||||
EncomspServerContext* context, wStream* s, ENCOMSP_ORDER_HEADER* header)
|
||||
{
|
||||
int beg, end;
|
||||
ENCOMSP_CHANGE_PARTICIPANT_CONTROL_LEVEL_PDU pdu;
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
|
||||
beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE;
|
||||
|
||||
CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER));
|
||||
|
||||
if (Stream_GetRemainingLength(s) < 6)
|
||||
@ -104,7 +100,6 @@ static UINT encomsp_recv_change_participant_control_level_pdu(EncomspServerConte
|
||||
|
||||
Stream_Read_UINT16(s, pdu.Flags); /* Flags (2 bytes) */
|
||||
Stream_Read_UINT32(s, pdu.ParticipantId); /* ParticipantId (4 bytes) */
|
||||
|
||||
end = (int) Stream_GetPosition(s);
|
||||
|
||||
if ((beg + header->Length) < end)
|
||||
@ -125,8 +120,10 @@ static UINT encomsp_recv_change_participant_control_level_pdu(EncomspServerConte
|
||||
}
|
||||
|
||||
IFCALLRET(context->ChangeParticipantControlLevel, error, context, &pdu);
|
||||
|
||||
if (error)
|
||||
WLog_ERR(TAG, "context->ChangeParticipantControlLevel failed with error %lu", error);
|
||||
WLog_ERR(TAG, "context->ChangeParticipantControlLevel failed with error %u",
|
||||
error);
|
||||
|
||||
return error;
|
||||
}
|
||||
@ -136,7 +133,8 @@ static UINT encomsp_recv_change_participant_control_level_pdu(EncomspServerConte
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT encomsp_server_receive_pdu(EncomspServerContext* context, wStream* s)
|
||||
static UINT encomsp_server_receive_pdu(EncomspServerContext* context,
|
||||
wStream* s)
|
||||
{
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
ENCOMSP_ORDER_HEADER header;
|
||||
@ -145,18 +143,22 @@ static UINT encomsp_server_receive_pdu(EncomspServerContext* context, wStream* s
|
||||
{
|
||||
if ((error = encomsp_read_header(s, &header)))
|
||||
{
|
||||
WLog_ERR(TAG, "encomsp_read_header failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "encomsp_read_header failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
WLog_INFO(TAG, "EncomspReceive: Type: %d Length: %d", header.Type, header.Length);
|
||||
WLog_INFO(TAG, "EncomspReceive: Type: %d Length: %d", header.Type,
|
||||
header.Length);
|
||||
|
||||
switch (header.Type)
|
||||
{
|
||||
case ODTYPE_PARTICIPANT_CTRL_CHANGED:
|
||||
if ((error = encomsp_recv_change_participant_control_level_pdu(context, s, &header)))
|
||||
if ((error = encomsp_recv_change_participant_control_level_pdu(context, s,
|
||||
&header)))
|
||||
{
|
||||
WLog_ERR(TAG, "encomsp_recv_change_participant_control_level_pdu failed with error %lu!", error);
|
||||
WLog_ERR(TAG,
|
||||
"encomsp_recv_change_participant_control_level_pdu failed with error %u!",
|
||||
error);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -183,15 +185,14 @@ static void* encomsp_server_thread(void* arg)
|
||||
ENCOMSP_ORDER_HEADER* header;
|
||||
EncomspServerContext* context;
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
DWORD status;
|
||||
|
||||
DWORD status;
|
||||
context = (EncomspServerContext*) arg;
|
||||
|
||||
buffer = NULL;
|
||||
BytesReturned = 0;
|
||||
ChannelEvent = NULL;
|
||||
|
||||
s = Stream_New(NULL, 4096);
|
||||
|
||||
if (!s)
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_New failed!");
|
||||
@ -199,7 +200,8 @@ static void* encomsp_server_thread(void* arg)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE)
|
||||
if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle,
|
||||
&buffer, &BytesReturned) == TRUE)
|
||||
{
|
||||
if (BytesReturned == sizeof(HANDLE))
|
||||
CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE));
|
||||
@ -213,23 +215,23 @@ static void* encomsp_server_thread(void* arg)
|
||||
|
||||
while (1)
|
||||
{
|
||||
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
|
||||
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
|
||||
|
||||
if (status == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu", error);
|
||||
break;
|
||||
}
|
||||
if (status == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForMultipleObjects failed with error %u", error);
|
||||
break;
|
||||
}
|
||||
|
||||
status = WaitForSingleObject(context->priv->StopEvent, 0);
|
||||
status = WaitForSingleObject(context->priv->StopEvent, 0);
|
||||
|
||||
if (status == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", error);
|
||||
break;
|
||||
}
|
||||
if (status == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %u", error);
|
||||
break;
|
||||
}
|
||||
|
||||
if (status == WAIT_OBJECT_0)
|
||||
{
|
||||
@ -237,16 +239,19 @@ static void* encomsp_server_thread(void* arg)
|
||||
}
|
||||
|
||||
WTSVirtualChannelRead(context->priv->ChannelHandle, 0, NULL, 0, &BytesReturned);
|
||||
|
||||
if (BytesReturned < 1)
|
||||
continue;
|
||||
|
||||
if (!Stream_EnsureRemainingCapacity(s, BytesReturned))
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
|
||||
error = CHANNEL_RC_NO_MEMORY;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0,
|
||||
(PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned))
|
||||
(PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned))
|
||||
{
|
||||
WLog_ERR(TAG, "WTSVirtualChannelRead failed!");
|
||||
error = ERROR_INTERNAL_ERROR;
|
||||
@ -261,11 +266,13 @@ static void* encomsp_server_thread(void* arg)
|
||||
{
|
||||
Stream_SealLength(s);
|
||||
Stream_SetPosition(s, 0);
|
||||
|
||||
if ((error = encomsp_server_receive_pdu(context, s)))
|
||||
{
|
||||
WLog_ERR(TAG, "encomsp_server_receive_pdu failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "encomsp_server_receive_pdu failed with error %u!", error);
|
||||
break;
|
||||
}
|
||||
|
||||
Stream_SetPosition(s, 0);
|
||||
}
|
||||
}
|
||||
@ -273,8 +280,10 @@ static void* encomsp_server_thread(void* arg)
|
||||
|
||||
Stream_Free(s, TRUE);
|
||||
out:
|
||||
|
||||
if (error && context->rdpcontext)
|
||||
setChannelError(context->rdpcontext, error, "encomsp_server_thread reported an error");
|
||||
setChannelError(context->rdpcontext, error,
|
||||
"encomsp_server_thread reported an error");
|
||||
|
||||
ExitThread((DWORD)error);
|
||||
return NULL;
|
||||
@ -287,7 +296,8 @@ out:
|
||||
*/
|
||||
static UINT encomsp_server_start(EncomspServerContext* context)
|
||||
{
|
||||
context->priv->ChannelHandle = WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, "encomsp");
|
||||
context->priv->ChannelHandle = WTSVirtualChannelOpen(context->vcm,
|
||||
WTS_CURRENT_SESSION, "encomsp");
|
||||
|
||||
if (!context->priv->ChannelHandle)
|
||||
return CHANNEL_RC_BAD_CHANNEL;
|
||||
@ -299,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)))
|
||||
(LPTHREAD_START_ROUTINE) encomsp_server_thread, (void*) context, 0, NULL)))
|
||||
{
|
||||
WLog_ERR(TAG, "CreateThread failed!");
|
||||
CloseHandle(context->priv->StopEvent);
|
||||
@ -317,33 +327,30 @@ static UINT encomsp_server_start(EncomspServerContext* context)
|
||||
*/
|
||||
static UINT encomsp_server_stop(EncomspServerContext* context)
|
||||
{
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
SetEvent(context->priv->StopEvent);
|
||||
|
||||
if (WaitForSingleObject(context->priv->Thread, INFINITE) == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", error);
|
||||
return error;
|
||||
}
|
||||
CloseHandle(context->priv->Thread);
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %u", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
CloseHandle(context->priv->Thread);
|
||||
return error;
|
||||
}
|
||||
|
||||
EncomspServerContext* encomsp_server_context_new(HANDLE vcm)
|
||||
{
|
||||
EncomspServerContext* context;
|
||||
|
||||
context = (EncomspServerContext*) calloc(1, sizeof(EncomspServerContext));
|
||||
|
||||
if (context)
|
||||
{
|
||||
context->vcm = vcm;
|
||||
|
||||
context->Start = encomsp_server_start;
|
||||
context->Stop = encomsp_server_stop;
|
||||
|
||||
context->priv = (EncomspServerPrivate*) calloc(1, sizeof(EncomspServerPrivate));
|
||||
|
||||
if (!context->priv)
|
||||
|
||||
@ -27,7 +27,7 @@ add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE
|
||||
target_link_libraries(${MODULE_NAME} freerdp winpr)
|
||||
|
||||
|
||||
if (WITH_DEBUG_SYMBOLS AND MSVC AND NOT STATIC_CHANNELS AND BUILD_SHARED_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()
|
||||
|
||||
|
||||
@ -84,14 +84,12 @@ static UINT parallel_process_irp_create(PARALLEL_DEVICE* parallel, IRP* irp)
|
||||
char* path = NULL;
|
||||
int status;
|
||||
UINT32 PathLength;
|
||||
|
||||
Stream_Seek(irp->input, 28);
|
||||
/* DesiredAccess(4) AllocationSize(8), FileAttributes(4) */
|
||||
/* SharedAccess(4) CreateDisposition(4), CreateOptions(4) */
|
||||
Stream_Read_UINT32(irp->input, PathLength);
|
||||
|
||||
status = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(irp->input),
|
||||
PathLength / 2, &path, 0, NULL, NULL);
|
||||
PathLength / 2, &path, 0, NULL, NULL);
|
||||
|
||||
if (status < 1)
|
||||
if (!(path = (char*) calloc(1, 1)))
|
||||
@ -113,15 +111,12 @@ static UINT parallel_process_irp_create(PARALLEL_DEVICE* parallel, IRP* irp)
|
||||
/* all read and write operations should be non-blocking */
|
||||
if (fcntl(parallel->file, F_SETFL, O_NONBLOCK) == -1)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Stream_Write_UINT32(irp->output, parallel->id);
|
||||
Stream_Write_UINT8(irp->output, 0);
|
||||
|
||||
free(path);
|
||||
|
||||
return irp->Complete(irp);
|
||||
}
|
||||
|
||||
@ -134,15 +129,12 @@ static UINT parallel_process_irp_close(PARALLEL_DEVICE* parallel, IRP* irp)
|
||||
{
|
||||
if (close(parallel->file) < 0)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Stream_Zero(irp->output, 5); /* Padding(5) */
|
||||
|
||||
return irp->Complete(irp);
|
||||
}
|
||||
|
||||
@ -157,11 +149,10 @@ static UINT parallel_process_irp_read(PARALLEL_DEVICE* parallel, IRP* irp)
|
||||
UINT64 Offset;
|
||||
ssize_t status;
|
||||
BYTE* buffer = NULL;
|
||||
|
||||
Stream_Read_UINT32(irp->input, Length);
|
||||
Stream_Read_UINT64(irp->input, Offset);
|
||||
|
||||
buffer = (BYTE*) malloc(Length);
|
||||
|
||||
if (!buffer)
|
||||
{
|
||||
WLog_ERR(TAG, "malloc failed!");
|
||||
@ -179,7 +170,6 @@ static UINT parallel_process_irp_read(PARALLEL_DEVICE* parallel, IRP* irp)
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Stream_Write_UINT32(irp->output, Length);
|
||||
@ -192,11 +182,11 @@ static UINT parallel_process_irp_read(PARALLEL_DEVICE* parallel, IRP* irp)
|
||||
free(buffer);
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
}
|
||||
|
||||
Stream_Write(irp->output, buffer, Length);
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
|
||||
return irp->Complete(irp);
|
||||
}
|
||||
|
||||
@ -211,11 +201,9 @@ static UINT parallel_process_irp_write(PARALLEL_DEVICE* parallel, IRP* irp)
|
||||
UINT32 Length;
|
||||
UINT64 Offset;
|
||||
ssize_t status;
|
||||
|
||||
Stream_Read_UINT32(irp->input, Length);
|
||||
Stream_Read_UINT64(irp->input, Offset);
|
||||
Stream_Seek(irp->input, 20); /* Padding */
|
||||
|
||||
len = Length;
|
||||
|
||||
while (len > 0)
|
||||
@ -235,7 +223,6 @@ static UINT parallel_process_irp_write(PARALLEL_DEVICE* parallel, IRP* irp)
|
||||
|
||||
Stream_Write_UINT32(irp->output, Length);
|
||||
Stream_Write_UINT8(irp->output, 0); /* Padding */
|
||||
|
||||
return irp->Complete(irp);
|
||||
}
|
||||
|
||||
@ -244,7 +231,8 @@ static UINT parallel_process_irp_write(PARALLEL_DEVICE* parallel, IRP* irp)
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT parallel_process_irp_device_control(PARALLEL_DEVICE* parallel, IRP* irp)
|
||||
static UINT parallel_process_irp_device_control(PARALLEL_DEVICE* parallel,
|
||||
IRP* irp)
|
||||
{
|
||||
Stream_Write_UINT32(irp->output, 0); /* OutputBufferLength */
|
||||
return irp->Complete(irp);
|
||||
@ -267,6 +255,7 @@ static UINT parallel_process_irp(PARALLEL_DEVICE* parallel, IRP* irp)
|
||||
WLog_ERR(TAG, "parallel_process_irp_create failed with error %d!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case IRP_MJ_CLOSE:
|
||||
@ -275,6 +264,7 @@ static UINT parallel_process_irp(PARALLEL_DEVICE* parallel, IRP* irp)
|
||||
WLog_ERR(TAG, "parallel_process_irp_close failed with error %d!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case IRP_MJ_READ:
|
||||
@ -283,6 +273,7 @@ static UINT parallel_process_irp(PARALLEL_DEVICE* parallel, IRP* irp)
|
||||
WLog_ERR(TAG, "parallel_process_irp_read failed with error %d!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case IRP_MJ_WRITE:
|
||||
@ -291,14 +282,17 @@ static UINT parallel_process_irp(PARALLEL_DEVICE* parallel, IRP* irp)
|
||||
WLog_ERR(TAG, "parallel_process_irp_write failed with error %d!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case IRP_MJ_DEVICE_CONTROL:
|
||||
if ((error = parallel_process_irp_device_control(parallel, irp)))
|
||||
{
|
||||
WLog_ERR(TAG, "parallel_process_irp_device_control failed with error %d!", error);
|
||||
WLog_ERR(TAG, "parallel_process_irp_device_control failed with error %d!",
|
||||
error);
|
||||
return error;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -306,6 +300,7 @@ static UINT parallel_process_irp(PARALLEL_DEVICE* parallel, IRP* irp)
|
||||
return irp->Complete(irp);
|
||||
break;
|
||||
}
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
@ -343,8 +338,10 @@ static void* parallel_thread_func(void* arg)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (error && parallel->rdpcontext)
|
||||
setChannelError(parallel->rdpcontext, error, "parallel_thread_func reported an error");
|
||||
setChannelError(parallel->rdpcontext, error,
|
||||
"parallel_thread_func reported an error");
|
||||
|
||||
ExitThread((DWORD)error);
|
||||
return NULL;
|
||||
@ -364,6 +361,7 @@ static UINT parallel_irp_request(DEVICE* device, IRP* irp)
|
||||
WLog_ERR(TAG, "MessageQueue_Post failed!");
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
@ -374,25 +372,25 @@ static UINT parallel_irp_request(DEVICE* device, IRP* irp)
|
||||
*/
|
||||
static UINT parallel_free(DEVICE* device)
|
||||
{
|
||||
UINT error;
|
||||
UINT error;
|
||||
PARALLEL_DEVICE* parallel = (PARALLEL_DEVICE*) device;
|
||||
|
||||
if (MessageQueue_PostQuit(parallel->queue, 0) && (WaitForSingleObject(parallel->thread, INFINITE) == WAIT_FAILED))
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
|
||||
return error;
|
||||
}
|
||||
CloseHandle(parallel->thread);
|
||||
if (MessageQueue_PostQuit(parallel->queue, 0)
|
||||
&& (WaitForSingleObject(parallel->thread, INFINITE) == WAIT_FAILED))
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
CloseHandle(parallel->thread);
|
||||
Stream_Free(parallel->device.data, TRUE);
|
||||
MessageQueue_Free(parallel->queue);
|
||||
|
||||
free(parallel);
|
||||
return CHANNEL_RC_OK;
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#ifdef BUILTIN_CHANNELS
|
||||
#define DeviceServiceEntry parallel_DeviceServiceEntry
|
||||
#else
|
||||
#define DeviceServiceEntry FREERDP_API DeviceServiceEntry
|
||||
@ -412,7 +410,6 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
RDPDR_PARALLEL* device;
|
||||
PARALLEL_DEVICE* parallel;
|
||||
UINT error;
|
||||
|
||||
device = (RDPDR_PARALLEL*) pEntryPoints->device;
|
||||
name = device->Name;
|
||||
path = device->Path;
|
||||
@ -426,6 +423,7 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
if (name[0] && path[0])
|
||||
{
|
||||
parallel = (PARALLEL_DEVICE*) calloc(1, sizeof(PARALLEL_DEVICE));
|
||||
|
||||
if (!parallel)
|
||||
{
|
||||
WLog_ERR(TAG, "calloc failed!");
|
||||
@ -437,9 +435,9 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
parallel->device.IRPRequest = parallel_irp_request;
|
||||
parallel->device.Free = parallel_free;
|
||||
parallel->rdpcontext = pEntryPoints->rdpcontext;
|
||||
|
||||
length = strlen(name);
|
||||
parallel->device.data = Stream_New(NULL, length + 1);
|
||||
|
||||
if (!parallel->device.data)
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_New failed!");
|
||||
@ -451,8 +449,8 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
Stream_Write_UINT8(parallel->device.data, name[i] < 0 ? '_' : name[i]);
|
||||
|
||||
parallel->path = path;
|
||||
|
||||
parallel->queue = MessageQueue_New(NULL);
|
||||
|
||||
if (!parallel->queue)
|
||||
{
|
||||
WLog_ERR(TAG, "MessageQueue_New failed!");
|
||||
@ -460,14 +458,15 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
if ((error = pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*) parallel)))
|
||||
if ((error = pEntryPoints->RegisterDevice(pEntryPoints->devman,
|
||||
(DEVICE*) parallel)))
|
||||
{
|
||||
WLog_ERR(TAG, "RegisterDevice failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "RegisterDevice failed with error %u!", error);
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
|
||||
if (!(parallel->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) parallel_thread_func, (void*) parallel, 0, NULL)))
|
||||
if (!(parallel->thread = CreateThread(NULL, 0,
|
||||
(LPTHREAD_START_ROUTINE) parallel_thread_func, (void*) parallel, 0, NULL)))
|
||||
{
|
||||
WLog_ERR(TAG, "CreateThread failed!");
|
||||
error = ERROR_INTERNAL_ERROR;
|
||||
|
||||
@ -30,7 +30,7 @@ if(WITH_CUPS)
|
||||
add_definitions(-DWITH_CUPS)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
if(WIN32 AND NOT UWP)
|
||||
set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS}
|
||||
printer_win.c
|
||||
printer_win.h)
|
||||
@ -49,7 +49,7 @@ endif()
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
|
||||
if (WITH_DEBUG_SYMBOLS AND MSVC AND NOT STATIC_CHANNELS AND BUILD_SHARED_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()
|
||||
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
* Copyright 2015 Thincast Technologies GmbH
|
||||
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
|
||||
* Copyright 2016 Armin Novak <armin.novak@gmail.com>
|
||||
* Copyright 2016 David PHAM-VAN <d.phamvan@inuvika.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -45,7 +46,7 @@
|
||||
|
||||
#include "printer_main.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#if defined(_WIN32) && !defined(_UWP)
|
||||
#include "printer_win.h"
|
||||
#endif
|
||||
|
||||
@ -60,7 +61,7 @@ struct _PRINTER_DEVICE
|
||||
|
||||
rdpPrinter* printer;
|
||||
|
||||
PSLIST_HEADER pIrpList;
|
||||
WINPR_PSLIST_HEADER pIrpList;
|
||||
|
||||
HANDLE event;
|
||||
HANDLE stopEvent;
|
||||
@ -79,7 +80,8 @@ static UINT printer_process_irp_create(PRINTER_DEVICE* printer_dev, IRP* irp)
|
||||
rdpPrintJob* printjob = NULL;
|
||||
|
||||
if (printer_dev->printer)
|
||||
printjob = printer_dev->printer->CreatePrintJob(printer_dev->printer, irp->devman->id_sequence++);
|
||||
printjob = printer_dev->printer->CreatePrintJob(printer_dev->printer,
|
||||
irp->devman->id_sequence++);
|
||||
|
||||
if (printjob)
|
||||
{
|
||||
@ -104,7 +106,8 @@ static UINT printer_process_irp_close(PRINTER_DEVICE* printer_dev, IRP* irp)
|
||||
rdpPrintJob* printjob = NULL;
|
||||
|
||||
if (printer_dev->printer)
|
||||
printjob = printer_dev->printer->FindPrintJob(printer_dev->printer, irp->FileId);
|
||||
printjob = printer_dev->printer->FindPrintJob(printer_dev->printer,
|
||||
irp->FileId);
|
||||
|
||||
if (!printjob)
|
||||
{
|
||||
@ -116,7 +119,6 @@ static UINT printer_process_irp_close(PRINTER_DEVICE* printer_dev, IRP* irp)
|
||||
}
|
||||
|
||||
Stream_Zero(irp->output, 4); /* Padding(4) */
|
||||
|
||||
return irp->Complete(irp);
|
||||
}
|
||||
|
||||
@ -131,13 +133,13 @@ static UINT printer_process_irp_write(PRINTER_DEVICE* printer_dev, IRP* irp)
|
||||
UINT64 Offset;
|
||||
rdpPrintJob* printjob = NULL;
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
|
||||
Stream_Read_UINT32(irp->input, Length);
|
||||
Stream_Read_UINT64(irp->input, Offset);
|
||||
Stream_Seek(irp->input, 20); /* Padding */
|
||||
|
||||
if (printer_dev->printer)
|
||||
printjob = printer_dev->printer->FindPrintJob(printer_dev->printer, irp->FileId);
|
||||
printjob = printer_dev->printer->FindPrintJob(printer_dev->printer,
|
||||
irp->FileId);
|
||||
|
||||
if (!printjob)
|
||||
{
|
||||
@ -151,13 +153,12 @@ static UINT printer_process_irp_write(PRINTER_DEVICE* printer_dev, IRP* irp)
|
||||
|
||||
if (error)
|
||||
{
|
||||
WLog_ERR(TAG, "printjob->Write failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "printjob->Write failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
Stream_Write_UINT32(irp->output, Length);
|
||||
Stream_Write_UINT8(irp->output, 0); /* Padding */
|
||||
|
||||
return irp->Complete(irp);
|
||||
}
|
||||
|
||||
@ -166,7 +167,8 @@ static UINT printer_process_irp_write(PRINTER_DEVICE* printer_dev, IRP* irp)
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT printer_process_irp_device_control(PRINTER_DEVICE* printer_dev, IRP* irp)
|
||||
static UINT printer_process_irp_device_control(PRINTER_DEVICE* printer_dev,
|
||||
IRP* irp)
|
||||
{
|
||||
Stream_Write_UINT32(irp->output, 0); /* OutputBufferLength */
|
||||
return irp->Complete(irp);
|
||||
@ -180,38 +182,44 @@ static UINT printer_process_irp_device_control(PRINTER_DEVICE* printer_dev, IRP*
|
||||
static UINT printer_process_irp(PRINTER_DEVICE* printer_dev, IRP* irp)
|
||||
{
|
||||
UINT error;
|
||||
|
||||
switch (irp->MajorFunction)
|
||||
{
|
||||
case IRP_MJ_CREATE:
|
||||
if ((error = printer_process_irp_create(printer_dev, irp)))
|
||||
{
|
||||
WLog_ERR(TAG, "printer_process_irp_create failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "printer_process_irp_create failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case IRP_MJ_CLOSE:
|
||||
if ((error = printer_process_irp_close(printer_dev, irp)))
|
||||
{
|
||||
WLog_ERR(TAG, "printer_process_irp_close failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "printer_process_irp_close failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case IRP_MJ_WRITE:
|
||||
if ((error = printer_process_irp_write(printer_dev, irp)))
|
||||
{
|
||||
WLog_ERR(TAG, "printer_process_irp_write failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "printer_process_irp_write failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case IRP_MJ_DEVICE_CONTROL:
|
||||
if ((error = printer_process_irp_device_control(printer_dev, irp)))
|
||||
{
|
||||
WLog_ERR(TAG, "printer_process_irp_device_control failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "printer_process_irp_device_control failed with error %u!",
|
||||
error);
|
||||
return error;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -219,6 +227,7 @@ static UINT printer_process_irp(PRINTER_DEVICE* printer_dev, IRP* irp)
|
||||
return irp->Complete(irp);
|
||||
break;
|
||||
}
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
@ -232,20 +241,20 @@ static void* printer_thread_func(void* arg)
|
||||
while (1)
|
||||
{
|
||||
DWORD rc = WaitForMultipleObjects(2, obj, FALSE, INFINITE);
|
||||
if (rc == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu!", error);
|
||||
break;
|
||||
}
|
||||
|
||||
if (rc == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForMultipleObjects failed with error %u!", error);
|
||||
break;
|
||||
}
|
||||
|
||||
if (rc == WAIT_OBJECT_0 + 1)
|
||||
break;
|
||||
else if( rc != WAIT_OBJECT_0 )
|
||||
else if (rc != WAIT_OBJECT_0)
|
||||
continue;
|
||||
|
||||
ResetEvent(printer_dev->event);
|
||||
|
||||
irp = (IRP*) InterlockedPopEntrySList(printer_dev->pIrpList);
|
||||
|
||||
if (irp == NULL)
|
||||
@ -261,11 +270,12 @@ static void* printer_thread_func(void* arg)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (error && printer_dev->rdpcontext)
|
||||
setChannelError(printer_dev->rdpcontext, error, "printer_thread_func reported an error");
|
||||
setChannelError(printer_dev->rdpcontext, error,
|
||||
"printer_thread_func reported an error");
|
||||
|
||||
ExitThread((DWORD) error);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -277,9 +287,7 @@ static void* printer_thread_func(void* arg)
|
||||
static UINT printer_irp_request(DEVICE* device, IRP* irp)
|
||||
{
|
||||
PRINTER_DEVICE* printer_dev = (PRINTER_DEVICE*) device;
|
||||
|
||||
InterlockedPushEntrySList(printer_dev->pIrpList, &(irp->ItemEntry));
|
||||
|
||||
SetEvent(printer_dev->event);
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
@ -293,15 +301,15 @@ static UINT printer_free(DEVICE* device)
|
||||
{
|
||||
IRP* irp;
|
||||
PRINTER_DEVICE* printer_dev = (PRINTER_DEVICE*) device;
|
||||
UINT error;
|
||||
|
||||
UINT error;
|
||||
SetEvent(printer_dev->stopEvent);
|
||||
|
||||
if (WaitForSingleObject(printer_dev->thread, INFINITE) == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", error);
|
||||
return error;
|
||||
}
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %u", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
while ((irp = (IRP*) InterlockedPopEntrySList(printer_dev->pIrpList)) != NULL)
|
||||
irp->Discard(irp);
|
||||
@ -309,16 +317,15 @@ static UINT printer_free(DEVICE* device)
|
||||
CloseHandle(printer_dev->thread);
|
||||
CloseHandle(printer_dev->stopEvent);
|
||||
CloseHandle(printer_dev->event);
|
||||
|
||||
_aligned_free(printer_dev->pIrpList);
|
||||
|
||||
if (printer_dev->printer)
|
||||
printer_dev->printer->Free(printer_dev->printer);
|
||||
|
||||
free(printer_dev->device.name);
|
||||
|
||||
Stream_Free(printer_dev->device.data, TRUE);
|
||||
free(printer_dev);
|
||||
return CHANNEL_RC_OK;
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -326,7 +333,8 @@ static UINT printer_free(DEVICE* device)
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, rdpPrinter* printer)
|
||||
UINT printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints,
|
||||
rdpPrinter* printer)
|
||||
{
|
||||
char* port;
|
||||
UINT32 Flags;
|
||||
@ -338,16 +346,17 @@ UINT printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, rdpPrinter* pri
|
||||
BYTE* CachedPrinterConfigData;
|
||||
PRINTER_DEVICE* printer_dev;
|
||||
UINT error;
|
||||
|
||||
port = malloc(10);
|
||||
|
||||
if (!port)
|
||||
{
|
||||
WLog_ERR(TAG, "malloc failed!");
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
}
|
||||
sprintf_s(port, 10, "PRN%d", printer->id);
|
||||
|
||||
sprintf_s(port, 10, "PRN%d", printer->id);
|
||||
printer_dev = (PRINTER_DEVICE*) calloc(1, sizeof(PRINTER_DEVICE));
|
||||
|
||||
if (!printer_dev)
|
||||
{
|
||||
WLog_ERR(TAG, "calloc failed!");
|
||||
@ -360,21 +369,21 @@ UINT printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, rdpPrinter* pri
|
||||
printer_dev->device.IRPRequest = printer_irp_request;
|
||||
printer_dev->device.Free = printer_free;
|
||||
printer_dev->rdpcontext = pEntryPoints->rdpcontext;
|
||||
|
||||
printer_dev->printer = printer;
|
||||
|
||||
CachedFieldsLen = 0;
|
||||
CachedPrinterConfigData = NULL;
|
||||
|
||||
Flags = 0;
|
||||
|
||||
if (printer->is_default)
|
||||
Flags |= RDPDR_PRINTER_ANNOUNCE_FLAG_DEFAULTPRINTER;
|
||||
|
||||
DriverNameLen = ConvertToUnicode(CP_UTF8, 0, printer->driver, -1, &DriverName, 0) * 2;
|
||||
PrintNameLen = ConvertToUnicode(CP_UTF8, 0, printer->name, -1, &PrintName, 0) * 2;
|
||||
DriverNameLen = ConvertToUnicode(CP_UTF8, 0, printer->driver, -1, &DriverName,
|
||||
0) * 2;
|
||||
PrintNameLen = ConvertToUnicode(CP_UTF8, 0, printer->name, -1, &PrintName,
|
||||
0) * 2;
|
||||
printer_dev->device.data = Stream_New(NULL,
|
||||
28 + DriverNameLen + PrintNameLen + CachedFieldsLen);
|
||||
|
||||
printer_dev->device.data = Stream_New(NULL, 28 + DriverNameLen + PrintNameLen + CachedFieldsLen);
|
||||
if (!printer_dev->device.data)
|
||||
{
|
||||
WLog_ERR(TAG, "calloc failed!");
|
||||
@ -397,19 +406,22 @@ UINT printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, rdpPrinter* pri
|
||||
|
||||
if (CachedFieldsLen > 0)
|
||||
{
|
||||
Stream_Write(printer_dev->device.data, CachedPrinterConfigData, CachedFieldsLen);
|
||||
Stream_Write(printer_dev->device.data, CachedPrinterConfigData,
|
||||
CachedFieldsLen);
|
||||
}
|
||||
|
||||
free(DriverName);
|
||||
free(PrintName);
|
||||
printer_dev->pIrpList = (WINPR_PSLIST_HEADER) _aligned_malloc(sizeof(
|
||||
WINPR_SLIST_HEADER), MEMORY_ALLOCATION_ALIGNMENT);
|
||||
|
||||
printer_dev->pIrpList = (PSLIST_HEADER) _aligned_malloc(sizeof(SLIST_HEADER), MEMORY_ALLOCATION_ALIGNMENT);
|
||||
if (!printer_dev->pIrpList)
|
||||
{
|
||||
WLog_ERR(TAG, "_aligned_malloc failed!");
|
||||
error = CHANNEL_RC_NO_MEMORY;
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
InitializeSListHead(printer_dev->pIrpList);
|
||||
|
||||
if (!(printer_dev->event = CreateEvent(NULL, TRUE, FALSE, NULL)))
|
||||
@ -418,6 +430,7 @@ UINT printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, rdpPrinter* pri
|
||||
error = ERROR_INTERNAL_ERROR;
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
if (!(printer_dev->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
|
||||
{
|
||||
WLog_ERR(TAG, "CreateEvent failed!");
|
||||
@ -425,14 +438,15 @@ UINT printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, rdpPrinter* pri
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
if ((error = pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*) printer_dev)))
|
||||
if ((error = pEntryPoints->RegisterDevice(pEntryPoints->devman,
|
||||
(DEVICE*) printer_dev)))
|
||||
{
|
||||
WLog_ERR(TAG, "RegisterDevice failed with error %d!", error);
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
if (!(printer_dev->thread = CreateThread(NULL, 0,
|
||||
(LPTHREAD_START_ROUTINE) printer_thread_func, (void*) printer_dev, 0, NULL)))
|
||||
(LPTHREAD_START_ROUTINE) printer_thread_func, (void*) printer_dev, 0, NULL)))
|
||||
{
|
||||
WLog_ERR(TAG, "CreateThread failed!");
|
||||
error = ERROR_INTERNAL_ERROR;
|
||||
@ -450,7 +464,7 @@ error_out:
|
||||
return error;
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#ifdef BUILTIN_CHANNELS
|
||||
#define DeviceServiceEntry printer_DeviceServiceEntry
|
||||
#else
|
||||
#define DeviceServiceEntry FREERDP_API DeviceServiceEntry
|
||||
@ -471,12 +485,10 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
RDPDR_PRINTER* device;
|
||||
rdpPrinterDriver* driver = NULL;
|
||||
UINT error;
|
||||
|
||||
#ifdef WITH_CUPS
|
||||
driver = printer_cups_get_driver();
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#if defined(_WIN32) && !defined(_UWP)
|
||||
driver = printer_win_get_driver();
|
||||
#endif
|
||||
|
||||
@ -502,7 +514,7 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
|
||||
if ((error = printer_register(pEntryPoints, printer)))
|
||||
{
|
||||
WLog_ERR(TAG, "printer_register failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "printer_register failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
@ -513,12 +525,12 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
for (i = 0; printers[i]; i++)
|
||||
{
|
||||
printer = printers[i];
|
||||
|
||||
if ((error = printer_register(pEntryPoints, printer)))
|
||||
{
|
||||
WLog_ERR(TAG, "printer_register failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "printer_register failed with error %u!", error);
|
||||
free(printers);
|
||||
return error;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -26,9 +26,9 @@ rdpPrinterDriver* printer_win_get_driver(void);
|
||||
|
||||
#define PRINTER_TAG CHANNELS_TAG("printer.client")
|
||||
#ifdef WITH_DEBUG_WINPR
|
||||
#define DEBUG_WINPR(fmt, ...) WLog_DBG(PRINTER_TAG, fmt, ## __VA_ARGS__)
|
||||
#define DEBUG_WINPR(...) WLog_DBG(PRINTER_TAG, __VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG_WINPR(fmt, ...) do { } while (0)
|
||||
#define DEBUG_WINPR(...) do { } while (0)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@ -25,7 +25,7 @@ set(${MODULE_PREFIX}_SRCS
|
||||
rail_orders.c
|
||||
rail_orders.h)
|
||||
|
||||
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntry")
|
||||
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntryEx")
|
||||
|
||||
|
||||
|
||||
|
||||
@ -45,7 +45,7 @@ RailClientContext* rail_get_client_interface(railPlugin* rail)
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT rail_send(railPlugin* rail, wStream* s)
|
||||
static UINT rail_send(railPlugin* rail, wStream* s)
|
||||
{
|
||||
UINT status;
|
||||
|
||||
@ -55,15 +55,15 @@ UINT rail_send(railPlugin* rail, wStream* s)
|
||||
}
|
||||
else
|
||||
{
|
||||
status = rail->channelEntryPoints.pVirtualChannelWrite(rail->OpenHandle,
|
||||
Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s);
|
||||
status = rail->channelEntryPoints.pVirtualChannelWriteEx(rail->InitHandle, rail->OpenHandle,
|
||||
Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s);
|
||||
}
|
||||
|
||||
if (status != CHANNEL_RC_OK)
|
||||
{
|
||||
Stream_Free(s, TRUE);
|
||||
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
|
||||
WTSErrorToString(status), status);
|
||||
WLog_ERR(TAG, "pVirtualChannelWriteEx failed with %s [%08X]",
|
||||
WTSErrorToString(status), status);
|
||||
}
|
||||
|
||||
return status;
|
||||
@ -77,15 +77,15 @@ UINT rail_send(railPlugin* rail, wStream* s)
|
||||
UINT rail_send_channel_data(railPlugin* rail, void* data, size_t length)
|
||||
{
|
||||
wStream* s = NULL;
|
||||
|
||||
s = Stream_New(NULL, length);
|
||||
|
||||
if (!s)
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_New failed!");
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
}
|
||||
Stream_Write(s, data, length);
|
||||
|
||||
Stream_Write(s, data, length);
|
||||
return rail_send(rail, s);
|
||||
}
|
||||
|
||||
@ -98,11 +98,11 @@ UINT rail_send_channel_data(railPlugin* rail, void* data, size_t length)
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT rail_client_execute(RailClientContext* context, RAIL_EXEC_ORDER* exec)
|
||||
static UINT rail_client_execute(RailClientContext* context,
|
||||
RAIL_EXEC_ORDER* exec)
|
||||
{
|
||||
char* exeOrFile;
|
||||
railPlugin* rail = (railPlugin*) context->handle;
|
||||
|
||||
exeOrFile = exec->RemoteApplicationProgram;
|
||||
|
||||
if (!exeOrFile)
|
||||
@ -114,10 +114,12 @@ UINT rail_client_execute(RailClientContext* context, RAIL_EXEC_ORDER* exec)
|
||||
exec->flags |= RAIL_EXEC_FLAG_FILE;
|
||||
}
|
||||
|
||||
rail_string_to_unicode_string(exec->RemoteApplicationProgram, &exec->exeOrFile); /* RemoteApplicationProgram */
|
||||
rail_string_to_unicode_string(exec->RemoteApplicationWorkingDir, &exec->workingDir); /* ShellWorkingDirectory */
|
||||
rail_string_to_unicode_string(exec->RemoteApplicationArguments, &exec->arguments); /* RemoteApplicationCmdLine */
|
||||
|
||||
rail_string_to_unicode_string(exec->RemoteApplicationProgram,
|
||||
&exec->exeOrFile); /* RemoteApplicationProgram */
|
||||
rail_string_to_unicode_string(exec->RemoteApplicationWorkingDir,
|
||||
&exec->workingDir); /* ShellWorkingDirectory */
|
||||
rail_string_to_unicode_string(exec->RemoteApplicationArguments,
|
||||
&exec->arguments); /* RemoteApplicationCmdLine */
|
||||
return rail_send_client_exec_order(rail, exec);
|
||||
}
|
||||
|
||||
@ -126,10 +128,10 @@ UINT rail_client_execute(RailClientContext* context, RAIL_EXEC_ORDER* exec)
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT rail_client_activate(RailClientContext* context, RAIL_ACTIVATE_ORDER* activate)
|
||||
static UINT rail_client_activate(RailClientContext* context,
|
||||
RAIL_ACTIVATE_ORDER* activate)
|
||||
{
|
||||
railPlugin* rail = (railPlugin*) context->handle;
|
||||
|
||||
return rail_send_client_activate_order(rail, activate);
|
||||
}
|
||||
|
||||
@ -138,13 +140,13 @@ UINT rail_client_activate(RailClientContext* context, RAIL_ACTIVATE_ORDER* activ
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT rail_send_client_sysparam(RailClientContext* context, RAIL_SYSPARAM_ORDER* sysparam)
|
||||
static UINT rail_send_client_sysparam(RailClientContext* context,
|
||||
RAIL_SYSPARAM_ORDER* sysparam)
|
||||
{
|
||||
wStream* s;
|
||||
int length;
|
||||
railPlugin* rail = (railPlugin*) context->handle;
|
||||
UINT error;
|
||||
|
||||
length = RAIL_SYSPARAM_ORDER_LENGTH;
|
||||
|
||||
switch (sysparam->param)
|
||||
@ -168,6 +170,7 @@ UINT rail_send_client_sysparam(RailClientContext* context, RAIL_SYSPARAM_ORDER*
|
||||
}
|
||||
|
||||
s = rail_pdu_init(RAIL_SYSPARAM_ORDER_LENGTH + 8);
|
||||
|
||||
if (!s)
|
||||
{
|
||||
WLog_ERR(TAG, "rail_pdu_init failed!");
|
||||
@ -176,14 +179,14 @@ UINT rail_send_client_sysparam(RailClientContext* context, RAIL_SYSPARAM_ORDER*
|
||||
|
||||
if ((error = rail_write_client_sysparam_order(s, sysparam)))
|
||||
{
|
||||
WLog_ERR(TAG, "rail_write_client_sysparam_order failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rail_write_client_sysparam_order failed with error %u!", error);
|
||||
Stream_Free(s, TRUE);
|
||||
return error;
|
||||
}
|
||||
|
||||
if ((error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_SYSPARAM)))
|
||||
{
|
||||
WLog_ERR(TAG, "rail_send_pdu failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rail_send_pdu failed with error %u!", error);
|
||||
}
|
||||
|
||||
Stream_Free(s, TRUE);
|
||||
@ -195,16 +198,18 @@ UINT rail_send_client_sysparam(RailClientContext* context, RAIL_SYSPARAM_ORDER*
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT rail_client_system_param(RailClientContext* context, RAIL_SYSPARAM_ORDER* sysparam)
|
||||
static UINT rail_client_system_param(RailClientContext* context,
|
||||
RAIL_SYSPARAM_ORDER* sysparam)
|
||||
{
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
|
||||
if (sysparam->params & SPI_MASK_SET_HIGH_CONTRAST)
|
||||
{
|
||||
sysparam->param = SPI_SET_HIGH_CONTRAST;
|
||||
|
||||
if ((error = rail_send_client_sysparam(context, sysparam)))
|
||||
{
|
||||
WLog_ERR(TAG, "rail_send_client_sysparam failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rail_send_client_sysparam failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
@ -212,9 +217,10 @@ UINT rail_client_system_param(RailClientContext* context, RAIL_SYSPARAM_ORDER* s
|
||||
if (sysparam->params & SPI_MASK_TASKBAR_POS)
|
||||
{
|
||||
sysparam->param = SPI_TASKBAR_POS;
|
||||
|
||||
if ((error = rail_send_client_sysparam(context, sysparam)))
|
||||
{
|
||||
WLog_ERR(TAG, "rail_send_client_sysparam failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rail_send_client_sysparam failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
@ -222,9 +228,10 @@ UINT rail_client_system_param(RailClientContext* context, RAIL_SYSPARAM_ORDER* s
|
||||
if (sysparam->params & SPI_MASK_SET_MOUSE_BUTTON_SWAP)
|
||||
{
|
||||
sysparam->param = SPI_SET_MOUSE_BUTTON_SWAP;
|
||||
|
||||
if ((error = rail_send_client_sysparam(context, sysparam)))
|
||||
{
|
||||
WLog_ERR(TAG, "rail_send_client_sysparam failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rail_send_client_sysparam failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
@ -232,9 +239,10 @@ UINT rail_client_system_param(RailClientContext* context, RAIL_SYSPARAM_ORDER* s
|
||||
if (sysparam->params & SPI_MASK_SET_KEYBOARD_PREF)
|
||||
{
|
||||
sysparam->param = SPI_SET_KEYBOARD_PREF;
|
||||
|
||||
if ((error = rail_send_client_sysparam(context, sysparam)))
|
||||
{
|
||||
WLog_ERR(TAG, "rail_send_client_sysparam failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rail_send_client_sysparam failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
@ -242,9 +250,10 @@ UINT rail_client_system_param(RailClientContext* context, RAIL_SYSPARAM_ORDER* s
|
||||
if (sysparam->params & SPI_MASK_SET_DRAG_FULL_WINDOWS)
|
||||
{
|
||||
sysparam->param = SPI_SET_DRAG_FULL_WINDOWS;
|
||||
|
||||
if ((error = rail_send_client_sysparam(context, sysparam)))
|
||||
{
|
||||
WLog_ERR(TAG, "rail_send_client_sysparam failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rail_send_client_sysparam failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
@ -252,9 +261,10 @@ UINT rail_client_system_param(RailClientContext* context, RAIL_SYSPARAM_ORDER* s
|
||||
if (sysparam->params & SPI_MASK_SET_KEYBOARD_CUES)
|
||||
{
|
||||
sysparam->param = SPI_SET_KEYBOARD_CUES;
|
||||
|
||||
if ((error = rail_send_client_sysparam(context, sysparam)))
|
||||
{
|
||||
WLog_ERR(TAG, "rail_send_client_sysparam failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rail_send_client_sysparam failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
@ -262,9 +272,10 @@ UINT rail_client_system_param(RailClientContext* context, RAIL_SYSPARAM_ORDER* s
|
||||
if (sysparam->params & SPI_MASK_SET_WORK_AREA)
|
||||
{
|
||||
sysparam->param = SPI_SET_WORK_AREA;
|
||||
|
||||
if ((error = rail_send_client_sysparam(context, sysparam)))
|
||||
{
|
||||
WLog_ERR(TAG, "rail_send_client_sysparam failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rail_send_client_sysparam failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
@ -277,7 +288,8 @@ UINT rail_client_system_param(RailClientContext* context, RAIL_SYSPARAM_ORDER* s
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT rail_server_system_param(RailClientContext* context, RAIL_SYSPARAM_ORDER* sysparam)
|
||||
static UINT rail_server_system_param(RailClientContext* context,
|
||||
RAIL_SYSPARAM_ORDER* sysparam)
|
||||
{
|
||||
return CHANNEL_RC_OK; /* stub - should be registered by client */
|
||||
}
|
||||
@ -287,10 +299,10 @@ UINT rail_server_system_param(RailClientContext* context, RAIL_SYSPARAM_ORDER* s
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT rail_client_system_command(RailClientContext* context, RAIL_SYSCOMMAND_ORDER* syscommand)
|
||||
static UINT rail_client_system_command(RailClientContext* context,
|
||||
RAIL_SYSCOMMAND_ORDER* syscommand)
|
||||
{
|
||||
railPlugin* rail = (railPlugin*) context->handle;
|
||||
|
||||
return rail_send_client_syscommand_order(rail, syscommand);
|
||||
}
|
||||
|
||||
@ -299,10 +311,10 @@ UINT rail_client_system_command(RailClientContext* context, RAIL_SYSCOMMAND_ORDE
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT rail_client_handshake(RailClientContext* context, RAIL_HANDSHAKE_ORDER* handshake)
|
||||
static UINT rail_client_handshake(RailClientContext* context,
|
||||
RAIL_HANDSHAKE_ORDER* handshake)
|
||||
{
|
||||
railPlugin* rail = (railPlugin*) context->handle;
|
||||
|
||||
return rail_send_handshake_order(rail, handshake);
|
||||
}
|
||||
|
||||
@ -311,7 +323,8 @@ UINT rail_client_handshake(RailClientContext* context, RAIL_HANDSHAKE_ORDER* han
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT rail_server_handshake(RailClientContext* context, RAIL_HANDSHAKE_ORDER* handshake)
|
||||
static UINT rail_server_handshake(RailClientContext* context,
|
||||
RAIL_HANDSHAKE_ORDER* handshake)
|
||||
{
|
||||
return CHANNEL_RC_OK; /* stub - should be registered by client */
|
||||
}
|
||||
@ -321,10 +334,10 @@ UINT rail_server_handshake(RailClientContext* context, RAIL_HANDSHAKE_ORDER* han
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT rail_client_handshake_ex(RailClientContext* context, RAIL_HANDSHAKE_EX_ORDER* handshakeEx)
|
||||
static UINT rail_client_handshake_ex(RailClientContext* context,
|
||||
RAIL_HANDSHAKE_EX_ORDER* handshakeEx)
|
||||
{
|
||||
railPlugin* rail = (railPlugin*) context->handle;
|
||||
|
||||
return rail_send_handshake_ex_order(rail, handshakeEx);
|
||||
}
|
||||
|
||||
@ -333,7 +346,8 @@ UINT rail_client_handshake_ex(RailClientContext* context, RAIL_HANDSHAKE_EX_ORDE
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT rail_server_handshake_ex(RailClientContext* context, RAIL_HANDSHAKE_EX_ORDER* handshakeEx)
|
||||
static UINT rail_server_handshake_ex(RailClientContext* context,
|
||||
RAIL_HANDSHAKE_EX_ORDER* handshakeEx)
|
||||
{
|
||||
return CHANNEL_RC_OK; /* stub - should be registered by client */
|
||||
}
|
||||
@ -343,10 +357,10 @@ UINT rail_server_handshake_ex(RailClientContext* context, RAIL_HANDSHAKE_EX_ORDE
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT rail_client_notify_event(RailClientContext* context, RAIL_NOTIFY_EVENT_ORDER* notifyEvent)
|
||||
static UINT rail_client_notify_event(RailClientContext* context,
|
||||
RAIL_NOTIFY_EVENT_ORDER* notifyEvent)
|
||||
{
|
||||
railPlugin* rail = (railPlugin*) context->handle;
|
||||
|
||||
return rail_send_client_notify_event_order(rail, notifyEvent);
|
||||
}
|
||||
|
||||
@ -355,10 +369,10 @@ UINT rail_client_notify_event(RailClientContext* context, RAIL_NOTIFY_EVENT_ORDE
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT rail_client_window_move(RailClientContext* context, RAIL_WINDOW_MOVE_ORDER* windowMove)
|
||||
static UINT rail_client_window_move(RailClientContext* context,
|
||||
RAIL_WINDOW_MOVE_ORDER* windowMove)
|
||||
{
|
||||
railPlugin* rail = (railPlugin*) context->handle;
|
||||
|
||||
return rail_send_client_window_move_order(rail, windowMove);
|
||||
}
|
||||
|
||||
@ -367,7 +381,8 @@ UINT rail_client_window_move(RailClientContext* context, RAIL_WINDOW_MOVE_ORDER*
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT rail_server_local_move_size(RailClientContext* context, RAIL_LOCALMOVESIZE_ORDER* localMoveSize)
|
||||
static UINT rail_server_local_move_size(RailClientContext* context,
|
||||
RAIL_LOCALMOVESIZE_ORDER* localMoveSize)
|
||||
{
|
||||
return CHANNEL_RC_OK; /* stub - should be registered by client */
|
||||
}
|
||||
@ -377,7 +392,8 @@ UINT rail_server_local_move_size(RailClientContext* context, RAIL_LOCALMOVESIZE_
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT rail_server_min_max_info(RailClientContext* context, RAIL_MINMAXINFO_ORDER* minMaxInfo)
|
||||
static UINT rail_server_min_max_info(RailClientContext* context,
|
||||
RAIL_MINMAXINFO_ORDER* minMaxInfo)
|
||||
{
|
||||
return CHANNEL_RC_OK; /* stub - should be registered by client */
|
||||
}
|
||||
@ -387,10 +403,10 @@ UINT rail_server_min_max_info(RailClientContext* context, RAIL_MINMAXINFO_ORDER*
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT rail_client_information(RailClientContext* context, RAIL_CLIENT_STATUS_ORDER* clientStatus)
|
||||
static UINT rail_client_information(RailClientContext* context,
|
||||
RAIL_CLIENT_STATUS_ORDER* clientStatus)
|
||||
{
|
||||
railPlugin* rail = (railPlugin*) context->handle;
|
||||
|
||||
return rail_send_client_status_order(rail, clientStatus);
|
||||
}
|
||||
|
||||
@ -399,10 +415,10 @@ UINT rail_client_information(RailClientContext* context, RAIL_CLIENT_STATUS_ORDE
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT rail_client_system_menu(RailClientContext* context, RAIL_SYSMENU_ORDER* sysmenu)
|
||||
static UINT rail_client_system_menu(RailClientContext* context,
|
||||
RAIL_SYSMENU_ORDER* sysmenu)
|
||||
{
|
||||
railPlugin* rail = (railPlugin*) context->handle;
|
||||
|
||||
return rail_send_client_sysmenu_order(rail, sysmenu);
|
||||
}
|
||||
|
||||
@ -411,10 +427,10 @@ UINT rail_client_system_menu(RailClientContext* context, RAIL_SYSMENU_ORDER* sys
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT rail_client_language_bar_info(RailClientContext* context, RAIL_LANGBAR_INFO_ORDER* langBarInfo)
|
||||
static UINT rail_client_language_bar_info(RailClientContext* context,
|
||||
RAIL_LANGBAR_INFO_ORDER* langBarInfo)
|
||||
{
|
||||
railPlugin* rail = (railPlugin*) context->handle;
|
||||
|
||||
return rail_send_client_langbar_info_order(rail, langBarInfo);
|
||||
}
|
||||
|
||||
@ -423,7 +439,8 @@ UINT rail_client_language_bar_info(RailClientContext* context, RAIL_LANGBAR_INFO
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT rail_server_language_bar_info(RailClientContext* context, RAIL_LANGBAR_INFO_ORDER* langBarInfo)
|
||||
static UINT rail_server_language_bar_info(RailClientContext* context,
|
||||
RAIL_LANGBAR_INFO_ORDER* langBarInfo)
|
||||
{
|
||||
return CHANNEL_RC_OK; /* stub - should be registered by client */
|
||||
}
|
||||
@ -433,7 +450,8 @@ UINT rail_server_language_bar_info(RailClientContext* context, RAIL_LANGBAR_INFO
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT rail_server_execute_result(RailClientContext* context, RAIL_EXEC_RESULT_ORDER* execResult)
|
||||
static UINT rail_server_execute_result(RailClientContext* context,
|
||||
RAIL_EXEC_RESULT_ORDER* execResult)
|
||||
{
|
||||
return CHANNEL_RC_OK; /* stub - should be registered by client */
|
||||
}
|
||||
@ -443,10 +461,10 @@ UINT rail_server_execute_result(RailClientContext* context, RAIL_EXEC_RESULT_ORD
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT rail_client_get_appid_request(RailClientContext* context, RAIL_GET_APPID_REQ_ORDER* getAppIdReq)
|
||||
static UINT rail_client_get_appid_request(RailClientContext* context,
|
||||
RAIL_GET_APPID_REQ_ORDER* getAppIdReq)
|
||||
{
|
||||
railPlugin* rail = (railPlugin*) context->handle;
|
||||
|
||||
return rail_send_client_get_appid_req_order(rail, getAppIdReq);
|
||||
}
|
||||
|
||||
@ -455,111 +473,19 @@ UINT rail_client_get_appid_request(RailClientContext* context, RAIL_GET_APPID_RE
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT rail_server_get_appid_response(RailClientContext* context, RAIL_GET_APPID_RESP_ORDER* getAppIdResp)
|
||||
static UINT rail_server_get_appid_response(RailClientContext* context,
|
||||
RAIL_GET_APPID_RESP_ORDER* getAppIdResp)
|
||||
{
|
||||
return CHANNEL_RC_OK; /* stub - should be registered by client */
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
static wListDictionary* g_InitHandles = NULL;
|
||||
static wListDictionary* g_OpenHandles = NULL;
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT rail_add_init_handle_data(void* pInitHandle, void* pUserData)
|
||||
{
|
||||
if (!g_InitHandles)
|
||||
{
|
||||
g_InitHandles = ListDictionary_New(TRUE);
|
||||
}
|
||||
if (!g_InitHandles)
|
||||
{
|
||||
WLog_ERR(TAG, "ListDictionary_New failed!");
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
}
|
||||
|
||||
if (!ListDictionary_Add(g_InitHandles, pInitHandle, pUserData))
|
||||
{
|
||||
WLog_ERR(TAG, "ListDictionary_Add failed!");
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
void* rail_get_init_handle_data(void* pInitHandle)
|
||||
{
|
||||
void* pUserData = NULL;
|
||||
pUserData = ListDictionary_GetItemValue(g_InitHandles, pInitHandle);
|
||||
return pUserData;
|
||||
}
|
||||
|
||||
void rail_remove_init_handle_data(void* pInitHandle)
|
||||
{
|
||||
ListDictionary_Remove(g_InitHandles, pInitHandle);
|
||||
if (ListDictionary_Count(g_InitHandles) < 1)
|
||||
{
|
||||
ListDictionary_Free(g_InitHandles);
|
||||
g_InitHandles = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT rail_add_open_handle_data(DWORD openHandle, void* pUserData)
|
||||
{
|
||||
void* pOpenHandle = (void*) (size_t) openHandle;
|
||||
|
||||
if (!g_OpenHandles)
|
||||
{
|
||||
g_OpenHandles = ListDictionary_New(TRUE);
|
||||
}
|
||||
if (!g_OpenHandles)
|
||||
{
|
||||
WLog_ERR(TAG, "ListDictionary_New failed!");
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
}
|
||||
|
||||
if (!ListDictionary_Add(g_OpenHandles, pOpenHandle, pUserData))
|
||||
{
|
||||
WLog_ERR(TAG, "ListDictionary_Add failed!");
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
void* rail_get_open_handle_data(DWORD openHandle)
|
||||
{
|
||||
void* pUserData = NULL;
|
||||
void* pOpenHandle = (void*) (size_t) openHandle;
|
||||
pUserData = ListDictionary_GetItemValue(g_OpenHandles, pOpenHandle);
|
||||
return pUserData;
|
||||
}
|
||||
|
||||
void rail_remove_open_handle_data(DWORD openHandle)
|
||||
{
|
||||
void* pOpenHandle = (void*) (size_t) openHandle;
|
||||
ListDictionary_Remove(g_OpenHandles, pOpenHandle);
|
||||
if (ListDictionary_Count(g_OpenHandles) < 1)
|
||||
{
|
||||
ListDictionary_Free(g_OpenHandles);
|
||||
g_OpenHandles = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT rail_virtual_channel_event_data_received(railPlugin* rail,
|
||||
void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
|
||||
void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
|
||||
{
|
||||
wStream* data_in;
|
||||
|
||||
@ -574,6 +500,7 @@ static UINT rail_virtual_channel_event_data_received(railPlugin* rail,
|
||||
Stream_Free(rail->data_in, TRUE);
|
||||
|
||||
rail->data_in = Stream_New(NULL, totalLength);
|
||||
|
||||
if (!rail->data_in)
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_New failed!");
|
||||
@ -582,11 +509,13 @@ static UINT rail_virtual_channel_event_data_received(railPlugin* rail,
|
||||
}
|
||||
|
||||
data_in = rail->data_in;
|
||||
|
||||
if (!Stream_EnsureRemainingCapacity(data_in, (int) dataLength))
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
}
|
||||
|
||||
Stream_Write(data_in, pData, dataLength);
|
||||
|
||||
if (dataFlags & CHANNEL_FLAG_LAST)
|
||||
@ -607,28 +536,31 @@ static UINT rail_virtual_channel_event_data_received(railPlugin* rail,
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
static VOID VCAPITYPE rail_virtual_channel_open_event(DWORD openHandle, UINT event,
|
||||
LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
|
||||
static VOID VCAPITYPE rail_virtual_channel_open_event_ex(LPVOID lpUserParam, DWORD openHandle,
|
||||
UINT event,
|
||||
LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
|
||||
{
|
||||
railPlugin* rail;
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
railPlugin* rail = (railPlugin*) lpUserParam;
|
||||
|
||||
rail = (railPlugin*) rail_get_open_handle_data(openHandle);
|
||||
|
||||
if (!rail)
|
||||
if (!rail || (rail->OpenHandle != openHandle))
|
||||
{
|
||||
WLog_ERR(TAG, "rail_virtual_channel_open_event: error no match");
|
||||
WLog_ERR(TAG, "error no match");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event)
|
||||
{
|
||||
case CHANNEL_EVENT_DATA_RECEIVED:
|
||||
if ((error = rail_virtual_channel_event_data_received(rail, pData, dataLength, totalLength, dataFlags)))
|
||||
WLog_ERR(TAG, "rail_virtual_channel_event_data_received failed with error %lu!", error);
|
||||
if ((error = rail_virtual_channel_event_data_received(rail, pData, dataLength,
|
||||
totalLength, dataFlags)))
|
||||
WLog_ERR(TAG, "rail_virtual_channel_event_data_received failed with error %u!",
|
||||
error);
|
||||
|
||||
break;
|
||||
|
||||
case CHANNEL_EVENT_WRITE_COMPLETE:
|
||||
@ -640,7 +572,8 @@ static VOID VCAPITYPE rail_virtual_channel_open_event(DWORD openHandle, UINT eve
|
||||
}
|
||||
|
||||
if (error && rail->rdpcontext)
|
||||
setChannelError(rail->rdpcontext, error, "rail_virtual_channel_open_event reported an error");
|
||||
setChannelError(rail->rdpcontext, error,
|
||||
"rail_virtual_channel_open_event reported an error");
|
||||
|
||||
return;
|
||||
}
|
||||
@ -667,12 +600,14 @@ static void* rail_virtual_channel_client_thread(void* arg)
|
||||
error = ERROR_INTERNAL_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (message.id == WMQ_QUIT)
|
||||
break;
|
||||
|
||||
if (message.id == 0)
|
||||
{
|
||||
data = (wStream*) message.wParam;
|
||||
|
||||
if ((error = rail_order_recv(rail, data)))
|
||||
{
|
||||
WLog_ERR(TAG, "rail_order_recv failed with error %d!", error);
|
||||
@ -682,7 +617,8 @@ static void* rail_virtual_channel_client_thread(void* arg)
|
||||
}
|
||||
|
||||
if (error && rail->rdpcontext)
|
||||
setChannelError(rail->rdpcontext, error, "rail_virtual_channel_client_thread reported an error");
|
||||
setChannelError(rail->rdpcontext, error,
|
||||
"rail_virtual_channel_client_thread reported an error");
|
||||
|
||||
ExitThread((DWORD)error);
|
||||
return NULL;
|
||||
@ -693,27 +629,22 @@ static void* rail_virtual_channel_client_thread(void* arg)
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT rail_virtual_channel_event_connected(railPlugin* rail, LPVOID pData, UINT32 dataLength)
|
||||
static UINT rail_virtual_channel_event_connected(railPlugin* rail, LPVOID pData,
|
||||
UINT32 dataLength)
|
||||
{
|
||||
UINT status;
|
||||
|
||||
status = rail->channelEntryPoints.pVirtualChannelOpen(rail->InitHandle,
|
||||
&rail->OpenHandle, rail->channelDef.name, rail_virtual_channel_open_event);
|
||||
status = rail->channelEntryPoints.pVirtualChannelOpenEx(rail->InitHandle,
|
||||
&rail->OpenHandle, rail->channelDef.name, rail_virtual_channel_open_event_ex);
|
||||
|
||||
if (status != CHANNEL_RC_OK)
|
||||
{
|
||||
WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08X]",
|
||||
WTSErrorToString(status), status);
|
||||
return status;
|
||||
}
|
||||
|
||||
if ((status = rail_add_open_handle_data(rail->OpenHandle, rail)))
|
||||
{
|
||||
WLog_ERR(TAG, "rail_add_open_handle_data failed with error %lu!", status);
|
||||
WTSErrorToString(status), status);
|
||||
return status;
|
||||
}
|
||||
|
||||
rail->queue = MessageQueue_New(NULL);
|
||||
|
||||
if (!rail->queue)
|
||||
{
|
||||
WLog_ERR(TAG, "MessageQueue_New failed!");
|
||||
@ -721,13 +652,15 @@ 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, NULL)))
|
||||
(LPTHREAD_START_ROUTINE) rail_virtual_channel_client_thread, (void*) rail, 0,
|
||||
NULL)))
|
||||
{
|
||||
WLog_ERR(TAG, "CreateThread failed!");
|
||||
MessageQueue_Free(rail->queue);
|
||||
rail->queue = NULL;
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
@ -739,53 +672,54 @@ static UINT rail_virtual_channel_event_connected(railPlugin* rail, LPVOID pData,
|
||||
static UINT rail_virtual_channel_event_disconnected(railPlugin* rail)
|
||||
{
|
||||
UINT rc;
|
||||
if (MessageQueue_PostQuit(rail->queue, 0) && (WaitForSingleObject(rail->thread, INFINITE) == WAIT_FAILED))
|
||||
{
|
||||
rc = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (MessageQueue_PostQuit(rail->queue, 0)
|
||||
&& (WaitForSingleObject(rail->thread, INFINITE) == WAIT_FAILED))
|
||||
{
|
||||
rc = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %u", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
MessageQueue_Free(rail->queue);
|
||||
CloseHandle(rail->thread);
|
||||
|
||||
rail->queue = NULL;
|
||||
rail->thread = NULL;
|
||||
rc = rail->channelEntryPoints.pVirtualChannelCloseEx(rail->InitHandle, rail->OpenHandle);
|
||||
|
||||
rc = rail->channelEntryPoints.pVirtualChannelClose(rail->OpenHandle);
|
||||
if (CHANNEL_RC_OK != rc)
|
||||
{
|
||||
WLog_ERR(TAG, "pVirtualChannelClose failed with %s [%08X]",
|
||||
WTSErrorToString(rc), rc);
|
||||
return rc;
|
||||
WLog_ERR(TAG, "pVirtualChannelCloseEx failed with %s [%08X]",
|
||||
WTSErrorToString(rc), rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rail->OpenHandle = 0;
|
||||
|
||||
if (rail->data_in)
|
||||
{
|
||||
Stream_Free(rail->data_in, TRUE);
|
||||
rail->data_in = NULL;
|
||||
}
|
||||
|
||||
rail_remove_open_handle_data(rail->OpenHandle);
|
||||
return CHANNEL_RC_OK;
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
static void rail_virtual_channel_event_terminated(railPlugin* rail)
|
||||
{
|
||||
rail_remove_init_handle_data(rail->InitHandle);
|
||||
rail->InitHandle = 0;
|
||||
free(rail);
|
||||
}
|
||||
|
||||
static VOID VCAPITYPE rail_virtual_channel_init_event(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength)
|
||||
static VOID VCAPITYPE rail_virtual_channel_init_event_ex(LPVOID lpUserParam, LPVOID pInitHandle,
|
||||
UINT event, LPVOID pData, UINT dataLength)
|
||||
{
|
||||
railPlugin* rail;
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
railPlugin* rail = (railPlugin*) lpUserParam;
|
||||
|
||||
rail = (railPlugin*) rail_get_init_handle_data(pInitHandle);
|
||||
|
||||
if (!rail)
|
||||
if (!rail || (rail->InitHandle != pInitHandle))
|
||||
{
|
||||
WLog_ERR(TAG, "rail_virtual_channel_init_event: error no match");
|
||||
WLog_ERR(TAG, "error no match");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -793,12 +727,16 @@ static VOID VCAPITYPE rail_virtual_channel_init_event(LPVOID pInitHandle, UINT e
|
||||
{
|
||||
case CHANNEL_EVENT_CONNECTED:
|
||||
if ((error = rail_virtual_channel_event_connected(rail, pData, dataLength)))
|
||||
WLog_ERR(TAG, "rail_virtual_channel_event_connected failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rail_virtual_channel_event_connected failed with error %u!",
|
||||
error);
|
||||
|
||||
break;
|
||||
|
||||
case CHANNEL_EVENT_DISCONNECTED:
|
||||
if ((error = rail_virtual_channel_event_disconnected(rail)))
|
||||
WLog_ERR(TAG, "rail_virtual_channel_event_disconnected failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rail_virtual_channel_event_disconnected failed with error %u!",
|
||||
error);
|
||||
|
||||
break;
|
||||
|
||||
case CHANNEL_EVENT_TERMINATED:
|
||||
@ -806,23 +744,22 @@ static VOID VCAPITYPE rail_virtual_channel_init_event(LPVOID pInitHandle, UINT e
|
||||
break;
|
||||
}
|
||||
|
||||
if(error && rail->rdpcontext)
|
||||
setChannelError(rail->rdpcontext, error, "rail_virtual_channel_init_event reported an error");
|
||||
if (error && rail->rdpcontext)
|
||||
setChannelError(rail->rdpcontext, error, "rail_virtual_channel_init_event_ex reported an error");
|
||||
}
|
||||
|
||||
/* rail is always built-in */
|
||||
#define VirtualChannelEntry rail_VirtualChannelEntry
|
||||
#define VirtualChannelEntryEx rail_VirtualChannelEntryEx
|
||||
|
||||
BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
||||
BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS pEntryPoints, PVOID pInitHandle)
|
||||
{
|
||||
UINT rc;
|
||||
railPlugin* rail;
|
||||
RailClientContext* context;
|
||||
CHANNEL_ENTRY_POINTS_FREERDP* pEntryPointsEx;
|
||||
RailClientContext* context = NULL;
|
||||
CHANNEL_ENTRY_POINTS_FREERDP_EX* pEntryPointsEx;
|
||||
BOOL isFreerdp = FALSE;
|
||||
UINT error;
|
||||
|
||||
rail = (railPlugin*) calloc(1, sizeof(railPlugin));
|
||||
|
||||
if (!rail)
|
||||
{
|
||||
WLog_ERR(TAG, "calloc failed!");
|
||||
@ -830,19 +767,18 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
||||
}
|
||||
|
||||
rail->channelDef.options =
|
||||
CHANNEL_OPTION_INITIALIZED |
|
||||
CHANNEL_OPTION_ENCRYPT_RDP |
|
||||
CHANNEL_OPTION_COMPRESS_RDP |
|
||||
CHANNEL_OPTION_SHOW_PROTOCOL;
|
||||
|
||||
CHANNEL_OPTION_INITIALIZED |
|
||||
CHANNEL_OPTION_ENCRYPT_RDP |
|
||||
CHANNEL_OPTION_COMPRESS_RDP |
|
||||
CHANNEL_OPTION_SHOW_PROTOCOL;
|
||||
strcpy(rail->channelDef.name, "rail");
|
||||
pEntryPointsEx = (CHANNEL_ENTRY_POINTS_FREERDP_EX*) pEntryPoints;
|
||||
|
||||
pEntryPointsEx = (CHANNEL_ENTRY_POINTS_FREERDP*) pEntryPoints;
|
||||
|
||||
if ((pEntryPointsEx->cbSize >= sizeof(CHANNEL_ENTRY_POINTS_FREERDP)) &&
|
||||
(pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER))
|
||||
if ((pEntryPointsEx->cbSize >= sizeof(CHANNEL_ENTRY_POINTS_FREERDP_EX)) &&
|
||||
(pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER))
|
||||
{
|
||||
context = (RailClientContext*) calloc(1, sizeof(RailClientContext));
|
||||
|
||||
if (!context)
|
||||
{
|
||||
WLog_ERR(TAG, "calloc failed!");
|
||||
@ -852,7 +788,6 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
||||
|
||||
context->handle = (void*) rail;
|
||||
context->custom = NULL;
|
||||
|
||||
context->ClientExecute = rail_client_execute;
|
||||
context->ClientActivate = rail_client_activate;
|
||||
context->ClientSystemParam = rail_client_system_param;
|
||||
@ -874,42 +809,34 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
||||
context->ClientGetAppIdRequest = rail_client_get_appid_request;
|
||||
context->ServerGetAppIdResponse = rail_server_get_appid_response;
|
||||
rail->rdpcontext = pEntryPointsEx->context;
|
||||
|
||||
*(pEntryPointsEx->ppInterface) = (void*) context;
|
||||
rail->context = context;
|
||||
isFreerdp = TRUE;
|
||||
}
|
||||
|
||||
WLog_Init();
|
||||
rail->log = WLog_Get("com.freerdp.channels.rail.client");
|
||||
|
||||
WLog_Print(rail->log, WLOG_DEBUG, "VirtualChannelEntry");
|
||||
|
||||
CopyMemory(&(rail->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP));
|
||||
|
||||
rc = rail->channelEntryPoints.pVirtualChannelInit(&rail->InitHandle,
|
||||
&rail->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, rail_virtual_channel_init_event);
|
||||
WLog_Print(rail->log, WLOG_DEBUG, "VirtualChannelEntryEx");
|
||||
CopyMemory(&(rail->channelEntryPoints), pEntryPoints,
|
||||
sizeof(CHANNEL_ENTRY_POINTS_FREERDP_EX));
|
||||
rail->InitHandle = pInitHandle;
|
||||
rc = rail->channelEntryPoints.pVirtualChannelInitEx(rail, context, pInitHandle,
|
||||
&rail->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000,
|
||||
rail_virtual_channel_init_event_ex);
|
||||
|
||||
if (CHANNEL_RC_OK != rc)
|
||||
{
|
||||
WLog_ERR(TAG, "pVirtualChannelInit failed with %s [%08X]",
|
||||
WTSErrorToString(rc), rc);
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
rail->channelEntryPoints.pInterface = *(rail->channelEntryPoints.ppInterface);
|
||||
rail->channelEntryPoints.ppInterface = &(rail->channelEntryPoints.pInterface);
|
||||
|
||||
if ((error = rail_add_init_handle_data(rail->InitHandle, (void*) rail)))
|
||||
{
|
||||
WLog_ERR(TAG, "rail_add_init_handle_data failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "failed with %s [%08X]",
|
||||
WTSErrorToString(rc), rc);
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
rail->channelEntryPoints.pInterface = context;
|
||||
return TRUE;
|
||||
error_out:
|
||||
|
||||
if (isFreerdp)
|
||||
free(rail->context);
|
||||
|
||||
free(rail);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -39,7 +39,7 @@
|
||||
struct rail_plugin
|
||||
{
|
||||
CHANNEL_DEF channelDef;
|
||||
CHANNEL_ENTRY_POINTS_FREERDP channelEntryPoints;
|
||||
CHANNEL_ENTRY_POINTS_FREERDP_EX channelEntryPoints;
|
||||
|
||||
RailClientContext* context;
|
||||
|
||||
|
||||
@ -268,17 +268,17 @@ UINT rail_write_client_exec_order(wStream* s, RAIL_EXEC_ORDER* exec)
|
||||
Stream_Write_UINT16(s, exec->arguments.length); /* argumentsLength (2 bytes) */
|
||||
if ((error = rail_write_unicode_string_value(s, &exec->exeOrFile)))
|
||||
{
|
||||
WLog_ERR(TAG, "rail_write_unicode_string_value failed with error %lu", error);
|
||||
WLog_ERR(TAG, "rail_write_unicode_string_value failed with error %u", error);
|
||||
return error;
|
||||
}
|
||||
if ((error = rail_write_unicode_string_value(s, &exec->workingDir)))
|
||||
{
|
||||
WLog_ERR(TAG, "rail_write_unicode_string_value failed with error %lu", error);
|
||||
WLog_ERR(TAG, "rail_write_unicode_string_value failed with error %u", error);
|
||||
return error;
|
||||
}
|
||||
if ((error = rail_write_unicode_string_value(s, &exec->arguments)))
|
||||
{
|
||||
WLog_ERR(TAG, "rail_write_unicode_string_value failed with error %lu", error);
|
||||
WLog_ERR(TAG, "rail_write_unicode_string_value failed with error %u", error);
|
||||
return error;
|
||||
}
|
||||
return error;
|
||||
@ -408,7 +408,7 @@ UINT rail_recv_handshake_order(railPlugin* rail, RAIL_HANDSHAKE_ORDER* handshake
|
||||
|
||||
if ((error = rail_read_handshake_order(s, handshake)))
|
||||
{
|
||||
WLog_ERR(TAG, "rail_read_handshake_order failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rail_read_handshake_order failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -416,7 +416,7 @@ UINT rail_recv_handshake_order(railPlugin* rail, RAIL_HANDSHAKE_ORDER* handshake
|
||||
{
|
||||
IFCALLRET(context->ServerHandshake, error, context, handshake);
|
||||
if (error)
|
||||
WLog_ERR(TAG, "context.ServerHandshake failed with error %lu", error);
|
||||
WLog_ERR(TAG, "context.ServerHandshake failed with error %u", error);
|
||||
}
|
||||
|
||||
return error;
|
||||
@ -434,7 +434,7 @@ UINT rail_recv_handshake_ex_order(railPlugin* rail, RAIL_HANDSHAKE_EX_ORDER* han
|
||||
|
||||
if ((error = rail_read_handshake_ex_order(s, handshakeEx)))
|
||||
{
|
||||
WLog_ERR(TAG, "rail_read_handshake_ex_order failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rail_read_handshake_ex_order failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -442,7 +442,7 @@ UINT rail_recv_handshake_ex_order(railPlugin* rail, RAIL_HANDSHAKE_EX_ORDER* han
|
||||
{
|
||||
IFCALLRET(context->ClientHandshakeEx, error, context, handshakeEx);
|
||||
if (error)
|
||||
WLog_ERR(TAG, "context.ClientHandshakeEx failed with error %lu", error);
|
||||
WLog_ERR(TAG, "context.ClientHandshakeEx failed with error %u", error);
|
||||
|
||||
}
|
||||
|
||||
@ -463,7 +463,7 @@ UINT rail_recv_exec_result_order(railPlugin* rail, RAIL_EXEC_RESULT_ORDER* execR
|
||||
|
||||
if ((error = rail_read_server_exec_result_order(s, execResult)))
|
||||
{
|
||||
WLog_ERR(TAG, "rail_read_server_exec_result_order failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rail_read_server_exec_result_order failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -471,7 +471,7 @@ UINT rail_recv_exec_result_order(railPlugin* rail, RAIL_EXEC_RESULT_ORDER* execR
|
||||
{
|
||||
IFCALLRET(context->ServerExecuteResult, error, context, execResult);
|
||||
if (error)
|
||||
WLog_ERR(TAG, "context.ServerExecuteResult failed with error %lu", error);
|
||||
WLog_ERR(TAG, "context.ServerExecuteResult failed with error %u", error);
|
||||
|
||||
}
|
||||
|
||||
@ -490,7 +490,7 @@ UINT rail_recv_server_sysparam_order(railPlugin* rail, RAIL_SYSPARAM_ORDER* sysp
|
||||
|
||||
if ((error = rail_read_server_sysparam_order(s, sysparam)))
|
||||
{
|
||||
WLog_ERR(TAG, "rail_read_server_sysparam_order failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rail_read_server_sysparam_order failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -498,7 +498,7 @@ UINT rail_recv_server_sysparam_order(railPlugin* rail, RAIL_SYSPARAM_ORDER* sysp
|
||||
{
|
||||
IFCALLRET(context->ServerSystemParam, error, context, sysparam);
|
||||
if (error)
|
||||
WLog_ERR(TAG, "context.ServerSystemParam failed with error %lu", error);
|
||||
WLog_ERR(TAG, "context.ServerSystemParam failed with error %u", error);
|
||||
}
|
||||
|
||||
return error;
|
||||
@ -516,7 +516,7 @@ UINT rail_recv_server_minmaxinfo_order(railPlugin* rail, RAIL_MINMAXINFO_ORDER*
|
||||
|
||||
if ((error = rail_read_server_minmaxinfo_order(s, minMaxInfo)))
|
||||
{
|
||||
WLog_ERR(TAG, "rail_read_server_minmaxinfo_order failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rail_read_server_minmaxinfo_order failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -524,7 +524,7 @@ UINT rail_recv_server_minmaxinfo_order(railPlugin* rail, RAIL_MINMAXINFO_ORDER*
|
||||
{
|
||||
IFCALLRET(context->ServerMinMaxInfo, error, context, minMaxInfo);
|
||||
if (error)
|
||||
WLog_ERR(TAG, "context.ServerMinMaxInfo failed with error %lu", error);
|
||||
WLog_ERR(TAG, "context.ServerMinMaxInfo failed with error %u", error);
|
||||
}
|
||||
|
||||
return error;
|
||||
@ -542,7 +542,7 @@ UINT rail_recv_server_localmovesize_order(railPlugin* rail, RAIL_LOCALMOVESIZE_O
|
||||
|
||||
if ((error = rail_read_server_localmovesize_order(s, localMoveSize)))
|
||||
{
|
||||
WLog_ERR(TAG, "rail_read_server_localmovesize_order failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rail_read_server_localmovesize_order failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -550,7 +550,7 @@ UINT rail_recv_server_localmovesize_order(railPlugin* rail, RAIL_LOCALMOVESIZE_O
|
||||
{
|
||||
IFCALLRET(context->ServerLocalMoveSize, error, context, localMoveSize);
|
||||
if (error)
|
||||
WLog_ERR(TAG, "context.ServerLocalMoveSize failed with error %lu", error);
|
||||
WLog_ERR(TAG, "context.ServerLocalMoveSize failed with error %u", error);
|
||||
}
|
||||
|
||||
return error;
|
||||
@ -568,7 +568,7 @@ UINT rail_recv_server_get_appid_resp_order(railPlugin* rail, RAIL_GET_APPID_RESP
|
||||
|
||||
if ((error = rail_read_server_get_appid_resp_order(s, getAppIdResp)))
|
||||
{
|
||||
WLog_ERR(TAG, "rail_read_server_get_appid_resp_order failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rail_read_server_get_appid_resp_order failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -576,7 +576,7 @@ UINT rail_recv_server_get_appid_resp_order(railPlugin* rail, RAIL_GET_APPID_RESP
|
||||
{
|
||||
IFCALLRET(context->ServerGetAppIdResponse, error, context, getAppIdResp);
|
||||
if (error)
|
||||
WLog_ERR(TAG, "context.ServerGetAppIdResponse failed with error %lu", error);
|
||||
WLog_ERR(TAG, "context.ServerGetAppIdResponse failed with error %u", error);
|
||||
}
|
||||
|
||||
return error;
|
||||
@ -594,7 +594,7 @@ UINT rail_recv_langbar_info_order(railPlugin* rail, RAIL_LANGBAR_INFO_ORDER* lan
|
||||
|
||||
if ((error = rail_read_langbar_info_order(s, langBarInfo)))
|
||||
{
|
||||
WLog_ERR(TAG, "rail_read_langbar_info_order failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rail_read_langbar_info_order failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -602,7 +602,7 @@ UINT rail_recv_langbar_info_order(railPlugin* rail, RAIL_LANGBAR_INFO_ORDER* lan
|
||||
{
|
||||
IFCALLRET(context->ServerLanguageBarInfo, error, context, langBarInfo);
|
||||
if (error)
|
||||
WLog_ERR(TAG, "context.ServerLanguageBarInfo failed with error %lu", error);
|
||||
WLog_ERR(TAG, "context.ServerLanguageBarInfo failed with error %u", error);
|
||||
}
|
||||
|
||||
return error;
|
||||
@ -621,12 +621,12 @@ UINT rail_order_recv(railPlugin* rail, wStream* s)
|
||||
|
||||
if ((error = rail_read_pdu_header(s, &orderType, &orderLength)))
|
||||
{
|
||||
WLog_ERR(TAG, "rail_read_pdu_header failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rail_read_pdu_header failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
WLog_Print(rail->log, WLOG_DEBUG, "Received %s PDU, length:%lu",
|
||||
RAIL_ORDER_TYPE_STRINGS[((orderType & 0xF0) >> 3) + (orderType & 0x0F)], orderLength);
|
||||
WLog_Print(rail->log, WLOG_DEBUG, "Received %s PDU, length:%u",
|
||||
RAIL_ORDER_TYPE_STRINGS[((orderType & 0xF0) >> 3) + (orderType & 0x0F)], (unsigned)orderLength);
|
||||
|
||||
switch (orderType)
|
||||
{
|
||||
@ -780,12 +780,12 @@ UINT rail_send_client_exec_order(railPlugin* rail, RAIL_EXEC_ORDER* exec)
|
||||
|
||||
if ((error = rail_write_client_exec_order(s, exec)))
|
||||
{
|
||||
WLog_ERR(TAG, "rail_write_client_exec_order failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rail_write_client_exec_order failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
if ((error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_EXEC)))
|
||||
{
|
||||
WLog_ERR(TAG, "rail_send_pdu failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rail_send_pdu failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
Stream_Free(s, TRUE);
|
||||
@ -834,13 +834,13 @@ UINT rail_send_client_sysparam_order(railPlugin* rail, RAIL_SYSPARAM_ORDER* sysp
|
||||
|
||||
if ((error = rail_write_client_sysparam_order(s, sysparam)))
|
||||
{
|
||||
WLog_ERR(TAG, "rail_write_client_sysparam_order failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rail_write_client_sysparam_order failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
if ((error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_SYSPARAM)))
|
||||
{
|
||||
WLog_ERR(TAG, "rail_send_pdu failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rail_send_pdu failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -862,7 +862,7 @@ UINT rail_send_client_sysparams_order(railPlugin* rail, RAIL_SYSPARAM_ORDER* sys
|
||||
sysparam->param = SPI_SET_HIGH_CONTRAST;
|
||||
if ((error = rail_send_client_sysparam_order(rail, sysparam)))
|
||||
{
|
||||
WLog_ERR(TAG, "rail_send_client_sysparam_order failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rail_send_client_sysparam_order failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
@ -872,7 +872,7 @@ UINT rail_send_client_sysparams_order(railPlugin* rail, RAIL_SYSPARAM_ORDER* sys
|
||||
sysparam->param = SPI_TASKBAR_POS;
|
||||
if ((error = rail_send_client_sysparam_order(rail, sysparam)))
|
||||
{
|
||||
WLog_ERR(TAG, "rail_send_client_sysparam_order failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rail_send_client_sysparam_order failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
@ -882,7 +882,7 @@ UINT rail_send_client_sysparams_order(railPlugin* rail, RAIL_SYSPARAM_ORDER* sys
|
||||
sysparam->param = SPI_SET_MOUSE_BUTTON_SWAP;
|
||||
if ((error = rail_send_client_sysparam_order(rail, sysparam)))
|
||||
{
|
||||
WLog_ERR(TAG, "rail_send_client_sysparam_order failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rail_send_client_sysparam_order failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
@ -892,7 +892,7 @@ UINT rail_send_client_sysparams_order(railPlugin* rail, RAIL_SYSPARAM_ORDER* sys
|
||||
sysparam->param = SPI_SET_KEYBOARD_PREF;
|
||||
if ((error = rail_send_client_sysparam_order(rail, sysparam)))
|
||||
{
|
||||
WLog_ERR(TAG, "rail_send_client_sysparam_order failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rail_send_client_sysparam_order failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
@ -902,7 +902,7 @@ UINT rail_send_client_sysparams_order(railPlugin* rail, RAIL_SYSPARAM_ORDER* sys
|
||||
sysparam->param = SPI_SET_DRAG_FULL_WINDOWS;
|
||||
if ((error = rail_send_client_sysparam_order(rail, sysparam)))
|
||||
{
|
||||
WLog_ERR(TAG, "rail_send_client_sysparam_order failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rail_send_client_sysparam_order failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
@ -912,7 +912,7 @@ UINT rail_send_client_sysparams_order(railPlugin* rail, RAIL_SYSPARAM_ORDER* sys
|
||||
sysparam->param = SPI_SET_KEYBOARD_CUES;
|
||||
if ((error = rail_send_client_sysparam_order(rail, sysparam)))
|
||||
{
|
||||
WLog_ERR(TAG, "rail_send_client_sysparam_order failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rail_send_client_sysparam_order failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
@ -922,7 +922,7 @@ UINT rail_send_client_sysparams_order(railPlugin* rail, RAIL_SYSPARAM_ORDER* sys
|
||||
sysparam->param = SPI_SET_WORK_AREA;
|
||||
if ((error = rail_send_client_sysparam_order(rail, sysparam)))
|
||||
{
|
||||
WLog_ERR(TAG, "rail_send_client_sysparam_order failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rail_send_client_sysparam_order failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,7 +29,7 @@ set(${MODULE_PREFIX}_SRCS
|
||||
rdpdr_capabilities.c
|
||||
rdpdr_capabilities.h)
|
||||
|
||||
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntry")
|
||||
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntryEx")
|
||||
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -49,7 +49,7 @@ typedef struct rdpdr_plugin rdpdrPlugin;
|
||||
struct rdpdr_plugin
|
||||
{
|
||||
CHANNEL_DEF channelDef;
|
||||
CHANNEL_ENTRY_POINTS_FREERDP channelEntryPoints;
|
||||
CHANNEL_ENTRY_POINTS_FREERDP_EX channelEntryPoints;
|
||||
|
||||
HANDLE thread;
|
||||
wStream* data_in;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -31,7 +31,7 @@ add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE
|
||||
target_link_libraries(${MODULE_NAME} winpr freerdp)
|
||||
|
||||
|
||||
if (WITH_DEBUG_SYMBOLS AND MSVC AND NOT STATIC_CHANNELS AND BUILD_SHARED_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()
|
||||
|
||||
|
||||
@ -138,16 +138,16 @@ UINT rdpei_add_frame(RdpeiClientContext* context)
|
||||
int i;
|
||||
RDPINPUT_CONTACT_DATA* contact;
|
||||
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) context->handle;
|
||||
|
||||
rdpei->frame.contactCount = 0;
|
||||
|
||||
for (i = 0; i < rdpei->maxTouchContacts; i++)
|
||||
{
|
||||
contact = (RDPINPUT_CONTACT_DATA*) &(rdpei->contactPoints[i].data);
|
||||
contact = (RDPINPUT_CONTACT_DATA*) & (rdpei->contactPoints[i].data);
|
||||
|
||||
if (rdpei->contactPoints[i].dirty)
|
||||
{
|
||||
CopyMemory(&(rdpei->contacts[rdpei->frame.contactCount]), contact, sizeof(RDPINPUT_CONTACT_DATA));
|
||||
CopyMemory(&(rdpei->contacts[rdpei->frame.contactCount]), contact,
|
||||
sizeof(RDPINPUT_CONTACT_DATA));
|
||||
rdpei->contactPoints[i].dirty = FALSE;
|
||||
rdpei->frame.contactCount++;
|
||||
}
|
||||
@ -160,7 +160,8 @@ UINT rdpei_add_frame(RdpeiClientContext* context)
|
||||
contact->contactFlags |= CONTACT_FLAG_INCONTACT;
|
||||
}
|
||||
|
||||
CopyMemory(&(rdpei->contacts[rdpei->frame.contactCount]), contact, sizeof(RDPINPUT_CONTACT_DATA));
|
||||
CopyMemory(&(rdpei->contacts[rdpei->frame.contactCount]), contact,
|
||||
sizeof(RDPINPUT_CONTACT_DATA));
|
||||
rdpei->frame.contactCount++;
|
||||
}
|
||||
}
|
||||
@ -182,7 +183,6 @@ static void* rdpei_schedule_thread(void* arg)
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
if (!context)
|
||||
{
|
||||
error = ERROR_INVALID_PARAMETER;
|
||||
@ -193,12 +193,12 @@ static void* rdpei_schedule_thread(void* arg)
|
||||
{
|
||||
status = WaitForMultipleObjects(2, hdl, FALSE, 20);
|
||||
|
||||
if (status == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu!", error);
|
||||
break;
|
||||
}
|
||||
if (status == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForMultipleObjects failed with error %u!", error);
|
||||
break;
|
||||
}
|
||||
|
||||
if (status == WAIT_OBJECT_0 + 1)
|
||||
break;
|
||||
@ -207,7 +207,7 @@ static void* rdpei_schedule_thread(void* arg)
|
||||
|
||||
if ((error = rdpei_add_frame(context)))
|
||||
{
|
||||
WLog_ERR(TAG, "rdpei_add_frame failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rdpei_add_frame failed with error %u!", error);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -215,7 +215,7 @@ static void* rdpei_schedule_thread(void* arg)
|
||||
{
|
||||
if ((error = rdpei_send_frame(context)))
|
||||
{
|
||||
WLog_ERR(TAG, "rdpei_send_frame failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rdpei_send_frame failed with error %u!", error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -227,11 +227,12 @@ static void* rdpei_schedule_thread(void* arg)
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
if (error && rdpei->rdpcontext)
|
||||
setChannelError(rdpei->rdpcontext, error, "rdpei_schedule_thread reported an error");
|
||||
setChannelError(rdpei->rdpcontext, error,
|
||||
"rdpei_schedule_thread reported an error");
|
||||
|
||||
ExitThread(0);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -240,22 +241,20 @@ out:
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT rdpei_send_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s, UINT16 eventId, UINT32 pduLength)
|
||||
UINT rdpei_send_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s,
|
||||
UINT16 eventId, UINT32 pduLength)
|
||||
{
|
||||
UINT status;
|
||||
|
||||
Stream_SetPosition(s, 0);
|
||||
Stream_Write_UINT16(s, eventId); /* eventId (2 bytes) */
|
||||
Stream_Write_UINT32(s, pduLength); /* pduLength (4 bytes) */
|
||||
Stream_SetPosition(s, Stream_Length(s));
|
||||
|
||||
status = callback->channel->Write(callback->channel, (UINT32) Stream_Length(s), Stream_Buffer(s), NULL);
|
||||
|
||||
status = callback->channel->Write(callback->channel, (UINT32) Stream_Length(s),
|
||||
Stream_Buffer(s), NULL);
|
||||
#ifdef WITH_DEBUG_RDPEI
|
||||
WLog_DBG(TAG, "rdpei_send_pdu: eventId: %d (%s) length: %d status: %d",
|
||||
eventId, RDPEI_EVENTID_STRINGS[eventId], pduLength, status);
|
||||
eventId, RDPEI_EVENTID_STRINGS[eventId], pduLength, status);
|
||||
#endif
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -271,29 +270,26 @@ UINT rdpei_send_cs_ready_pdu(RDPEI_CHANNEL_CALLBACK* callback)
|
||||
UINT32 flags;
|
||||
UINT32 pduLength;
|
||||
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) callback->plugin;
|
||||
|
||||
flags = 0;
|
||||
flags |= READY_FLAGS_SHOW_TOUCH_VISUALS;
|
||||
//flags |= READY_FLAGS_DISABLE_TIMESTAMP_INJECTION;
|
||||
|
||||
pduLength = RDPINPUT_HEADER_LENGTH + 10;
|
||||
s = Stream_New(NULL, pduLength);
|
||||
|
||||
if (!s)
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_New failed!");
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
}
|
||||
Stream_Seek(s, RDPINPUT_HEADER_LENGTH);
|
||||
|
||||
Stream_Seek(s, RDPINPUT_HEADER_LENGTH);
|
||||
Stream_Write_UINT32(s, flags); /* flags (4 bytes) */
|
||||
Stream_Write_UINT32(s, RDPINPUT_PROTOCOL_V10); /* protocolVersion (4 bytes) */
|
||||
Stream_Write_UINT16(s, rdpei->maxTouchContacts); /* maxTouchContacts (2 bytes) */
|
||||
|
||||
Stream_Write_UINT16(s,
|
||||
rdpei->maxTouchContacts); /* maxTouchContacts (2 bytes) */
|
||||
Stream_SealLength(s);
|
||||
|
||||
status = rdpei_send_pdu(callback, s, EVENTID_CS_READY, pduLength);
|
||||
Stream_Free(s, TRUE);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -328,19 +324,18 @@ UINT rdpei_write_touch_frame(wStream* s, RDPINPUT_TOUCH_FRAME* frame)
|
||||
UINT32 index;
|
||||
int rectSize = 2;
|
||||
RDPINPUT_CONTACT_DATA* contact;
|
||||
|
||||
#ifdef WITH_DEBUG_RDPEI
|
||||
WLog_DBG(TAG, "contactCount: %d", frame->contactCount);
|
||||
WLog_DBG(TAG, "frameOffset: 0x%08X", (UINT32) frame->frameOffset);
|
||||
#endif
|
||||
|
||||
rdpei_write_2byte_unsigned(s, frame->contactCount); /* contactCount (TWO_BYTE_UNSIGNED_INTEGER) */
|
||||
|
||||
rdpei_write_2byte_unsigned(s,
|
||||
frame->contactCount); /* contactCount (TWO_BYTE_UNSIGNED_INTEGER) */
|
||||
/**
|
||||
* the time offset from the previous frame (in microseconds).
|
||||
* If this is the first frame being transmitted then this field MUST be set to zero.
|
||||
*/
|
||||
rdpei_write_8byte_unsigned(s, frame->frameOffset * 1000); /* frameOffset (EIGHT_BYTE_UNSIGNED_INTEGER) */
|
||||
rdpei_write_8byte_unsigned(s,
|
||||
frame->frameOffset * 1000); /* frameOffset (EIGHT_BYTE_UNSIGNED_INTEGER) */
|
||||
|
||||
if (!Stream_EnsureRemainingCapacity(s, (size_t) frame->contactCount * 64))
|
||||
{
|
||||
@ -351,13 +346,11 @@ UINT rdpei_write_touch_frame(wStream* s, RDPINPUT_TOUCH_FRAME* frame)
|
||||
for (index = 0; index < frame->contactCount; index++)
|
||||
{
|
||||
contact = &frame->contacts[index];
|
||||
|
||||
contact->fieldsPresent |= CONTACT_DATA_CONTACTRECT_PRESENT;
|
||||
contact->contactRectLeft = contact->x - rectSize;
|
||||
contact->contactRectTop = contact->y - rectSize;
|
||||
contact->contactRectRight = contact->x + rectSize;
|
||||
contact->contactRectBottom = contact->y + rectSize;
|
||||
|
||||
#ifdef WITH_DEBUG_RDPEI
|
||||
WLog_DBG(TAG, "contact[%d].contactId: %d", index, contact->contactId);
|
||||
WLog_DBG(TAG, "contact[%d].fieldsPresent: %d", index, contact->fieldsPresent);
|
||||
@ -366,15 +359,11 @@ UINT rdpei_write_touch_frame(wStream* s, RDPINPUT_TOUCH_FRAME* frame)
|
||||
WLog_DBG(TAG, "contact[%d].contactFlags: 0x%04X", index, contact->contactFlags);
|
||||
rdpei_print_contact_flags(contact->contactFlags);
|
||||
#endif
|
||||
|
||||
Stream_Write_UINT8(s, contact->contactId); /* contactId (1 byte) */
|
||||
|
||||
/* fieldsPresent (TWO_BYTE_UNSIGNED_INTEGER) */
|
||||
rdpei_write_2byte_unsigned(s, contact->fieldsPresent);
|
||||
|
||||
rdpei_write_4byte_signed(s, contact->x); /* x (FOUR_BYTE_SIGNED_INTEGER) */
|
||||
rdpei_write_4byte_signed(s, contact->y); /* y (FOUR_BYTE_SIGNED_INTEGER) */
|
||||
|
||||
/* contactFlags (FOUR_BYTE_UNSIGNED_INTEGER) */
|
||||
rdpei_write_4byte_unsigned(s, contact->contactFlags);
|
||||
|
||||
@ -411,43 +400,41 @@ UINT rdpei_write_touch_frame(wStream* s, RDPINPUT_TOUCH_FRAME* frame)
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT rdpei_send_touch_event_pdu(RDPEI_CHANNEL_CALLBACK* callback, RDPINPUT_TOUCH_FRAME* frame)
|
||||
UINT rdpei_send_touch_event_pdu(RDPEI_CHANNEL_CALLBACK* callback,
|
||||
RDPINPUT_TOUCH_FRAME* frame)
|
||||
{
|
||||
UINT status;
|
||||
wStream* s;
|
||||
UINT32 pduLength;
|
||||
|
||||
pduLength = 64 + (frame->contactCount * 64);
|
||||
|
||||
s = Stream_New(NULL, pduLength);
|
||||
|
||||
if (!s)
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_New failed!");
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
}
|
||||
Stream_Seek(s, RDPINPUT_HEADER_LENGTH);
|
||||
|
||||
Stream_Seek(s, RDPINPUT_HEADER_LENGTH);
|
||||
/**
|
||||
* the time that has elapsed (in milliseconds) from when the oldest touch frame
|
||||
* was generated to when it was encoded for transmission by the client.
|
||||
*/
|
||||
rdpei_write_4byte_unsigned(s, (UINT32) frame->frameOffset); /* encodeTime (FOUR_BYTE_UNSIGNED_INTEGER) */
|
||||
|
||||
rdpei_write_4byte_unsigned(s,
|
||||
(UINT32) frame->frameOffset); /* encodeTime (FOUR_BYTE_UNSIGNED_INTEGER) */
|
||||
rdpei_write_2byte_unsigned(s, 1); /* (frameCount) TWO_BYTE_UNSIGNED_INTEGER */
|
||||
|
||||
if ((status = rdpei_write_touch_frame(s, frame)))
|
||||
{
|
||||
WLog_ERR(TAG, "rdpei_write_touch_frame failed with error %lu!", status);
|
||||
WLog_ERR(TAG, "rdpei_write_touch_frame failed with error %u!", status);
|
||||
Stream_Free(s, TRUE);
|
||||
return status;
|
||||
}
|
||||
|
||||
Stream_SealLength(s);
|
||||
pduLength = Stream_Length(s);
|
||||
|
||||
status = rdpei_send_pdu(callback, s, EVENTID_TOUCH, pduLength);
|
||||
Stream_Free(s, TRUE);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -459,17 +446,16 @@ UINT rdpei_send_touch_event_pdu(RDPEI_CHANNEL_CALLBACK* callback, RDPINPUT_TOUCH
|
||||
UINT rdpei_recv_sc_ready_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s)
|
||||
{
|
||||
UINT32 protocolVersion;
|
||||
|
||||
Stream_Read_UINT32(s, protocolVersion); /* protocolVersion (4 bytes) */
|
||||
|
||||
#if 0
|
||||
|
||||
if (protocolVersion != RDPINPUT_PROTOCOL_V10)
|
||||
{
|
||||
WLog_ERR(TAG, "Unknown [MS-RDPEI] protocolVersion: 0x%08X", protocolVersion);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
@ -482,10 +468,10 @@ UINT rdpei_recv_suspend_touch_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s)
|
||||
{
|
||||
RdpeiClientContext* rdpei = (RdpeiClientContext*) callback->plugin->pInterface;
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
|
||||
IFCALLRET(rdpei->SuspendTouch, error, rdpei);
|
||||
|
||||
if (error)
|
||||
WLog_ERR(TAG, "rdpei->SuspendTouch failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rdpei->SuspendTouch failed with error %u!", error);
|
||||
|
||||
return error;
|
||||
}
|
||||
@ -499,10 +485,10 @@ UINT rdpei_recv_resume_touch_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s)
|
||||
{
|
||||
RdpeiClientContext* rdpei = (RdpeiClientContext*) callback->plugin->pInterface;
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
|
||||
IFCALLRET(rdpei->ResumeTouch, error, rdpei);
|
||||
|
||||
if (error)
|
||||
WLog_ERR(TAG, "rdpei->ResumeTouch failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rdpei->ResumeTouch failed with error %u!", error);
|
||||
|
||||
return error;
|
||||
}
|
||||
@ -517,13 +503,11 @@ UINT rdpei_recv_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s)
|
||||
UINT16 eventId;
|
||||
UINT32 pduLength;
|
||||
UINT error;
|
||||
|
||||
Stream_Read_UINT16(s, eventId); /* eventId (2 bytes) */
|
||||
Stream_Read_UINT32(s, pduLength); /* pduLength (4 bytes) */
|
||||
|
||||
#ifdef WITH_DEBUG_RDPEI
|
||||
WLog_DBG(TAG, "rdpei_recv_pdu: eventId: %d (%s) length: %d",
|
||||
eventId, RDPEI_EVENTID_STRINGS[eventId], pduLength);
|
||||
eventId, RDPEI_EVENTID_STRINGS[eventId], pduLength);
|
||||
#endif
|
||||
|
||||
switch (eventId)
|
||||
@ -531,30 +515,34 @@ UINT rdpei_recv_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s)
|
||||
case EVENTID_SC_READY:
|
||||
if ((error = rdpei_recv_sc_ready_pdu(callback, s)))
|
||||
{
|
||||
WLog_ERR(TAG, "rdpei_recv_sc_ready_pdu failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rdpei_recv_sc_ready_pdu failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
if ((error = rdpei_send_cs_ready_pdu(callback)))
|
||||
{
|
||||
WLog_ERR(TAG, "rdpei_send_cs_ready_pdu failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rdpei_send_cs_ready_pdu failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case EVENTID_SUSPEND_TOUCH:
|
||||
if ((error = rdpei_recv_suspend_touch_pdu(callback, s)))
|
||||
{
|
||||
WLog_ERR(TAG, "rdpei_recv_suspend_touch_pdu failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rdpei_recv_suspend_touch_pdu failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case EVENTID_RESUME_TOUCH:
|
||||
if ((error = rdpei_recv_resume_touch_pdu(callback, s)))
|
||||
{
|
||||
WLog_ERR(TAG, "rdpei_recv_resume_touch_pdu failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rdpei_recv_resume_touch_pdu failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -569,10 +557,10 @@ UINT rdpei_recv_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s)
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT rdpei_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream *data)
|
||||
static UINT rdpei_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
|
||||
wStream* data)
|
||||
{
|
||||
RDPEI_CHANNEL_CALLBACK* callback = (RDPEI_CHANNEL_CALLBACK*) pChannelCallback;
|
||||
|
||||
return rdpei_recv_pdu(callback, data);
|
||||
}
|
||||
|
||||
@ -584,9 +572,7 @@ static UINT rdpei_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
|
||||
static UINT rdpei_on_close(IWTSVirtualChannelCallback* pChannelCallback)
|
||||
{
|
||||
RDPEI_CHANNEL_CALLBACK* callback = (RDPEI_CHANNEL_CALLBACK*) pChannelCallback;
|
||||
|
||||
free(callback);
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
@ -595,17 +581,19 @@ static UINT rdpei_on_close(IWTSVirtualChannelCallback* pChannelCallback)
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT rdpei_on_new_channel_connection(IWTSListenerCallback* pListenerCallback,
|
||||
IWTSVirtualChannel* pChannel, BYTE* Data, BOOL* pbAccept,
|
||||
IWTSVirtualChannelCallback** ppCallback)
|
||||
static UINT rdpei_on_new_channel_connection(IWTSListenerCallback*
|
||||
pListenerCallback,
|
||||
IWTSVirtualChannel* pChannel, BYTE* Data, BOOL* pbAccept,
|
||||
IWTSVirtualChannelCallback** ppCallback)
|
||||
{
|
||||
RDPEI_CHANNEL_CALLBACK* callback;
|
||||
RDPEI_LISTENER_CALLBACK* listener_callback = (RDPEI_LISTENER_CALLBACK*) pListenerCallback;
|
||||
|
||||
RDPEI_LISTENER_CALLBACK* listener_callback = (RDPEI_LISTENER_CALLBACK*)
|
||||
pListenerCallback;
|
||||
callback = (RDPEI_CHANNEL_CALLBACK*) calloc(1, sizeof(RDPEI_CHANNEL_CALLBACK));
|
||||
|
||||
if (!callback)
|
||||
{
|
||||
WLog_ERR(TAG,"calloc failed!");
|
||||
WLog_ERR(TAG, "calloc failed!");
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
}
|
||||
|
||||
@ -615,9 +603,7 @@ static UINT rdpei_on_new_channel_connection(IWTSListenerCallback* pListenerCallb
|
||||
callback->channel_mgr = listener_callback->channel_mgr;
|
||||
callback->channel = pChannel;
|
||||
listener_callback->channel_callback = callback;
|
||||
|
||||
*ppCallback = (IWTSVirtualChannelCallback*) callback;
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
@ -626,52 +612,52 @@ static UINT rdpei_on_new_channel_connection(IWTSListenerCallback* pListenerCallb
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT rdpei_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr)
|
||||
static UINT rdpei_plugin_initialize(IWTSPlugin* pPlugin,
|
||||
IWTSVirtualChannelManager* pChannelMgr)
|
||||
{
|
||||
UINT error;
|
||||
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) pPlugin;
|
||||
rdpei->listener_callback = (RDPEI_LISTENER_CALLBACK*) calloc(1 ,
|
||||
sizeof(RDPEI_LISTENER_CALLBACK));
|
||||
|
||||
rdpei->listener_callback = (RDPEI_LISTENER_CALLBACK*) calloc(1 ,sizeof(RDPEI_LISTENER_CALLBACK));
|
||||
if (!rdpei->listener_callback)
|
||||
{
|
||||
WLog_ERR(TAG, "calloc failed!");
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
}
|
||||
|
||||
rdpei->listener_callback->iface.OnNewChannelConnection = rdpei_on_new_channel_connection;
|
||||
rdpei->listener_callback->iface.OnNewChannelConnection =
|
||||
rdpei_on_new_channel_connection;
|
||||
rdpei->listener_callback->plugin = pPlugin;
|
||||
rdpei->listener_callback->channel_mgr = pChannelMgr;
|
||||
|
||||
if ((error = pChannelMgr->CreateListener(pChannelMgr, RDPEI_DVC_CHANNEL_NAME, 0,
|
||||
(IWTSListenerCallback*) rdpei->listener_callback, &(rdpei->listener))))
|
||||
(IWTSListenerCallback*) rdpei->listener_callback, &(rdpei->listener))))
|
||||
{
|
||||
WLog_ERR(TAG, "ChannelMgr->CreateListener failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "ChannelMgr->CreateListener failed with error %u!", error);
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
rdpei->listener->pInterface = rdpei->iface.pInterface;
|
||||
|
||||
InitializeCriticalSection(&rdpei->lock);
|
||||
|
||||
if (!(rdpei->event = CreateEvent(NULL, TRUE, FALSE, NULL)))
|
||||
{
|
||||
WLog_ERR(TAG, "CreateEvent failed!");
|
||||
goto error_out;
|
||||
|
||||
}
|
||||
|
||||
if (!(rdpei->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
|
||||
{
|
||||
WLog_ERR(TAG, "CreateEvent failed!");
|
||||
goto error_out;
|
||||
|
||||
}
|
||||
|
||||
if (!(rdpei->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)
|
||||
rdpei_schedule_thread, (void*) rdpei, 0, NULL)))
|
||||
rdpei_schedule_thread, (void*) rdpei, 0, NULL)))
|
||||
{
|
||||
WLog_ERR(TAG, "CreateThread failed!");
|
||||
goto error_out;
|
||||
|
||||
}
|
||||
|
||||
return error;
|
||||
@ -690,7 +676,7 @@ error_out:
|
||||
static UINT rdpei_plugin_terminated(IWTSPlugin* pPlugin)
|
||||
{
|
||||
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) pPlugin;
|
||||
UINT error;
|
||||
UINT error;
|
||||
|
||||
if (!pPlugin)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
@ -699,22 +685,19 @@ static UINT rdpei_plugin_terminated(IWTSPlugin* pPlugin)
|
||||
EnterCriticalSection(&rdpei->lock);
|
||||
|
||||
if (WaitForSingleObject(rdpei->thread, INFINITE) == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
|
||||
return error;
|
||||
}
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
CloseHandle(rdpei->stopEvent);
|
||||
CloseHandle(rdpei->event);
|
||||
CloseHandle(rdpei->thread);
|
||||
|
||||
DeleteCriticalSection(&rdpei->lock);
|
||||
|
||||
free(rdpei->listener_callback);
|
||||
free(rdpei->context);
|
||||
free(rdpei);
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
@ -739,7 +722,6 @@ UINT rdpei_send_frame(RdpeiClientContext* context)
|
||||
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) context->handle;
|
||||
RDPEI_CHANNEL_CALLBACK* callback = rdpei->listener_callback->channel_callback;
|
||||
UINT error;
|
||||
|
||||
currentTime = GetTickCount64();
|
||||
|
||||
if (!rdpei->previousFrameTime && !rdpei->currentFrameTime)
|
||||
@ -755,12 +737,12 @@ UINT rdpei_send_frame(RdpeiClientContext* context)
|
||||
|
||||
if ((error = rdpei_send_touch_event_pdu(callback, &rdpei->frame)))
|
||||
{
|
||||
WLog_ERR(TAG, "rdpei_send_touch_event_pdu failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rdpei_send_touch_event_pdu failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
rdpei->previousFrameTime = rdpei->currentFrameTime;
|
||||
rdpei->frame.contactCount = 0;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -769,21 +751,18 @@ UINT rdpei_send_frame(RdpeiClientContext* context)
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT rdpei_add_contact(RdpeiClientContext* context, RDPINPUT_CONTACT_DATA* contact)
|
||||
UINT rdpei_add_contact(RdpeiClientContext* context,
|
||||
RDPINPUT_CONTACT_DATA* contact)
|
||||
{
|
||||
RDPINPUT_CONTACT_POINT* contactPoint;
|
||||
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) context->handle;
|
||||
|
||||
EnterCriticalSection(&rdpei->lock);
|
||||
|
||||
contactPoint = (RDPINPUT_CONTACT_POINT*) &rdpei->contactPoints[contact->contactId];
|
||||
contactPoint = (RDPINPUT_CONTACT_POINT*)
|
||||
&rdpei->contactPoints[contact->contactId];
|
||||
CopyMemory(&(contactPoint->data), contact, sizeof(RDPINPUT_CONTACT_DATA));
|
||||
contactPoint->dirty = TRUE;
|
||||
|
||||
SetEvent(rdpei->event);
|
||||
|
||||
LeaveCriticalSection(&rdpei->lock);
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
@ -792,7 +771,8 @@ UINT rdpei_add_contact(RdpeiClientContext* context, RDPINPUT_CONTACT_DATA* conta
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT rdpei_touch_begin(RdpeiClientContext* context, int externalId, int x, int y, int* contactId)
|
||||
UINT rdpei_touch_begin(RdpeiClientContext* context, int externalId, int x,
|
||||
int y, int* contactId)
|
||||
{
|
||||
unsigned int i;
|
||||
int contactIdlocal = -1;
|
||||
@ -821,20 +801,17 @@ UINT rdpei_touch_begin(RdpeiClientContext* context, int externalId, int x, int y
|
||||
if (contactIdlocal >= 0)
|
||||
{
|
||||
ZeroMemory(&contact, sizeof(RDPINPUT_CONTACT_DATA));
|
||||
|
||||
contactPoint->lastX = x;
|
||||
contactPoint->lastY = y;
|
||||
|
||||
contact.x = x;
|
||||
contact.y = y;
|
||||
contact.contactId = (UINT32) contactIdlocal;
|
||||
|
||||
contact.contactFlags |= CONTACT_FLAG_DOWN;
|
||||
contact.contactFlags |= CONTACT_FLAG_INRANGE;
|
||||
contact.contactFlags |= CONTACT_FLAG_INCONTACT;
|
||||
|
||||
error = context->AddContact(context, &contact);
|
||||
}
|
||||
|
||||
*contactId = contactIdlocal;
|
||||
return error;
|
||||
}
|
||||
@ -844,7 +821,8 @@ UINT rdpei_touch_begin(RdpeiClientContext* context, int externalId, int x, int y
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT rdpei_touch_update(RdpeiClientContext* context, int externalId, int x, int y, int* contactId)
|
||||
UINT rdpei_touch_update(RdpeiClientContext* context, int externalId, int x,
|
||||
int y, int* contactId)
|
||||
{
|
||||
unsigned int i;
|
||||
int contactIdlocal = -1;
|
||||
@ -870,23 +848,18 @@ UINT rdpei_touch_update(RdpeiClientContext* context, int externalId, int x, int
|
||||
if (contactIdlocal >= 0)
|
||||
{
|
||||
ZeroMemory(&contact, sizeof(RDPINPUT_CONTACT_DATA));
|
||||
|
||||
contactPoint->lastX = x;
|
||||
contactPoint->lastY = y;
|
||||
|
||||
contact.x = x;
|
||||
contact.y = y;
|
||||
contact.contactId = (UINT32) contactIdlocal;
|
||||
|
||||
contact.contactFlags |= CONTACT_FLAG_UPDATE;
|
||||
contact.contactFlags |= CONTACT_FLAG_INRANGE;
|
||||
contact.contactFlags |= CONTACT_FLAG_INCONTACT;
|
||||
|
||||
error = context->AddContact(context, &contact);
|
||||
}
|
||||
|
||||
*contactId = contactIdlocal;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -895,7 +868,8 @@ UINT rdpei_touch_update(RdpeiClientContext* context, int externalId, int x, int
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT rdpei_touch_end(RdpeiClientContext* context, int externalId, int x, int y, int* contactId)
|
||||
UINT rdpei_touch_end(RdpeiClientContext* context, int externalId, int x, int y,
|
||||
int* contactId)
|
||||
{
|
||||
unsigned int i;
|
||||
int contactIdlocal = -1;
|
||||
@ -927,7 +901,7 @@ UINT rdpei_touch_end(RdpeiClientContext* context, int externalId, int x, int y,
|
||||
{
|
||||
if ((error = context->TouchUpdate(context, externalId, x, y, &tempvalue)))
|
||||
{
|
||||
WLog_ERR(TAG, "context->TouchUpdate failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "context->TouchUpdate failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
@ -935,12 +909,11 @@ UINT rdpei_touch_end(RdpeiClientContext* context, int externalId, int x, int y,
|
||||
contact.x = x;
|
||||
contact.y = y;
|
||||
contact.contactId = (UINT32) contactIdlocal;
|
||||
|
||||
contact.contactFlags |= CONTACT_FLAG_UP;
|
||||
|
||||
if ((error = context->AddContact(context, &contact)))
|
||||
{
|
||||
WLog_ERR(TAG, "context->AddContact failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "context->AddContact failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -950,12 +923,12 @@ UINT rdpei_touch_end(RdpeiClientContext* context, int externalId, int x, int y,
|
||||
contactPoint->contactId = 0;
|
||||
contactPoint->state = RDPINPUT_CONTACT_STATE_OUT_OF_RANGE;
|
||||
}
|
||||
*contactId = contactIdlocal;
|
||||
|
||||
*contactId = contactIdlocal;
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#ifdef BUILTIN_CHANNELS
|
||||
#define DVCPluginEntry rdpei_DVCPluginEntry
|
||||
#else
|
||||
#define DVCPluginEntry FREERDP_API DVCPluginEntry
|
||||
@ -971,15 +944,14 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
|
||||
UINT error;
|
||||
RDPEI_PLUGIN* rdpei = NULL;
|
||||
RdpeiClientContext* context = NULL;
|
||||
|
||||
rdpei = (RDPEI_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "rdpei");
|
||||
|
||||
if (!rdpei)
|
||||
{
|
||||
size_t size;
|
||||
|
||||
rdpei = (RDPEI_PLUGIN*) calloc(1, sizeof(RDPEI_PLUGIN));
|
||||
if(!rdpei)
|
||||
|
||||
if (!rdpei)
|
||||
{
|
||||
WLog_ERR(TAG, "calloc failed!");
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
@ -989,18 +961,15 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
|
||||
rdpei->iface.Connected = NULL;
|
||||
rdpei->iface.Disconnected = NULL;
|
||||
rdpei->iface.Terminated = rdpei_plugin_terminated;
|
||||
|
||||
rdpei->version = 1;
|
||||
rdpei->currentFrameTime = 0;
|
||||
rdpei->previousFrameTime = 0;
|
||||
rdpei->frame.contacts = (RDPINPUT_CONTACT_DATA*) rdpei->contacts;
|
||||
|
||||
rdpei->maxTouchContacts = 10;
|
||||
size = rdpei->maxTouchContacts * sizeof(RDPINPUT_CONTACT_POINT);
|
||||
rdpei->contactPoints = (RDPINPUT_CONTACT_POINT*) calloc(1, size);
|
||||
|
||||
rdpei->rdpcontext = ((freerdp*)((rdpSettings*) pEntryPoints->GetRdpSettings(pEntryPoints))->instance)->context;
|
||||
|
||||
rdpei->rdpcontext = ((freerdp*)((rdpSettings*) pEntryPoints->GetRdpSettings(
|
||||
pEntryPoints))->instance)->context;
|
||||
|
||||
if (!rdpei->contactPoints)
|
||||
{
|
||||
@ -1010,6 +979,7 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
|
||||
}
|
||||
|
||||
context = (RdpeiClientContext*) calloc(1, sizeof(RdpeiClientContext));
|
||||
|
||||
if (!context)
|
||||
{
|
||||
WLog_ERR(TAG, "calloc failed!");
|
||||
@ -1020,16 +990,15 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
|
||||
context->handle = (void*) rdpei;
|
||||
context->GetVersion = rdpei_get_version;
|
||||
context->AddContact = rdpei_add_contact;
|
||||
|
||||
context->TouchBegin = rdpei_touch_begin;
|
||||
context->TouchUpdate = rdpei_touch_update;
|
||||
context->TouchEnd = rdpei_touch_end;
|
||||
|
||||
rdpei->iface.pInterface = (void*) context;
|
||||
|
||||
if ((error = pEntryPoints->RegisterPlugin(pEntryPoints, "rdpei", (IWTSPlugin*) rdpei)))
|
||||
if ((error = pEntryPoints->RegisterPlugin(pEntryPoints, "rdpei",
|
||||
(IWTSPlugin*) rdpei)))
|
||||
{
|
||||
WLog_ERR(TAG, "EntryPoints->RegisterPlugin failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "EntryPoints->RegisterPlugin failed with error %u!", error);
|
||||
error = CHANNEL_RC_NO_MEMORY;
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
@ -82,9 +82,9 @@ struct _RDPINPUT_CONTACT_POINT
|
||||
typedef struct _RDPINPUT_CONTACT_POINT RDPINPUT_CONTACT_POINT;
|
||||
|
||||
#ifdef WITH_DEBUG_DVC
|
||||
#define DEBUG_DVC(fmt, ...) WLog_DBG(TAG, fmt, ## __VA_ARGS__)
|
||||
#define DEBUG_DVC(...) WLog_DBG(TAG, __VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG_DVC(fmt, ...) do { } while (0)
|
||||
#define DEBUG_DVC(...) do { } while (0)
|
||||
#endif
|
||||
|
||||
#endif /* FREERDP_CHANNEL_RDPEI_CLIENT_MAIN_H */
|
||||
|
||||
@ -185,7 +185,7 @@ static UINT read_cs_ready_message(RdpeiServerContext *context, wStream *s)
|
||||
|
||||
IFCALLRET(context->onClientReady, error, context);
|
||||
if (error)
|
||||
WLog_ERR(TAG, "context->onClientReady failed with error %lu", error);
|
||||
WLog_ERR(TAG, "context->onClientReady failed with error %u", error);
|
||||
|
||||
return error;
|
||||
}
|
||||
@ -271,7 +271,7 @@ static UINT read_touch_frame(RdpeiServerContext *context, wStream *s, RDPINPUT_T
|
||||
{
|
||||
if ((error = read_touch_contact_data(context, s, contact)))
|
||||
{
|
||||
WLog_ERR(TAG, "read_touch_contact_data failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "read_touch_contact_data failed with error %u!", error);
|
||||
frame->contactCount = i;
|
||||
touch_frame_reset(frame);
|
||||
return error;
|
||||
@ -311,7 +311,7 @@ static UINT read_touch_event(RdpeiServerContext *context, wStream *s)
|
||||
{
|
||||
if ((error = read_touch_frame(context, s, frame)))
|
||||
{
|
||||
WLog_ERR(TAG, "read_touch_contact_data failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "read_touch_contact_data failed with error %u!", error);
|
||||
event->frameCount = i;
|
||||
goto out_cleanup;
|
||||
}
|
||||
@ -320,7 +320,7 @@ static UINT read_touch_event(RdpeiServerContext *context, wStream *s)
|
||||
|
||||
IFCALLRET(context->onTouchEvent, error, context, event);
|
||||
if (error)
|
||||
WLog_ERR(TAG, "context->onTouchEvent failed with error %lu", error);
|
||||
WLog_ERR(TAG, "context->onTouchEvent failed with error %u", error);
|
||||
|
||||
out_cleanup:
|
||||
touch_event_reset(event);
|
||||
@ -347,7 +347,7 @@ static UINT read_dismiss_hovering_contact(RdpeiServerContext *context, wStream *
|
||||
|
||||
IFCALLRET(context->onTouchReleased, error, context, contactId);
|
||||
if (error)
|
||||
WLog_ERR(TAG, "context->onTouchReleased failed with error %lu", error);
|
||||
WLog_ERR(TAG, "context->onTouchReleased failed with error %u", error);
|
||||
|
||||
return error;
|
||||
}
|
||||
@ -420,7 +420,7 @@ UINT rdpei_server_handle_messages(RdpeiServerContext *context) {
|
||||
|
||||
if ((error = read_cs_ready_message(context, s)))
|
||||
{
|
||||
WLog_ERR(TAG, "read_cs_ready_message failed with error %lu", error);
|
||||
WLog_ERR(TAG, "read_cs_ready_message failed with error %u", error);
|
||||
return error;
|
||||
}
|
||||
break;
|
||||
@ -428,14 +428,14 @@ UINT rdpei_server_handle_messages(RdpeiServerContext *context) {
|
||||
case EVENTID_TOUCH:
|
||||
if ((error = read_touch_event(context, s)))
|
||||
{
|
||||
WLog_ERR(TAG, "read_touch_event failed with error %lu", error);
|
||||
WLog_ERR(TAG, "read_touch_event failed with error %u", error);
|
||||
return error;
|
||||
}
|
||||
break;
|
||||
case EVENTID_DISMISS_HOVERING_CONTACT:
|
||||
if ((error = read_dismiss_hovering_contact(context, s)))
|
||||
{
|
||||
WLog_ERR(TAG, "read_dismiss_hovering_contact failed with error %lu", error);
|
||||
WLog_ERR(TAG, "read_dismiss_hovering_contact failed with error %u", error);
|
||||
return error;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -21,3 +21,6 @@ if(WITH_CLIENT_CHANNELS)
|
||||
add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME})
|
||||
endif()
|
||||
|
||||
if(WITH_SERVER_CHANNELS)
|
||||
add_channel_server(${MODULE_PREFIX} ${CHANNEL_NAME})
|
||||
endif()
|
||||
|
||||
@ -22,8 +22,8 @@ set(${MODULE_PREFIX}_SRCS
|
||||
rdpgfx_main.h
|
||||
rdpgfx_codec.c
|
||||
rdpgfx_codec.h
|
||||
rdpgfx_common.c
|
||||
rdpgfx_common.h)
|
||||
../rdpgfx_common.c
|
||||
../rdpgfx_common.h)
|
||||
|
||||
include_directories(..)
|
||||
|
||||
@ -33,7 +33,7 @@ add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE
|
||||
|
||||
target_link_libraries(${MODULE_NAME} winpr freerdp)
|
||||
|
||||
if (WITH_DEBUG_SYMBOLS AND MSVC AND NOT STATIC_CHANNELS AND BUILD_SHARED_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()
|
||||
|
||||
|
||||
@ -57,7 +57,7 @@ static UINT rdpgfx_read_h264_metablock(RDPGFX_PLUGIN* gfx, wStream* s,
|
||||
|
||||
Stream_Read_UINT32(s, meta->numRegionRects); /* numRegionRects (4 bytes) */
|
||||
|
||||
if (Stream_GetRemainingLength(s) < (meta->numRegionRects * sizeof(RECTANGLE_16)))
|
||||
if (Stream_GetRemainingLength(s) < (meta->numRegionRects * 8))
|
||||
{
|
||||
WLog_ERR(TAG, "not enough data!");
|
||||
goto error_out;
|
||||
@ -88,7 +88,7 @@ static UINT rdpgfx_read_h264_metablock(RDPGFX_PLUGIN* gfx, wStream* s,
|
||||
regionRect = &(meta->regionRects[index]);
|
||||
if ((error = rdpgfx_read_rect16(s, regionRect)))
|
||||
{
|
||||
WLog_ERR(TAG, "rdpgfx_read_rect16 failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rdpgfx_read_rect16 failed with error %u!", error);
|
||||
goto error_out;
|
||||
}
|
||||
WLog_DBG(TAG, "regionRects[%d]: left: %d top: %d right: %d bottom: %d",
|
||||
@ -146,7 +146,7 @@ static UINT rdpgfx_decode_AVC420(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd
|
||||
|
||||
if ((error = rdpgfx_read_h264_metablock(gfx, s, &(h264.meta))))
|
||||
{
|
||||
WLog_ERR(TAG, "rdpgfx_read_h264_metablock failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rdpgfx_read_h264_metablock failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -161,7 +161,7 @@ static UINT rdpgfx_decode_AVC420(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd
|
||||
{
|
||||
IFCALLRET(context->SurfaceCommand, error, context, cmd);
|
||||
if (error)
|
||||
WLog_ERR(TAG, "context->SurfaceCommand failed with error %lu", error);
|
||||
WLog_ERR(TAG, "context->SurfaceCommand failed with error %u", error);
|
||||
}
|
||||
|
||||
free(h264.meta.regionRects);
|
||||
@ -205,7 +205,7 @@ static UINT rdpgfx_decode_AVC444(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd
|
||||
pos1 = Stream_GetPosition(s);
|
||||
if ((error = rdpgfx_read_h264_metablock(gfx, s, &(h264.bitstream[0].meta))))
|
||||
{
|
||||
WLog_ERR(TAG, "rdpgfx_read_h264_metablock failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rdpgfx_read_h264_metablock failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
pos2 = Stream_GetPosition(s);
|
||||
@ -223,7 +223,7 @@ static UINT rdpgfx_decode_AVC444(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd
|
||||
|
||||
if ((error = rdpgfx_read_h264_metablock(gfx, s, &(h264.bitstream[1].meta))))
|
||||
{
|
||||
WLog_ERR(TAG, "rdpgfx_read_h264_metablock failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "rdpgfx_read_h264_metablock failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -244,7 +244,7 @@ static UINT rdpgfx_decode_AVC444(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd
|
||||
{
|
||||
IFCALLRET(context->SurfaceCommand, error, context, cmd);
|
||||
if (error)
|
||||
WLog_ERR(TAG, "context->SurfaceCommand failed with error %lu", error);
|
||||
WLog_ERR(TAG, "context->SurfaceCommand failed with error %u", error);
|
||||
}
|
||||
|
||||
free(h264.bitstream[0].meta.regionRects);
|
||||
@ -270,7 +270,7 @@ UINT rdpgfx_decode(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd)
|
||||
case RDPGFX_CODECID_AVC420:
|
||||
if ((error = rdpgfx_decode_AVC420(gfx, cmd)))
|
||||
{
|
||||
WLog_ERR(TAG, "rdpgfx_decode_AVC420 failed with error %lu", error);
|
||||
WLog_ERR(TAG, "rdpgfx_decode_AVC420 failed with error %u", error);
|
||||
return error;
|
||||
}
|
||||
break;
|
||||
@ -278,7 +278,7 @@ UINT rdpgfx_decode(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd)
|
||||
case RDPGFX_CODECID_AVC444:
|
||||
if ((error = rdpgfx_decode_AVC444(gfx, cmd)))
|
||||
{
|
||||
WLog_ERR(TAG, "rdpgfx_decode_AVC444 failed with error %lu", error);
|
||||
WLog_ERR(TAG, "rdpgfx_decode_AVC444 failed with error %u", error);
|
||||
return error;
|
||||
}
|
||||
break;
|
||||
@ -288,7 +288,7 @@ UINT rdpgfx_decode(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd)
|
||||
{
|
||||
IFCALLRET(context->SurfaceCommand, error, context, cmd);
|
||||
if (error)
|
||||
WLog_ERR(TAG, "context->SurfaceCommand failed with error %lu", error);
|
||||
WLog_ERR(TAG, "context->SurfaceCommand failed with error %u", error);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@ -26,9 +26,10 @@
|
||||
#include <winpr/stream.h>
|
||||
|
||||
#include <freerdp/channels/rdpgfx.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
#include "rdpgfx_main.h"
|
||||
|
||||
UINT rdpgfx_decode(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd);
|
||||
FREERDP_LOCAL UINT rdpgfx_decode(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd);
|
||||
|
||||
#endif /* FREERDP_CHANNEL_RDPGFX_CLIENT_CODEC_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -31,7 +31,7 @@
|
||||
|
||||
#include "rdpgfx_common.h"
|
||||
|
||||
const char* RDPGFX_CMDID_STRINGS[] =
|
||||
static const char* RDPGFX_CMDID_STRINGS[] =
|
||||
{
|
||||
"RDPGFX_CMDID_UNUSED_0000",
|
||||
"RDPGFX_CMDID_WIRETOSURFACE_1",
|
||||
@ -54,7 +54,8 @@ const char* RDPGFX_CMDID_STRINGS[] =
|
||||
"RDPGFX_CMDID_CAPSADVERTISE",
|
||||
"RDPGFX_CMDID_CAPSCONFIRM",
|
||||
"RDPGFX_CMDID_UNUSED_0014",
|
||||
"RDPGFX_CMDID_MAPSURFACETOWINDOW"
|
||||
"RDPGFX_CMDID_MAPSURFACETOWINDOW",
|
||||
"RDPGFX_CMDID_QOEFRAMEACKNOWLEDGE"
|
||||
};
|
||||
|
||||
const char* rdpgfx_get_cmd_id_string(UINT16 cmdId)
|
||||
@ -71,20 +72,28 @@ const char* rdpgfx_get_codec_id_string(UINT16 codecId)
|
||||
{
|
||||
case RDPGFX_CODECID_UNCOMPRESSED:
|
||||
return "RDPGFX_CODECID_UNCOMPRESSED";
|
||||
|
||||
case RDPGFX_CODECID_CAVIDEO:
|
||||
return "RDPGFX_CODECID_CAVIDEO";
|
||||
|
||||
case RDPGFX_CODECID_CLEARCODEC:
|
||||
return "RDPGFX_CODECID_CLEARCODEC";
|
||||
|
||||
case RDPGFX_CODECID_PLANAR:
|
||||
return "RDPGFX_CODECID_PLANAR";
|
||||
|
||||
case RDPGFX_CODECID_AVC420:
|
||||
return "RDPGFX_CODECID_AVC420";
|
||||
|
||||
case RDPGFX_CODECID_AVC444:
|
||||
return "RDPGFX_CODECID_AVC444";
|
||||
|
||||
case RDPGFX_CODECID_ALPHA:
|
||||
return "RDPGFX_CODECID_ALPHA";
|
||||
|
||||
case RDPGFX_CODECID_CAPROGRESSIVE:
|
||||
return "RDPGFX_CODECID_CAPROGRESSIVE";
|
||||
|
||||
case RDPGFX_CODECID_CAPROGRESSIVE_V2:
|
||||
return "RDPGFX_CODECID_CAPROGRESSIVE_V2";
|
||||
}
|
||||
@ -108,7 +117,6 @@ UINT rdpgfx_read_header(wStream* s, RDPGFX_HEADER* header)
|
||||
Stream_Read_UINT16(s, header->cmdId); /* cmdId (2 bytes) */
|
||||
Stream_Read_UINT16(s, header->flags); /* flags (2 bytes) */
|
||||
Stream_Read_UINT32(s, header->pduLength); /* pduLength (4 bytes) */
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
@ -122,7 +130,6 @@ UINT rdpgfx_write_header(wStream* s, RDPGFX_HEADER* header)
|
||||
Stream_Write_UINT16(s, header->cmdId); /* cmdId (2 bytes) */
|
||||
Stream_Write_UINT16(s, header->flags); /* flags (2 bytes) */
|
||||
Stream_Write_UINT32(s, header->pduLength); /* pduLength (4 bytes) */
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
@ -141,7 +148,6 @@ UINT rdpgfx_read_point16(wStream* s, RDPGFX_POINT16* pt16)
|
||||
|
||||
Stream_Read_UINT16(s, pt16->x); /* x (2 bytes) */
|
||||
Stream_Read_UINT16(s, pt16->y); /* y (2 bytes) */
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
@ -154,7 +160,6 @@ UINT rdpgfx_write_point16(wStream* s, RDPGFX_POINT16* point16)
|
||||
{
|
||||
Stream_Write_UINT16(s, point16->x); /* x (2 bytes) */
|
||||
Stream_Write_UINT16(s, point16->y); /* y (2 bytes) */
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
@ -175,7 +180,6 @@ UINT rdpgfx_read_rect16(wStream* s, RECTANGLE_16* rect16)
|
||||
Stream_Read_UINT16(s, rect16->top); /* top (2 bytes) */
|
||||
Stream_Read_UINT16(s, rect16->right); /* right (2 bytes) */
|
||||
Stream_Read_UINT16(s, rect16->bottom); /* bottom (2 bytes) */
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
@ -190,7 +194,6 @@ UINT rdpgfx_write_rect16(wStream* s, RECTANGLE_16* rect16)
|
||||
Stream_Write_UINT16(s, rect16->top); /* top (2 bytes) */
|
||||
Stream_Write_UINT16(s, rect16->right); /* right (2 bytes) */
|
||||
Stream_Write_UINT16(s, rect16->bottom); /* bottom (2 bytes) */
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
@ -211,7 +214,6 @@ UINT rdpgfx_read_color32(wStream* s, RDPGFX_COLOR32* color32)
|
||||
Stream_Read_UINT8(s, color32->G); /* G (1 byte) */
|
||||
Stream_Read_UINT8(s, color32->R); /* R (1 byte) */
|
||||
Stream_Read_UINT8(s, color32->XA); /* XA (1 byte) */
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
@ -226,6 +228,5 @@ UINT rdpgfx_write_color32(wStream* s, RDPGFX_COLOR32* color32)
|
||||
Stream_Write_UINT8(s, color32->G); /* G (1 byte) */
|
||||
Stream_Write_UINT8(s, color32->R); /* R (1 byte) */
|
||||
Stream_Write_UINT8(s, color32->XA); /* XA (1 byte) */
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
@ -26,21 +26,22 @@
|
||||
#include <winpr/stream.h>
|
||||
|
||||
#include <freerdp/channels/rdpgfx.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
const char* rdpgfx_get_cmd_id_string(UINT16 cmdId);
|
||||
const char* rdpgfx_get_codec_id_string(UINT16 codecId);
|
||||
FREERDP_LOCAL const char* rdpgfx_get_cmd_id_string(UINT16 cmdId);
|
||||
FREERDP_LOCAL const char* rdpgfx_get_codec_id_string(UINT16 codecId);
|
||||
|
||||
UINT rdpgfx_read_header(wStream* s, RDPGFX_HEADER* header);
|
||||
UINT rdpgfx_write_header(wStream* s, RDPGFX_HEADER* header);
|
||||
FREERDP_LOCAL UINT rdpgfx_read_header(wStream* s, RDPGFX_HEADER* header);
|
||||
FREERDP_LOCAL UINT rdpgfx_write_header(wStream* s, RDPGFX_HEADER* header);
|
||||
|
||||
UINT rdpgfx_read_point16(wStream* s, RDPGFX_POINT16* pt16);
|
||||
UINT rdpgfx_write_point16(wStream* s, RDPGFX_POINT16* point16);
|
||||
FREERDP_LOCAL UINT rdpgfx_read_point16(wStream* s, RDPGFX_POINT16* pt16);
|
||||
FREERDP_LOCAL UINT rdpgfx_write_point16(wStream* s, RDPGFX_POINT16* point16);
|
||||
|
||||
UINT rdpgfx_read_rect16(wStream* s, RECTANGLE_16* rect16);
|
||||
UINT rdpgfx_write_rect16(wStream* s, RECTANGLE_16* rect16);
|
||||
FREERDP_LOCAL UINT rdpgfx_read_rect16(wStream* s, RECTANGLE_16* rect16);
|
||||
FREERDP_LOCAL UINT rdpgfx_write_rect16(wStream* s, RECTANGLE_16* rect16);
|
||||
|
||||
UINT rdpgfx_read_color32(wStream* s, RDPGFX_COLOR32* color32);
|
||||
UINT rdpgfx_write_color32(wStream* s, RDPGFX_COLOR32* color32);
|
||||
FREERDP_LOCAL UINT rdpgfx_read_color32(wStream* s, RDPGFX_COLOR32* color32);
|
||||
FREERDP_LOCAL UINT rdpgfx_write_color32(wStream* s, RDPGFX_COLOR32* color32);
|
||||
|
||||
#endif /* FREERDP_CHANNEL_RDPGFX_CLIENT_COMMON_H */
|
||||
|
||||
34
channels/rdpgfx/server/CMakeLists.txt
Normal file
34
channels/rdpgfx/server/CMakeLists.txt
Normal file
@ -0,0 +1,34 @@
|
||||
# FreeRDP: A Remote Desktop Protocol Implementation
|
||||
# FreeRDP cmake build script
|
||||
#
|
||||
# Copyright 2016 Jiang Zihao <zihao.jiang@yahoo.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_server("rdpgfx")
|
||||
|
||||
set(${MODULE_PREFIX}_SRCS
|
||||
rdpgfx_main.c
|
||||
rdpgfx_main.h
|
||||
../rdpgfx_common.c
|
||||
../rdpgfx_common.h)
|
||||
|
||||
include_directories(..)
|
||||
|
||||
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")
|
||||
1666
channels/rdpgfx/server/rdpgfx_main.c
Normal file
1666
channels/rdpgfx/server/rdpgfx_main.c
Normal file
File diff suppressed because it is too large
Load Diff
40
channels/rdpgfx/server/rdpgfx_main.h
Normal file
40
channels/rdpgfx/server/rdpgfx_main.h
Normal file
@ -0,0 +1,40 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Graphics Pipeline Extension
|
||||
*
|
||||
* Copyright 2016 Jiang Zihao <zihao.jiang@yahoo.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_RDPGFX_SERVER_MAIN_H
|
||||
#define FREERDP_CHANNEL_RDPGFX_SERVER_MAIN_H
|
||||
|
||||
#include <freerdp/server/rdpgfx.h>
|
||||
#include <freerdp/codec/zgfx.h>
|
||||
|
||||
struct _rdpgfx_server_private
|
||||
{
|
||||
ZGFX_CONTEXT* zgfx;
|
||||
BOOL ownThread;
|
||||
HANDLE thread;
|
||||
HANDLE stopEvent;
|
||||
HANDLE channelEvent;
|
||||
void* rdpgfx_channel;
|
||||
DWORD SessionId;
|
||||
wStream* input_stream;
|
||||
BOOL isOpened;
|
||||
BOOL isReady;
|
||||
};
|
||||
|
||||
#endif /* FREERDP_CHANNEL_RDPGFX_SERVER_MAIN_H */
|
||||
@ -21,7 +21,7 @@ set(${MODULE_PREFIX}_SRCS
|
||||
rdpsnd_main.c
|
||||
rdpsnd_main.h)
|
||||
|
||||
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntry")
|
||||
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntryEx")
|
||||
|
||||
|
||||
|
||||
|
||||
@ -647,7 +647,7 @@ static UINT rdpsnd_alsa_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV*
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#ifdef BUILTIN_CHANNELS
|
||||
#define freerdp_rdpsnd_client_subsystem_entry alsa_freerdp_rdpsnd_client_subsystem_entry
|
||||
#else
|
||||
#define freerdp_rdpsnd_client_subsystem_entry FREERDP_API freerdp_rdpsnd_client_subsystem_entry
|
||||
@ -686,7 +686,7 @@ UINT freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS p
|
||||
{
|
||||
if ((error = rdpsnd_alsa_parse_addin_args((rdpsndDevicePlugin *) alsa, args)))
|
||||
{
|
||||
WLog_ERR(TAG, "rdpsnd_alsa_parse_addin_args failed with error %lu", error);
|
||||
WLog_ERR(TAG, "rdpsnd_alsa_parse_addin_args failed with error %u", error);
|
||||
goto error_parse_args;
|
||||
}
|
||||
}
|
||||
|
||||
@ -279,7 +279,7 @@ static void rdpsnd_ios_free(rdpsndDevicePlugin* device)
|
||||
free(p);
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#ifdef BUILTIN_CHANNELS
|
||||
#define freerdp_rdpsnd_client_subsystem_entry ios_freerdp_rdpsnd_client_subsystem_entry
|
||||
#else
|
||||
#define freerdp_rdpsnd_client_subsystem_entry FREERDP_API freerdp_rdpsnd_client_subsystem_entry
|
||||
|
||||
@ -34,6 +34,9 @@
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/codec/dsp.h>
|
||||
|
||||
#define __COREFOUNDATION_CFPLUGINCOM__ 1
|
||||
#define IUNKNOWN_C_GUTS void *_reserved; void* QueryInterface; void* AddRef; void* Release
|
||||
|
||||
#include <AudioToolbox/AudioToolbox.h>
|
||||
#include <AudioToolbox/AudioQueue.h>
|
||||
|
||||
@ -324,6 +327,8 @@ static void rdpsnd_mac_waveplay(rdpsndDevicePlugin* device, RDPSND_WAVE* wave)
|
||||
length = wave->length > audioBuffer->mAudioDataBytesCapacity ? audioBuffer->mAudioDataBytesCapacity : wave->length;
|
||||
|
||||
CopyMemory(audioBuffer->mAudioData, wave->data, length);
|
||||
free(wave->data);
|
||||
wave->data = NULL;
|
||||
audioBuffer->mAudioDataByteSize = length;
|
||||
audioBuffer->mUserData = wave;
|
||||
|
||||
@ -343,7 +348,7 @@ static void rdpsnd_mac_waveplay(rdpsndDevicePlugin* device, RDPSND_WAVE* wave)
|
||||
device->Start(device);
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#ifdef BUILTIN_CHANNELS
|
||||
#define freerdp_rdpsnd_client_subsystem_entry mac_freerdp_rdpsnd_client_subsystem_entry
|
||||
#else
|
||||
#define freerdp_rdpsnd_client_subsystem_entry FREERDP_API freerdp_rdpsnd_client_subsystem_entry
|
||||
|
||||
@ -6,14 +6,14 @@ All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* 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.
|
||||
* Neither the name of the <organization> nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* 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.
|
||||
* Neither the name of the <organization> nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
@ -34,203 +34,238 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#define CONV16BIT 32768
|
||||
#define CONVMYFLT (1./32768.)
|
||||
|
||||
static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context);
|
||||
static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void* context);
|
||||
|
||||
// creates the OpenSL ES audio engine
|
||||
static SLresult openSLCreateEngine(OPENSL_STREAM *p)
|
||||
static SLresult openSLCreateEngine(OPENSL_STREAM* p)
|
||||
{
|
||||
SLresult result;
|
||||
// create engine
|
||||
result = slCreateEngine(&(p->engineObject), 0, NULL, 0, NULL, NULL);
|
||||
SLresult result;
|
||||
// create engine
|
||||
result = slCreateEngine(&(p->engineObject), 0, NULL, 0, NULL, NULL);
|
||||
DEBUG_SND("engineObject=%p", p->engineObject);
|
||||
if(result != SL_RESULT_SUCCESS) goto engine_end;
|
||||
|
||||
// realize the engine
|
||||
result = (*p->engineObject)->Realize(p->engineObject, SL_BOOLEAN_FALSE);
|
||||
if (result != SL_RESULT_SUCCESS) goto engine_end;
|
||||
|
||||
// realize the engine
|
||||
result = (*p->engineObject)->Realize(p->engineObject, SL_BOOLEAN_FALSE);
|
||||
DEBUG_SND("Realize=%d", result);
|
||||
if(result != SL_RESULT_SUCCESS) goto engine_end;
|
||||
|
||||
// get the engine interface, which is needed in order to create other objects
|
||||
result = (*p->engineObject)->GetInterface(p->engineObject, SL_IID_ENGINE, &(p->engineEngine));
|
||||
if (result != SL_RESULT_SUCCESS) goto engine_end;
|
||||
|
||||
// get the engine interface, which is needed in order to create other objects
|
||||
result = (*p->engineObject)->GetInterface(p->engineObject, SL_IID_ENGINE,
|
||||
&(p->engineEngine));
|
||||
DEBUG_SND("engineEngine=%p", p->engineEngine);
|
||||
if(result != SL_RESULT_SUCCESS) goto engine_end;
|
||||
|
||||
engine_end:
|
||||
return result;
|
||||
if (result != SL_RESULT_SUCCESS) goto engine_end;
|
||||
|
||||
engine_end:
|
||||
return result;
|
||||
}
|
||||
|
||||
// opens the OpenSL ES device for output
|
||||
static SLresult openSLPlayOpen(OPENSL_STREAM *p)
|
||||
static SLresult openSLPlayOpen(OPENSL_STREAM* p)
|
||||
{
|
||||
SLresult result;
|
||||
SLuint32 sr = p->sr;
|
||||
SLuint32 channels = p->outchannels;
|
||||
|
||||
SLresult result;
|
||||
SLuint32 sr = p->sr;
|
||||
SLuint32 channels = p->outchannels;
|
||||
assert(p->engineObject);
|
||||
assert(p->engineEngine);
|
||||
|
||||
if(channels){
|
||||
// configure audio source
|
||||
SLDataLocator_AndroidSimpleBufferQueue loc_bufq =
|
||||
if (channels)
|
||||
{
|
||||
// configure audio source
|
||||
SLDataLocator_AndroidSimpleBufferQueue loc_bufq =
|
||||
{
|
||||
SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,
|
||||
p->queuesize
|
||||
};
|
||||
|
||||
switch(sr){
|
||||
switch (sr)
|
||||
{
|
||||
case 8000:
|
||||
sr = SL_SAMPLINGRATE_8;
|
||||
break;
|
||||
|
||||
case 8000:
|
||||
sr = SL_SAMPLINGRATE_8;
|
||||
break;
|
||||
case 11025:
|
||||
sr = SL_SAMPLINGRATE_11_025;
|
||||
break;
|
||||
case 16000:
|
||||
sr = SL_SAMPLINGRATE_16;
|
||||
break;
|
||||
case 22050:
|
||||
sr = SL_SAMPLINGRATE_22_05;
|
||||
break;
|
||||
case 24000:
|
||||
sr = SL_SAMPLINGRATE_24;
|
||||
break;
|
||||
case 32000:
|
||||
sr = SL_SAMPLINGRATE_32;
|
||||
break;
|
||||
case 44100:
|
||||
sr = SL_SAMPLINGRATE_44_1;
|
||||
break;
|
||||
case 48000:
|
||||
sr = SL_SAMPLINGRATE_48;
|
||||
break;
|
||||
case 64000:
|
||||
sr = SL_SAMPLINGRATE_64;
|
||||
break;
|
||||
case 88200:
|
||||
sr = SL_SAMPLINGRATE_88_2;
|
||||
break;
|
||||
case 96000:
|
||||
sr = SL_SAMPLINGRATE_96;
|
||||
break;
|
||||
case 192000:
|
||||
sr = SL_SAMPLINGRATE_192;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
const SLInterfaceID ids[] = {SL_IID_VOLUME};
|
||||
const SLboolean req[] = {SL_BOOLEAN_FALSE};
|
||||
result = (*p->engineEngine)->CreateOutputMix(p->engineEngine, &(p->outputMixObject), 1, ids, req);
|
||||
case 11025:
|
||||
sr = SL_SAMPLINGRATE_11_025;
|
||||
break;
|
||||
|
||||
case 16000:
|
||||
sr = SL_SAMPLINGRATE_16;
|
||||
break;
|
||||
|
||||
case 22050:
|
||||
sr = SL_SAMPLINGRATE_22_05;
|
||||
break;
|
||||
|
||||
case 24000:
|
||||
sr = SL_SAMPLINGRATE_24;
|
||||
break;
|
||||
|
||||
case 32000:
|
||||
sr = SL_SAMPLINGRATE_32;
|
||||
break;
|
||||
|
||||
case 44100:
|
||||
sr = SL_SAMPLINGRATE_44_1;
|
||||
break;
|
||||
|
||||
case 48000:
|
||||
sr = SL_SAMPLINGRATE_48;
|
||||
break;
|
||||
|
||||
case 64000:
|
||||
sr = SL_SAMPLINGRATE_64;
|
||||
break;
|
||||
|
||||
case 88200:
|
||||
sr = SL_SAMPLINGRATE_88_2;
|
||||
break;
|
||||
|
||||
case 96000:
|
||||
sr = SL_SAMPLINGRATE_96;
|
||||
break;
|
||||
|
||||
case 192000:
|
||||
sr = SL_SAMPLINGRATE_192;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
const SLInterfaceID ids[] = {SL_IID_VOLUME};
|
||||
const SLboolean req[] = {SL_BOOLEAN_FALSE};
|
||||
result = (*p->engineEngine)->CreateOutputMix(p->engineEngine,
|
||||
&(p->outputMixObject), 1, ids, req);
|
||||
DEBUG_SND("engineEngine=%p", p->engineEngine);
|
||||
assert(!result);
|
||||
if(result != SL_RESULT_SUCCESS) goto end_openaudio;
|
||||
|
||||
// realize the output mix
|
||||
result = (*p->outputMixObject)->Realize(p->outputMixObject, SL_BOOLEAN_FALSE);
|
||||
if (result != SL_RESULT_SUCCESS) goto end_openaudio;
|
||||
|
||||
// realize the output mix
|
||||
result = (*p->outputMixObject)->Realize(p->outputMixObject, SL_BOOLEAN_FALSE);
|
||||
DEBUG_SND("Realize=%d", result);
|
||||
assert(!result);
|
||||
if(result != SL_RESULT_SUCCESS) goto end_openaudio;
|
||||
|
||||
int speakers;
|
||||
if(channels > 1)
|
||||
speakers = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
|
||||
else speakers = SL_SPEAKER_FRONT_CENTER;
|
||||
SLDataFormat_PCM format_pcm = {SL_DATAFORMAT_PCM,channels, sr,
|
||||
SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16,
|
||||
speakers, SL_BYTEORDER_LITTLEENDIAN};
|
||||
|
||||
SLDataSource audioSrc = {&loc_bufq, &format_pcm};
|
||||
if (result != SL_RESULT_SUCCESS) goto end_openaudio;
|
||||
|
||||
// configure audio sink
|
||||
SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, p->outputMixObject};
|
||||
SLDataSink audioSnk = {&loc_outmix, NULL};
|
||||
int speakers;
|
||||
|
||||
// create audio player
|
||||
const SLInterfaceID ids1[] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_VOLUME};
|
||||
const SLboolean req1[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
|
||||
result = (*p->engineEngine)->CreateAudioPlayer(p->engineEngine,
|
||||
&(p->bqPlayerObject), &audioSrc, &audioSnk, 2, ids1, req1);
|
||||
if (channels > 1)
|
||||
speakers = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
|
||||
else speakers = SL_SPEAKER_FRONT_CENTER;
|
||||
|
||||
SLDataFormat_PCM format_pcm = {SL_DATAFORMAT_PCM, channels, sr,
|
||||
SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16,
|
||||
speakers, SL_BYTEORDER_LITTLEENDIAN
|
||||
};
|
||||
SLDataSource audioSrc = {&loc_bufq, &format_pcm};
|
||||
// configure audio sink
|
||||
SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, p->outputMixObject};
|
||||
SLDataSink audioSnk = {&loc_outmix, NULL};
|
||||
// create audio player
|
||||
const SLInterfaceID ids1[] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_VOLUME};
|
||||
const SLboolean req1[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
|
||||
result = (*p->engineEngine)->CreateAudioPlayer(p->engineEngine,
|
||||
&(p->bqPlayerObject), &audioSrc, &audioSnk, 2, ids1, req1);
|
||||
DEBUG_SND("bqPlayerObject=%p", p->bqPlayerObject);
|
||||
assert(!result);
|
||||
if(result != SL_RESULT_SUCCESS) goto end_openaudio;
|
||||
|
||||
// realize the player
|
||||
result = (*p->bqPlayerObject)->Realize(p->bqPlayerObject, SL_BOOLEAN_FALSE);
|
||||
if (result != SL_RESULT_SUCCESS) goto end_openaudio;
|
||||
|
||||
// realize the player
|
||||
result = (*p->bqPlayerObject)->Realize(p->bqPlayerObject, SL_BOOLEAN_FALSE);
|
||||
DEBUG_SND("Realize=%d", result);
|
||||
assert(!result);
|
||||
if(result != SL_RESULT_SUCCESS) goto end_openaudio;
|
||||
|
||||
// get the play interface
|
||||
result = (*p->bqPlayerObject)->GetInterface(p->bqPlayerObject, SL_IID_PLAY, &(p->bqPlayerPlay));
|
||||
if (result != SL_RESULT_SUCCESS) goto end_openaudio;
|
||||
|
||||
// get the play interface
|
||||
result = (*p->bqPlayerObject)->GetInterface(p->bqPlayerObject, SL_IID_PLAY,
|
||||
&(p->bqPlayerPlay));
|
||||
DEBUG_SND("bqPlayerPlay=%p", p->bqPlayerPlay);
|
||||
assert(!result);
|
||||
if(result != SL_RESULT_SUCCESS) goto end_openaudio;
|
||||
|
||||
// get the volume interface
|
||||
result = (*p->bqPlayerObject)->GetInterface(p->bqPlayerObject, SL_IID_VOLUME, &(p->bqPlayerVolume));
|
||||
if (result != SL_RESULT_SUCCESS) goto end_openaudio;
|
||||
|
||||
// get the volume interface
|
||||
result = (*p->bqPlayerObject)->GetInterface(p->bqPlayerObject, SL_IID_VOLUME,
|
||||
&(p->bqPlayerVolume));
|
||||
DEBUG_SND("bqPlayerVolume=%p", p->bqPlayerVolume);
|
||||
assert(!result);
|
||||
if(result != SL_RESULT_SUCCESS) goto end_openaudio;
|
||||
|
||||
// get the buffer queue interface
|
||||
result = (*p->bqPlayerObject)->GetInterface(p->bqPlayerObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
|
||||
&(p->bqPlayerBufferQueue));
|
||||
if (result != SL_RESULT_SUCCESS) goto end_openaudio;
|
||||
|
||||
// get the buffer queue interface
|
||||
result = (*p->bqPlayerObject)->GetInterface(p->bqPlayerObject,
|
||||
SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
|
||||
&(p->bqPlayerBufferQueue));
|
||||
DEBUG_SND("bqPlayerBufferQueue=%p", p->bqPlayerBufferQueue);
|
||||
assert(!result);
|
||||
if(result != SL_RESULT_SUCCESS) goto end_openaudio;
|
||||
|
||||
// register callback on the buffer queue
|
||||
result = (*p->bqPlayerBufferQueue)->RegisterCallback(p->bqPlayerBufferQueue, bqPlayerCallback, p);
|
||||
if (result != SL_RESULT_SUCCESS) goto end_openaudio;
|
||||
|
||||
// register callback on the buffer queue
|
||||
result = (*p->bqPlayerBufferQueue)->RegisterCallback(p->bqPlayerBufferQueue,
|
||||
bqPlayerCallback, p);
|
||||
DEBUG_SND("bqPlayerCallback=%p", p->bqPlayerCallback);
|
||||
assert(!result);
|
||||
if(result != SL_RESULT_SUCCESS) goto end_openaudio;
|
||||
|
||||
// set the player's state to playing
|
||||
result = (*p->bqPlayerPlay)->SetPlayState(p->bqPlayerPlay, SL_PLAYSTATE_PLAYING);
|
||||
if (result != SL_RESULT_SUCCESS) goto end_openaudio;
|
||||
|
||||
// set the player's state to playing
|
||||
result = (*p->bqPlayerPlay)->SetPlayState(p->bqPlayerPlay,
|
||||
SL_PLAYSTATE_PLAYING);
|
||||
DEBUG_SND("SetPlayState=%d", result);
|
||||
assert(!result);
|
||||
|
||||
end_openaudio:
|
||||
end_openaudio:
|
||||
assert(!result);
|
||||
return result;
|
||||
}
|
||||
return SL_RESULT_SUCCESS;
|
||||
return result;
|
||||
}
|
||||
|
||||
return SL_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
// close the OpenSL IO and destroy the audio engine
|
||||
static void openSLDestroyEngine(OPENSL_STREAM *p){
|
||||
static void openSLDestroyEngine(OPENSL_STREAM* p)
|
||||
{
|
||||
// destroy buffer queue audio player object, and invalidate all associated interfaces
|
||||
if (p->bqPlayerObject != NULL)
|
||||
{
|
||||
(*p->bqPlayerObject)->Destroy(p->bqPlayerObject);
|
||||
p->bqPlayerObject = NULL;
|
||||
p->bqPlayerVolume = NULL;
|
||||
p->bqPlayerPlay = NULL;
|
||||
p->bqPlayerBufferQueue = NULL;
|
||||
p->bqPlayerEffectSend = NULL;
|
||||
}
|
||||
|
||||
// destroy buffer queue audio player object, and invalidate all associated interfaces
|
||||
if (p->bqPlayerObject != NULL) {
|
||||
(*p->bqPlayerObject)->Destroy(p->bqPlayerObject);
|
||||
p->bqPlayerObject = NULL;
|
||||
p->bqPlayerVolume = NULL;
|
||||
p->bqPlayerPlay = NULL;
|
||||
p->bqPlayerBufferQueue = NULL;
|
||||
p->bqPlayerEffectSend = NULL;
|
||||
}
|
||||
|
||||
// destroy output mix object, and invalidate all associated interfaces
|
||||
if (p->outputMixObject != NULL) {
|
||||
(*p->outputMixObject)->Destroy(p->outputMixObject);
|
||||
p->outputMixObject = NULL;
|
||||
}
|
||||
|
||||
// destroy engine object, and invalidate all associated interfaces
|
||||
if (p->engineObject != NULL) {
|
||||
(*p->engineObject)->Destroy(p->engineObject);
|
||||
p->engineObject = NULL;
|
||||
p->engineEngine = NULL;
|
||||
}
|
||||
// destroy output mix object, and invalidate all associated interfaces
|
||||
if (p->outputMixObject != NULL)
|
||||
{
|
||||
(*p->outputMixObject)->Destroy(p->outputMixObject);
|
||||
p->outputMixObject = NULL;
|
||||
}
|
||||
|
||||
// destroy engine object, and invalidate all associated interfaces
|
||||
if (p->engineObject != NULL)
|
||||
{
|
||||
(*p->engineObject)->Destroy(p->engineObject);
|
||||
p->engineObject = NULL;
|
||||
p->engineEngine = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// open the android audio device for and/or output
|
||||
OPENSL_STREAM *android_OpenAudioDevice(int sr, int outchannels, int bufferframes){
|
||||
OPENSL_STREAM *p;
|
||||
p = (OPENSL_STREAM *) calloc(sizeof(OPENSL_STREAM), 1);
|
||||
OPENSL_STREAM* android_OpenAudioDevice(int sr, int outchannels,
|
||||
int bufferframes)
|
||||
{
|
||||
OPENSL_STREAM* p;
|
||||
p = (OPENSL_STREAM*) calloc(sizeof(OPENSL_STREAM), 1);
|
||||
|
||||
if (!p)
|
||||
return NULL;
|
||||
|
||||
@ -238,19 +273,20 @@ OPENSL_STREAM *android_OpenAudioDevice(int sr, int outchannels, int bufferframes
|
||||
p->outchannels = outchannels;
|
||||
p->sr = sr;
|
||||
|
||||
if(openSLCreateEngine(p) != SL_RESULT_SUCCESS)
|
||||
if (openSLCreateEngine(p) != SL_RESULT_SUCCESS)
|
||||
{
|
||||
android_CloseAudioDevice(p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(openSLPlayOpen(p) != SL_RESULT_SUCCESS)
|
||||
if (openSLPlayOpen(p) != SL_RESULT_SUCCESS)
|
||||
{
|
||||
android_CloseAudioDevice(p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p->queue = Queue_New(TRUE, -1, -1);
|
||||
|
||||
if (!p->queue)
|
||||
{
|
||||
android_CloseAudioDevice(p);
|
||||
@ -261,107 +297,120 @@ OPENSL_STREAM *android_OpenAudioDevice(int sr, int outchannels, int bufferframes
|
||||
}
|
||||
|
||||
// close the android audio device
|
||||
void android_CloseAudioDevice(OPENSL_STREAM *p){
|
||||
void android_CloseAudioDevice(OPENSL_STREAM* p)
|
||||
{
|
||||
if (p == NULL)
|
||||
return;
|
||||
|
||||
if (p == NULL)
|
||||
return;
|
||||
openSLDestroyEngine(p);
|
||||
|
||||
openSLDestroyEngine(p);
|
||||
if (p->queue)
|
||||
Queue_Free(p->queue);
|
||||
|
||||
free(p);
|
||||
free(p);
|
||||
}
|
||||
|
||||
// this callback handler is called every time a buffer finishes playing
|
||||
void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context)
|
||||
static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void* context)
|
||||
{
|
||||
OPENSL_STREAM *p = (OPENSL_STREAM *) context;
|
||||
|
||||
OPENSL_STREAM* p = (OPENSL_STREAM*) context;
|
||||
assert(p);
|
||||
assert(p->queue);
|
||||
|
||||
void *data = Queue_Dequeue(p->queue);
|
||||
void* data = Queue_Dequeue(p->queue);
|
||||
free(data);
|
||||
}
|
||||
|
||||
// puts a buffer of size samples to the device
|
||||
int android_AudioOut(OPENSL_STREAM *p, const short *buffer,int size)
|
||||
int android_AudioOut(OPENSL_STREAM* p, const short* buffer, int size)
|
||||
{
|
||||
assert(p);
|
||||
assert(buffer);
|
||||
assert(size > 0);
|
||||
|
||||
/* Assure, that the queue is not full. */
|
||||
if (p->queuesize <= Queue_Count(p->queue) && WaitForSingleObject(p->queue->event, INFINITE) == WAIT_FAILED)
|
||||
{
|
||||
DEBUG_SND("WaitForSingleObject failed!");
|
||||
return -1;
|
||||
}
|
||||
if (p->queuesize <= Queue_Count(p->queue)
|
||||
&& WaitForSingleObject(p->queue->event, INFINITE) == WAIT_FAILED)
|
||||
{
|
||||
DEBUG_SND("WaitForSingleObject failed!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
void* data = calloc(size, sizeof(short));
|
||||
|
||||
void *data = calloc(size, sizeof(short));
|
||||
if (!data)
|
||||
{
|
||||
DEBUG_SND("unable to allocate a buffer");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(data, buffer, size * sizeof(short));
|
||||
Queue_Enqueue(p->queue, data);
|
||||
(*p->bqPlayerBufferQueue)->Enqueue(p->bqPlayerBufferQueue,
|
||||
data, sizeof(short) * size);
|
||||
|
||||
(*p->bqPlayerBufferQueue)->Enqueue(p->bqPlayerBufferQueue,
|
||||
data, sizeof(short) * size);
|
||||
return size;
|
||||
}
|
||||
|
||||
int android_GetOutputMute(OPENSL_STREAM *p) {
|
||||
int android_GetOutputMute(OPENSL_STREAM* p)
|
||||
{
|
||||
SLboolean mute;
|
||||
|
||||
assert(p);
|
||||
assert(p->bqPlayerVolume);
|
||||
|
||||
SLresult rc = (*p->bqPlayerVolume)->GetMute(p->bqPlayerVolume, &mute);
|
||||
assert(SL_RESULT_SUCCESS == rc);
|
||||
|
||||
if (SL_RESULT_SUCCESS != rc)
|
||||
return SL_BOOLEAN_FALSE;
|
||||
|
||||
return mute;
|
||||
}
|
||||
|
||||
void android_SetOutputMute(OPENSL_STREAM *p, BOOL _mute) {
|
||||
BOOL android_SetOutputMute(OPENSL_STREAM* p, BOOL _mute)
|
||||
{
|
||||
SLboolean mute = _mute;
|
||||
|
||||
assert(p);
|
||||
assert(p->bqPlayerVolume);
|
||||
|
||||
SLresult rc = (*p->bqPlayerVolume)->SetMute(p->bqPlayerVolume, mute);
|
||||
assert(SL_RESULT_SUCCESS == rc);
|
||||
|
||||
if (SL_RESULT_SUCCESS != rc)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int android_GetOutputVolume(OPENSL_STREAM *p){
|
||||
int android_GetOutputVolume(OPENSL_STREAM* p)
|
||||
{
|
||||
SLmillibel level;
|
||||
|
||||
assert(p);
|
||||
assert(p->bqPlayerVolume);
|
||||
|
||||
SLresult rc = (*p->bqPlayerVolume)->GetVolumeLevel(p->bqPlayerVolume, &level);
|
||||
assert(SL_RESULT_SUCCESS == rc);
|
||||
|
||||
if (SL_RESULT_SUCCESS != rc)
|
||||
return 0;
|
||||
|
||||
return level;
|
||||
}
|
||||
|
||||
int android_GetOutputVolumeMax(OPENSL_STREAM *p){
|
||||
int android_GetOutputVolumeMax(OPENSL_STREAM* p)
|
||||
{
|
||||
SLmillibel level;
|
||||
|
||||
assert(p);
|
||||
assert(p->bqPlayerVolume);
|
||||
SLresult rc = (*p->bqPlayerVolume)->GetMaxVolumeLevel(p->bqPlayerVolume,
|
||||
&level);
|
||||
|
||||
SLresult rc = (*p->bqPlayerVolume)->GetMaxVolumeLevel(p->bqPlayerVolume, &level);
|
||||
assert(SL_RESULT_SUCCESS == rc);
|
||||
if (SL_RESULT_SUCCESS != rc)
|
||||
return 0;
|
||||
|
||||
return level;
|
||||
}
|
||||
|
||||
|
||||
void android_SetOutputVolume(OPENSL_STREAM *p, int level){
|
||||
BOOL android_SetOutputVolume(OPENSL_STREAM* p, int level)
|
||||
{
|
||||
SLresult rc = (*p->bqPlayerVolume)->SetVolumeLevel(p->bqPlayerVolume, level);
|
||||
assert(SL_RESULT_SUCCESS == rc);
|
||||
|
||||
if (SL_RESULT_SUCCESS != rc)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
@ -6,14 +6,14 @@ All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* 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.
|
||||
* Neither the name of the <organization> nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* 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.
|
||||
* Neither the name of the <organization> nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
@ -35,70 +35,75 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <stdlib.h>
|
||||
#include <winpr/synch.h>
|
||||
|
||||
#include <freerdp/api.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct opensl_stream {
|
||||
// engine interfaces
|
||||
SLObjectItf engineObject;
|
||||
SLEngineItf engineEngine;
|
||||
typedef struct opensl_stream
|
||||
{
|
||||
// engine interfaces
|
||||
SLObjectItf engineObject;
|
||||
SLEngineItf engineEngine;
|
||||
|
||||
// output mix interfaces
|
||||
SLObjectItf outputMixObject;
|
||||
// output mix interfaces
|
||||
SLObjectItf outputMixObject;
|
||||
|
||||
// buffer queue player interfaces
|
||||
SLObjectItf bqPlayerObject;
|
||||
SLPlayItf bqPlayerPlay;
|
||||
// buffer queue player interfaces
|
||||
SLObjectItf bqPlayerObject;
|
||||
SLPlayItf bqPlayerPlay;
|
||||
SLVolumeItf bqPlayerVolume;
|
||||
SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue;
|
||||
SLEffectSendItf bqPlayerEffectSend;
|
||||
SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue;
|
||||
SLEffectSendItf bqPlayerEffectSend;
|
||||
|
||||
unsigned int outchannels;
|
||||
unsigned int sr;
|
||||
unsigned int outchannels;
|
||||
unsigned int sr;
|
||||
|
||||
unsigned int queuesize;
|
||||
wQueue *queue;
|
||||
wQueue* queue;
|
||||
} OPENSL_STREAM;
|
||||
|
||||
/*
|
||||
Open the audio device with a given sampling rate (sr), output channels and IO buffer size
|
||||
in frames. Returns a handle to the OpenSL stream
|
||||
*/
|
||||
OPENSL_STREAM* android_OpenAudioDevice(int sr, int outchannels, int bufferframes);
|
||||
/*
|
||||
Close the audio device
|
||||
*/
|
||||
void android_CloseAudioDevice(OPENSL_STREAM *p);
|
||||
/*
|
||||
Write a buffer to the OpenSL stream *p, of size samples. Returns the number of samples written.
|
||||
*/
|
||||
int android_AudioOut(OPENSL_STREAM *p, const short *buffer, int size);
|
||||
/*
|
||||
* Set the volume input level.
|
||||
*/
|
||||
void android_SetInputVolume(OPENSL_STREAM *p, int level);
|
||||
/*
|
||||
* Get the current output mute setting.
|
||||
*/
|
||||
int android_GetOutputMute(OPENSL_STREAM *p);
|
||||
/*
|
||||
* Change the current output mute setting.
|
||||
*/
|
||||
void android_SetOutputMute(OPENSL_STREAM *p, BOOL mute);
|
||||
/*
|
||||
* Get the current output volume level.
|
||||
*/
|
||||
int android_GetOutputVolume(OPENSL_STREAM *p);
|
||||
/*
|
||||
* Get the maximum output volume level.
|
||||
*/
|
||||
int android_GetOutputVolumeMax(OPENSL_STREAM *p);
|
||||
/*
|
||||
Open the audio device with a given sampling rate (sr), output channels and IO buffer size
|
||||
in frames. Returns a handle to the OpenSL stream
|
||||
*/
|
||||
FREERDP_LOCAL OPENSL_STREAM* android_OpenAudioDevice(int sr, int outchannels,
|
||||
int bufferframes);
|
||||
/*
|
||||
Close the audio device
|
||||
*/
|
||||
FREERDP_LOCAL void android_CloseAudioDevice(OPENSL_STREAM* p);
|
||||
/*
|
||||
Write a buffer to the OpenSL stream *p, of size samples. Returns the number of samples written.
|
||||
*/
|
||||
FREERDP_LOCAL int android_AudioOut(OPENSL_STREAM* p, const short* buffer,
|
||||
int size);
|
||||
/*
|
||||
* Set the volume input level.
|
||||
*/
|
||||
FREERDP_LOCAL void android_SetInputVolume(OPENSL_STREAM* p, int level);
|
||||
/*
|
||||
* Get the current output mute setting.
|
||||
*/
|
||||
FREERDP_LOCAL int android_GetOutputMute(OPENSL_STREAM* p);
|
||||
/*
|
||||
* Change the current output mute setting.
|
||||
*/
|
||||
FREERDP_LOCAL BOOL android_SetOutputMute(OPENSL_STREAM* p, BOOL mute);
|
||||
/*
|
||||
* Get the current output volume level.
|
||||
*/
|
||||
FREERDP_LOCAL int android_GetOutputVolume(OPENSL_STREAM* p);
|
||||
/*
|
||||
* Get the maximum output volume level.
|
||||
*/
|
||||
FREERDP_LOCAL int android_GetOutputVolumeMax(OPENSL_STREAM* p);
|
||||
|
||||
/*
|
||||
* Set the volume output level.
|
||||
*/
|
||||
void android_SetOutputVolume(OPENSL_STREAM *p, int level);
|
||||
/*
|
||||
* Set the volume output level.
|
||||
*/
|
||||
FREERDP_LOCAL BOOL android_SetOutputVolume(OPENSL_STREAM* p, int level);
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -53,7 +53,7 @@ struct rdpsnd_opensles_plugin
|
||||
int block_size;
|
||||
char* device_name;
|
||||
|
||||
OPENSL_STREAM *stream;
|
||||
OPENSL_STREAM* stream;
|
||||
|
||||
UINT32 volume;
|
||||
|
||||
@ -68,10 +68,8 @@ static int rdpsnd_opensles_volume_to_millibel(unsigned short level, int max)
|
||||
const int min = SL_MILLIBEL_MIN;
|
||||
const int step = max - min;
|
||||
const int rc = (level * step / 0xFFFF) + min;
|
||||
|
||||
DEBUG_SND("level=%d, min=%d, max=%d, step=%d, result=%d",
|
||||
level, min, max, step, rc);
|
||||
|
||||
level, min, max, step, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -80,14 +78,12 @@ static unsigned short rdpsnd_opensles_millibel_to_volume(int millibel, int max)
|
||||
const int min = SL_MILLIBEL_MIN;
|
||||
const int range = max - min;
|
||||
const int rc = ((millibel - min) * 0xFFFF + range / 2 + 1) / range;
|
||||
|
||||
DEBUG_SND("millibel=%d, min=%d, max=%d, range=%d, result=%d",
|
||||
millibel, min, max, range, rc);
|
||||
|
||||
millibel, min, max, range, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static bool rdpsnd_opensles_check_handle(const rdpsndopenslesPlugin *hdl)
|
||||
static bool rdpsnd_opensles_check_handle(const rdpsndopenslesPlugin* hdl)
|
||||
{
|
||||
bool rc = true;
|
||||
|
||||
@ -97,6 +93,7 @@ static bool rdpsnd_opensles_check_handle(const rdpsndopenslesPlugin *hdl)
|
||||
{
|
||||
if (!hdl->dsp_context)
|
||||
rc = false;
|
||||
|
||||
if (!hdl->stream)
|
||||
rc = false;
|
||||
}
|
||||
@ -105,11 +102,12 @@ static bool rdpsnd_opensles_check_handle(const rdpsndopenslesPlugin *hdl)
|
||||
}
|
||||
|
||||
static BOOL rdpsnd_opensles_set_volume(rdpsndDevicePlugin* device,
|
||||
UINT32 volume);
|
||||
UINT32 volume);
|
||||
|
||||
static int rdpsnd_opensles_set_params(rdpsndopenslesPlugin* opensles)
|
||||
{
|
||||
DEBUG_SND("opensles=%p", opensles);
|
||||
|
||||
if (!rdpsnd_opensles_check_handle(opensles))
|
||||
return 0;
|
||||
|
||||
@ -117,25 +115,22 @@ static int rdpsnd_opensles_set_params(rdpsndopenslesPlugin* opensles)
|
||||
android_CloseAudioDevice(opensles->stream);
|
||||
|
||||
opensles->stream = android_OpenAudioDevice(
|
||||
opensles->rate, opensles->channels, 20);
|
||||
|
||||
opensles->rate, opensles->channels, 20);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL rdpsnd_opensles_set_format(rdpsndDevicePlugin* device,
|
||||
AUDIO_FORMAT* format, int latency)
|
||||
AUDIO_FORMAT* format, int latency)
|
||||
{
|
||||
rdpsndopenslesPlugin* opensles = (rdpsndopenslesPlugin*) device;
|
||||
rdpsnd_opensles_check_handle(opensles);
|
||||
|
||||
DEBUG_SND("opensles=%p format=%p, latency=%d", opensles, format, latency);
|
||||
|
||||
if (format)
|
||||
{
|
||||
DEBUG_SND("format=%d, cbsize=%d, samples=%d, bits=%d, channels=%d, align=%d",
|
||||
format->wFormatTag, format->cbSize, format->nSamplesPerSec,
|
||||
format->wBitsPerSample, format->nChannels, format->nBlockAlign);
|
||||
|
||||
format->wFormatTag, format->cbSize, format->nSamplesPerSec,
|
||||
format->wBitsPerSample, format->nChannels, format->nBlockAlign);
|
||||
opensles->rate = format->nSamplesPerSec;
|
||||
opensles->channels = format->nChannels;
|
||||
opensles->format = format->wFormatTag;
|
||||
@ -144,22 +139,21 @@ static BOOL rdpsnd_opensles_set_format(rdpsndDevicePlugin* device,
|
||||
}
|
||||
|
||||
opensles->latency = latency;
|
||||
|
||||
return (rdpsnd_opensles_set_params(opensles) == 0);
|
||||
}
|
||||
|
||||
static BOOL rdpsnd_opensles_open(rdpsndDevicePlugin* device,
|
||||
AUDIO_FORMAT* format, int latency)
|
||||
AUDIO_FORMAT* format, int latency)
|
||||
{
|
||||
rdpsndopenslesPlugin* opensles = (rdpsndopenslesPlugin*) device;
|
||||
|
||||
DEBUG_SND("opensles=%p format=%p, latency=%d, rate=%d",
|
||||
opensles, format, latency, opensles->rate);
|
||||
|
||||
opensles, format, latency, opensles->rate);
|
||||
|
||||
if (rdpsnd_opensles_check_handle(opensles))
|
||||
return TRUE;
|
||||
|
||||
opensles->stream = android_OpenAudioDevice(opensles->rate, opensles->channels, 20);
|
||||
opensles->stream = android_OpenAudioDevice(opensles->rate, opensles->channels,
|
||||
20);
|
||||
assert(opensles->stream);
|
||||
|
||||
if (!opensles->stream)
|
||||
@ -174,9 +168,9 @@ static BOOL rdpsnd_opensles_open(rdpsndDevicePlugin* device,
|
||||
static void rdpsnd_opensles_close(rdpsndDevicePlugin* device)
|
||||
{
|
||||
rdpsndopenslesPlugin* opensles = (rdpsndopenslesPlugin*) device;
|
||||
|
||||
DEBUG_SND("opensles=%p", opensles);
|
||||
if( !rdpsnd_opensles_check_handle(opensles))
|
||||
|
||||
if (!rdpsnd_opensles_check_handle(opensles))
|
||||
return;
|
||||
|
||||
android_CloseAudioDevice(opensles->stream);
|
||||
@ -186,51 +180,46 @@ static void rdpsnd_opensles_close(rdpsndDevicePlugin* device)
|
||||
static void rdpsnd_opensles_free(rdpsndDevicePlugin* device)
|
||||
{
|
||||
rdpsndopenslesPlugin* opensles = (rdpsndopenslesPlugin*) device;
|
||||
|
||||
DEBUG_SND("opensles=%p", opensles);
|
||||
assert(opensles);
|
||||
|
||||
assert(opensles->device_name);
|
||||
free(opensles->device_name);
|
||||
|
||||
assert(opensles->dsp_context);
|
||||
freerdp_dsp_context_free(opensles->dsp_context);
|
||||
|
||||
free(opensles);
|
||||
}
|
||||
|
||||
static BOOL rdpsnd_opensles_format_supported(rdpsndDevicePlugin* device,
|
||||
AUDIO_FORMAT* format)
|
||||
AUDIO_FORMAT* format)
|
||||
{
|
||||
rdpsndopenslesPlugin* opensles = (rdpsndopenslesPlugin*) device;
|
||||
|
||||
DEBUG_SND("format=%d, cbsize=%d, samples=%d, bits=%d, channels=%d, align=%d",
|
||||
format->wFormatTag, format->cbSize, format->nSamplesPerSec,
|
||||
format->wBitsPerSample, format->nChannels, format->nBlockAlign);
|
||||
|
||||
assert(opensles);
|
||||
format->wFormatTag, format->cbSize, format->nSamplesPerSec,
|
||||
format->wBitsPerSample, format->nChannels, format->nBlockAlign);
|
||||
assert(device);
|
||||
assert(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 TRUE;
|
||||
}
|
||||
|
||||
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 TRUE;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case WAVE_FORMAT_ALAW:
|
||||
@ -246,7 +235,6 @@ static BOOL rdpsnd_opensles_format_supported(rdpsndDevicePlugin* device,
|
||||
static UINT32 rdpsnd_opensles_get_volume(rdpsndDevicePlugin* device)
|
||||
{
|
||||
rdpsndopenslesPlugin* opensles = (rdpsndopenslesPlugin*) device;
|
||||
|
||||
DEBUG_SND("opensles=%p", opensles);
|
||||
assert(opensles);
|
||||
|
||||
@ -263,31 +251,32 @@ static UINT32 rdpsnd_opensles_get_volume(rdpsndDevicePlugin* device)
|
||||
opensles->volume = (vol << 16) | (vol & 0xFFFF);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return opensles->volume;
|
||||
}
|
||||
|
||||
static BOOL rdpsnd_opensles_set_volume(rdpsndDevicePlugin* device,
|
||||
UINT32 value)
|
||||
UINT32 value)
|
||||
{
|
||||
rdpsndopenslesPlugin* opensles = (rdpsndopenslesPlugin*) device;
|
||||
|
||||
DEBUG_SND("opensles=%p, value=%d", opensles, value);
|
||||
assert(opensles);
|
||||
|
||||
opensles->volume = value;
|
||||
|
||||
if (opensles->stream)
|
||||
{
|
||||
if (0 == opensles->volume)
|
||||
android_SetOutputMute(opensles->stream, true);
|
||||
return android_SetOutputMute(opensles->stream, true);
|
||||
else
|
||||
{
|
||||
const int max = android_GetOutputVolumeMax(opensles->stream);
|
||||
const int vol = rdpsnd_opensles_volume_to_millibel(value & 0xFFFF, max);
|
||||
|
||||
android_SetOutputMute(opensles->stream, false);
|
||||
android_SetOutputVolume(opensles->stream, vol);
|
||||
if (!android_SetOutputMute(opensles->stream, false))
|
||||
return FALSE;
|
||||
|
||||
if (!android_SetOutputVolume(opensles->stream, vol))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -295,53 +284,49 @@ static BOOL rdpsnd_opensles_set_volume(rdpsndDevicePlugin* device,
|
||||
}
|
||||
|
||||
static void rdpsnd_opensles_play(rdpsndDevicePlugin* device,
|
||||
BYTE *data, int size)
|
||||
BYTE* data, int size)
|
||||
{
|
||||
union
|
||||
{
|
||||
BYTE *b;
|
||||
short *s;
|
||||
BYTE* b;
|
||||
short* s;
|
||||
} src;
|
||||
int ret;
|
||||
rdpsndopenslesPlugin* opensles = (rdpsndopenslesPlugin*) device;
|
||||
|
||||
DEBUG_SND("opensles=%p, data=%p, size=%d", opensles, data, size);
|
||||
|
||||
if (!rdpsnd_opensles_check_handle(opensles))
|
||||
return;
|
||||
|
||||
if (opensles->format == WAVE_FORMAT_ADPCM)
|
||||
{
|
||||
DEBUG_SND("dsp_context=%p, channels=%d, block_size=%d",
|
||||
opensles->dsp_context, opensles->channels, opensles->block_size);
|
||||
|
||||
opensles->dsp_context, opensles->channels, opensles->block_size);
|
||||
opensles->dsp_context->decode_ms_adpcm(opensles->dsp_context,
|
||||
data, size, opensles->channels, opensles->block_size);
|
||||
|
||||
data, size, opensles->channels, opensles->block_size);
|
||||
size = opensles->dsp_context->adpcm_size;
|
||||
src.b = opensles->dsp_context->adpcm_buffer;
|
||||
}
|
||||
else if (opensles->format == WAVE_FORMAT_DVI_ADPCM)
|
||||
{
|
||||
DEBUG_SND("dsp_context=%p, channels=%d, block_size=%d",
|
||||
opensles->dsp_context, opensles->channels, opensles->block_size);
|
||||
|
||||
opensles->dsp_context, opensles->channels, opensles->block_size);
|
||||
opensles->dsp_context->decode_ima_adpcm(opensles->dsp_context,
|
||||
data, size, opensles->channels, opensles->block_size);
|
||||
|
||||
data, size, opensles->channels, opensles->block_size);
|
||||
size = opensles->dsp_context->adpcm_size;
|
||||
src.b = opensles->dsp_context->adpcm_buffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
src.b = data;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_SND("size=%d, src=%p", size, src.b);
|
||||
assert(0 == size % 2);
|
||||
assert(size > 0);
|
||||
assert(src.b);
|
||||
|
||||
ret = android_AudioOut(opensles->stream, src.s, size / 2);
|
||||
|
||||
if (ret < 0)
|
||||
WLog_ERR(TAG, "android_AudioOut failed (%d)", ret);
|
||||
}
|
||||
@ -350,34 +335,33 @@ static void rdpsnd_opensles_start(rdpsndDevicePlugin* device)
|
||||
{
|
||||
rdpsndopenslesPlugin* opensles = (rdpsndopenslesPlugin*) device;
|
||||
rdpsnd_opensles_check_handle(opensles);
|
||||
|
||||
DEBUG_SND("opensles=%p", opensles);
|
||||
}
|
||||
|
||||
static COMMAND_LINE_ARGUMENT_A rdpsnd_opensles_args[] =
|
||||
{
|
||||
{ "dev", COMMAND_LINE_VALUE_REQUIRED, "<device>",
|
||||
NULL, NULL, -1, NULL, "device" },
|
||||
{
|
||||
"dev", COMMAND_LINE_VALUE_REQUIRED, "<device>",
|
||||
NULL, NULL, -1, NULL, "device"
|
||||
},
|
||||
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
|
||||
};
|
||||
|
||||
static int rdpsnd_opensles_parse_addin_args(rdpsndDevicePlugin* device,
|
||||
ADDIN_ARGV* args)
|
||||
ADDIN_ARGV* args)
|
||||
{
|
||||
int status;
|
||||
DWORD flags;
|
||||
COMMAND_LINE_ARGUMENT_A* arg;
|
||||
rdpsndopenslesPlugin* opensles = (rdpsndopenslesPlugin*) device;
|
||||
|
||||
assert(opensles);
|
||||
assert(args);
|
||||
|
||||
DEBUG_SND("opensles=%p, args=%p", opensles, args);
|
||||
|
||||
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD;
|
||||
|
||||
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON |
|
||||
COMMAND_LINE_IGN_UNKNOWN_KEYWORD;
|
||||
status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv,
|
||||
rdpsnd_opensles_args, flags, opensles, NULL, NULL);
|
||||
rdpsnd_opensles_args, flags, opensles, NULL, NULL);
|
||||
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
@ -389,14 +373,13 @@ static int rdpsnd_opensles_parse_addin_args(rdpsndDevicePlugin* device,
|
||||
continue;
|
||||
|
||||
CommandLineSwitchStart(arg)
|
||||
|
||||
CommandLineSwitchCase(arg, "dev")
|
||||
{
|
||||
opensles->device_name = _strdup(arg->Value);
|
||||
|
||||
if (!opensles->device_name)
|
||||
return ERROR_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
CommandLineSwitchEnd(arg)
|
||||
}
|
||||
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
|
||||
@ -404,7 +387,7 @@ static int rdpsnd_opensles_parse_addin_args(rdpsndDevicePlugin* device,
|
||||
return status;
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#ifdef BUILTIN_CHANNELS
|
||||
#define freerdp_rdpsnd_client_subsystem_entry \
|
||||
opensles_freerdp_rdpsnd_client_subsystem_entry
|
||||
#else
|
||||
@ -418,15 +401,14 @@ static int rdpsnd_opensles_parse_addin_args(rdpsndDevicePlugin* device,
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT freerdp_rdpsnd_client_subsystem_entry(
|
||||
PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints)
|
||||
PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints)
|
||||
{
|
||||
ADDIN_ARGV* args;
|
||||
rdpsndopenslesPlugin* opensles;
|
||||
UINT error;
|
||||
|
||||
DEBUG_SND("pEntryPoints=%p", pEntryPoints);
|
||||
|
||||
opensles = (rdpsndopenslesPlugin*) calloc(1, sizeof(rdpsndopenslesPlugin));
|
||||
|
||||
if (!opensles)
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
|
||||
@ -439,13 +421,13 @@ UINT freerdp_rdpsnd_client_subsystem_entry(
|
||||
opensles->device.Play = rdpsnd_opensles_play;
|
||||
opensles->device.Close = rdpsnd_opensles_close;
|
||||
opensles->device.Free = rdpsnd_opensles_free;
|
||||
|
||||
args = pEntryPoints->args;
|
||||
rdpsnd_opensles_parse_addin_args((rdpsndDevicePlugin*) opensles, args);
|
||||
|
||||
if (!opensles->device_name)
|
||||
{
|
||||
opensles->device_name = _strdup("default");
|
||||
|
||||
if (!opensles->device_name)
|
||||
{
|
||||
error = CHANNEL_RC_NO_MEMORY;
|
||||
@ -456,8 +438,8 @@ UINT freerdp_rdpsnd_client_subsystem_entry(
|
||||
opensles->rate = 44100;
|
||||
opensles->channels = 2;
|
||||
opensles->format = WAVE_FORMAT_ADPCM;
|
||||
|
||||
opensles->dsp_context = freerdp_dsp_context_new();
|
||||
|
||||
if (!opensles->dsp_context)
|
||||
{
|
||||
error = CHANNEL_RC_NO_MEMORY;
|
||||
@ -465,8 +447,7 @@ UINT freerdp_rdpsnd_client_subsystem_entry(
|
||||
}
|
||||
|
||||
pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd,
|
||||
(rdpsndDevicePlugin*) opensles);
|
||||
|
||||
(rdpsndDevicePlugin*) opensles);
|
||||
DEBUG_SND("success");
|
||||
return CHANNEL_RC_OK;
|
||||
out_dsp_new:
|
||||
|
||||
@ -475,7 +475,7 @@ static int rdpsnd_oss_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV* a
|
||||
return status;
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#ifdef BUILTIN_CHANNELS
|
||||
#define freerdp_rdpsnd_client_subsystem_entry oss_freerdp_rdpsnd_client_subsystem_entry
|
||||
#else
|
||||
#define freerdp_rdpsnd_client_subsystem_entry FREERDP_API freerdp_rdpsnd_client_subsystem_entry
|
||||
|
||||
@ -584,7 +584,9 @@ static void rdpsnd_pulse_start(rdpsndDevicePlugin* device)
|
||||
if (!pulse->stream)
|
||||
return;
|
||||
|
||||
pa_threaded_mainloop_lock(pulse->mainloop);
|
||||
pa_stream_trigger(pulse->stream, NULL, NULL);
|
||||
pa_threaded_mainloop_unlock(pulse->mainloop);
|
||||
}
|
||||
|
||||
COMMAND_LINE_ARGUMENT_A rdpsnd_pulse_args[] =
|
||||
@ -634,7 +636,7 @@ static UINT rdpsnd_pulse_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#ifdef BUILTIN_CHANNELS
|
||||
#define freerdp_rdpsnd_client_subsystem_entry pulse_freerdp_rdpsnd_client_subsystem_entry
|
||||
#else
|
||||
#define freerdp_rdpsnd_client_subsystem_entry FREERDP_API freerdp_rdpsnd_client_subsystem_entry
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -30,9 +30,9 @@
|
||||
#define TAG CHANNELS_TAG("rdpsnd.client")
|
||||
|
||||
#if defined(WITH_DEBUG_SND)
|
||||
#define DEBUG_SND(fmt, ...) WLog_DBG(TAG, fmt, ## __VA_ARGS__)
|
||||
#define DEBUG_SND(...) WLog_DBG(TAG, __VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG_SND(fmt, ...) do { } while (0)
|
||||
#define DEBUG_SND(...) do { } while (0)
|
||||
#endif
|
||||
|
||||
UINT rdpsnd_virtual_channel_write(rdpsndPlugin* rdpsnd, wStream* s);
|
||||
|
||||
@ -32,7 +32,7 @@ set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} freerdp)
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
if (WITH_DEBUG_SYMBOLS AND MSVC AND NOT STATIC_CHANNELS AND BUILD_SHARED_LIBS)
|
||||
if (WITH_DEBUG_SYMBOLS AND MSVC AND NOT BUILTIN_CHANNELS AND BUILD_SHARED_LIBS)
|
||||
install(FILES ${CMAKE_PDB_BINARY_DIR}/${MODULE_NAME}.pdb DESTINATION ${FREERDP_ADDIN_PATH} COMPONENT symbols)
|
||||
endif()
|
||||
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
* Copyright 2010-2012 Vic Lee
|
||||
* Copyright 2015 Thincast Technologies GmbH
|
||||
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
|
||||
* Copyright 2016 David PHAM-VAN <d.phamvan@inuvika.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -136,6 +137,7 @@ static void CALLBACK rdpsnd_winmm_callback_function(HWAVEOUT hwo, UINT uMsg, DWO
|
||||
winmm->device.WaveConfirm(&(winmm->device), wave);
|
||||
|
||||
free(lpWaveHdr->lpData);
|
||||
free(lpWaveHdr);
|
||||
|
||||
free(wave);
|
||||
}
|
||||
@ -330,6 +332,7 @@ void rdpsnd_winmm_wave_play(rdpsndDevicePlugin* device, RDPSND_WAVE* wave)
|
||||
{
|
||||
WLog_ERR(TAG, "waveOutWrite failure: %d", mmResult);
|
||||
waveOutUnprepareHeader(winmm->hWaveOut, lpWaveHdr, sizeof(WAVEHDR));
|
||||
free(lpWaveHdr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -344,7 +347,7 @@ static void rdpsnd_winmm_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV
|
||||
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#ifdef BUILTIN_CHANNELS
|
||||
#define freerdp_rdpsnd_client_subsystem_entry winmm_freerdp_rdpsnd_client_subsystem_entry
|
||||
#else
|
||||
#define freerdp_rdpsnd_client_subsystem_entry FREERDP_API freerdp_rdpsnd_client_subsystem_entry
|
||||
|
||||
@ -46,11 +46,9 @@ UINT rdpsnd_server_send_formats(RdpsndServerContext* context, wStream* s)
|
||||
UINT16 i;
|
||||
BOOL status;
|
||||
ULONG written;
|
||||
|
||||
Stream_Write_UINT8(s, SNDC_FORMATS);
|
||||
Stream_Write_UINT8(s, 0);
|
||||
Stream_Seek_UINT16(s);
|
||||
|
||||
Stream_Write_UINT32(s, 0); /* dwFlags */
|
||||
Stream_Write_UINT32(s, 0); /* dwVolume */
|
||||
Stream_Write_UINT32(s, 0); /* dwPitch */
|
||||
@ -59,24 +57,27 @@ UINT rdpsnd_server_send_formats(RdpsndServerContext* context, wStream* s)
|
||||
Stream_Write_UINT8(s, context->block_no); /* cLastBlockConfirmed */
|
||||
Stream_Write_UINT16(s, 0x06); /* wVersion */
|
||||
Stream_Write_UINT8(s, 0); /* bPad */
|
||||
|
||||
|
||||
for (i = 0; i < context->num_server_formats; i++)
|
||||
{
|
||||
Stream_Write_UINT16(s, context->server_formats[i].wFormatTag); /* wFormatTag (WAVE_FORMAT_PCM) */
|
||||
Stream_Write_UINT16(s,
|
||||
context->server_formats[i].wFormatTag); /* wFormatTag (WAVE_FORMAT_PCM) */
|
||||
Stream_Write_UINT16(s, context->server_formats[i].nChannels); /* nChannels */
|
||||
Stream_Write_UINT32(s, context->server_formats[i].nSamplesPerSec); /* nSamplesPerSec */
|
||||
|
||||
Stream_Write_UINT32(s,
|
||||
context->server_formats[i].nSamplesPerSec); /* nSamplesPerSec */
|
||||
Stream_Write_UINT32(s, context->server_formats[i].nSamplesPerSec *
|
||||
context->server_formats[i].nChannels *
|
||||
context->server_formats[i].wBitsPerSample / 8); /* nAvgBytesPerSec */
|
||||
|
||||
Stream_Write_UINT16(s, context->server_formats[i].nBlockAlign); /* nBlockAlign */
|
||||
Stream_Write_UINT16(s, context->server_formats[i].wBitsPerSample); /* wBitsPerSample */
|
||||
context->server_formats[i].nChannels *
|
||||
context->server_formats[i].wBitsPerSample / 8); /* nAvgBytesPerSec */
|
||||
Stream_Write_UINT16(s,
|
||||
context->server_formats[i].nBlockAlign); /* nBlockAlign */
|
||||
Stream_Write_UINT16(s,
|
||||
context->server_formats[i].wBitsPerSample); /* wBitsPerSample */
|
||||
Stream_Write_UINT16(s, context->server_formats[i].cbSize); /* cbSize */
|
||||
|
||||
if (context->server_formats[i].cbSize > 0)
|
||||
{
|
||||
Stream_Write(s, context->server_formats[i].data, context->server_formats[i].cbSize);
|
||||
Stream_Write(s, context->server_formats[i].data,
|
||||
context->server_formats[i].cbSize);
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,10 +85,10 @@ UINT rdpsnd_server_send_formats(RdpsndServerContext* context, wStream* s)
|
||||
Stream_SetPosition(s, 2);
|
||||
Stream_Write_UINT16(s, pos - 4);
|
||||
Stream_SetPosition(s, pos);
|
||||
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written);
|
||||
status = WTSVirtualChannelWrite(context->priv->ChannelHandle,
|
||||
(PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written);
|
||||
Stream_SetPosition(s, 0);
|
||||
|
||||
return status ? CHANNEL_RC_OK: ERROR_INTERNAL_ERROR;
|
||||
return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -95,7 +96,8 @@ UINT rdpsnd_server_send_formats(RdpsndServerContext* context, wStream* s)
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT rdpsnd_server_recv_waveconfirm(RdpsndServerContext* context, wStream* s)
|
||||
static UINT rdpsnd_server_recv_waveconfirm(RdpsndServerContext* context,
|
||||
wStream* s)
|
||||
{
|
||||
UINT16 timestamp;
|
||||
BYTE confirmBlockNum;
|
||||
@ -110,10 +112,10 @@ static UINT rdpsnd_server_recv_waveconfirm(RdpsndServerContext* context, wStream
|
||||
Stream_Read_UINT16(s, timestamp);
|
||||
Stream_Read_UINT8(s, confirmBlockNum);
|
||||
Stream_Seek_UINT8(s);
|
||||
|
||||
IFCALLRET(context->ConfirmBlock, error, context, confirmBlockNum, timestamp);
|
||||
|
||||
if (error)
|
||||
WLog_ERR(TAG, "context->ConfirmBlock failed with error %lu", error);
|
||||
WLog_ERR(TAG, "context->ConfirmBlock failed with error %u", error);
|
||||
|
||||
return error;
|
||||
}
|
||||
@ -123,10 +125,11 @@ static UINT rdpsnd_server_recv_waveconfirm(RdpsndServerContext* context, wStream
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT rdpsnd_server_recv_quality_mode(RdpsndServerContext* context, wStream* s)
|
||||
static UINT rdpsnd_server_recv_quality_mode(RdpsndServerContext* context,
|
||||
wStream* s)
|
||||
{
|
||||
UINT16 quality;
|
||||
|
||||
|
||||
if (Stream_GetRemainingLength(s) < 4)
|
||||
{
|
||||
WLog_ERR(TAG, "not enought data in stream!");
|
||||
@ -180,7 +183,9 @@ static UINT rdpsnd_server_recv_formats(RdpsndServerContext* context, wStream* s)
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
context->client_formats = (AUDIO_FORMAT *)calloc(context->num_client_formats, sizeof(AUDIO_FORMAT));
|
||||
context->client_formats = (AUDIO_FORMAT*)calloc(context->num_client_formats,
|
||||
sizeof(AUDIO_FORMAT));
|
||||
|
||||
if (!context->client_formats)
|
||||
{
|
||||
WLog_ERR(TAG, "calloc failed!");
|
||||
@ -196,7 +201,6 @@ static UINT rdpsnd_server_recv_formats(RdpsndServerContext* context, wStream* s)
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
|
||||
Stream_Read_UINT16(s, context->client_formats[i].wFormatTag);
|
||||
Stream_Read_UINT16(s, context->client_formats[i].nChannels);
|
||||
Stream_Read_UINT32(s, context->client_formats[i].nSamplesPerSec);
|
||||
@ -213,7 +217,6 @@ static UINT rdpsnd_server_recv_formats(RdpsndServerContext* context, wStream* s)
|
||||
error = ERROR_INTERNAL_ERROR;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (context->client_formats[i].wFormatTag != 0)
|
||||
@ -231,7 +234,6 @@ static UINT rdpsnd_server_recv_formats(RdpsndServerContext* context, wStream* s)
|
||||
}
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
|
||||
out_free:
|
||||
free(context->client_formats);
|
||||
return error;
|
||||
@ -243,15 +245,15 @@ static void* rdpsnd_server_thread(void* arg)
|
||||
HANDLE events[8];
|
||||
RdpsndServerContext* context;
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
context = (RdpsndServerContext*)arg;
|
||||
|
||||
context = (RdpsndServerContext *)arg;
|
||||
nCount = 0;
|
||||
events[nCount++] = context->priv->channelEvent;
|
||||
events[nCount++] = context->priv->StopEvent;
|
||||
|
||||
if ((error = rdpsnd_server_send_formats(context, context->priv->rdpsnd_pdu)))
|
||||
{
|
||||
WLog_ERR(TAG, "rdpsnd_server_send_formats failed with error %lu", error);
|
||||
WLog_ERR(TAG, "rdpsnd_server_send_formats failed with error %u", error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -259,36 +261,38 @@ static void* rdpsnd_server_thread(void* arg)
|
||||
{
|
||||
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
|
||||
|
||||
if (status == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu!", error);
|
||||
break;
|
||||
}
|
||||
if (status == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForMultipleObjects failed with error %u!", error);
|
||||
break;
|
||||
}
|
||||
|
||||
status = WaitForSingleObject(context->priv->StopEvent, 0);
|
||||
|
||||
if (status == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
|
||||
break;
|
||||
}
|
||||
status = WaitForSingleObject(context->priv->StopEvent, 0);
|
||||
|
||||
if (status == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %u!", error);
|
||||
break;
|
||||
}
|
||||
|
||||
if (status == WAIT_OBJECT_0)
|
||||
break;
|
||||
|
||||
if ((error = rdpsnd_server_handle_messages(context)))
|
||||
{
|
||||
WLog_ERR(TAG, "rdpsnd_server_handle_messages failed with error %lu", error);
|
||||
WLog_ERR(TAG, "rdpsnd_server_handle_messages failed with error %u", error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
if (error && context->rdpcontext)
|
||||
setChannelError(context->rdpcontext, error, "rdpsnd_server_thread reported an error");
|
||||
setChannelError(context->rdpcontext, error,
|
||||
"rdpsnd_server_thread reported an error");
|
||||
|
||||
ExitThread((DWORD)error);
|
||||
return NULL;
|
||||
}
|
||||
@ -298,7 +302,8 @@ out:
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT rdpsnd_server_initialize(RdpsndServerContext* context, BOOL ownThread)
|
||||
static UINT rdpsnd_server_initialize(RdpsndServerContext* context,
|
||||
BOOL ownThread)
|
||||
{
|
||||
context->priv->ownThread = ownThread;
|
||||
return context->Start(context);
|
||||
@ -309,63 +314,79 @@ static UINT rdpsnd_server_initialize(RdpsndServerContext* context, BOOL ownThrea
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT rdpsnd_server_select_format(RdpsndServerContext* context, int client_format_index)
|
||||
static UINT rdpsnd_server_select_format(RdpsndServerContext* context,
|
||||
int client_format_index)
|
||||
{
|
||||
int bs;
|
||||
int out_buffer_size;
|
||||
AUDIO_FORMAT *format;
|
||||
AUDIO_FORMAT* format;
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
|
||||
if (client_format_index < 0 || client_format_index >= context->num_client_formats)
|
||||
if (client_format_index < 0
|
||||
|| client_format_index >= context->num_client_formats)
|
||||
{
|
||||
WLog_ERR(TAG, "index %d is not correct.", client_format_index);
|
||||
return ERROR_INVALID_DATA;
|
||||
}
|
||||
|
||||
context->priv->src_bytes_per_sample = context->src_format.wBitsPerSample / 8;
|
||||
context->priv->src_bytes_per_frame = context->priv->src_bytes_per_sample * context->src_format.nChannels;
|
||||
|
||||
EnterCriticalSection(&context->priv->lock);
|
||||
context->priv->src_bytes_per_sample = context->src_format.wBitsPerSample / 8;
|
||||
context->priv->src_bytes_per_frame = context->priv->src_bytes_per_sample *
|
||||
context->src_format.nChannels;
|
||||
context->selected_client_format = client_format_index;
|
||||
format = &context->client_formats[client_format_index];
|
||||
|
||||
|
||||
if (format->nSamplesPerSec == 0)
|
||||
{
|
||||
WLog_ERR(TAG, "invalid Client Sound Format!!");
|
||||
return ERROR_INVALID_DATA;
|
||||
error = ERROR_INVALID_DATA;
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch(format->wFormatTag)
|
||||
if (context->latency <= 0)
|
||||
context->latency = 50;
|
||||
|
||||
context->priv->out_frames = context->src_format.nSamplesPerSec *
|
||||
context->latency / 1000;
|
||||
|
||||
if (context->priv->out_frames < 1)
|
||||
context->priv->out_frames = 1;
|
||||
|
||||
switch (format->wFormatTag)
|
||||
{
|
||||
case WAVE_FORMAT_DVI_ADPCM:
|
||||
bs = (format->nBlockAlign - 4 * format->nChannels) * 4;
|
||||
context->priv->out_frames = (format->nBlockAlign * 4 * format->nChannels * 2 / bs + 1) * bs / (format->nChannels * 2);
|
||||
context->priv->out_frames -= context->priv->out_frames % bs;
|
||||
|
||||
if (context->priv->out_frames < bs)
|
||||
context->priv->out_frames = bs;
|
||||
|
||||
break;
|
||||
|
||||
case WAVE_FORMAT_ADPCM:
|
||||
bs = (format->nBlockAlign - 7 * format->nChannels) * 2 / format->nChannels + 2;
|
||||
context->priv->out_frames = bs * 4;
|
||||
break;
|
||||
default:
|
||||
context->priv->out_frames = 0x4000 / context->priv->src_bytes_per_frame;
|
||||
context->priv->out_frames -= context->priv->out_frames % bs;
|
||||
|
||||
if (context->priv->out_frames < bs)
|
||||
context->priv->out_frames = bs;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (format->nSamplesPerSec != context->src_format.nSamplesPerSec)
|
||||
{
|
||||
context->priv->out_frames = (context->priv->out_frames * context->src_format.nSamplesPerSec + format->nSamplesPerSec - 100) / format->nSamplesPerSec;
|
||||
}
|
||||
context->priv->out_pending_frames = 0;
|
||||
out_buffer_size = context->priv->out_frames *
|
||||
context->priv->src_bytes_per_frame;
|
||||
|
||||
out_buffer_size = context->priv->out_frames * context->priv->src_bytes_per_frame;
|
||||
|
||||
if (context->priv->out_buffer_size < out_buffer_size)
|
||||
{
|
||||
BYTE *newBuffer;
|
||||
BYTE* newBuffer;
|
||||
newBuffer = (BYTE*)realloc(context->priv->out_buffer, out_buffer_size);
|
||||
|
||||
newBuffer = (BYTE *)realloc(context->priv->out_buffer, out_buffer_size);
|
||||
if (!newBuffer)
|
||||
{
|
||||
WLog_ERR(TAG, "realloc failed!");
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
error = CHANNEL_RC_NO_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
context->priv->out_buffer = newBuffer;
|
||||
@ -373,15 +394,19 @@ static UINT rdpsnd_server_select_format(RdpsndServerContext* context, int client
|
||||
}
|
||||
|
||||
freerdp_dsp_context_reset_adpcm(context->priv->dsp_context);
|
||||
return CHANNEL_RC_OK;
|
||||
out:
|
||||
LeaveCriticalSection(&context->priv->lock);
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function description
|
||||
* context->priv->lock should be obtained before calling this function
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT rdpsnd_server_send_audio_pdu(RdpsndServerContext* context, UINT16 wTimestamp)
|
||||
static UINT rdpsnd_server_send_audio_pdu(RdpsndServerContext* context,
|
||||
UINT16 wTimestamp)
|
||||
{
|
||||
int size;
|
||||
BYTE* src;
|
||||
@ -393,50 +418,51 @@ static UINT rdpsnd_server_send_audio_pdu(RdpsndServerContext* context, UINT16 wT
|
||||
ULONG written;
|
||||
wStream* s = context->priv->rdpsnd_pdu;
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
|
||||
format = &context->client_formats[context->selected_client_format];
|
||||
tbytes_per_frame = format->nChannels * context->priv->src_bytes_per_sample;
|
||||
|
||||
if ((format->nSamplesPerSec == context->src_format.nSamplesPerSec) &&
|
||||
(format->nChannels == context->src_format.nChannels))
|
||||
(format->nChannels == context->src_format.nChannels))
|
||||
{
|
||||
src = context->priv->out_buffer;
|
||||
frames = context->priv->out_pending_frames;
|
||||
}
|
||||
else
|
||||
{
|
||||
context->priv->dsp_context->resample(context->priv->dsp_context, context->priv->out_buffer,
|
||||
context->priv->src_bytes_per_sample, context->src_format.nChannels,
|
||||
context->src_format.nSamplesPerSec, context->priv->out_pending_frames,
|
||||
format->nChannels, format->nSamplesPerSec);
|
||||
context->priv->dsp_context->resample(context->priv->dsp_context,
|
||||
context->priv->out_buffer,
|
||||
context->priv->src_bytes_per_sample, context->src_format.nChannels,
|
||||
context->src_format.nSamplesPerSec, context->priv->out_pending_frames,
|
||||
format->nChannels, format->nSamplesPerSec);
|
||||
frames = context->priv->dsp_context->resampled_frames;
|
||||
src = context->priv->dsp_context->resampled_buffer;
|
||||
}
|
||||
|
||||
size = frames * tbytes_per_frame;
|
||||
|
||||
if (format->wFormatTag == WAVE_FORMAT_DVI_ADPCM)
|
||||
{
|
||||
context->priv->dsp_context->encode_ima_adpcm(context->priv->dsp_context,
|
||||
src, size, format->nChannels, format->nBlockAlign);
|
||||
src, size, format->nChannels, format->nBlockAlign);
|
||||
src = context->priv->dsp_context->adpcm_buffer;
|
||||
size = context->priv->dsp_context->adpcm_size;
|
||||
}
|
||||
else if (format->wFormatTag == WAVE_FORMAT_ADPCM)
|
||||
{
|
||||
context->priv->dsp_context->encode_ms_adpcm(context->priv->dsp_context,
|
||||
src, size, format->nChannels, format->nBlockAlign);
|
||||
src, size, format->nChannels, format->nBlockAlign);
|
||||
src = context->priv->dsp_context->adpcm_buffer;
|
||||
size = context->priv->dsp_context->adpcm_size;
|
||||
}
|
||||
|
||||
context->block_no = (context->block_no + 1) % 256;
|
||||
|
||||
/* Fill to nBlockAlign for the last audio packet */
|
||||
|
||||
fill_size = 0;
|
||||
|
||||
if ((format->wFormatTag == WAVE_FORMAT_DVI_ADPCM || format->wFormatTag == WAVE_FORMAT_ADPCM) &&
|
||||
(context->priv->out_pending_frames < context->priv->out_frames) && ((size % format->nBlockAlign) != 0))
|
||||
if ((format->wFormatTag == WAVE_FORMAT_DVI_ADPCM
|
||||
|| format->wFormatTag == WAVE_FORMAT_ADPCM) &&
|
||||
(context->priv->out_pending_frames < context->priv->out_frames)
|
||||
&& ((size % format->nBlockAlign) != 0))
|
||||
{
|
||||
fill_size = format->nBlockAlign - (size % format->nBlockAlign);
|
||||
}
|
||||
@ -446,14 +472,14 @@ static UINT rdpsnd_server_send_audio_pdu(RdpsndServerContext* context, UINT16 wT
|
||||
Stream_Write_UINT8(s, SNDC_WAVE); /* msgType */
|
||||
Stream_Write_UINT8(s, 0); /* bPad */
|
||||
Stream_Write_UINT16(s, size + fill_size + 8); /* BodySize */
|
||||
|
||||
Stream_Write_UINT16(s, wTimestamp); /* wTimeStamp */
|
||||
Stream_Write_UINT16(s, context->selected_client_format); /* wFormatNo */
|
||||
Stream_Write_UINT8(s, context->block_no); /* cBlockNo */
|
||||
Stream_Seek(s, 3); /* bPad */
|
||||
Stream_Write(s, src, 4);
|
||||
status = WTSVirtualChannelWrite(context->priv->ChannelHandle,
|
||||
(PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written);
|
||||
|
||||
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written);
|
||||
if (!status)
|
||||
{
|
||||
WLog_ERR(TAG, "WTSVirtualChannelWrite failed!");
|
||||
@ -470,13 +496,15 @@ static UINT rdpsnd_server_send_audio_pdu(RdpsndServerContext* context, UINT16 wT
|
||||
error = CHANNEL_RC_NO_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
Stream_Write_UINT32(s, 0); /* bPad */
|
||||
Stream_Write(s, src + 4, size - 4);
|
||||
|
||||
if (fill_size > 0)
|
||||
Stream_Zero(s, fill_size);
|
||||
|
||||
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written);
|
||||
status = WTSVirtualChannelWrite(context->priv->ChannelHandle,
|
||||
(PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written);
|
||||
|
||||
if (!status)
|
||||
{
|
||||
@ -495,22 +523,30 @@ out:
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT rdpsnd_server_send_samples(RdpsndServerContext* context, const void* buf, int nframes, UINT16 wTimestamp)
|
||||
static UINT rdpsnd_server_send_samples(RdpsndServerContext* context,
|
||||
const void* buf, int nframes, UINT16 wTimestamp)
|
||||
{
|
||||
int cframes;
|
||||
int cframesize;
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
EnterCriticalSection(&context->priv->lock);
|
||||
|
||||
if (context->selected_client_format < 0)
|
||||
return ERROR_INVALID_DATA;
|
||||
{
|
||||
/* It's possible while format negotiation has not been done */
|
||||
WLog_WARN(TAG, "Drop samples because client format has not been negotiated.");
|
||||
error = ERROR_NOT_READY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
while (nframes > 0)
|
||||
{
|
||||
cframes = MIN(nframes, context->priv->out_frames - context->priv->out_pending_frames);
|
||||
cframes = MIN(nframes, context->priv->out_frames -
|
||||
context->priv->out_pending_frames);
|
||||
cframesize = cframes * context->priv->src_bytes_per_frame;
|
||||
|
||||
CopyMemory(context->priv->out_buffer +
|
||||
(context->priv->out_pending_frames * context->priv->src_bytes_per_frame), buf, cframesize);
|
||||
(context->priv->out_pending_frames * context->priv->src_bytes_per_frame), buf,
|
||||
cframesize);
|
||||
buf = (BYTE*) buf + cframesize;
|
||||
nframes -= cframes;
|
||||
context->priv->out_pending_frames += cframes;
|
||||
@ -518,11 +554,15 @@ static UINT rdpsnd_server_send_samples(RdpsndServerContext* context, const void*
|
||||
if (context->priv->out_pending_frames >= context->priv->out_frames)
|
||||
{
|
||||
if ((error = rdpsnd_server_send_audio_pdu(context, wTimestamp)))
|
||||
WLog_ERR(TAG, "rdpsnd_server_send_audio_pdu failed with error %lu", error);
|
||||
|
||||
{
|
||||
WLog_ERR(TAG, "rdpsnd_server_send_audio_pdu failed with error %u", error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
LeaveCriticalSection(&context->priv->lock);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -531,27 +571,25 @@ static UINT rdpsnd_server_send_samples(RdpsndServerContext* context, const void*
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT rdpsnd_server_set_volume(RdpsndServerContext* context, int left, int right)
|
||||
static UINT rdpsnd_server_set_volume(RdpsndServerContext* context, int left,
|
||||
int right)
|
||||
{
|
||||
int 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);
|
||||
|
||||
Stream_Write_UINT16(s, left);
|
||||
Stream_Write_UINT16(s, right);
|
||||
|
||||
pos = Stream_GetPosition(s);
|
||||
Stream_SetPosition(s, 2);
|
||||
Stream_Write_UINT16(s, pos - 4);
|
||||
Stream_SetPosition(s, pos);
|
||||
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written);
|
||||
status = WTSVirtualChannelWrite(context->priv->ChannelHandle,
|
||||
(PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written);
|
||||
Stream_SetPosition(s, 0);
|
||||
|
||||
return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
@ -567,32 +605,37 @@ static UINT rdpsnd_server_close(RdpsndServerContext* context)
|
||||
ULONG written;
|
||||
wStream* s = context->priv->rdpsnd_pdu;
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
|
||||
if (context->selected_client_format < 0)
|
||||
return ERROR_INVALID_DATA;
|
||||
EnterCriticalSection(&context->priv->lock);
|
||||
|
||||
if (context->priv->out_pending_frames > 0)
|
||||
{
|
||||
if ((error = rdpsnd_server_send_audio_pdu(context, 0)))
|
||||
if (context->selected_client_format < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "rdpsnd_server_send_audio_pdu failed with error %lu", error);
|
||||
return error;
|
||||
WLog_ERR(TAG, "Pending audio frame exists while no format selected.");
|
||||
error = ERROR_INVALID_DATA;
|
||||
}
|
||||
else if ((error = rdpsnd_server_send_audio_pdu(context, 0)))
|
||||
{
|
||||
WLog_ERR(TAG, "rdpsnd_server_send_audio_pdu failed with error %u", error);
|
||||
}
|
||||
}
|
||||
|
||||
context->selected_client_format = -1;
|
||||
LeaveCriticalSection(&context->priv->lock);
|
||||
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
context->selected_client_format = -1;
|
||||
Stream_Write_UINT8(s, SNDC_CLOSE);
|
||||
Stream_Write_UINT8(s, 0);
|
||||
Stream_Seek_UINT16(s);
|
||||
|
||||
pos = Stream_GetPosition(s);
|
||||
Stream_SetPosition(s, 2);
|
||||
Stream_Write_UINT16(s, pos - 4);
|
||||
Stream_SetPosition(s, pos);
|
||||
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written);
|
||||
status = WTSVirtualChannelWrite(context->priv->ChannelHandle,
|
||||
(PCHAR) Stream_Buffer(s), Stream_GetPosition(s), &written);
|
||||
Stream_SetPosition(s, 0);
|
||||
|
||||
return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
@ -603,31 +646,36 @@ static UINT rdpsnd_server_close(RdpsndServerContext* context)
|
||||
*/
|
||||
static UINT rdpsnd_server_start(RdpsndServerContext* context)
|
||||
{
|
||||
void *buffer = NULL;
|
||||
void* buffer = NULL;
|
||||
DWORD bytesReturned;
|
||||
RdpsndServerPrivate *priv = context->priv;
|
||||
RdpsndServerPrivate* priv = context->priv;
|
||||
UINT error = ERROR_INTERNAL_ERROR;
|
||||
priv->ChannelHandle = WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION,
|
||||
"rdpsnd");
|
||||
|
||||
priv->ChannelHandle = WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, "rdpsnd");
|
||||
if (!priv->ChannelHandle)
|
||||
{
|
||||
WLog_ERR(TAG, "WTSVirtualChannelOpen failed!");
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
if (!WTSVirtualChannelQuery(priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &bytesReturned) || (bytesReturned != sizeof(HANDLE)))
|
||||
if (!WTSVirtualChannelQuery(priv->ChannelHandle, WTSVirtualEventHandle, &buffer,
|
||||
&bytesReturned) || (bytesReturned != sizeof(HANDLE)))
|
||||
{
|
||||
WLog_ERR(TAG, "error during WTSVirtualChannelQuery(WTSVirtualEventHandle) or invalid returned size(%d)",
|
||||
bytesReturned);
|
||||
WLog_ERR(TAG,
|
||||
"error during WTSVirtualChannelQuery(WTSVirtualEventHandle) or invalid returned size(%d)",
|
||||
bytesReturned);
|
||||
|
||||
if (buffer)
|
||||
WTSFreeMemory(buffer);
|
||||
|
||||
goto out_close;
|
||||
}
|
||||
|
||||
CopyMemory(&priv->channelEvent, buffer, sizeof(HANDLE));
|
||||
WTSFreeMemory(buffer);
|
||||
|
||||
priv->rdpsnd_pdu = Stream_New(NULL, 4096);
|
||||
|
||||
if (!priv->rdpsnd_pdu)
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_New failed!");
|
||||
@ -635,30 +683,38 @@ static UINT rdpsnd_server_start(RdpsndServerContext* context)
|
||||
goto out_close;
|
||||
}
|
||||
|
||||
if (!InitializeCriticalSectionEx(&context->priv->lock, 0, 0))
|
||||
{
|
||||
WLog_ERR(TAG, "InitializeCriticalSectionEx failed!");
|
||||
goto out_pdu;
|
||||
}
|
||||
|
||||
if (priv->ownThread)
|
||||
{
|
||||
context->priv->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
if (!context->priv->StopEvent)
|
||||
{
|
||||
WLog_ERR(TAG, "CreateEvent failed!");
|
||||
goto out_pdu;
|
||||
goto out_lock;
|
||||
}
|
||||
|
||||
context->priv->Thread = CreateThread(NULL, 0,
|
||||
(LPTHREAD_START_ROUTINE) rdpsnd_server_thread, (void*) context, 0, NULL);
|
||||
(LPTHREAD_START_ROUTINE) rdpsnd_server_thread, (void*) context, 0, NULL);
|
||||
|
||||
if (!context->priv->Thread)
|
||||
{
|
||||
WLog_ERR(TAG, "CreateThread failed!");
|
||||
goto out_stopEvent;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
|
||||
out_stopEvent:
|
||||
CloseHandle(context->priv->StopEvent);
|
||||
context->priv->StopEvent = NULL;
|
||||
out_lock:
|
||||
DeleteCriticalSection(&context->priv->lock);
|
||||
out_pdu:
|
||||
Stream_Free(context->priv->rdpsnd_pdu, TRUE);
|
||||
context->priv->rdpsnd_pdu = NULL;
|
||||
@ -675,7 +731,8 @@ out_close:
|
||||
*/
|
||||
static UINT rdpsnd_server_stop(RdpsndServerContext* context)
|
||||
{
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
|
||||
if (context->priv->ownThread)
|
||||
{
|
||||
if (context->priv->StopEvent)
|
||||
@ -683,16 +740,19 @@ static UINT rdpsnd_server_stop(RdpsndServerContext* context)
|
||||
SetEvent(context->priv->StopEvent);
|
||||
|
||||
if (WaitForSingleObject(context->priv->Thread, INFINITE) == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
|
||||
return error;
|
||||
}
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
CloseHandle(context->priv->Thread);
|
||||
CloseHandle(context->priv->StopEvent);
|
||||
}
|
||||
}
|
||||
|
||||
DeleteCriticalSection(&context->priv->lock);
|
||||
|
||||
if (context->priv->rdpsnd_pdu)
|
||||
Stream_Free(context->priv->rdpsnd_pdu, TRUE);
|
||||
|
||||
@ -702,9 +762,9 @@ static UINT rdpsnd_server_stop(RdpsndServerContext* context)
|
||||
RdpsndServerContext* rdpsnd_server_context_new(HANDLE vcm)
|
||||
{
|
||||
RdpsndServerContext* context;
|
||||
RdpsndServerPrivate *priv;
|
||||
RdpsndServerPrivate* priv;
|
||||
context = (RdpsndServerContext*)calloc(1, sizeof(RdpsndServerContext));
|
||||
|
||||
context = (RdpsndServerContext *)calloc(1, sizeof(RdpsndServerContext));
|
||||
if (!context)
|
||||
{
|
||||
WLog_ERR(TAG, "calloc failed!");
|
||||
@ -712,18 +772,17 @@ RdpsndServerContext* rdpsnd_server_context_new(HANDLE vcm)
|
||||
}
|
||||
|
||||
context->vcm = vcm;
|
||||
|
||||
context->Start = rdpsnd_server_start;
|
||||
context->Stop = rdpsnd_server_stop;
|
||||
|
||||
context->selected_client_format = -1;
|
||||
context->Initialize = rdpsnd_server_initialize;
|
||||
context->SelectFormat = rdpsnd_server_select_format;
|
||||
context->SendSamples = rdpsnd_server_send_samples;
|
||||
context->SetVolume = rdpsnd_server_set_volume;
|
||||
context->Close = rdpsnd_server_close;
|
||||
context->priv = priv = (RdpsndServerPrivate*)calloc(1,
|
||||
sizeof(RdpsndServerPrivate));
|
||||
|
||||
context->priv = priv = (RdpsndServerPrivate *)calloc(1, sizeof(RdpsndServerPrivate));
|
||||
if (!priv)
|
||||
{
|
||||
WLog_ERR(TAG, "calloc failed!");
|
||||
@ -731,6 +790,7 @@ RdpsndServerContext* rdpsnd_server_context_new(HANDLE vcm)
|
||||
}
|
||||
|
||||
priv->dsp_context = freerdp_dsp_context_new();
|
||||
|
||||
if (!priv->dsp_context)
|
||||
{
|
||||
WLog_ERR(TAG, "freerdp_dsp_context_new failed!");
|
||||
@ -738,6 +798,7 @@ RdpsndServerContext* rdpsnd_server_context_new(HANDLE vcm)
|
||||
}
|
||||
|
||||
priv->input_stream = Stream_New(NULL, 4);
|
||||
|
||||
if (!priv->input_stream)
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_New failed!");
|
||||
@ -748,7 +809,6 @@ RdpsndServerContext* rdpsnd_server_context_new(HANDLE vcm)
|
||||
priv->waitingHeader = TRUE;
|
||||
priv->ownThread = TRUE;
|
||||
return context;
|
||||
|
||||
out_free_dsp:
|
||||
freerdp_dsp_context_free(priv->dsp_context);
|
||||
out_free_priv:
|
||||
@ -759,11 +819,10 @@ out_free:
|
||||
}
|
||||
|
||||
|
||||
void rdpsnd_server_context_reset(RdpsndServerContext *context)
|
||||
void rdpsnd_server_context_reset(RdpsndServerContext* context)
|
||||
{
|
||||
context->priv->expectedBytes = 4;
|
||||
context->priv->waitingHeader = TRUE;
|
||||
|
||||
Stream_SetPosition(context->priv->input_stream, 0);
|
||||
}
|
||||
|
||||
@ -781,13 +840,11 @@ void rdpsnd_server_context_free(RdpsndServerContext* context)
|
||||
Stream_Free(context->priv->input_stream, TRUE);
|
||||
|
||||
free(context->client_formats);
|
||||
|
||||
free(context->priv);
|
||||
|
||||
free(context);
|
||||
}
|
||||
|
||||
HANDLE rdpsnd_server_get_event_handle(RdpsndServerContext *context)
|
||||
HANDLE rdpsnd_server_get_event_handle(RdpsndServerContext* context)
|
||||
{
|
||||
return context->priv->channelEvent;
|
||||
}
|
||||
@ -806,15 +863,15 @@ HANDLE rdpsnd_server_get_event_handle(RdpsndServerContext *context)
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT rdpsnd_server_handle_messages(RdpsndServerContext *context)
|
||||
UINT rdpsnd_server_handle_messages(RdpsndServerContext* context)
|
||||
{
|
||||
DWORD bytesReturned;
|
||||
UINT ret = CHANNEL_RC_OK;
|
||||
RdpsndServerPrivate* priv = context->priv;
|
||||
wStream* s = priv->input_stream;
|
||||
|
||||
RdpsndServerPrivate *priv = context->priv;
|
||||
wStream *s = priv->input_stream;
|
||||
|
||||
if (!WTSVirtualChannelRead(priv->ChannelHandle, 0, (PCHAR)Stream_Pointer(s), priv->expectedBytes, &bytesReturned))
|
||||
if (!WTSVirtualChannelRead(priv->ChannelHandle, 0, (PCHAR)Stream_Pointer(s),
|
||||
priv->expectedBytes, &bytesReturned))
|
||||
{
|
||||
if (GetLastError() == ERROR_NO_DATA)
|
||||
return ERROR_NO_DATA;
|
||||
@ -822,6 +879,7 @@ UINT rdpsnd_server_handle_messages(RdpsndServerContext *context)
|
||||
WLog_ERR(TAG, "channel connection closed");
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
priv->expectedBytes -= bytesReturned;
|
||||
Stream_Seek(s, bytesReturned);
|
||||
|
||||
@ -830,15 +888,16 @@ UINT rdpsnd_server_handle_messages(RdpsndServerContext *context)
|
||||
|
||||
Stream_SealLength(s);
|
||||
Stream_SetPosition(s, 0);
|
||||
|
||||
if (priv->waitingHeader)
|
||||
{
|
||||
/* header case */
|
||||
Stream_Read_UINT8(s, priv->msgType);
|
||||
Stream_Seek_UINT8(s); /* bPad */
|
||||
Stream_Read_UINT16(s, priv->expectedBytes);
|
||||
|
||||
priv->waitingHeader = FALSE;
|
||||
Stream_SetPosition(s, 0);
|
||||
|
||||
if (priv->expectedBytes)
|
||||
{
|
||||
if (!Stream_EnsureCapacity(s, priv->expectedBytes))
|
||||
@ -846,6 +905,7 @@ UINT rdpsnd_server_handle_messages(RdpsndServerContext *context)
|
||||
WLog_ERR(TAG, "Stream_EnsureCapacity failed!");
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
}
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
}
|
||||
@ -873,10 +933,12 @@ UINT rdpsnd_server_handle_messages(RdpsndServerContext *context)
|
||||
|
||||
case SNDC_QUALITYMODE:
|
||||
ret = rdpsnd_server_recv_quality_mode(context, s);
|
||||
Stream_SetPosition(s, 0); /* in case the Activated callback tries to treat some messages */
|
||||
Stream_SetPosition(s,
|
||||
0); /* in case the Activated callback tries to treat some messages */
|
||||
|
||||
if ((ret == CHANNEL_RC_OK) && (context->clientVersion >= 6))
|
||||
IFCALL(context->Activated, context);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -884,7 +946,7 @@ UINT rdpsnd_server_handle_messages(RdpsndServerContext *context)
|
||||
ret = ERROR_INVALID_DATA;
|
||||
break;
|
||||
}
|
||||
Stream_SetPosition(s, 0);
|
||||
|
||||
Stream_SetPosition(s, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -52,6 +52,7 @@ struct _rdpsnd_server_private
|
||||
UINT32 src_bytes_per_sample;
|
||||
UINT32 src_bytes_per_frame;
|
||||
FREERDP_DSP_CONTEXT* dsp_context;
|
||||
CRITICAL_SECTION lock; /* Protect out_buffer and related parameters */
|
||||
};
|
||||
|
||||
#endif /* FREERDP_CHANNEL_SERVER_RDPSND_MAIN_H */
|
||||
|
||||
@ -21,7 +21,7 @@ set(${MODULE_PREFIX}_SRCS
|
||||
remdesk_main.c
|
||||
remdesk_main.h)
|
||||
|
||||
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntry")
|
||||
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntryEx")
|
||||
|
||||
|
||||
|
||||
|
||||
@ -33,7 +33,8 @@
|
||||
|
||||
#include "remdesk_main.h"
|
||||
|
||||
RemdeskClientContext* remdesk_get_client_interface(remdeskPlugin* remdesk)
|
||||
static RemdeskClientContext* remdesk_get_client_interface(
|
||||
remdeskPlugin* remdesk)
|
||||
{
|
||||
RemdeskClientContext* pInterface;
|
||||
pInterface = (RemdeskClientContext*) remdesk->channelEntryPoints.pInterface;
|
||||
@ -55,12 +56,13 @@ static UINT remdesk_virtual_channel_write(remdeskPlugin* remdesk, wStream* s)
|
||||
return CHANNEL_RC_INVALID_INSTANCE;
|
||||
}
|
||||
|
||||
status = remdesk->channelEntryPoints.pVirtualChannelWrite(remdesk->OpenHandle,
|
||||
Stream_Buffer(s), (UINT32) Stream_Length(s), s);
|
||||
status = remdesk->channelEntryPoints.pVirtualChannelWriteEx(remdesk->InitHandle,
|
||||
remdesk->OpenHandle,
|
||||
Stream_Buffer(s), (UINT32) Stream_Length(s), s);
|
||||
|
||||
if (status != CHANNEL_RC_OK)
|
||||
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
|
||||
WTSErrorToString(status), status);
|
||||
WLog_ERR(TAG, "pVirtualChannelWriteEx failed with %s [%08X]",
|
||||
WTSErrorToString(status), status);
|
||||
|
||||
return status;
|
||||
}
|
||||
@ -70,7 +72,7 @@ static UINT remdesk_virtual_channel_write(remdeskPlugin* remdesk, wStream* s)
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT remdesk_generate_expert_blob(remdeskPlugin* remdesk)
|
||||
static UINT remdesk_generate_expert_blob(remdeskPlugin* remdesk)
|
||||
{
|
||||
char* name;
|
||||
char* pass;
|
||||
@ -97,7 +99,7 @@ UINT remdesk_generate_expert_blob(remdeskPlugin* remdesk)
|
||||
name = "Expert";
|
||||
|
||||
remdesk->EncryptedPassStub = freerdp_assistance_encrypt_pass_stub(password,
|
||||
settings->RemoteAssistancePassStub, &(remdesk->EncryptedPassStubSize));
|
||||
settings->RemoteAssistancePassStub, &(remdesk->EncryptedPassStubSize));
|
||||
|
||||
if (!remdesk->EncryptedPassStub)
|
||||
{
|
||||
@ -105,7 +107,8 @@ UINT remdesk_generate_expert_blob(remdeskPlugin* remdesk)
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
pass = freerdp_assistance_bin_to_hex_string(remdesk->EncryptedPassStub, remdesk->EncryptedPassStubSize);
|
||||
pass = freerdp_assistance_bin_to_hex_string(remdesk->EncryptedPassStub,
|
||||
remdesk->EncryptedPassStubSize);
|
||||
|
||||
if (!pass)
|
||||
{
|
||||
@ -129,7 +132,8 @@ UINT remdesk_generate_expert_blob(remdeskPlugin* remdesk)
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT remdesk_read_channel_header(wStream* s, REMDESK_CHANNEL_HEADER* header)
|
||||
static UINT remdesk_read_channel_header(wStream* s,
|
||||
REMDESK_CHANNEL_HEADER* header)
|
||||
{
|
||||
int status;
|
||||
UINT32 ChannelNameLen;
|
||||
@ -152,7 +156,7 @@ static UINT remdesk_read_channel_header(wStream* s, REMDESK_CHANNEL_HEADER* head
|
||||
|
||||
if ((ChannelNameLen % 2) != 0)
|
||||
{
|
||||
WLog_ERR(TAG, "ChannelNameLen % 2) != 0 ");
|
||||
WLog_ERR(TAG, "ChannelNameLen %% 2) != 0 ");
|
||||
return ERROR_INVALID_DATA;
|
||||
}
|
||||
|
||||
@ -163,11 +167,9 @@ static UINT remdesk_read_channel_header(wStream* s, REMDESK_CHANNEL_HEADER* head
|
||||
}
|
||||
|
||||
ZeroMemory(header->ChannelName, sizeof(header->ChannelName));
|
||||
|
||||
pChannelName = (char*) header->ChannelName;
|
||||
status = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s),
|
||||
ChannelNameLen / 2, &pChannelName, 32, NULL, NULL);
|
||||
|
||||
ChannelNameLen / 2, &pChannelName, 32, NULL, NULL);
|
||||
Stream_Seek(s, ChannelNameLen);
|
||||
|
||||
if (status <= 0)
|
||||
@ -184,12 +186,12 @@ static UINT remdesk_read_channel_header(wStream* s, REMDESK_CHANNEL_HEADER* head
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT remdesk_write_channel_header(wStream* s, REMDESK_CHANNEL_HEADER* header)
|
||||
static UINT remdesk_write_channel_header(wStream* s,
|
||||
REMDESK_CHANNEL_HEADER* header)
|
||||
{
|
||||
int index;
|
||||
UINT32 ChannelNameLen;
|
||||
WCHAR ChannelNameW[32];
|
||||
|
||||
ZeroMemory(ChannelNameW, sizeof(ChannelNameW));
|
||||
|
||||
for (index = 0; index < 32; index++)
|
||||
@ -198,12 +200,9 @@ static UINT remdesk_write_channel_header(wStream* s, REMDESK_CHANNEL_HEADER* hea
|
||||
}
|
||||
|
||||
ChannelNameLen = (strlen(header->ChannelName) + 1) * 2;
|
||||
|
||||
Stream_Write_UINT32(s, ChannelNameLen); /* ChannelNameLen (4 bytes) */
|
||||
Stream_Write_UINT32(s, header->DataLength); /* DataLen (4 bytes) */
|
||||
|
||||
Stream_Write(s, ChannelNameW, ChannelNameLen); /* ChannelName (variable) */
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
@ -224,7 +223,8 @@ static UINT remdesk_write_ctl_header(wStream* s, REMDESK_CTL_HEADER* ctlHeader)
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT remdesk_prepare_ctl_header(REMDESK_CTL_HEADER* ctlHeader, UINT32 msgType, UINT32 msgSize)
|
||||
static UINT remdesk_prepare_ctl_header(REMDESK_CTL_HEADER* ctlHeader,
|
||||
UINT32 msgType, UINT32 msgSize)
|
||||
{
|
||||
ctlHeader->msgType = msgType;
|
||||
strcpy(ctlHeader->ChannelName, REMDESK_CHANNEL_CTL_NAME);
|
||||
@ -237,7 +237,8 @@ static UINT remdesk_prepare_ctl_header(REMDESK_CTL_HEADER* ctlHeader, UINT32 msg
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT remdesk_recv_ctl_server_announce_pdu(remdeskPlugin* remdesk, wStream* s, REMDESK_CHANNEL_HEADER* header)
|
||||
static UINT remdesk_recv_ctl_server_announce_pdu(remdeskPlugin* remdesk,
|
||||
wStream* s, REMDESK_CHANNEL_HEADER* header)
|
||||
{
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
@ -247,7 +248,8 @@ static UINT remdesk_recv_ctl_server_announce_pdu(remdeskPlugin* remdesk, wStream
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT remdesk_recv_ctl_version_info_pdu(remdeskPlugin* remdesk, wStream* s, REMDESK_CHANNEL_HEADER* header)
|
||||
static UINT remdesk_recv_ctl_version_info_pdu(remdeskPlugin* remdesk,
|
||||
wStream* s, REMDESK_CHANNEL_HEADER* header)
|
||||
{
|
||||
UINT32 versionMajor;
|
||||
UINT32 versionMinor;
|
||||
@ -260,9 +262,7 @@ static UINT remdesk_recv_ctl_version_info_pdu(remdeskPlugin* remdesk, wStream* s
|
||||
|
||||
Stream_Read_UINT32(s, versionMajor); /* versionMajor (4 bytes) */
|
||||
Stream_Read_UINT32(s, versionMinor); /* versionMinor (4 bytes) */
|
||||
|
||||
remdesk->Version = versionMajor;
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
@ -276,13 +276,11 @@ static UINT remdesk_send_ctl_version_info_pdu(remdeskPlugin* remdesk)
|
||||
wStream* s;
|
||||
REMDESK_CTL_VERSION_INFO_PDU pdu;
|
||||
UINT error;
|
||||
|
||||
remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_VERSIONINFO, 8);
|
||||
|
||||
pdu.versionMajor = 1;
|
||||
pdu.versionMinor = 2;
|
||||
|
||||
s = Stream_New(NULL, REMDESK_CHANNEL_CTL_SIZE + pdu.ctlHeader.DataLength);
|
||||
|
||||
if (!s)
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_New failed!");
|
||||
@ -290,17 +288,16 @@ static UINT remdesk_send_ctl_version_info_pdu(remdeskPlugin* remdesk)
|
||||
}
|
||||
|
||||
remdesk_write_ctl_header(s, &(pdu.ctlHeader));
|
||||
|
||||
Stream_Write_UINT32(s, pdu.versionMajor); /* versionMajor (4 bytes) */
|
||||
Stream_Write_UINT32(s, pdu.versionMinor); /* versionMinor (4 bytes) */
|
||||
|
||||
Stream_SealLength(s);
|
||||
|
||||
if ((error = remdesk_virtual_channel_write(remdesk, s)))
|
||||
WLog_ERR(TAG, "remdesk_virtual_channel_write failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "remdesk_virtual_channel_write failed with error %u!", error);
|
||||
|
||||
if (error != CHANNEL_RC_OK)
|
||||
Stream_Free(s, TRUE);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -309,7 +306,8 @@ static UINT remdesk_send_ctl_version_info_pdu(remdeskPlugin* remdesk)
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT remdesk_recv_ctl_result_pdu(remdeskPlugin* remdesk, wStream* s, REMDESK_CHANNEL_HEADER* header, UINT32 *pResult)
|
||||
static UINT remdesk_recv_ctl_result_pdu(remdeskPlugin* remdesk, wStream* s,
|
||||
REMDESK_CHANNEL_HEADER* header, UINT32* pResult)
|
||||
{
|
||||
UINT32 result;
|
||||
|
||||
@ -320,7 +318,6 @@ static UINT remdesk_recv_ctl_result_pdu(remdeskPlugin* remdesk, wStream* s, REMD
|
||||
}
|
||||
|
||||
Stream_Read_UINT32(s, result); /* result (4 bytes) */
|
||||
|
||||
*pResult = result;
|
||||
//WLog_DBG(TAG, "RemdeskRecvResult: 0x%04X", result);
|
||||
return CHANNEL_RC_OK;
|
||||
@ -344,14 +341,14 @@ static UINT remdesk_send_ctl_authenticate_pdu(remdeskPlugin* remdesk)
|
||||
|
||||
if ((error = remdesk_generate_expert_blob(remdesk)))
|
||||
{
|
||||
WLog_ERR(TAG, "remdesk_generate_expert_blob failed with error %lu", error);
|
||||
WLog_ERR(TAG, "remdesk_generate_expert_blob failed with error %u", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
pdu.expertBlob = remdesk->ExpertBlob;
|
||||
pdu.raConnectionString = remdesk->settings->RemoteAssistanceRCTicket;
|
||||
|
||||
status = ConvertToUnicode(CP_UTF8, 0, pdu.raConnectionString, -1, &raConnectionStringW, 0);
|
||||
status = ConvertToUnicode(CP_UTF8, 0, pdu.raConnectionString, -1,
|
||||
&raConnectionStringW, 0);
|
||||
|
||||
if (status <= 0)
|
||||
{
|
||||
@ -360,7 +357,6 @@ static UINT remdesk_send_ctl_authenticate_pdu(remdeskPlugin* remdesk)
|
||||
}
|
||||
|
||||
cbRaConnectionStringW = status * 2;
|
||||
|
||||
status = ConvertToUnicode(CP_UTF8, 0, pdu.expertBlob, -1, &expertBlobW, 0);
|
||||
|
||||
if (status <= 0)
|
||||
@ -371,11 +367,10 @@ static UINT remdesk_send_ctl_authenticate_pdu(remdeskPlugin* remdesk)
|
||||
}
|
||||
|
||||
cbExpertBlobW = status * 2;
|
||||
|
||||
remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_AUTHENTICATE,
|
||||
cbRaConnectionStringW + cbExpertBlobW);
|
||||
|
||||
cbRaConnectionStringW + cbExpertBlobW);
|
||||
s = Stream_New(NULL, REMDESK_CHANNEL_CTL_SIZE + pdu.ctlHeader.DataLength);
|
||||
|
||||
if (!s)
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_New failed!");
|
||||
@ -384,18 +379,17 @@ static UINT remdesk_send_ctl_authenticate_pdu(remdeskPlugin* remdesk)
|
||||
}
|
||||
|
||||
remdesk_write_ctl_header(s, &(pdu.ctlHeader));
|
||||
|
||||
Stream_Write(s, (BYTE*) raConnectionStringW, cbRaConnectionStringW);
|
||||
Stream_Write(s, (BYTE*) expertBlobW, cbExpertBlobW);
|
||||
|
||||
Stream_SealLength(s);
|
||||
|
||||
if ((error = remdesk_virtual_channel_write(remdesk, s)))
|
||||
WLog_ERR(TAG, "remdesk_virtual_channel_write failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "remdesk_virtual_channel_write failed with error %u!", error);
|
||||
|
||||
out:
|
||||
free(raConnectionStringW);
|
||||
free(expertBlobW);
|
||||
|
||||
if (error != CHANNEL_RC_OK)
|
||||
Stream_Free(s, TRUE);
|
||||
|
||||
@ -415,10 +409,9 @@ static UINT remdesk_send_ctl_remote_control_desktop_pdu(remdeskPlugin* remdesk)
|
||||
int cbRaConnectionStringW = 0;
|
||||
WCHAR* raConnectionStringW = NULL;
|
||||
REMDESK_CTL_REMOTE_CONTROL_DESKTOP_PDU pdu;
|
||||
|
||||
pdu.raConnectionString = remdesk->settings->RemoteAssistanceRCTicket;
|
||||
|
||||
status = ConvertToUnicode(CP_UTF8, 0, pdu.raConnectionString, -1, &raConnectionStringW, 0);
|
||||
status = ConvertToUnicode(CP_UTF8, 0, pdu.raConnectionString, -1,
|
||||
&raConnectionStringW, 0);
|
||||
|
||||
if (status <= 0)
|
||||
{
|
||||
@ -427,10 +420,10 @@ static UINT remdesk_send_ctl_remote_control_desktop_pdu(remdeskPlugin* remdesk)
|
||||
}
|
||||
|
||||
cbRaConnectionStringW = status * 2;
|
||||
|
||||
remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_REMOTE_CONTROL_DESKTOP, cbRaConnectionStringW);
|
||||
|
||||
remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_REMOTE_CONTROL_DESKTOP,
|
||||
cbRaConnectionStringW);
|
||||
s = Stream_New(NULL, REMDESK_CHANNEL_CTL_SIZE + pdu.ctlHeader.DataLength);
|
||||
|
||||
if (!s)
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_New failed!");
|
||||
@ -439,16 +432,15 @@ static UINT remdesk_send_ctl_remote_control_desktop_pdu(remdeskPlugin* remdesk)
|
||||
}
|
||||
|
||||
remdesk_write_ctl_header(s, &(pdu.ctlHeader));
|
||||
|
||||
Stream_Write(s, (BYTE*) raConnectionStringW, cbRaConnectionStringW);
|
||||
|
||||
Stream_SealLength(s);
|
||||
|
||||
if ((error = remdesk_virtual_channel_write(remdesk, s)))
|
||||
WLog_ERR(TAG, "remdesk_virtual_channel_write failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "remdesk_virtual_channel_write failed with error %u!", error);
|
||||
|
||||
out:
|
||||
free(raConnectionStringW);
|
||||
|
||||
if (error != CHANNEL_RC_OK)
|
||||
Stream_Free(s, TRUE);
|
||||
|
||||
@ -471,12 +463,11 @@ static UINT remdesk_send_ctl_verify_password_pdu(remdeskPlugin* remdesk)
|
||||
|
||||
if ((error = remdesk_generate_expert_blob(remdesk)))
|
||||
{
|
||||
WLog_ERR(TAG, "remdesk_generate_expert_blob failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "remdesk_generate_expert_blob failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
pdu.expertBlob = remdesk->ExpertBlob;
|
||||
|
||||
status = ConvertToUnicode(CP_UTF8, 0, pdu.expertBlob, -1, &expertBlobW, 0);
|
||||
|
||||
if (status <= 0)
|
||||
@ -486,10 +477,10 @@ static UINT remdesk_send_ctl_verify_password_pdu(remdeskPlugin* remdesk)
|
||||
}
|
||||
|
||||
cbExpertBlobW = status * 2;
|
||||
|
||||
remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_VERIFY_PASSWORD, cbExpertBlobW);
|
||||
|
||||
remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_VERIFY_PASSWORD,
|
||||
cbExpertBlobW);
|
||||
s = Stream_New(NULL, REMDESK_CHANNEL_CTL_SIZE + pdu.ctlHeader.DataLength);
|
||||
|
||||
if (!s)
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_New failed!");
|
||||
@ -498,16 +489,15 @@ static UINT remdesk_send_ctl_verify_password_pdu(remdeskPlugin* remdesk)
|
||||
}
|
||||
|
||||
remdesk_write_ctl_header(s, &(pdu.ctlHeader));
|
||||
|
||||
Stream_Write(s, (BYTE*) expertBlobW, cbExpertBlobW);
|
||||
|
||||
Stream_SealLength(s);
|
||||
|
||||
if ((error = remdesk_virtual_channel_write(remdesk, s)))
|
||||
WLog_ERR(TAG, "remdesk_virtual_channel_write failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "remdesk_virtual_channel_write failed with error %u!", error);
|
||||
|
||||
out:
|
||||
free(expertBlobW);
|
||||
|
||||
if (error != CHANNEL_RC_OK)
|
||||
Stream_Free(s, TRUE);
|
||||
|
||||
@ -527,17 +517,16 @@ static UINT remdesk_send_ctl_expert_on_vista_pdu(remdeskPlugin* remdesk)
|
||||
|
||||
if ((error = remdesk_generate_expert_blob(remdesk)))
|
||||
{
|
||||
WLog_ERR(TAG, "remdesk_generate_expert_blob failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "remdesk_generate_expert_blob failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
pdu.EncryptedPasswordLength = remdesk->EncryptedPassStubSize;
|
||||
pdu.EncryptedPassword = remdesk->EncryptedPassStub;
|
||||
|
||||
remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_EXPERT_ON_VISTA,
|
||||
pdu.EncryptedPasswordLength);
|
||||
|
||||
pdu.EncryptedPasswordLength);
|
||||
s = Stream_New(NULL, REMDESK_CHANNEL_CTL_SIZE + pdu.ctlHeader.DataLength);
|
||||
|
||||
if (!s)
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_New failed!");
|
||||
@ -545,11 +534,8 @@ static UINT remdesk_send_ctl_expert_on_vista_pdu(remdeskPlugin* remdesk)
|
||||
}
|
||||
|
||||
remdesk_write_ctl_header(s, &(pdu.ctlHeader));
|
||||
|
||||
Stream_Write(s, pdu.EncryptedPassword, pdu.EncryptedPasswordLength);
|
||||
|
||||
Stream_SealLength(s);
|
||||
|
||||
return remdesk_virtual_channel_write(remdesk, s);
|
||||
}
|
||||
|
||||
@ -558,7 +544,8 @@ static UINT remdesk_send_ctl_expert_on_vista_pdu(remdeskPlugin* remdesk)
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT remdesk_recv_ctl_pdu(remdeskPlugin* remdesk, wStream* s, REMDESK_CHANNEL_HEADER* header)
|
||||
static UINT remdesk_recv_ctl_pdu(remdeskPlugin* remdesk, wStream* s,
|
||||
REMDESK_CHANNEL_HEADER* header)
|
||||
{
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
UINT32 msgType = 0;
|
||||
@ -581,7 +568,8 @@ static UINT remdesk_recv_ctl_pdu(remdeskPlugin* remdesk, wStream* s, REMDESK_CHA
|
||||
|
||||
case REMDESK_CTL_RESULT:
|
||||
if ((error = remdesk_recv_ctl_result_pdu(remdesk, s, header, &result)))
|
||||
WLog_ERR(TAG, "remdesk_recv_ctl_result_pdu failed with error %lu", error);
|
||||
WLog_ERR(TAG, "remdesk_recv_ctl_result_pdu failed with error %u", error);
|
||||
|
||||
break;
|
||||
|
||||
case REMDESK_CTL_AUTHENTICATE:
|
||||
@ -589,7 +577,9 @@ static UINT remdesk_recv_ctl_pdu(remdeskPlugin* remdesk, wStream* s, REMDESK_CHA
|
||||
|
||||
case REMDESK_CTL_SERVER_ANNOUNCE:
|
||||
if ((error = remdesk_recv_ctl_server_announce_pdu(remdesk, s, header)))
|
||||
WLog_ERR(TAG, "remdesk_recv_ctl_server_announce_pdu failed with error %lu", error);
|
||||
WLog_ERR(TAG, "remdesk_recv_ctl_server_announce_pdu failed with error %u",
|
||||
error);
|
||||
|
||||
break;
|
||||
|
||||
case REMDESK_CTL_DISCONNECT:
|
||||
@ -598,7 +588,7 @@ static UINT remdesk_recv_ctl_pdu(remdeskPlugin* remdesk, wStream* s, REMDESK_CHA
|
||||
case REMDESK_CTL_VERSIONINFO:
|
||||
if ((error = remdesk_recv_ctl_version_info_pdu(remdesk, s, header)))
|
||||
{
|
||||
WLog_ERR(TAG, "remdesk_recv_ctl_version_info_pdu failed with error %lu", error);
|
||||
WLog_ERR(TAG, "remdesk_recv_ctl_version_info_pdu failed with error %u", error);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -606,19 +596,20 @@ static UINT remdesk_recv_ctl_pdu(remdeskPlugin* remdesk, wStream* s, REMDESK_CHA
|
||||
{
|
||||
if ((error = remdesk_send_ctl_version_info_pdu(remdesk)))
|
||||
{
|
||||
WLog_ERR(TAG, "remdesk_send_ctl_version_info_pdu failed with error %lu", error);
|
||||
WLog_ERR(TAG, "remdesk_send_ctl_version_info_pdu failed with error %u", error);
|
||||
break;
|
||||
}
|
||||
|
||||
if ((error = remdesk_send_ctl_authenticate_pdu(remdesk)))
|
||||
{
|
||||
WLog_ERR(TAG, "remdesk_send_ctl_authenticate_pdu failed with error %lu", error);
|
||||
WLog_ERR(TAG, "remdesk_send_ctl_authenticate_pdu failed with error %u", error);
|
||||
break;
|
||||
}
|
||||
|
||||
if ((error = remdesk_send_ctl_remote_control_desktop_pdu(remdesk)))
|
||||
{
|
||||
WLog_ERR(TAG, "remdesk_send_ctl_remote_control_desktop_pdu failed with error %lu", error);
|
||||
WLog_ERR(TAG,
|
||||
"remdesk_send_ctl_remote_control_desktop_pdu failed with error %u", error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -626,13 +617,15 @@ static UINT remdesk_recv_ctl_pdu(remdeskPlugin* remdesk, wStream* s, REMDESK_CHA
|
||||
{
|
||||
if ((error = remdesk_send_ctl_expert_on_vista_pdu(remdesk)))
|
||||
{
|
||||
WLog_ERR(TAG, "remdesk_send_ctl_expert_on_vista_pdu failed with error %lu", error);
|
||||
WLog_ERR(TAG, "remdesk_send_ctl_expert_on_vista_pdu failed with error %u",
|
||||
error);
|
||||
break;
|
||||
}
|
||||
|
||||
if ((error = remdesk_send_ctl_verify_password_pdu(remdesk)))
|
||||
{
|
||||
WLog_ERR(TAG, "remdesk_send_ctl_verify_password_pdu failed with error %lu", error);
|
||||
WLog_ERR(TAG, "remdesk_send_ctl_verify_password_pdu failed with error %u",
|
||||
error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -675,7 +668,6 @@ static UINT remdesk_process_receive(remdeskPlugin* remdesk, wStream* s)
|
||||
{
|
||||
UINT status;
|
||||
REMDESK_CHANNEL_HEADER header;
|
||||
|
||||
#if 0
|
||||
WLog_DBG(TAG, "RemdeskReceive: %d", Stream_GetRemainingLength(s));
|
||||
winpr_HexDump(Stream_Pointer(s), Stream_GetRemainingLength(s));
|
||||
@ -683,7 +675,7 @@ static UINT remdesk_process_receive(remdeskPlugin* remdesk, wStream* s)
|
||||
|
||||
if ((status = remdesk_read_channel_header(s, &header)))
|
||||
{
|
||||
WLog_ERR(TAG, "remdesk_read_channel_header failed with error %lu", status);
|
||||
WLog_ERR(TAG, "remdesk_read_channel_header failed with error %u", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -693,27 +685,21 @@ static UINT remdesk_process_receive(remdeskPlugin* remdesk, wStream* s)
|
||||
}
|
||||
else if (strcmp(header.ChannelName, "70") == 0)
|
||||
{
|
||||
|
||||
}
|
||||
else if (strcmp(header.ChannelName, "71") == 0)
|
||||
{
|
||||
|
||||
}
|
||||
else if (strcmp(header.ChannelName, ".") == 0)
|
||||
{
|
||||
|
||||
}
|
||||
else if (strcmp(header.ChannelName, "1000.") == 0)
|
||||
{
|
||||
|
||||
}
|
||||
else if (strcmp(header.ChannelName, "RA_FX") == 0)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return status;
|
||||
@ -724,89 +710,12 @@ static void remdesk_process_connect(remdeskPlugin* remdesk)
|
||||
remdesk->settings = (rdpSettings*) remdesk->channelEntryPoints.pExtendedData;
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
static wListDictionary* g_InitHandles = NULL;
|
||||
static wListDictionary* g_OpenHandles = NULL;
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT remdesk_add_init_handle_data(void* pInitHandle, void* pUserData)
|
||||
{
|
||||
if (!g_InitHandles)
|
||||
{
|
||||
g_InitHandles = ListDictionary_New(TRUE);
|
||||
if (!g_InitHandles)
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
}
|
||||
|
||||
return ListDictionary_Add(g_InitHandles, pInitHandle, pUserData) ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
void* remdesk_get_init_handle_data(void* pInitHandle)
|
||||
{
|
||||
void* pUserData = NULL;
|
||||
pUserData = ListDictionary_GetItemValue(g_InitHandles, pInitHandle);
|
||||
return pUserData;
|
||||
}
|
||||
|
||||
void remdesk_remove_init_handle_data(void* pInitHandle)
|
||||
{
|
||||
ListDictionary_Remove(g_InitHandles, pInitHandle);
|
||||
if (ListDictionary_Count(g_InitHandles) < 1)
|
||||
{
|
||||
ListDictionary_Free(g_InitHandles);
|
||||
g_InitHandles = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT remdesk_add_open_handle_data(DWORD openHandle, void* pUserData)
|
||||
{
|
||||
void* pOpenHandle = (void*) (size_t) openHandle;
|
||||
|
||||
if (!g_OpenHandles)
|
||||
{
|
||||
g_OpenHandles = ListDictionary_New(TRUE);
|
||||
if (!g_OpenHandles)
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
}
|
||||
|
||||
return ListDictionary_Add(g_OpenHandles, pOpenHandle, pUserData) ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
void* remdesk_get_open_handle_data(DWORD openHandle)
|
||||
{
|
||||
void* pUserData = NULL;
|
||||
void* pOpenHandle = (void*) (size_t) openHandle;
|
||||
pUserData = ListDictionary_GetItemValue(g_OpenHandles, pOpenHandle);
|
||||
return pUserData;
|
||||
}
|
||||
|
||||
void remdesk_remove_open_handle_data(DWORD openHandle)
|
||||
{
|
||||
void* pOpenHandle = (void*) (size_t) openHandle;
|
||||
ListDictionary_Remove(g_OpenHandles, pOpenHandle);
|
||||
if (ListDictionary_Count(g_OpenHandles) < 1)
|
||||
{
|
||||
ListDictionary_Free(g_OpenHandles);
|
||||
g_OpenHandles = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT remdesk_send(remdeskPlugin* remdesk, wStream* s)
|
||||
static UINT remdesk_send(remdeskPlugin* remdesk, wStream* s)
|
||||
{
|
||||
UINT status = 0;
|
||||
remdeskPlugin* plugin = (remdeskPlugin*) remdesk;
|
||||
@ -817,15 +726,15 @@ UINT remdesk_send(remdeskPlugin* remdesk, wStream* s)
|
||||
}
|
||||
else
|
||||
{
|
||||
status = plugin->channelEntryPoints.pVirtualChannelWrite(plugin->OpenHandle,
|
||||
Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s);
|
||||
status = plugin->channelEntryPoints.pVirtualChannelWriteEx(plugin->InitHandle, plugin->OpenHandle,
|
||||
Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s);
|
||||
}
|
||||
|
||||
if (status != CHANNEL_RC_OK)
|
||||
{
|
||||
Stream_Free(s, TRUE);
|
||||
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
|
||||
WTSErrorToString(status), status);
|
||||
WLog_ERR(TAG, "pVirtualChannelWriteEx failed with %s [%08X]",
|
||||
WTSErrorToString(status), status);
|
||||
}
|
||||
|
||||
return status;
|
||||
@ -837,7 +746,7 @@ UINT remdesk_send(remdeskPlugin* remdesk, wStream* s)
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT remdesk_virtual_channel_event_data_received(remdeskPlugin* remdesk,
|
||||
void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
|
||||
void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
|
||||
{
|
||||
wStream* data_in;
|
||||
|
||||
@ -852,6 +761,7 @@ static UINT remdesk_virtual_channel_event_data_received(remdeskPlugin* remdesk,
|
||||
Stream_Free(remdesk->data_in, TRUE);
|
||||
|
||||
remdesk->data_in = Stream_New(NULL, totalLength);
|
||||
|
||||
if (!remdesk->data_in)
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_New failed!");
|
||||
@ -860,11 +770,13 @@ static UINT remdesk_virtual_channel_event_data_received(remdeskPlugin* remdesk,
|
||||
}
|
||||
|
||||
data_in = remdesk->data_in;
|
||||
|
||||
if (!Stream_EnsureRemainingCapacity(data_in, (int) dataLength))
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
}
|
||||
|
||||
Stream_Write(data_in, pData, dataLength);
|
||||
|
||||
if (dataFlags & CHANNEL_FLAG_LAST)
|
||||
@ -885,18 +797,18 @@ static UINT remdesk_virtual_channel_event_data_received(remdeskPlugin* remdesk,
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
static VOID VCAPITYPE remdesk_virtual_channel_open_event(DWORD openHandle, UINT event,
|
||||
LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
|
||||
static VOID VCAPITYPE remdesk_virtual_channel_open_event_ex(LPVOID lpUserParam, DWORD openHandle,
|
||||
UINT event,
|
||||
LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
|
||||
{
|
||||
remdeskPlugin* remdesk;
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
remdeskPlugin* remdesk = (remdeskPlugin*) lpUserParam;
|
||||
|
||||
remdesk = (remdeskPlugin*) remdesk_get_open_handle_data(openHandle);
|
||||
|
||||
if (!remdesk)
|
||||
if (!remdesk || (remdesk->OpenHandle != openHandle))
|
||||
{
|
||||
WLog_ERR(TAG, "error no match");
|
||||
return;
|
||||
@ -905,8 +817,11 @@ static VOID VCAPITYPE remdesk_virtual_channel_open_event(DWORD openHandle, UINT
|
||||
switch (event)
|
||||
{
|
||||
case CHANNEL_EVENT_DATA_RECEIVED:
|
||||
if ((error = remdesk_virtual_channel_event_data_received(remdesk, pData, dataLength, totalLength, dataFlags)))
|
||||
WLog_ERR(TAG, "remdesk_virtual_channel_event_data_received failed with error %lu!", error);
|
||||
if ((error = remdesk_virtual_channel_event_data_received(remdesk, pData,
|
||||
dataLength, totalLength, dataFlags)))
|
||||
WLog_ERR(TAG,
|
||||
"remdesk_virtual_channel_event_data_received failed with error %u!", error);
|
||||
|
||||
break;
|
||||
|
||||
case CHANNEL_EVENT_WRITE_COMPLETE:
|
||||
@ -917,13 +832,13 @@ static VOID VCAPITYPE remdesk_virtual_channel_open_event(DWORD openHandle, UINT
|
||||
break;
|
||||
|
||||
default:
|
||||
WLog_ERR(TAG, "unhandled event %lu!", event);
|
||||
WLog_ERR(TAG, "unhandled event %u!", event);
|
||||
error = ERROR_INTERNAL_ERROR;
|
||||
|
||||
}
|
||||
if (error && remdesk->rdpcontext)
|
||||
setChannelError(remdesk->rdpcontext, error, "remdesk_virtual_channel_open_event reported an error");
|
||||
|
||||
if (error && remdesk->rdpcontext)
|
||||
setChannelError(remdesk->rdpcontext, error,
|
||||
"remdesk_virtual_channel_open_event_ex reported an error");
|
||||
}
|
||||
|
||||
static void* remdesk_virtual_channel_client_thread(void* arg)
|
||||
@ -932,7 +847,6 @@ static void* remdesk_virtual_channel_client_thread(void* arg)
|
||||
wMessage message;
|
||||
remdeskPlugin* remdesk = (remdeskPlugin*) arg;
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
|
||||
remdesk_process_connect(remdesk);
|
||||
|
||||
while (1)
|
||||
@ -944,27 +858,31 @@ static void* remdesk_virtual_channel_client_thread(void* arg)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!MessageQueue_Peek(remdesk->queue, &message, TRUE)) {
|
||||
if (!MessageQueue_Peek(remdesk->queue, &message, TRUE))
|
||||
{
|
||||
WLog_ERR(TAG, "MessageQueue_Peek failed!");
|
||||
error = ERROR_INTERNAL_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (message.id == WMQ_QUIT)
|
||||
break;
|
||||
|
||||
if (message.id == 0)
|
||||
{
|
||||
data = (wStream*) message.wParam;
|
||||
|
||||
if ((error = remdesk_process_receive(remdesk, data)))
|
||||
{
|
||||
WLog_ERR(TAG, "remdesk_process_receive failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "remdesk_process_receive failed with error %u!", error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (error && remdesk->rdpcontext)
|
||||
setChannelError(remdesk->rdpcontext, error, "remdesk_virtual_channel_client_thread reported an error");
|
||||
setChannelError(remdesk->rdpcontext, error,
|
||||
"remdesk_virtual_channel_client_thread reported an error");
|
||||
|
||||
ExitThread((DWORD)error);
|
||||
return NULL;
|
||||
@ -975,28 +893,24 @@ static void* remdesk_virtual_channel_client_thread(void* arg)
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT remdesk_virtual_channel_event_connected(remdeskPlugin* remdesk, LPVOID pData, UINT32 dataLength)
|
||||
static UINT remdesk_virtual_channel_event_connected(remdeskPlugin* remdesk,
|
||||
LPVOID pData, UINT32 dataLength)
|
||||
{
|
||||
UINT32 status;
|
||||
UINT error;
|
||||
|
||||
status = remdesk->channelEntryPoints.pVirtualChannelOpen(remdesk->InitHandle,
|
||||
&remdesk->OpenHandle, remdesk->channelDef.name, remdesk_virtual_channel_open_event);
|
||||
status = remdesk->channelEntryPoints.pVirtualChannelOpenEx(remdesk->InitHandle,
|
||||
&remdesk->OpenHandle, remdesk->channelDef.name,
|
||||
remdesk_virtual_channel_open_event_ex);
|
||||
|
||||
if (status != CHANNEL_RC_OK)
|
||||
{
|
||||
WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08X]",
|
||||
WTSErrorToString(status), status);
|
||||
WLog_ERR(TAG, "pVirtualChannelOpenEx failed with %s [%08X]",
|
||||
WTSErrorToString(status), status);
|
||||
return status;
|
||||
}
|
||||
|
||||
if ((error = remdesk_add_open_handle_data(remdesk->OpenHandle, remdesk)))
|
||||
{
|
||||
WLog_ERR(TAG, "remdesk_add_open_handle_data failed with error %lu", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
remdesk->queue = MessageQueue_New(NULL);
|
||||
|
||||
if (!remdesk->queue)
|
||||
{
|
||||
WLog_ERR(TAG, "MessageQueue_New failed!");
|
||||
@ -1005,16 +919,18 @@ static UINT remdesk_virtual_channel_event_connected(remdeskPlugin* remdesk, LPVO
|
||||
}
|
||||
|
||||
remdesk->thread = CreateThread(NULL, 0,
|
||||
(LPTHREAD_START_ROUTINE) remdesk_virtual_channel_client_thread, (void*) remdesk, 0, NULL);
|
||||
(LPTHREAD_START_ROUTINE) remdesk_virtual_channel_client_thread, (void*) remdesk,
|
||||
0, NULL);
|
||||
|
||||
if (!remdesk->thread)
|
||||
{
|
||||
WLog_ERR(TAG, "CreateThread failed");
|
||||
error = ERROR_INTERNAL_ERROR;
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
error_out:
|
||||
remdesk_remove_open_handle_data(remdesk->OpenHandle);
|
||||
MessageQueue_Free(remdesk->queue);
|
||||
remdesk->queue = NULL;
|
||||
return error;
|
||||
@ -1029,53 +945,51 @@ static UINT remdesk_virtual_channel_event_disconnected(remdeskPlugin* remdesk)
|
||||
{
|
||||
UINT rc;
|
||||
|
||||
if (MessageQueue_PostQuit(remdesk->queue, 0) && (WaitForSingleObject(remdesk->thread, INFINITE) == WAIT_FAILED))
|
||||
if (MessageQueue_PostQuit(remdesk->queue, 0)
|
||||
&& (WaitForSingleObject(remdesk->thread, INFINITE) == WAIT_FAILED))
|
||||
{
|
||||
rc = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", rc);
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %u", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
MessageQueue_Free(remdesk->queue);
|
||||
CloseHandle(remdesk->thread);
|
||||
|
||||
remdesk->queue = NULL;
|
||||
remdesk->thread = NULL;
|
||||
rc = remdesk->channelEntryPoints.pVirtualChannelCloseEx(remdesk->InitHandle, remdesk->OpenHandle);
|
||||
|
||||
rc = remdesk->channelEntryPoints.pVirtualChannelClose(remdesk->OpenHandle);
|
||||
if (CHANNEL_RC_OK != rc)
|
||||
{
|
||||
WLog_ERR(TAG, "pVirtualChannelClose failed with %s [%08X]",
|
||||
WTSErrorToString(rc), rc);
|
||||
WLog_ERR(TAG, "pVirtualChannelCloseEx failed with %s [%08X]",
|
||||
WTSErrorToString(rc), rc);
|
||||
}
|
||||
|
||||
remdesk->OpenHandle = 0;
|
||||
|
||||
if (remdesk->data_in)
|
||||
{
|
||||
Stream_Free(remdesk->data_in, TRUE);
|
||||
remdesk->data_in = NULL;
|
||||
}
|
||||
|
||||
remdesk_remove_open_handle_data(remdesk->OpenHandle);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void remdesk_virtual_channel_event_terminated(remdeskPlugin* remdesk)
|
||||
{
|
||||
remdesk_remove_init_handle_data(remdesk->InitHandle);
|
||||
|
||||
remdesk->InitHandle = 0;
|
||||
free(remdesk);
|
||||
}
|
||||
|
||||
static VOID VCAPITYPE remdesk_virtual_channel_init_event(LPVOID pInitHandle,
|
||||
UINT event, LPVOID pData,
|
||||
UINT dataLength)
|
||||
static VOID VCAPITYPE remdesk_virtual_channel_init_event_ex(LPVOID lpUserParam, LPVOID pInitHandle,
|
||||
UINT event, LPVOID pData,
|
||||
UINT dataLength)
|
||||
{
|
||||
remdeskPlugin* remdesk;
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
remdeskPlugin* remdesk = (remdeskPlugin*) lpUserParam;
|
||||
|
||||
remdesk = (remdeskPlugin*) remdesk_get_init_handle_data(pInitHandle);
|
||||
|
||||
if (!remdesk)
|
||||
if (!remdesk || (remdesk->InitHandle != pInitHandle))
|
||||
{
|
||||
WLog_ERR(TAG, "error no match");
|
||||
return;
|
||||
@ -1084,34 +998,44 @@ static VOID VCAPITYPE remdesk_virtual_channel_init_event(LPVOID pInitHandle,
|
||||
switch (event)
|
||||
{
|
||||
case CHANNEL_EVENT_CONNECTED:
|
||||
if ((error = remdesk_virtual_channel_event_connected(remdesk, pData, dataLength)))
|
||||
WLog_ERR(TAG, "remdesk_virtual_channel_event_connected failed with error %lu", error);
|
||||
if ((error = remdesk_virtual_channel_event_connected(remdesk, pData,
|
||||
dataLength)))
|
||||
WLog_ERR(TAG, "remdesk_virtual_channel_event_connected failed with error %u",
|
||||
error);
|
||||
|
||||
break;
|
||||
|
||||
case CHANNEL_EVENT_DISCONNECTED:
|
||||
if ((error = remdesk_virtual_channel_event_disconnected(remdesk)))
|
||||
WLog_ERR(TAG, "remdesk_virtual_channel_event_disconnected failed with error %lu", error);
|
||||
WLog_ERR(TAG,
|
||||
"remdesk_virtual_channel_event_disconnected failed with error %u", error);
|
||||
|
||||
break;
|
||||
|
||||
case CHANNEL_EVENT_TERMINATED:
|
||||
remdesk_virtual_channel_event_terminated(remdesk);
|
||||
break;
|
||||
}
|
||||
|
||||
if (error && remdesk->rdpcontext)
|
||||
setChannelError(remdesk->rdpcontext, error, "remdesk_virtual_channel_init_event reported an error");
|
||||
setChannelError(remdesk->rdpcontext, error,
|
||||
"remdesk_virtual_channel_init_event reported an error");
|
||||
}
|
||||
|
||||
/* remdesk is always built-in */
|
||||
#define VirtualChannelEntry remdesk_VirtualChannelEntry
|
||||
#define VirtualChannelEntryEx remdesk_VirtualChannelEntryEx
|
||||
|
||||
BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
||||
BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS pEntryPoints, PVOID pInitHandle)
|
||||
{
|
||||
UINT rc;
|
||||
UINT error;
|
||||
|
||||
remdeskPlugin* remdesk;
|
||||
RemdeskClientContext* context = NULL;
|
||||
CHANNEL_ENTRY_POINTS_FREERDP* pEntryPointsEx;
|
||||
CHANNEL_ENTRY_POINTS_FREERDP_EX* pEntryPointsEx;
|
||||
|
||||
if (!pEntryPoints)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
remdesk = (remdeskPlugin*) calloc(1, sizeof(remdeskPlugin));
|
||||
|
||||
@ -1122,21 +1046,19 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
||||
}
|
||||
|
||||
remdesk->channelDef.options =
|
||||
CHANNEL_OPTION_INITIALIZED |
|
||||
CHANNEL_OPTION_ENCRYPT_RDP |
|
||||
CHANNEL_OPTION_COMPRESS_RDP |
|
||||
CHANNEL_OPTION_SHOW_PROTOCOL;
|
||||
|
||||
CHANNEL_OPTION_INITIALIZED |
|
||||
CHANNEL_OPTION_ENCRYPT_RDP |
|
||||
CHANNEL_OPTION_COMPRESS_RDP |
|
||||
CHANNEL_OPTION_SHOW_PROTOCOL;
|
||||
strcpy(remdesk->channelDef.name, "remdesk");
|
||||
|
||||
remdesk->Version = 2;
|
||||
pEntryPointsEx = (CHANNEL_ENTRY_POINTS_FREERDP_EX*) pEntryPoints;
|
||||
|
||||
pEntryPointsEx = (CHANNEL_ENTRY_POINTS_FREERDP*) pEntryPoints;
|
||||
|
||||
if ((pEntryPointsEx->cbSize >= sizeof(CHANNEL_ENTRY_POINTS_FREERDP)) &&
|
||||
(pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER))
|
||||
if ((pEntryPointsEx->cbSize >= sizeof(CHANNEL_ENTRY_POINTS_FREERDP_EX)) &&
|
||||
(pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER))
|
||||
{
|
||||
context = (RemdeskClientContext*) calloc(1, sizeof(RemdeskClientContext));
|
||||
|
||||
if (!context)
|
||||
{
|
||||
WLog_ERR(TAG, "calloc failed!");
|
||||
@ -1144,31 +1066,25 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
||||
}
|
||||
|
||||
context->handle = (void*) remdesk;
|
||||
|
||||
*(pEntryPointsEx->ppInterface) = (void*) context;
|
||||
remdesk->context = context;
|
||||
remdesk->rdpcontext = pEntryPointsEx->context;
|
||||
}
|
||||
|
||||
CopyMemory(&(remdesk->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP));
|
||||
CopyMemory(&(remdesk->channelEntryPoints), pEntryPoints,
|
||||
sizeof(CHANNEL_ENTRY_POINTS_FREERDP_EX));
|
||||
remdesk->InitHandle = pInitHandle;
|
||||
rc = remdesk->channelEntryPoints.pVirtualChannelInitEx(remdesk, context, pInitHandle,
|
||||
&remdesk->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000,
|
||||
remdesk_virtual_channel_init_event_ex);
|
||||
|
||||
rc = remdesk->channelEntryPoints.pVirtualChannelInit(&remdesk->InitHandle,
|
||||
&remdesk->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, remdesk_virtual_channel_init_event);
|
||||
if (CHANNEL_RC_OK != rc)
|
||||
{
|
||||
WLog_ERR(TAG, "pVirtualChannelInit failed with %s [%08X]",
|
||||
WTSErrorToString(rc), rc);
|
||||
WLog_ERR(TAG, "pVirtualChannelInitEx failed with %s [%08X]",
|
||||
WTSErrorToString(rc), rc);
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
remdesk->channelEntryPoints.pInterface = *(remdesk->channelEntryPoints.ppInterface);
|
||||
remdesk->channelEntryPoints.ppInterface = &(remdesk->channelEntryPoints.pInterface);
|
||||
|
||||
if ((error = remdesk_add_init_handle_data(remdesk->InitHandle, (void*) remdesk)))
|
||||
{
|
||||
WLog_ERR(TAG, "remdesk_add_init_handle_data failed with error %lu!", error);
|
||||
goto error_out;
|
||||
}
|
||||
remdesk->channelEntryPoints.pInterface = context;
|
||||
return TRUE;
|
||||
error_out:
|
||||
free(remdesk);
|
||||
|
||||
@ -41,7 +41,7 @@
|
||||
struct remdesk_plugin
|
||||
{
|
||||
CHANNEL_DEF channelDef;
|
||||
CHANNEL_ENTRY_POINTS_FREERDP channelEntryPoints;
|
||||
CHANNEL_ENTRY_POINTS_FREERDP_EX channelEntryPoints;
|
||||
|
||||
RemdeskClientContext* context;
|
||||
|
||||
|
||||
@ -34,14 +34,13 @@
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT remdesk_virtual_channel_write(RemdeskServerContext* context, wStream* s)
|
||||
static UINT remdesk_virtual_channel_write(RemdeskServerContext* context,
|
||||
wStream* s)
|
||||
{
|
||||
BOOL status;
|
||||
ULONG BytesWritten = 0;
|
||||
|
||||
status = WTSVirtualChannelWrite(context->priv->ChannelHandle,
|
||||
(PCHAR) Stream_Buffer(s), Stream_Length(s), &BytesWritten);
|
||||
|
||||
(PCHAR) Stream_Buffer(s), Stream_Length(s), &BytesWritten);
|
||||
return (status) ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
@ -50,7 +49,8 @@ static UINT remdesk_virtual_channel_write(RemdeskServerContext* context, wStream
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT remdesk_read_channel_header(wStream* s, REMDESK_CHANNEL_HEADER* header)
|
||||
static UINT remdesk_read_channel_header(wStream* s,
|
||||
REMDESK_CHANNEL_HEADER* header)
|
||||
{
|
||||
int status;
|
||||
UINT32 ChannelNameLen;
|
||||
@ -73,7 +73,7 @@ static UINT remdesk_read_channel_header(wStream* s, REMDESK_CHANNEL_HEADER* head
|
||||
|
||||
if ((ChannelNameLen % 2) != 0)
|
||||
{
|
||||
WLog_ERR(TAG, "(ChannelNameLen % 2) != 0!");
|
||||
WLog_ERR(TAG, "(ChannelNameLen %% 2) != 0!");
|
||||
return ERROR_INVALID_DATA;
|
||||
}
|
||||
|
||||
@ -84,11 +84,9 @@ static UINT remdesk_read_channel_header(wStream* s, REMDESK_CHANNEL_HEADER* head
|
||||
}
|
||||
|
||||
ZeroMemory(header->ChannelName, sizeof(header->ChannelName));
|
||||
|
||||
pChannelName = (char*) header->ChannelName;
|
||||
status = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s),
|
||||
ChannelNameLen / 2, &pChannelName, 32, NULL, NULL);
|
||||
|
||||
ChannelNameLen / 2, &pChannelName, 32, NULL, NULL);
|
||||
Stream_Seek(s, ChannelNameLen);
|
||||
|
||||
if (status <= 0)
|
||||
@ -105,12 +103,12 @@ static UINT remdesk_read_channel_header(wStream* s, REMDESK_CHANNEL_HEADER* head
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT remdesk_write_channel_header(wStream* s, REMDESK_CHANNEL_HEADER* header)
|
||||
static UINT remdesk_write_channel_header(wStream* s,
|
||||
REMDESK_CHANNEL_HEADER* header)
|
||||
{
|
||||
int index;
|
||||
UINT32 ChannelNameLen;
|
||||
WCHAR ChannelNameW[32];
|
||||
|
||||
ZeroMemory(ChannelNameW, sizeof(ChannelNameW));
|
||||
|
||||
for (index = 0; index < 32; index++)
|
||||
@ -119,12 +117,9 @@ static UINT remdesk_write_channel_header(wStream* s, REMDESK_CHANNEL_HEADER* hea
|
||||
}
|
||||
|
||||
ChannelNameLen = (strlen(header->ChannelName) + 1) * 2;
|
||||
|
||||
Stream_Write_UINT32(s, ChannelNameLen); /* ChannelNameLen (4 bytes) */
|
||||
Stream_Write_UINT32(s, header->DataLength); /* DataLen (4 bytes) */
|
||||
|
||||
Stream_Write(s, ChannelNameW, ChannelNameLen); /* ChannelName (variable) */
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
@ -136,11 +131,14 @@ static UINT remdesk_write_channel_header(wStream* s, REMDESK_CHANNEL_HEADER* hea
|
||||
static UINT remdesk_write_ctl_header(wStream* s, REMDESK_CTL_HEADER* ctlHeader)
|
||||
{
|
||||
UINT error;
|
||||
if ((error = remdesk_write_channel_header(s, (REMDESK_CHANNEL_HEADER*) ctlHeader)))
|
||||
|
||||
if ((error = remdesk_write_channel_header(s,
|
||||
(REMDESK_CHANNEL_HEADER*) ctlHeader)))
|
||||
{
|
||||
WLog_ERR(TAG, "remdesk_write_channel_header failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "remdesk_write_channel_header failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
Stream_Write_UINT32(s, ctlHeader->msgType); /* msgType (4 bytes) */
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
@ -150,7 +148,8 @@ static UINT remdesk_write_ctl_header(wStream* s, REMDESK_CTL_HEADER* ctlHeader)
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT remdesk_prepare_ctl_header(REMDESK_CTL_HEADER* ctlHeader, UINT32 msgType, UINT32 msgSize)
|
||||
static UINT remdesk_prepare_ctl_header(REMDESK_CTL_HEADER* ctlHeader,
|
||||
UINT32 msgType, UINT32 msgSize)
|
||||
{
|
||||
ctlHeader->msgType = msgType;
|
||||
strcpy(ctlHeader->ChannelName, REMDESK_CHANNEL_CTL_NAME);
|
||||
@ -163,21 +162,23 @@ static UINT remdesk_prepare_ctl_header(REMDESK_CTL_HEADER* ctlHeader, UINT32 msg
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT remdesk_send_ctl_result_pdu(RemdeskServerContext* context, UINT32 result)
|
||||
static UINT remdesk_send_ctl_result_pdu(RemdeskServerContext* context,
|
||||
UINT32 result)
|
||||
{
|
||||
wStream* s;
|
||||
REMDESK_CTL_RESULT_PDU pdu;
|
||||
UINT error;
|
||||
|
||||
pdu.result = result;
|
||||
|
||||
if ((error = remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_RESULT, 4)))
|
||||
if ((error = remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_RESULT,
|
||||
4)))
|
||||
{
|
||||
WLog_ERR(TAG, "remdesk_prepare_ctl_header failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "remdesk_prepare_ctl_header failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
s = Stream_New(NULL, REMDESK_CHANNEL_CTL_SIZE + pdu.ctlHeader.DataLength);
|
||||
|
||||
if (!s)
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_New failed!");
|
||||
@ -186,20 +187,18 @@ static UINT remdesk_send_ctl_result_pdu(RemdeskServerContext* context, UINT32 re
|
||||
|
||||
if ((error = remdesk_write_ctl_header(s, &(pdu.ctlHeader))))
|
||||
{
|
||||
WLog_ERR(TAG, "remdesk_write_ctl_header failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "remdesk_write_ctl_header failed with error %u!", error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
Stream_Write_UINT32(s, pdu.result); /* result (4 bytes) */
|
||||
|
||||
Stream_SealLength(s);
|
||||
|
||||
if ((error = remdesk_virtual_channel_write(context, s)))
|
||||
WLog_ERR(TAG, "remdesk_virtual_channel_write failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "remdesk_virtual_channel_write failed with error %u!", error);
|
||||
|
||||
out:
|
||||
Stream_Free(s, TRUE);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -214,16 +213,17 @@ static UINT remdesk_send_ctl_version_info_pdu(RemdeskServerContext* context)
|
||||
REMDESK_CTL_VERSION_INFO_PDU pdu;
|
||||
UINT error;
|
||||
|
||||
if ((error = remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_VERSIONINFO, 8)))
|
||||
if ((error = remdesk_prepare_ctl_header(&(pdu.ctlHeader),
|
||||
REMDESK_CTL_VERSIONINFO, 8)))
|
||||
{
|
||||
WLog_ERR(TAG, "remdesk_prepare_ctl_header failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "remdesk_prepare_ctl_header failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
pdu.versionMajor = 1;
|
||||
pdu.versionMinor = 2;
|
||||
|
||||
s = Stream_New(NULL, REMDESK_CHANNEL_CTL_SIZE + pdu.ctlHeader.DataLength);
|
||||
|
||||
if (!s)
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_New failed!");
|
||||
@ -232,20 +232,19 @@ static UINT remdesk_send_ctl_version_info_pdu(RemdeskServerContext* context)
|
||||
|
||||
if ((error = remdesk_write_ctl_header(s, &(pdu.ctlHeader))))
|
||||
{
|
||||
WLog_ERR(TAG, "remdesk_write_ctl_header failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "remdesk_write_ctl_header failed with error %u!", error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
Stream_Write_UINT32(s, pdu.versionMajor); /* versionMajor (4 bytes) */
|
||||
Stream_Write_UINT32(s, pdu.versionMinor); /* versionMinor (4 bytes) */
|
||||
|
||||
Stream_SealLength(s);
|
||||
|
||||
if ((error = remdesk_virtual_channel_write(context, s)))
|
||||
WLog_ERR(TAG, "remdesk_virtual_channel_write failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "remdesk_virtual_channel_write failed with error %u!", error);
|
||||
|
||||
out:
|
||||
Stream_Free(s, TRUE);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -254,7 +253,8 @@ out:
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT remdesk_recv_ctl_version_info_pdu(RemdeskServerContext* context, wStream* s, REMDESK_CHANNEL_HEADER* header)
|
||||
static UINT remdesk_recv_ctl_version_info_pdu(RemdeskServerContext* context,
|
||||
wStream* s, REMDESK_CHANNEL_HEADER* header)
|
||||
{
|
||||
UINT32 versionMajor;
|
||||
UINT32 versionMinor;
|
||||
@ -267,7 +267,6 @@ static UINT remdesk_recv_ctl_version_info_pdu(RemdeskServerContext* context, wSt
|
||||
|
||||
Stream_Read_UINT32(s, versionMajor); /* versionMajor (4 bytes) */
|
||||
Stream_Read_UINT32(s, versionMinor); /* versionMinor (4 bytes) */
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
@ -276,7 +275,8 @@ static UINT remdesk_recv_ctl_version_info_pdu(RemdeskServerContext* context, wSt
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT remdesk_recv_ctl_remote_control_desktop_pdu(RemdeskServerContext* context, wStream* s, REMDESK_CHANNEL_HEADER* header)
|
||||
static UINT remdesk_recv_ctl_remote_control_desktop_pdu(
|
||||
RemdeskServerContext* context, wStream* s, REMDESK_CHANNEL_HEADER* header)
|
||||
{
|
||||
int status;
|
||||
int cchStringW;
|
||||
@ -286,9 +286,7 @@ static UINT remdesk_recv_ctl_remote_control_desktop_pdu(RemdeskServerContext* co
|
||||
WCHAR* raConnectionStringW = NULL;
|
||||
REMDESK_CTL_REMOTE_CONTROL_DESKTOP_PDU pdu;
|
||||
UINT error;
|
||||
|
||||
msgLength = header->DataLength - 4;
|
||||
|
||||
pStringW = (WCHAR*) Stream_Pointer(s);
|
||||
raConnectionStringW = pStringW;
|
||||
cchStringW = 0;
|
||||
@ -304,11 +302,9 @@ static UINT remdesk_recv_ctl_remote_control_desktop_pdu(RemdeskServerContext* co
|
||||
|
||||
cchStringW++;
|
||||
cbRaConnectionStringW = cchStringW * 2;
|
||||
|
||||
pdu.raConnectionString = NULL;
|
||||
|
||||
status = ConvertFromUnicode(CP_UTF8, 0, raConnectionStringW,
|
||||
cbRaConnectionStringW / 2, &pdu.raConnectionString, 0, NULL, NULL);
|
||||
cbRaConnectionStringW / 2, &pdu.raConnectionString, 0, NULL, NULL);
|
||||
|
||||
if (status <= 0)
|
||||
{
|
||||
@ -317,11 +313,11 @@ static UINT remdesk_recv_ctl_remote_control_desktop_pdu(RemdeskServerContext* co
|
||||
}
|
||||
|
||||
WLog_INFO(TAG, "RaConnectionString: %s",
|
||||
pdu.raConnectionString);
|
||||
pdu.raConnectionString);
|
||||
free(pdu.raConnectionString);
|
||||
|
||||
if ((error = remdesk_send_ctl_result_pdu(context, 0)))
|
||||
WLog_ERR(TAG, "remdesk_send_ctl_result_pdu failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "remdesk_send_ctl_result_pdu failed with error %u!", error);
|
||||
|
||||
return error;
|
||||
}
|
||||
@ -331,7 +327,8 @@ static UINT remdesk_recv_ctl_remote_control_desktop_pdu(RemdeskServerContext* co
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT remdesk_recv_ctl_authenticate_pdu(RemdeskServerContext* context, wStream* s, REMDESK_CHANNEL_HEADER* header)
|
||||
static UINT remdesk_recv_ctl_authenticate_pdu(RemdeskServerContext* context,
|
||||
wStream* s, REMDESK_CHANNEL_HEADER* header)
|
||||
{
|
||||
int status;
|
||||
int cchStringW;
|
||||
@ -342,9 +339,7 @@ static UINT remdesk_recv_ctl_authenticate_pdu(RemdeskServerContext* context, wSt
|
||||
int cbRaConnectionStringW = 0;
|
||||
WCHAR* raConnectionStringW = NULL;
|
||||
REMDESK_CTL_AUTHENTICATE_PDU pdu;
|
||||
|
||||
msgLength = header->DataLength - 4;
|
||||
|
||||
pStringW = (WCHAR*) Stream_Pointer(s);
|
||||
raConnectionStringW = pStringW;
|
||||
cchStringW = 0;
|
||||
@ -360,7 +355,6 @@ static UINT remdesk_recv_ctl_authenticate_pdu(RemdeskServerContext* context, wSt
|
||||
|
||||
cchStringW++;
|
||||
cbRaConnectionStringW = cchStringW * 2;
|
||||
|
||||
pStringW += cchStringW;
|
||||
expertBlobW = pStringW;
|
||||
cchStringW = 0;
|
||||
@ -376,11 +370,9 @@ static UINT remdesk_recv_ctl_authenticate_pdu(RemdeskServerContext* context, wSt
|
||||
|
||||
cchStringW++;
|
||||
cbExpertBlobW = cchStringW * 2;
|
||||
|
||||
pdu.raConnectionString = NULL;
|
||||
|
||||
status = ConvertFromUnicode(CP_UTF8, 0, raConnectionStringW,
|
||||
cbRaConnectionStringW / 2, &pdu.raConnectionString, 0, NULL, NULL);
|
||||
cbRaConnectionStringW / 2, &pdu.raConnectionString, 0, NULL, NULL);
|
||||
|
||||
if (status <= 0)
|
||||
{
|
||||
@ -389,9 +381,8 @@ static UINT remdesk_recv_ctl_authenticate_pdu(RemdeskServerContext* context, wSt
|
||||
}
|
||||
|
||||
pdu.expertBlob = NULL;
|
||||
|
||||
status = ConvertFromUnicode(CP_UTF8, 0, expertBlobW,
|
||||
cbExpertBlobW / 2, &pdu.expertBlob, 0, NULL, NULL);
|
||||
cbExpertBlobW / 2, &pdu.expertBlob, 0, NULL, NULL);
|
||||
|
||||
if (status <= 0)
|
||||
{
|
||||
@ -401,10 +392,9 @@ static UINT remdesk_recv_ctl_authenticate_pdu(RemdeskServerContext* context, wSt
|
||||
}
|
||||
|
||||
WLog_INFO(TAG, "RaConnectionString: %s ExpertBlob: %s",
|
||||
pdu.raConnectionString, pdu.expertBlob);
|
||||
pdu.raConnectionString, pdu.expertBlob);
|
||||
free(pdu.raConnectionString);
|
||||
free(pdu.expertBlob);
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
@ -413,7 +403,8 @@ static UINT remdesk_recv_ctl_authenticate_pdu(RemdeskServerContext* context, wSt
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT remdesk_recv_ctl_verify_password_pdu(RemdeskServerContext* context, wStream* s, REMDESK_CHANNEL_HEADER* header)
|
||||
static UINT remdesk_recv_ctl_verify_password_pdu(RemdeskServerContext* context,
|
||||
wStream* s, REMDESK_CHANNEL_HEADER* header)
|
||||
{
|
||||
int status;
|
||||
int cbExpertBlobW = 0;
|
||||
@ -430,8 +421,8 @@ static UINT remdesk_recv_ctl_verify_password_pdu(RemdeskServerContext* context,
|
||||
pdu.expertBlob = NULL;
|
||||
expertBlobW = (WCHAR*) Stream_Pointer(s);
|
||||
cbExpertBlobW = header->DataLength - 4;
|
||||
|
||||
status = ConvertFromUnicode(CP_UTF8, 0, expertBlobW, cbExpertBlobW / 2, &pdu.expertBlob, 0, NULL, NULL);
|
||||
status = ConvertFromUnicode(CP_UTF8, 0, expertBlobW, cbExpertBlobW / 2,
|
||||
&pdu.expertBlob, 0, NULL, NULL);
|
||||
|
||||
if (status <= 0)
|
||||
{
|
||||
@ -440,8 +431,9 @@ static UINT remdesk_recv_ctl_verify_password_pdu(RemdeskServerContext* context,
|
||||
}
|
||||
|
||||
WLog_INFO(TAG, "ExpertBlob: %s", pdu.expertBlob);
|
||||
|
||||
if ((error = remdesk_send_ctl_result_pdu(context, 0)))
|
||||
WLog_ERR(TAG, "remdesk_send_ctl_result_pdu failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "remdesk_send_ctl_result_pdu failed with error %u!", error);
|
||||
|
||||
return error;
|
||||
}
|
||||
@ -451,7 +443,8 @@ static UINT remdesk_recv_ctl_verify_password_pdu(RemdeskServerContext* context,
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT remdesk_recv_ctl_pdu(RemdeskServerContext* context, wStream* s, REMDESK_CHANNEL_HEADER* header)
|
||||
static UINT remdesk_recv_ctl_pdu(RemdeskServerContext* context, wStream* s,
|
||||
REMDESK_CHANNEL_HEADER* header)
|
||||
{
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
UINT32 msgType = 0;
|
||||
@ -470,28 +463,34 @@ static UINT remdesk_recv_ctl_pdu(RemdeskServerContext* context, wStream* s, REMD
|
||||
case REMDESK_CTL_REMOTE_CONTROL_DESKTOP:
|
||||
if ((error = remdesk_recv_ctl_remote_control_desktop_pdu(context, s, header)))
|
||||
{
|
||||
WLog_ERR(TAG, "remdesk_recv_ctl_remote_control_desktop_pdu failed with error %lu!", error);
|
||||
WLog_ERR(TAG,
|
||||
"remdesk_recv_ctl_remote_control_desktop_pdu failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case REMDESK_CTL_AUTHENTICATE:
|
||||
if ((error = remdesk_recv_ctl_authenticate_pdu(context, s, header)))
|
||||
{
|
||||
WLog_ERR(TAG, "remdesk_recv_ctl_authenticate_pdu failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "remdesk_recv_ctl_authenticate_pdu failed with error %u!",
|
||||
error);
|
||||
return error;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case REMDESK_CTL_DISCONNECT:
|
||||
break;
|
||||
|
||||
case REMDESK_CTL_VERSIONINFO:
|
||||
if((error = remdesk_recv_ctl_version_info_pdu(context, s, header)))
|
||||
if ((error = remdesk_recv_ctl_version_info_pdu(context, s, header)))
|
||||
{
|
||||
WLog_ERR(TAG, "remdesk_recv_ctl_version_info_pdu failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "remdesk_recv_ctl_version_info_pdu failed with error %u!",
|
||||
error);
|
||||
return error;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case REMDESK_CTL_ISCONNECTED:
|
||||
@ -500,9 +499,11 @@ static UINT remdesk_recv_ctl_pdu(RemdeskServerContext* context, wStream* s, REMD
|
||||
case REMDESK_CTL_VERIFY_PASSWORD:
|
||||
if ((error = remdesk_recv_ctl_verify_password_pdu(context, s, header)))
|
||||
{
|
||||
WLog_ERR(TAG, "remdesk_recv_ctl_verify_password_pdu failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "remdesk_recv_ctl_verify_password_pdu failed with error %u!",
|
||||
error);
|
||||
return error;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case REMDESK_CTL_EXPERT_ON_VISTA:
|
||||
@ -531,11 +532,11 @@ static UINT remdesk_recv_ctl_pdu(RemdeskServerContext* context, wStream* s, REMD
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT remdesk_server_receive_pdu(RemdeskServerContext* context, wStream* s)
|
||||
static UINT remdesk_server_receive_pdu(RemdeskServerContext* context,
|
||||
wStream* s)
|
||||
{
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
REMDESK_CHANNEL_HEADER header;
|
||||
|
||||
#if 0
|
||||
WLog_INFO(TAG, "RemdeskReceive: %d", Stream_GetRemainingLength(s));
|
||||
winpr_HexDump(Stream_Pointer(s), Stream_GetRemainingLength(s));
|
||||
@ -543,42 +544,35 @@ static UINT remdesk_server_receive_pdu(RemdeskServerContext* context, wStream* s
|
||||
|
||||
if ((error = remdesk_read_channel_header(s, &header)))
|
||||
{
|
||||
WLog_ERR(TAG, "remdesk_read_channel_header failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "remdesk_read_channel_header failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
if (strcmp(header.ChannelName, "RC_CTL") == 0)
|
||||
{
|
||||
if ((error = remdesk_recv_ctl_pdu(context, s, &header)))
|
||||
{
|
||||
WLog_ERR(TAG, "remdesk_recv_ctl_pdu failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "remdesk_recv_ctl_pdu failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
else if (strcmp(header.ChannelName, "70") == 0)
|
||||
{
|
||||
|
||||
}
|
||||
else if (strcmp(header.ChannelName, "71") == 0)
|
||||
{
|
||||
|
||||
}
|
||||
else if (strcmp(header.ChannelName, ".") == 0)
|
||||
{
|
||||
|
||||
}
|
||||
else if (strcmp(header.ChannelName, "1000.") == 0)
|
||||
{
|
||||
|
||||
}
|
||||
else if (strcmp(header.ChannelName, "RA_FX") == 0)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return error;
|
||||
@ -597,14 +591,13 @@ static void* remdesk_server_thread(void* arg)
|
||||
DWORD BytesReturned;
|
||||
RemdeskServerContext* context;
|
||||
UINT error;
|
||||
|
||||
context = (RemdeskServerContext*) arg;
|
||||
|
||||
buffer = NULL;
|
||||
BytesReturned = 0;
|
||||
ChannelEvent = NULL;
|
||||
|
||||
s = Stream_New(NULL, 4096);
|
||||
|
||||
if (!s)
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_New failed!");
|
||||
@ -612,7 +605,8 @@ static void* remdesk_server_thread(void* arg)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE)
|
||||
if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle,
|
||||
&buffer, &BytesReturned) == TRUE)
|
||||
{
|
||||
if (BytesReturned == sizeof(HANDLE))
|
||||
CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE));
|
||||
@ -632,7 +626,8 @@ static void* remdesk_server_thread(void* arg)
|
||||
|
||||
if ((error = remdesk_send_ctl_version_info_pdu(context)))
|
||||
{
|
||||
WLog_ERR(TAG, "remdesk_send_ctl_version_info_pdu failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "remdesk_send_ctl_version_info_pdu failed with error %u!",
|
||||
error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -640,22 +635,21 @@ static void* remdesk_server_thread(void* arg)
|
||||
{
|
||||
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
|
||||
|
||||
if (status == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu", error);
|
||||
break;
|
||||
}
|
||||
if (status == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForMultipleObjects failed with error %u", error);
|
||||
break;
|
||||
}
|
||||
|
||||
status = WaitForSingleObject(context->priv->StopEvent, 0);
|
||||
|
||||
if (status == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", error);
|
||||
break;
|
||||
}
|
||||
status = WaitForSingleObject(context->priv->StopEvent, 0);
|
||||
|
||||
if (status == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %u", error);
|
||||
break;
|
||||
}
|
||||
|
||||
if (status == WAIT_OBJECT_0)
|
||||
{
|
||||
@ -663,7 +657,7 @@ static void* remdesk_server_thread(void* arg)
|
||||
}
|
||||
|
||||
if (WTSVirtualChannelRead(context->priv->ChannelHandle, 0,
|
||||
(PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned))
|
||||
(PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned))
|
||||
{
|
||||
if (BytesReturned)
|
||||
Stream_Seek(s, BytesReturned);
|
||||
@ -687,11 +681,13 @@ static void* remdesk_server_thread(void* arg)
|
||||
{
|
||||
Stream_SealLength(s);
|
||||
Stream_SetPosition(s, 0);
|
||||
|
||||
if ((error = remdesk_server_receive_pdu(context, s)))
|
||||
{
|
||||
WLog_ERR(TAG, "remdesk_server_receive_pdu failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "remdesk_server_receive_pdu failed with error %u!", error);
|
||||
break;
|
||||
}
|
||||
|
||||
Stream_SetPosition(s, 0);
|
||||
}
|
||||
}
|
||||
@ -699,8 +695,10 @@ static void* remdesk_server_thread(void* arg)
|
||||
|
||||
Stream_Free(s, TRUE);
|
||||
out:
|
||||
|
||||
if (error && context->rdpcontext)
|
||||
setChannelError(context->rdpcontext, error, "remdesk_server_thread reported an error");
|
||||
setChannelError(context->rdpcontext, error,
|
||||
"remdesk_server_thread reported an error");
|
||||
|
||||
ExitThread((DWORD)error);
|
||||
return NULL;
|
||||
@ -713,7 +711,8 @@ out:
|
||||
*/
|
||||
static UINT remdesk_server_start(RemdeskServerContext* context)
|
||||
{
|
||||
context->priv->ChannelHandle = WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, "remdesk");
|
||||
context->priv->ChannelHandle = WTSVirtualChannelOpen(context->vcm,
|
||||
WTS_CURRENT_SESSION, "remdesk");
|
||||
|
||||
if (!context->priv->ChannelHandle)
|
||||
{
|
||||
@ -728,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)))
|
||||
(LPTHREAD_START_ROUTINE) remdesk_server_thread, (void*) context, 0, NULL)))
|
||||
{
|
||||
WLog_ERR(TAG, "CreateThread failed!");
|
||||
CloseHandle(context->priv->StopEvent);
|
||||
@ -746,34 +745,30 @@ static UINT remdesk_server_start(RemdeskServerContext* context)
|
||||
*/
|
||||
static UINT remdesk_server_stop(RemdeskServerContext* context)
|
||||
{
|
||||
UINT error;
|
||||
|
||||
UINT error;
|
||||
SetEvent(context->priv->StopEvent);
|
||||
|
||||
if (WaitForSingleObject(context->priv->Thread, INFINITE) == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
|
||||
return error;
|
||||
}
|
||||
CloseHandle(context->priv->Thread);
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
CloseHandle(context->priv->Thread);
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
RemdeskServerContext* remdesk_server_context_new(HANDLE vcm)
|
||||
{
|
||||
RemdeskServerContext* context;
|
||||
|
||||
context = (RemdeskServerContext*) calloc(1, sizeof(RemdeskServerContext));
|
||||
|
||||
if (context)
|
||||
{
|
||||
context->vcm = vcm;
|
||||
|
||||
context->Start = remdesk_server_start;
|
||||
context->Stop = remdesk_server_stop;
|
||||
|
||||
context->priv = (RemdeskServerPrivate*) calloc(1, sizeof(RemdeskServerPrivate));
|
||||
|
||||
if (!context->priv)
|
||||
@ -781,6 +776,7 @@ RemdeskServerContext* remdesk_server_context_new(HANDLE vcm)
|
||||
free(context);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
context->priv->Version = 1;
|
||||
}
|
||||
|
||||
|
||||
@ -27,7 +27,7 @@ add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE
|
||||
target_link_libraries(${MODULE_NAME} winpr freerdp)
|
||||
|
||||
|
||||
if (WITH_DEBUG_SYMBOLS AND MSVC AND NOT STATIC_CHANNELS AND BUILD_SHARED_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()
|
||||
|
||||
|
||||
@ -47,7 +47,7 @@
|
||||
/* TODO: all #ifdef __linux__ could be removed once only some generic
|
||||
* functions will be used. Replace CommReadFile by ReadFile,
|
||||
* CommWriteFile by WriteFile etc.. */
|
||||
#if defined __linux__ && !defined ANDROID
|
||||
#if defined __linux__ && !defined ANDROID
|
||||
|
||||
#define MAX_IRP_THREADS 5
|
||||
|
||||
@ -65,7 +65,7 @@ struct _SERIAL_DEVICE
|
||||
wMessageQueue* MainIrpQueue;
|
||||
|
||||
/* one thread per pending IRP and indexed according their CompletionId */
|
||||
wListDictionary *IrpThreads;
|
||||
wListDictionary* IrpThreads;
|
||||
UINT32 IrpThreadToBeTerminatedCount;
|
||||
CRITICAL_SECTION TerminatingIrpThreadsLock;
|
||||
rdpContext* rdpcontext;
|
||||
@ -75,15 +75,14 @@ typedef struct _IRP_THREAD_DATA IRP_THREAD_DATA;
|
||||
|
||||
struct _IRP_THREAD_DATA
|
||||
{
|
||||
SERIAL_DEVICE *serial;
|
||||
IRP *irp;
|
||||
SERIAL_DEVICE* serial;
|
||||
IRP* irp;
|
||||
};
|
||||
|
||||
static UINT32 _GetLastErrorToIoStatus(SERIAL_DEVICE* serial)
|
||||
{
|
||||
/* http://msdn.microsoft.com/en-us/library/ff547466%28v=vs.85%29.aspx#generic_status_values_for_serial_device_control_requests */
|
||||
|
||||
switch(GetLastError())
|
||||
switch (GetLastError())
|
||||
{
|
||||
case ERROR_BAD_DEVICE:
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
@ -117,11 +116,11 @@ static UINT32 _GetLastErrorToIoStatus(SERIAL_DEVICE* serial)
|
||||
|
||||
case ERROR_TIMEOUT:
|
||||
return STATUS_TIMEOUT;
|
||||
|
||||
/* no default */
|
||||
/* no default */
|
||||
}
|
||||
|
||||
WLog_Print(serial->log, WLOG_DEBUG, "unexpected last-error: 0x%lx", GetLastError());
|
||||
WLog_Print(serial->log, WLOG_DEBUG, "unexpected last-error: 0x%lx",
|
||||
GetLastError());
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
@ -131,19 +130,16 @@ static void serial_process_irp_create(SERIAL_DEVICE* serial, IRP* irp)
|
||||
DWORD SharedAccess;
|
||||
DWORD CreateDisposition;
|
||||
UINT32 PathLength;
|
||||
|
||||
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) */
|
||||
Stream_Seek(irp->input, PathLength); /* Path (variable) */
|
||||
|
||||
assert(PathLength == 0); /* MS-RDPESP 2.2.2.2 */
|
||||
|
||||
|
||||
#ifndef _WIN32
|
||||
/* Windows 2012 server sends on a first call :
|
||||
* DesiredAccess = 0x00100080: SYNCHRONIZE | FILE_READ_ATTRIBUTES
|
||||
@ -160,35 +156,32 @@ static void serial_process_irp_create(SERIAL_DEVICE* serial, IRP* irp)
|
||||
* assert(CreateDisposition == OPEN_EXISTING);
|
||||
*
|
||||
*/
|
||||
|
||||
WLog_Print(serial->log, WLOG_DEBUG, "DesiredAccess: 0x%lX, SharedAccess: 0x%lX, CreateDisposition: 0x%lX", DesiredAccess, SharedAccess, CreateDisposition);
|
||||
|
||||
WLog_Print(serial->log, WLOG_DEBUG,
|
||||
"DesiredAccess: 0x%lX, SharedAccess: 0x%lX, CreateDisposition: 0x%lX",
|
||||
DesiredAccess, SharedAccess, CreateDisposition);
|
||||
/* FIXME: As of today only the flags below are supported by CommCreateFileA: */
|
||||
DesiredAccess = GENERIC_READ | GENERIC_WRITE;
|
||||
SharedAccess = 0;
|
||||
CreateDisposition = OPEN_EXISTING;
|
||||
#endif
|
||||
|
||||
serial->hComm = CreateFile(serial->device.name,
|
||||
DesiredAccess,
|
||||
SharedAccess,
|
||||
NULL, /* SecurityAttributes */
|
||||
CreateDisposition,
|
||||
0, /* FlagsAndAttributes */
|
||||
NULL); /* TemplateFile */
|
||||
DesiredAccess,
|
||||
SharedAccess,
|
||||
NULL, /* SecurityAttributes */
|
||||
CreateDisposition,
|
||||
0, /* FlagsAndAttributes */
|
||||
NULL); /* TemplateFile */
|
||||
|
||||
if (!serial->hComm || (serial->hComm == INVALID_HANDLE_VALUE))
|
||||
{
|
||||
WLog_Print(serial->log, WLOG_WARN, "CreateFile failure: %s last-error: 0x%lX\n", serial->device.name, GetLastError());
|
||||
|
||||
WLog_Print(serial->log, WLOG_WARN, "CreateFile failure: %s last-error: 0x%lX\n",
|
||||
serial->device.name, GetLastError());
|
||||
irp->IoStatus = STATUS_UNSUCCESSFUL;
|
||||
goto error_handle;
|
||||
}
|
||||
|
||||
_comm_setServerSerialDriver(serial->hComm, serial->ServerSerialDriverId);
|
||||
|
||||
_comm_set_permissive(serial->hComm, serial->permissive);
|
||||
|
||||
/* NOTE: binary mode/raw mode required for the redirection. On
|
||||
* Linux, CommCreateFileA forces this setting.
|
||||
*/
|
||||
@ -197,15 +190,13 @@ static void serial_process_irp_create(SERIAL_DEVICE* serial, IRP* irp)
|
||||
/* GetCommState(serial->hComm, &dcb); */
|
||||
/* 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: %d, FileId: %d) created.", serial->device.name, irp->device->id, irp->FileId);
|
||||
|
||||
error_handle:
|
||||
WLog_Print(serial->log, WLOG_DEBUG, "%s (DeviceId: %d, FileId: %d) 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) */
|
||||
}
|
||||
@ -216,17 +207,17 @@ static void serial_process_irp_close(SERIAL_DEVICE* serial, IRP* irp)
|
||||
|
||||
if (!CloseHandle(serial->hComm))
|
||||
{
|
||||
WLog_Print(serial->log, WLOG_WARN, "CloseHandle failure: %s (%d) closed.", serial->device.name, irp->device->id);
|
||||
WLog_Print(serial->log, WLOG_WARN, "CloseHandle failure: %s (%d) closed.",
|
||||
serial->device.name, irp->device->id);
|
||||
irp->IoStatus = STATUS_UNSUCCESSFUL;
|
||||
goto error_handle;
|
||||
}
|
||||
|
||||
WLog_Print(serial->log, WLOG_DEBUG, "%s (DeviceId: %d, FileId: %d) closed.", serial->device.name, irp->device->id, irp->FileId);
|
||||
|
||||
WLog_Print(serial->log, WLOG_DEBUG, "%s (DeviceId: %d, FileId: %d) closed.",
|
||||
serial->device.name, irp->device->id, irp->FileId);
|
||||
serial->hComm = NULL;
|
||||
irp->IoStatus = STATUS_SUCCESS;
|
||||
|
||||
error_handle:
|
||||
error_handle:
|
||||
Stream_Zero(irp->output, 5); /* Padding (5 bytes) */
|
||||
}
|
||||
|
||||
@ -241,26 +232,22 @@ static UINT serial_process_irp_read(SERIAL_DEVICE* serial, IRP* irp)
|
||||
UINT64 Offset;
|
||||
BYTE* buffer = NULL;
|
||||
DWORD nbRead = 0;
|
||||
|
||||
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) */
|
||||
|
||||
|
||||
buffer = (BYTE*)calloc(Length, sizeof(BYTE));
|
||||
|
||||
if (buffer == NULL)
|
||||
{
|
||||
irp->IoStatus = STATUS_NO_MEMORY;
|
||||
goto error_handle;
|
||||
}
|
||||
|
||||
|
||||
/* MS-RDPESP 3.2.5.1.4: If the Offset field is not set to 0, the value MUST be ignored
|
||||
* assert(Offset == 0);
|
||||
*/
|
||||
|
||||
|
||||
WLog_Print(serial->log, WLOG_DEBUG, "reading %d bytes from %s", Length, serial->device.name);
|
||||
WLog_Print(serial->log, WLOG_DEBUG, "reading %d bytes from %s", Length,
|
||||
serial->device.name);
|
||||
|
||||
/* FIXME: CommReadFile to be replaced by ReadFile */
|
||||
if (CommReadFile(serial->hComm, buffer, Length, &nbRead, NULL))
|
||||
@ -269,15 +256,15 @@ static UINT serial_process_irp_read(SERIAL_DEVICE* serial, IRP* irp)
|
||||
}
|
||||
else
|
||||
{
|
||||
WLog_Print(serial->log, WLOG_DEBUG, "read failure to %s, nbRead=%ld, last-error: 0x%lX", serial->device.name, nbRead, GetLastError());
|
||||
|
||||
WLog_Print(serial->log, WLOG_DEBUG,
|
||||
"read failure to %s, nbRead=%ld, last-error: 0x%lX", serial->device.name,
|
||||
nbRead, GetLastError());
|
||||
irp->IoStatus = _GetLastErrorToIoStatus(serial);
|
||||
}
|
||||
|
||||
WLog_Print(serial->log, WLOG_DEBUG, "%lu bytes read from %s", nbRead, serial->device.name);
|
||||
|
||||
error_handle:
|
||||
|
||||
WLog_Print(serial->log, WLOG_DEBUG, "%lu bytes read from %s", nbRead,
|
||||
serial->device.name);
|
||||
error_handle:
|
||||
Stream_Write_UINT32(irp->output, nbRead); /* Length (4 bytes) */
|
||||
|
||||
if (nbRead > 0)
|
||||
@ -288,6 +275,7 @@ static UINT serial_process_irp_read(SERIAL_DEVICE* serial, IRP* irp)
|
||||
free(buffer);
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
}
|
||||
|
||||
Stream_Write(irp->output, buffer, nbRead); /* ReadData */
|
||||
}
|
||||
|
||||
@ -300,34 +288,34 @@ static void serial_process_irp_write(SERIAL_DEVICE* serial, IRP* irp)
|
||||
UINT32 Length;
|
||||
UINT64 Offset;
|
||||
DWORD nbWritten = 0;
|
||||
|
||||
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) */
|
||||
|
||||
/* MS-RDPESP 3.2.5.1.5: The Offset field is ignored
|
||||
* assert(Offset == 0);
|
||||
*
|
||||
* Using a serial printer, noticed though this field could be
|
||||
* set.
|
||||
*/
|
||||
|
||||
WLog_Print(serial->log, WLOG_DEBUG, "writing %d bytes to %s", Length, serial->device.name);
|
||||
WLog_Print(serial->log, WLOG_DEBUG, "writing %d bytes to %s", Length,
|
||||
serial->device.name);
|
||||
|
||||
/* FIXME: CommWriteFile to be replaced by WriteFile */
|
||||
if (CommWriteFile(serial->hComm, Stream_Pointer(irp->input), Length, &nbWritten, NULL))
|
||||
if (CommWriteFile(serial->hComm, Stream_Pointer(irp->input), Length, &nbWritten,
|
||||
NULL))
|
||||
{
|
||||
irp->IoStatus = STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
WLog_Print(serial->log, WLOG_DEBUG, "write failure to %s, nbWritten=%ld, last-error: 0x%lX", serial->device.name, nbWritten, GetLastError());
|
||||
|
||||
WLog_Print(serial->log, WLOG_DEBUG,
|
||||
"write failure to %s, nbWritten=%ld, last-error: 0x%lX", serial->device.name,
|
||||
nbWritten, GetLastError());
|
||||
irp->IoStatus = _GetLastErrorToIoStatus(serial);
|
||||
}
|
||||
|
||||
WLog_Print(serial->log, WLOG_DEBUG, "%lu bytes written to %s", nbWritten, serial->device.name);
|
||||
|
||||
WLog_Print(serial->log, WLOG_DEBUG, "%lu bytes written to %s", (unsigned long) nbWritten,
|
||||
serial->device.name);
|
||||
Stream_Write_UINT32(irp->output, nbWritten); /* Length (4 bytes) */
|
||||
Stream_Write_UINT8(irp->output, 0); /* Padding (1 byte) */
|
||||
}
|
||||
@ -346,13 +334,14 @@ 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) */
|
||||
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) */
|
||||
|
||||
OutputBuffer = (BYTE*)calloc(OutputBufferLength, sizeof(BYTE));
|
||||
|
||||
if (OutputBuffer == NULL)
|
||||
{
|
||||
irp->IoStatus = STATUS_NO_MEMORY;
|
||||
@ -360,6 +349,7 @@ static UINT serial_process_irp_device_control(SERIAL_DEVICE* serial, IRP* irp)
|
||||
}
|
||||
|
||||
InputBuffer = (BYTE*)calloc(InputBufferLength, sizeof(BYTE));
|
||||
|
||||
if (InputBuffer == NULL)
|
||||
{
|
||||
irp->IoStatus = STATUS_NO_MEMORY;
|
||||
@ -367,32 +357,32 @@ static UINT serial_process_irp_device_control(SERIAL_DEVICE* serial, IRP* irp)
|
||||
}
|
||||
|
||||
Stream_Read(irp->input, InputBuffer, InputBufferLength);
|
||||
|
||||
WLog_Print(serial->log, WLOG_DEBUG, "CommDeviceIoControl: CompletionId=%d, IoControlCode=[0x%X] %s", irp->CompletionId, IoControlCode, _comm_serial_ioctl_name(IoControlCode));
|
||||
WLog_Print(serial->log, WLOG_DEBUG,
|
||||
"CommDeviceIoControl: CompletionId=%d, IoControlCode=[0x%X] %s",
|
||||
irp->CompletionId, IoControlCode, _comm_serial_ioctl_name(IoControlCode));
|
||||
|
||||
/* FIXME: CommDeviceIoControl to be replaced by DeviceIoControl() */
|
||||
if (CommDeviceIoControl(serial->hComm, IoControlCode, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength, &BytesReturned, NULL))
|
||||
if (CommDeviceIoControl(serial->hComm, IoControlCode, InputBuffer,
|
||||
InputBufferLength, OutputBuffer, OutputBufferLength, &BytesReturned, NULL))
|
||||
{
|
||||
/* WLog_Print(serial->log, WLOG_DEBUG, "CommDeviceIoControl: CompletionId=%d, IoControlCode=[0x%X] %s done", irp->CompletionId, IoControlCode, _comm_serial_ioctl_name(IoControlCode)); */
|
||||
|
||||
irp->IoStatus = STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
WLog_Print(serial->log, WLOG_DEBUG, "CommDeviceIoControl failure: IoControlCode=[0x%X] %s, last-error: 0x%lX",
|
||||
IoControlCode, _comm_serial_ioctl_name(IoControlCode), GetLastError());
|
||||
|
||||
WLog_Print(serial->log, WLOG_DEBUG,
|
||||
"CommDeviceIoControl failure: IoControlCode=[0x%X] %s, last-error: 0x%lX",
|
||||
IoControlCode, _comm_serial_ioctl_name(IoControlCode), GetLastError());
|
||||
irp->IoStatus = _GetLastErrorToIoStatus(serial);
|
||||
}
|
||||
|
||||
error_handle:
|
||||
|
||||
error_handle:
|
||||
/* FIXME: find out whether it's required or not to get
|
||||
* 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)
|
||||
{
|
||||
@ -406,6 +396,7 @@ static UINT serial_process_irp_device_control(SERIAL_DEVICE* serial, IRP* irp)
|
||||
|
||||
Stream_Write(irp->output, OutputBuffer, BytesReturned); /* OutputBuffer */
|
||||
}
|
||||
|
||||
/* FIXME: Why at least Windows 2008R2 gets lost with this
|
||||
* extra byte and likely on a IOCTL_SERIAL_SET_BAUD_RATE? The
|
||||
* extra byte is well required according MS-RDPEFS
|
||||
@ -414,7 +405,6 @@ static UINT serial_process_irp_device_control(SERIAL_DEVICE* serial, IRP* irp)
|
||||
/* { */
|
||||
/* Stream_Write_UINT8(irp->output, 0); /\* Padding (1 byte) *\/ */
|
||||
/* } */
|
||||
|
||||
free(InputBuffer);
|
||||
free(OutputBuffer);
|
||||
return CHANNEL_RC_OK;
|
||||
@ -428,8 +418,9 @@ static UINT serial_process_irp_device_control(SERIAL_DEVICE* serial, IRP* irp)
|
||||
static UINT serial_process_irp(SERIAL_DEVICE* serial, IRP* irp)
|
||||
{
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
WLog_Print(serial->log, WLOG_DEBUG, "IRP MajorFunction: 0x%04X MinorFunction: 0x%04X\n",
|
||||
irp->MajorFunction, irp->MinorFunction);
|
||||
WLog_Print(serial->log, WLOG_DEBUG,
|
||||
"IRP MajorFunction: 0x%04X MinorFunction: 0x%04X\n",
|
||||
irp->MajorFunction, irp->MinorFunction);
|
||||
|
||||
switch (irp->MajorFunction)
|
||||
{
|
||||
@ -443,7 +434,8 @@ static UINT serial_process_irp(SERIAL_DEVICE* serial, IRP* irp)
|
||||
|
||||
case IRP_MJ_READ:
|
||||
if ((error = serial_process_irp_read(serial, irp)))
|
||||
WLog_ERR(TAG, "serial_process_irp_read failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "serial_process_irp_read failed with error %u!", error);
|
||||
|
||||
break;
|
||||
|
||||
case IRP_MJ_WRITE:
|
||||
@ -452,58 +444,57 @@ static UINT serial_process_irp(SERIAL_DEVICE* serial, IRP* irp)
|
||||
|
||||
case IRP_MJ_DEVICE_CONTROL:
|
||||
if ((error = serial_process_irp_device_control(serial, irp)))
|
||||
WLog_ERR(TAG, "serial_process_irp_device_control failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "serial_process_irp_device_control failed with error %u!",
|
||||
error);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
irp->IoStatus = STATUS_NOT_SUPPORTED;
|
||||
break;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
static void* irp_thread_func(void* arg)
|
||||
{
|
||||
IRP_THREAD_DATA *data = (IRP_THREAD_DATA*)arg;
|
||||
IRP_THREAD_DATA* data = (IRP_THREAD_DATA*)arg;
|
||||
UINT error;
|
||||
|
||||
/* blocks until the end of the request */
|
||||
if ((error = serial_process_irp(data->serial, data->irp)))
|
||||
{
|
||||
WLog_ERR(TAG, "serial_process_irp failed with error %lu", error);
|
||||
WLog_ERR(TAG, "serial_process_irp failed with error %u", error);
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
EnterCriticalSection(&data->serial->TerminatingIrpThreadsLock);
|
||||
data->serial->IrpThreadToBeTerminatedCount++;
|
||||
|
||||
error = data->irp->Complete(data->irp);
|
||||
|
||||
LeaveCriticalSection(&data->serial->TerminatingIrpThreadsLock);
|
||||
|
||||
error_out:
|
||||
|
||||
if (error && data->serial->rdpcontext)
|
||||
setChannelError(data->serial->rdpcontext, error, "irp_thread_func reported an error");
|
||||
setChannelError(data->serial->rdpcontext, error,
|
||||
"irp_thread_func reported an error");
|
||||
|
||||
/* NB: At this point, the server might already being reusing
|
||||
* the CompletionId whereas the thread is not yet
|
||||
* terminated */
|
||||
|
||||
free(data);
|
||||
|
||||
ExitThread((DWORD)error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void create_irp_thread(SERIAL_DEVICE *serial, IRP *irp)
|
||||
static void create_irp_thread(SERIAL_DEVICE* serial, IRP* irp)
|
||||
{
|
||||
IRP_THREAD_DATA *data = NULL;
|
||||
IRP_THREAD_DATA* data = NULL;
|
||||
HANDLE irpThread;
|
||||
HANDLE previousIrpThread;
|
||||
uintptr_t key;
|
||||
|
||||
/* for a test/debug purpose, uncomment the code below to get a
|
||||
* single thread for all IRPs. NB: two IRPs could not be
|
||||
* processed at the same time, typically two concurent
|
||||
@ -511,65 +502,57 @@ static void create_irp_thread(SERIAL_DEVICE *serial, IRP *irp)
|
||||
/* serial_process_irp(serial, irp); */
|
||||
/* irp->Complete(irp); */
|
||||
/* return; */
|
||||
|
||||
|
||||
/* NOTE: for good or bad, this implementation relies on the
|
||||
* server to avoid a flooding of requests. see also _purge().
|
||||
*/
|
||||
|
||||
EnterCriticalSection(&serial->TerminatingIrpThreadsLock);
|
||||
|
||||
while (serial->IrpThreadToBeTerminatedCount > 0)
|
||||
{
|
||||
/* Cleaning up termitating and pending irp
|
||||
* threads. See also: irp_thread_func() */
|
||||
|
||||
HANDLE irpThread;
|
||||
ULONG_PTR *ids;
|
||||
ULONG_PTR* ids;
|
||||
int i, nbIds;
|
||||
|
||||
nbIds = ListDictionary_GetKeys(serial->IrpThreads, &ids);
|
||||
for (i=0; i<nbIds; i++)
|
||||
|
||||
for (i = 0; i < nbIds; i++)
|
||||
{
|
||||
/* Checking if ids[i] is terminating or pending */
|
||||
|
||||
DWORD waitResult;
|
||||
ULONG_PTR id = ids[i];
|
||||
|
||||
irpThread = ListDictionary_GetItemValue(serial->IrpThreads, (void*)id);
|
||||
|
||||
/* FIXME: not quite sure a zero timeout is a good thing to check whether a thread is stil alived or not */
|
||||
waitResult = WaitForSingleObject(irpThread, 0);
|
||||
|
||||
if (waitResult == WAIT_OBJECT_0)
|
||||
{
|
||||
/* terminating thread */
|
||||
|
||||
/* WLog_Print(serial->log, WLOG_DEBUG, "IRP thread with CompletionId=%d naturally died", id); */
|
||||
|
||||
CloseHandle(irpThread);
|
||||
ListDictionary_Remove(serial->IrpThreads, (void*)id);
|
||||
|
||||
serial->IrpThreadToBeTerminatedCount--;
|
||||
}
|
||||
else if (waitResult != WAIT_TIMEOUT)
|
||||
{
|
||||
{
|
||||
/* unexpected thread state */
|
||||
|
||||
WLog_Print(serial->log, WLOG_WARN, "WaitForSingleObject, got an unexpected result=0x%lX\n", waitResult);
|
||||
WLog_Print(serial->log, WLOG_WARN,
|
||||
"WaitForSingleObject, got an unexpected result=0x%lX\n", waitResult);
|
||||
assert(FALSE);
|
||||
}
|
||||
|
||||
/* pending thread (but not yet terminating thread) if waitResult == WAIT_TIMEOUT */
|
||||
}
|
||||
|
||||
|
||||
if (serial->IrpThreadToBeTerminatedCount > 0)
|
||||
{
|
||||
WLog_Print(serial->log, WLOG_DEBUG, "%d IRP thread(s) not yet terminated", serial->IrpThreadToBeTerminatedCount);
|
||||
WLog_Print(serial->log, WLOG_DEBUG, "%d IRP thread(s) not yet terminated",
|
||||
serial->IrpThreadToBeTerminatedCount);
|
||||
Sleep(1); /* 1 ms */
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection(&serial->TerminatingIrpThreadsLock);
|
||||
|
||||
LeaveCriticalSection(&serial->TerminatingIrpThreadsLock);
|
||||
/* NB: At this point and thanks to the synchronization we're
|
||||
* sure that the incoming IRP uses well a recycled
|
||||
* CompletionId or the server sent again an IRP already posted
|
||||
@ -580,22 +563,20 @@ static void create_irp_thread(SERIAL_DEVICE *serial, IRP *irp)
|
||||
* FIXME: behavior documented somewhere? behavior not yet
|
||||
* observed with FreeRDP).
|
||||
*/
|
||||
|
||||
key = irp->CompletionId;
|
||||
previousIrpThread = ListDictionary_GetItemValue(serial->IrpThreads, (void*)key);
|
||||
|
||||
if (previousIrpThread)
|
||||
{
|
||||
/* Thread still alived <=> Request still pending */
|
||||
|
||||
WLog_Print(serial->log, WLOG_DEBUG, "IRP recall: IRP with the CompletionId=%d not yet completed!", irp->CompletionId);
|
||||
|
||||
WLog_Print(serial->log, WLOG_DEBUG,
|
||||
"IRP recall: IRP with the CompletionId=%d not yet completed!",
|
||||
irp->CompletionId);
|
||||
assert(FALSE); /* unimplemented */
|
||||
|
||||
/* TODO: asserts that previousIrpThread handles well
|
||||
* the same request by checking more details. Need an
|
||||
* access to the IRP object used by previousIrpThread
|
||||
*/
|
||||
|
||||
/* TODO: taking over the pending IRP or sending a kind
|
||||
* of wake up signal to accelerate the pending
|
||||
* request
|
||||
@ -605,18 +586,16 @@ static void create_irp_thread(SERIAL_DEVICE *serial, IRP *irp)
|
||||
* pComm->PendingEvents |= SERIAL_EV_FREERDP_*;
|
||||
* }
|
||||
*/
|
||||
|
||||
irp->Discard(irp);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (ListDictionary_Count(serial->IrpThreads) >= MAX_IRP_THREADS)
|
||||
{
|
||||
WLog_Print(serial->log, WLOG_WARN, "Number of IRP threads threshold reached: %d, keep on anyway", ListDictionary_Count(serial->IrpThreads));
|
||||
|
||||
WLog_Print(serial->log, WLOG_WARN,
|
||||
"Number of IRP threads threshold reached: %d, keep on anyway",
|
||||
ListDictionary_Count(serial->IrpThreads));
|
||||
assert(FALSE); /* unimplemented */
|
||||
|
||||
/* TODO: MAX_IRP_THREADS has been thought to avoid a
|
||||
* flooding of pending requests. Use
|
||||
* WaitForMultipleObjects() when available in winpr
|
||||
@ -624,10 +603,9 @@ static void create_irp_thread(SERIAL_DEVICE *serial, IRP *irp)
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
/* error_handle to be used ... */
|
||||
|
||||
data = (IRP_THREAD_DATA*)calloc(1, sizeof(IRP_THREAD_DATA));
|
||||
|
||||
if (data == NULL)
|
||||
{
|
||||
WLog_Print(serial->log, WLOG_WARN, "Could not allocate a new IRP_THREAD_DATA.");
|
||||
@ -636,15 +614,13 @@ static void create_irp_thread(SERIAL_DEVICE *serial, IRP *irp)
|
||||
|
||||
data->serial = serial;
|
||||
data->irp = irp;
|
||||
|
||||
/* data freed by irp_thread_func */
|
||||
|
||||
irpThread = CreateThread(NULL,
|
||||
0,
|
||||
(LPTHREAD_START_ROUTINE)irp_thread_func,
|
||||
(void*)data,
|
||||
0,
|
||||
NULL);
|
||||
0,
|
||||
(LPTHREAD_START_ROUTINE)irp_thread_func,
|
||||
(void*)data,
|
||||
0,
|
||||
NULL);
|
||||
|
||||
if (irpThread == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
@ -652,8 +628,8 @@ static void create_irp_thread(SERIAL_DEVICE *serial, IRP *irp)
|
||||
goto error_handle;
|
||||
}
|
||||
|
||||
|
||||
key = irp->CompletionId;
|
||||
|
||||
if (!ListDictionary_Add(serial->IrpThreads, (void*)key, irpThread))
|
||||
{
|
||||
WLog_ERR(TAG, "ListDictionary_Add failed!");
|
||||
@ -661,43 +637,36 @@ static void create_irp_thread(SERIAL_DEVICE *serial, IRP *irp)
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
error_handle:
|
||||
|
||||
error_handle:
|
||||
irp->IoStatus = STATUS_NO_MEMORY;
|
||||
irp->Complete(irp);
|
||||
|
||||
free(data);
|
||||
}
|
||||
|
||||
|
||||
static void terminate_pending_irp_threads(SERIAL_DEVICE *serial)
|
||||
static void terminate_pending_irp_threads(SERIAL_DEVICE* serial)
|
||||
{
|
||||
ULONG_PTR *ids;
|
||||
ULONG_PTR* ids;
|
||||
int i, nbIds;
|
||||
|
||||
nbIds = ListDictionary_GetKeys(serial->IrpThreads, &ids);
|
||||
|
||||
WLog_Print(serial->log, WLOG_DEBUG, "Terminating %d IRP thread(s)", nbIds);
|
||||
|
||||
for (i=0; i<nbIds; i++)
|
||||
for (i = 0; i < nbIds; i++)
|
||||
{
|
||||
HANDLE irpThread;
|
||||
ULONG_PTR id = ids[i];
|
||||
|
||||
irpThread = ListDictionary_GetItemValue(serial->IrpThreads, (void*)id);
|
||||
|
||||
TerminateThread(irpThread, 0);
|
||||
|
||||
if (WaitForSingleObject(irpThread, INFINITE) == WAIT_FAILED)
|
||||
{
|
||||
WLog_ERR(TAG,"WaitForSingleObject failed!");
|
||||
continue;
|
||||
}
|
||||
{
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed!");
|
||||
continue;
|
||||
}
|
||||
|
||||
CloseHandle(irpThread);
|
||||
|
||||
WLog_Print(serial->log, WLOG_DEBUG, "IRP thread terminated, CompletionId %d", id);
|
||||
WLog_Print(serial->log, WLOG_DEBUG, "IRP thread terminated, CompletionId %d",
|
||||
id);
|
||||
}
|
||||
|
||||
ListDictionary_Clear(serial->IrpThreads);
|
||||
@ -740,7 +709,8 @@ static void* serial_thread_func(void* arg)
|
||||
}
|
||||
|
||||
if (error && serial->rdpcontext)
|
||||
setChannelError(serial->rdpcontext, error, "serial_thread_func reported an error");
|
||||
setChannelError(serial->rdpcontext, error,
|
||||
"serial_thread_func reported an error");
|
||||
|
||||
ExitThread((DWORD) error);
|
||||
return NULL;
|
||||
@ -755,7 +725,6 @@ static void* serial_thread_func(void* arg)
|
||||
static UINT serial_irp_request(DEVICE* device, IRP* irp)
|
||||
{
|
||||
SERIAL_DEVICE* serial = (SERIAL_DEVICE*) device;
|
||||
|
||||
assert(irp != NULL);
|
||||
|
||||
if (irp == NULL)
|
||||
@ -771,6 +740,7 @@ static UINT serial_irp_request(DEVICE* device, IRP* irp)
|
||||
WLog_ERR(TAG, "MessageQueue_Post failed!");
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
@ -782,18 +752,18 @@ static UINT serial_irp_request(DEVICE* device, IRP* irp)
|
||||
*/
|
||||
static UINT serial_free(DEVICE* device)
|
||||
{
|
||||
UINT error;
|
||||
UINT error;
|
||||
SERIAL_DEVICE* serial = (SERIAL_DEVICE*) device;
|
||||
|
||||
WLog_Print(serial->log, WLOG_DEBUG, "freeing");
|
||||
|
||||
MessageQueue_PostQuit(serial->MainIrpQueue, 0);
|
||||
|
||||
if (WaitForSingleObject(serial->MainThread, INFINITE) == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
|
||||
return error;
|
||||
}
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
CloseHandle(serial->MainThread);
|
||||
|
||||
if (serial->hComm)
|
||||
@ -804,14 +774,13 @@ static UINT serial_free(DEVICE* device)
|
||||
MessageQueue_Free(serial->MainIrpQueue);
|
||||
ListDictionary_Free(serial->IrpThreads);
|
||||
DeleteCriticalSection(&serial->TerminatingIrpThreadsLock);
|
||||
|
||||
free(serial);
|
||||
return CHANNEL_RC_OK;
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
#endif /* __linux__ */
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#ifdef BUILTIN_CHANNELS
|
||||
#define DeviceServiceEntry serial_DeviceServiceEntry
|
||||
#else
|
||||
#define DeviceServiceEntry FREERDP_API DeviceServiceEntry
|
||||
@ -833,7 +802,6 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
SERIAL_DEVICE* serial;
|
||||
#endif /* __linux__ */
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
|
||||
device = (RDPDR_SERIAL*) pEntryPoints->device;
|
||||
name = device->Name;
|
||||
path = device->Path;
|
||||
@ -848,18 +816,14 @@ 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 */
|
||||
|
||||
WLog_Print(log, WLOG_WARN, "Serial ports redirection not supported on this platform.");
|
||||
WLog_Print(log, WLOG_WARN,
|
||||
"Serial ports redirection not supported on this platform.");
|
||||
return CHANNEL_RC_INITIALIZATION_ERROR;
|
||||
|
||||
#else /* __linux __ */
|
||||
|
||||
WLog_Print(log, WLOG_DEBUG, "Defining %s as %s", name, path);
|
||||
|
||||
if (!DefineCommDevice(name /* eg: COM1 */, path /* eg: /dev/ttyS0 */))
|
||||
@ -869,6 +833,7 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
}
|
||||
|
||||
serial = (SERIAL_DEVICE*) calloc(1, sizeof(SERIAL_DEVICE));
|
||||
|
||||
if (!serial)
|
||||
{
|
||||
WLog_ERR(TAG, "calloc failed!");
|
||||
@ -876,15 +841,14 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
}
|
||||
|
||||
serial->log = log;
|
||||
|
||||
serial->device.type = RDPDR_DTYP_SERIAL;
|
||||
serial->device.name = name;
|
||||
serial->device.IRPRequest = serial_irp_request;
|
||||
serial->device.Free = serial_free;
|
||||
serial->rdpcontext = pEntryPoints->rdpcontext;
|
||||
|
||||
len = strlen(name);
|
||||
serial->device.data = Stream_New(NULL, len + 1);
|
||||
|
||||
if (!serial->device.data)
|
||||
{
|
||||
WLog_ERR(TAG, "calloc failed!");
|
||||
@ -906,8 +870,8 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
else
|
||||
{
|
||||
assert(FALSE);
|
||||
|
||||
WLog_Print(serial->log, WLOG_DEBUG, "Unknown server's serial driver: %s. SerCx2 will be used", driver);
|
||||
WLog_Print(serial->log, WLOG_DEBUG,
|
||||
"Unknown server's serial driver: %s. SerCx2 will be used", driver);
|
||||
serial->ServerSerialDriverId = SerialDriverSerialSys;
|
||||
}
|
||||
}
|
||||
@ -917,7 +881,6 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
serial->ServerSerialDriverId = SerialDriverSerialSys;
|
||||
}
|
||||
|
||||
|
||||
if (device->Permissive != NULL)
|
||||
{
|
||||
if (_stricmp(device->Permissive, "permissive") == 0)
|
||||
@ -931,11 +894,11 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
WLog_Print(serial->log, WLOG_DEBUG, "Server's serial driver: %s (id: %d)", driver, serial->ServerSerialDriverId);
|
||||
WLog_Print(serial->log, WLOG_DEBUG, "Server's serial driver: %s (id: %d)",
|
||||
driver, serial->ServerSerialDriverId);
|
||||
/* TODO: implement auto detection of the server's serial driver */
|
||||
|
||||
serial->MainIrpQueue = MessageQueue_New(NULL);
|
||||
|
||||
if (!serial->MainIrpQueue)
|
||||
{
|
||||
WLog_ERR(TAG, "MessageQueue_New failed!");
|
||||
@ -945,32 +908,36 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
|
||||
/* IrpThreads content only modified by create_irp_thread() */
|
||||
serial->IrpThreads = ListDictionary_New(FALSE);
|
||||
if(!serial->IrpThreads)
|
||||
|
||||
if (!serial->IrpThreads)
|
||||
{
|
||||
WLog_ERR(TAG, "ListDictionary_New failed!");
|
||||
error = CHANNEL_RC_NO_MEMORY;
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
serial->IrpThreadToBeTerminatedCount = 0;
|
||||
InitializeCriticalSection(&serial->TerminatingIrpThreadsLock);
|
||||
|
||||
if ((error = pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*) serial)))
|
||||
if ((error = pEntryPoints->RegisterDevice(pEntryPoints->devman,
|
||||
(DEVICE*) serial)))
|
||||
{
|
||||
WLog_ERR(TAG, "EntryPoints->RegisterDevice failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "EntryPoints->RegisterDevice failed with error %u!", error);
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
if (!(serial->MainThread = CreateThread(NULL,
|
||||
0,
|
||||
(LPTHREAD_START_ROUTINE) serial_thread_func,
|
||||
(void*) serial,
|
||||
0,
|
||||
NULL)))
|
||||
0,
|
||||
(LPTHREAD_START_ROUTINE) serial_thread_func,
|
||||
(void*) serial,
|
||||
0,
|
||||
NULL)))
|
||||
{
|
||||
WLog_ERR(TAG, "CreateThread failed!");
|
||||
error = ERROR_INTERNAL_ERROR;
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
#endif /* __linux __ */
|
||||
}
|
||||
|
||||
|
||||
@ -49,6 +49,7 @@
|
||||
#include <freerdp/server/drdynvc.h>
|
||||
#include <freerdp/server/remdesk.h>
|
||||
#include <freerdp/server/encomsp.h>
|
||||
#include <freerdp/server/rdpgfx.h>
|
||||
|
||||
void freerdp_channels_dummy()
|
||||
{
|
||||
@ -79,6 +80,8 @@ void freerdp_channels_dummy()
|
||||
encomsp_server_context_new(NULL);
|
||||
encomsp_server_context_free(NULL);
|
||||
|
||||
rdpgfx_server_context_new(NULL);
|
||||
rdpgfx_server_context_free(NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
* Copyright 2011 Anthony Tong <atong@trustedcs.com>
|
||||
* Copyright 2015 Thincast Technologies GmbH
|
||||
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
|
||||
* Copyright 2016 David PHAM-VAN <d.phamvan@inuvika.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -43,7 +44,6 @@ void* smartcard_context_thread(SMARTCARD_CONTEXT* pContext)
|
||||
SMARTCARD_DEVICE* smartcard;
|
||||
SMARTCARD_OPERATION* operation;
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
|
||||
smartcard = pContext->smartcard;
|
||||
|
||||
nCount = 0;
|
||||
@ -56,7 +56,7 @@ void* smartcard_context_thread(SMARTCARD_CONTEXT* pContext)
|
||||
if (waitStatus == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "WaitForMultipleObjects failed with error %u!", error);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -65,7 +65,7 @@ void* smartcard_context_thread(SMARTCARD_CONTEXT* pContext)
|
||||
if (waitStatus == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %u!", error);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -78,7 +78,6 @@ void* smartcard_context_thread(SMARTCARD_CONTEXT* pContext)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (message.id == WMQ_QUIT)
|
||||
break;
|
||||
|
||||
@ -88,7 +87,8 @@ void* smartcard_context_thread(SMARTCARD_CONTEXT* pContext)
|
||||
{
|
||||
if ((status = smartcard_irp_device_control_call(smartcard, operation)))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_irp_device_control_call failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_irp_device_control_call failed with error %u",
|
||||
status);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -97,7 +97,6 @@ void* smartcard_context_thread(SMARTCARD_CONTEXT* pContext)
|
||||
WLog_ERR(TAG, "Queue_Enqueue failed!");
|
||||
status = ERROR_INTERNAL_ERROR;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
free(operation);
|
||||
@ -106,17 +105,19 @@ void* smartcard_context_thread(SMARTCARD_CONTEXT* pContext)
|
||||
}
|
||||
|
||||
if (status && smartcard->rdpcontext)
|
||||
setChannelError(smartcard->rdpcontext, error, "smartcard_context_thread reported an error");
|
||||
setChannelError(smartcard->rdpcontext, error,
|
||||
"smartcard_context_thread reported an error");
|
||||
|
||||
ExitThread((DWORD)status);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SMARTCARD_CONTEXT* smartcard_context_new(SMARTCARD_DEVICE* smartcard, SCARDCONTEXT hContext)
|
||||
SMARTCARD_CONTEXT* smartcard_context_new(SMARTCARD_DEVICE* smartcard,
|
||||
SCARDCONTEXT hContext)
|
||||
{
|
||||
SMARTCARD_CONTEXT* pContext;
|
||||
|
||||
pContext = (SMARTCARD_CONTEXT*) calloc(1, sizeof(SMARTCARD_CONTEXT));
|
||||
|
||||
if (!pContext)
|
||||
{
|
||||
WLog_ERR(TAG, "calloc failed!");
|
||||
@ -125,8 +126,8 @@ SMARTCARD_CONTEXT* smartcard_context_new(SMARTCARD_DEVICE* smartcard, SCARDCONTE
|
||||
|
||||
pContext->smartcard = smartcard;
|
||||
pContext->hContext = hContext;
|
||||
|
||||
pContext->IrpQueue = MessageQueue_New(NULL);
|
||||
|
||||
if (!pContext->IrpQueue)
|
||||
{
|
||||
WLog_ERR(TAG, "MessageQueue_New failed!");
|
||||
@ -134,8 +135,9 @@ SMARTCARD_CONTEXT* smartcard_context_new(SMARTCARD_DEVICE* smartcard, SCARDCONTE
|
||||
}
|
||||
|
||||
pContext->thread = CreateThread(NULL, 0,
|
||||
(LPTHREAD_START_ROUTINE) smartcard_context_thread,
|
||||
pContext, 0, NULL);
|
||||
(LPTHREAD_START_ROUTINE) smartcard_context_thread,
|
||||
pContext, 0, NULL);
|
||||
|
||||
if (!pContext->thread)
|
||||
{
|
||||
WLog_ERR(TAG, "CreateThread failed!");
|
||||
@ -143,7 +145,6 @@ SMARTCARD_CONTEXT* smartcard_context_new(SMARTCARD_DEVICE* smartcard, SCARDCONTE
|
||||
}
|
||||
|
||||
return pContext;
|
||||
|
||||
error_thread:
|
||||
MessageQueue_Free(pContext->IrpQueue);
|
||||
error_irpqueue:
|
||||
@ -158,18 +159,19 @@ void smartcard_context_free(SMARTCARD_CONTEXT* pContext)
|
||||
|
||||
/* cancel blocking calls like SCardGetStatusChange */
|
||||
SCardCancel(pContext->hContext);
|
||||
if (MessageQueue_PostQuit(pContext->IrpQueue, 0) && (WaitForSingleObject(pContext->thread, INFINITE) == WAIT_FAILED))
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", GetLastError());
|
||||
|
||||
if (MessageQueue_PostQuit(pContext->IrpQueue, 0)
|
||||
&& (WaitForSingleObject(pContext->thread, INFINITE) == WAIT_FAILED))
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", (unsigned long) GetLastError());
|
||||
|
||||
CloseHandle(pContext->thread);
|
||||
|
||||
MessageQueue_Free(pContext->IrpQueue);
|
||||
|
||||
free(pContext);
|
||||
}
|
||||
|
||||
|
||||
static void smartcard_release_all_contexts(SMARTCARD_DEVICE* smartcard) {
|
||||
static void smartcard_release_all_contexts(SMARTCARD_DEVICE* smartcard)
|
||||
{
|
||||
int index;
|
||||
int keyCount;
|
||||
ULONG_PTR* pKeys;
|
||||
@ -193,7 +195,8 @@ static void smartcard_release_all_contexts(SMARTCARD_DEVICE* smartcard) {
|
||||
|
||||
for (index = 0; index < keyCount; index++)
|
||||
{
|
||||
pContext = (SMARTCARD_CONTEXT*) ListDictionary_GetItemValue(smartcard->rgSCardContextList, (void*) pKeys[index]);
|
||||
pContext = (SMARTCARD_CONTEXT*) ListDictionary_GetItemValue(
|
||||
smartcard->rgSCardContextList, (void*) pKeys[index]);
|
||||
|
||||
if (!pContext)
|
||||
continue;
|
||||
@ -220,7 +223,8 @@ static void smartcard_release_all_contexts(SMARTCARD_DEVICE* smartcard) {
|
||||
|
||||
for (index = 0; index < keyCount; index++)
|
||||
{
|
||||
pContext = (SMARTCARD_CONTEXT*) ListDictionary_Remove(smartcard->rgSCardContextList, (void*) pKeys[index]);
|
||||
pContext = (SMARTCARD_CONTEXT*) ListDictionary_Remove(
|
||||
smartcard->rgSCardContextList, (void*) pKeys[index]);
|
||||
|
||||
if (!pContext)
|
||||
continue;
|
||||
@ -230,6 +234,14 @@ static void smartcard_release_all_contexts(SMARTCARD_DEVICE* smartcard) {
|
||||
if (SCardIsValidContext(hContext) == SCARD_S_SUCCESS)
|
||||
{
|
||||
SCardReleaseContext(hContext);
|
||||
|
||||
if (MessageQueue_PostQuit(pContext->IrpQueue, 0)
|
||||
&& (WaitForSingleObject(pContext->thread, INFINITE) == WAIT_FAILED))
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", (unsigned long) GetLastError());
|
||||
|
||||
CloseHandle(pContext->thread);
|
||||
MessageQueue_Free(pContext->IrpQueue);
|
||||
free(pContext);
|
||||
}
|
||||
}
|
||||
|
||||
@ -247,28 +259,26 @@ static UINT smartcard_free(DEVICE* device)
|
||||
{
|
||||
UINT error;
|
||||
SMARTCARD_DEVICE* smartcard = (SMARTCARD_DEVICE*) device;
|
||||
|
||||
/**
|
||||
* Calling smartcard_release_all_contexts to unblock all operations waiting for transactions
|
||||
* to unlock.
|
||||
*/
|
||||
|
||||
smartcard_release_all_contexts(smartcard);
|
||||
|
||||
/* Stopping all threads and cancelling all IRPs */
|
||||
|
||||
if (smartcard->IrpQueue)
|
||||
{
|
||||
if (MessageQueue_PostQuit(smartcard->IrpQueue, 0) && (WaitForSingleObject(smartcard->thread, INFINITE) == WAIT_FAILED))
|
||||
if (MessageQueue_PostQuit(smartcard->IrpQueue, 0)
|
||||
&& (WaitForSingleObject(smartcard->thread, INFINITE) == WAIT_FAILED))
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %u!", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
MessageQueue_Free(smartcard->IrpQueue);
|
||||
smartcard->IrpQueue = NULL;
|
||||
|
||||
CloseHandle(smartcard->thread);
|
||||
smartcard->thread = NULL;
|
||||
}
|
||||
@ -290,7 +300,6 @@ static UINT smartcard_free(DEVICE* device)
|
||||
}
|
||||
|
||||
free(device);
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
@ -307,9 +316,7 @@ static UINT smartcard_free(DEVICE* device)
|
||||
static UINT smartcard_init(DEVICE* device)
|
||||
{
|
||||
SMARTCARD_DEVICE* smartcard = (SMARTCARD_DEVICE*) device;
|
||||
|
||||
smartcard_release_all_contexts(smartcard);
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
@ -321,10 +328,8 @@ static UINT smartcard_init(DEVICE* device)
|
||||
UINT smartcard_complete_irp(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
||||
{
|
||||
void* key;
|
||||
|
||||
key = (void*) (size_t) irp->CompletionId;
|
||||
key = (void*)(size_t) irp->CompletionId;
|
||||
ListDictionary_Remove(smartcard->rgOutstandingMessages, key);
|
||||
|
||||
return irp->Complete(irp);
|
||||
}
|
||||
|
||||
@ -345,8 +350,8 @@ UINT smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
||||
BOOL asyncIrp = FALSE;
|
||||
SMARTCARD_CONTEXT* pContext = NULL;
|
||||
SMARTCARD_OPERATION* operation = NULL;
|
||||
key = (void*)(size_t) irp->CompletionId;
|
||||
|
||||
key = (void*) (size_t) irp->CompletionId;
|
||||
if (!ListDictionary_Add(smartcard->rgOutstandingMessages, key, irp))
|
||||
{
|
||||
WLog_ERR(TAG, "ListDictionary_Add failed!");
|
||||
@ -364,7 +369,6 @@ UINT smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
||||
}
|
||||
|
||||
operation->irp = irp;
|
||||
|
||||
status = smartcard_irp_device_control_decode(smartcard, operation);
|
||||
|
||||
if (status != SCARD_S_SUCCESS)
|
||||
@ -451,7 +455,8 @@ UINT smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
||||
break;
|
||||
}
|
||||
|
||||
pContext = ListDictionary_GetItemValue(smartcard->rgSCardContextList, (void*) operation->hContext);
|
||||
pContext = ListDictionary_GetItemValue(smartcard->rgSCardContextList,
|
||||
(void*) operation->hContext);
|
||||
|
||||
if (!pContext)
|
||||
asyncIrp = FALSE;
|
||||
@ -460,14 +465,17 @@ UINT smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
||||
{
|
||||
if ((status = smartcard_irp_device_control_call(smartcard, operation)))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_irp_device_control_call failed with error %lu!", status);
|
||||
WLog_ERR(TAG, "smartcard_irp_device_control_call failed with error %ld!",
|
||||
status);
|
||||
return (UINT32)status;
|
||||
}
|
||||
|
||||
if (!Queue_Enqueue(smartcard->CompletedIrpQueue, (void*) irp))
|
||||
{
|
||||
WLog_ERR(TAG, "Queue_Enqueue failed!");
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
free(operation);
|
||||
}
|
||||
else
|
||||
@ -484,8 +492,9 @@ UINT smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
||||
}
|
||||
else
|
||||
{
|
||||
WLog_ERR(TAG, "Unexpected SmartCard IRP: MajorFunction 0x%08X MinorFunction: 0x%08X",
|
||||
irp->MajorFunction, irp->MinorFunction);
|
||||
WLog_ERR(TAG,
|
||||
"Unexpected SmartCard IRP: MajorFunction 0x%08X MinorFunction: 0x%08X",
|
||||
irp->MajorFunction, irp->MinorFunction);
|
||||
irp->IoStatus = (UINT32)STATUS_NOT_SUPPORTED;
|
||||
|
||||
if (!Queue_Enqueue(smartcard->CompletedIrpQueue, (void*) irp))
|
||||
@ -494,6 +503,7 @@ UINT smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
@ -518,7 +528,7 @@ static void* smartcard_thread_func(void* arg)
|
||||
if (status == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "WaitForMultipleObjects failed with error %u!", error);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -527,7 +537,7 @@ static void* smartcard_thread_func(void* arg)
|
||||
if (status == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %u!", error);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -540,7 +550,6 @@ static void* smartcard_thread_func(void* arg)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (message.id == WMQ_QUIT)
|
||||
{
|
||||
while (1)
|
||||
@ -550,7 +559,7 @@ static void* smartcard_thread_func(void* arg)
|
||||
if (status == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %u!", error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -568,7 +577,7 @@ static void* smartcard_thread_func(void* arg)
|
||||
if (status == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %u!", error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -578,7 +587,7 @@ static void* smartcard_thread_func(void* arg)
|
||||
|
||||
if ((error = smartcard_complete_irp(smartcard, irp)))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_complete_irp failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "smartcard_complete_irp failed with error %u!", error);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
@ -593,7 +602,7 @@ static void* smartcard_thread_func(void* arg)
|
||||
{
|
||||
if ((error = smartcard_process_irp(smartcard, irp)))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_process_irp failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "smartcard_process_irp failed with error %u!", error);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
@ -604,13 +613,12 @@ static void* smartcard_thread_func(void* arg)
|
||||
if (status == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %u!", error);
|
||||
break;
|
||||
}
|
||||
|
||||
if (status == WAIT_OBJECT_0)
|
||||
{
|
||||
|
||||
irp = (IRP*) Queue_Dequeue(smartcard->CompletedIrpQueue);
|
||||
|
||||
if (irp)
|
||||
@ -622,7 +630,7 @@ static void* smartcard_thread_func(void* arg)
|
||||
if (status == WAIT_FAILED)
|
||||
{
|
||||
error = GetLastError();
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "WaitForSingleObject failed with error %u!", error);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -632,15 +640,24 @@ static void* smartcard_thread_func(void* arg)
|
||||
|
||||
if ((error = smartcard_complete_irp(smartcard, irp)))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_complete_irp failed with error %lu!", error);
|
||||
if (error == CHANNEL_RC_NOT_CONNECTED)
|
||||
{
|
||||
error = CHANNEL_RC_OK;
|
||||
goto out;
|
||||
}
|
||||
|
||||
WLog_ERR(TAG, "smartcard_complete_irp failed with error %u!", error);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
if (error && smartcard->rdpcontext)
|
||||
setChannelError(smartcard->rdpcontext, error, "smartcard_thread_func reported an error");
|
||||
setChannelError(smartcard->rdpcontext, error,
|
||||
"smartcard_thread_func reported an error");
|
||||
|
||||
ExitThread((DWORD)error);
|
||||
return NULL;
|
||||
@ -654,11 +671,13 @@ out:
|
||||
static UINT smartcard_irp_request(DEVICE* device, IRP* irp)
|
||||
{
|
||||
SMARTCARD_DEVICE* smartcard = (SMARTCARD_DEVICE*) device;
|
||||
|
||||
if (!MessageQueue_Post(smartcard->IrpQueue, NULL, 0, (void*) irp, NULL))
|
||||
{
|
||||
WLog_ERR(TAG, "MessageQueue_Post failed!");
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
@ -679,13 +698,11 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
RDPDR_SMARTCARD* device;
|
||||
SMARTCARD_DEVICE* smartcard;
|
||||
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)
|
||||
{
|
||||
WLog_ERR(TAG, "calloc failed!");
|
||||
@ -698,9 +715,9 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
smartcard->device.Init = smartcard_init;
|
||||
smartcard->device.Free = smartcard_free;
|
||||
smartcard->rdpcontext = pEntryPoints->rdpcontext;
|
||||
|
||||
length = strlen(smartcard->device.name);
|
||||
smartcard->device.data = Stream_New(NULL, length + 1);
|
||||
|
||||
if (!smartcard->device.data)
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_New failed!");
|
||||
@ -708,7 +725,6 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
}
|
||||
|
||||
Stream_Write(smartcard->device.data, "SCARD", 6);
|
||||
|
||||
smartcard->name = NULL;
|
||||
smartcard->path = NULL;
|
||||
|
||||
@ -726,14 +742,15 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
}
|
||||
|
||||
smartcard->IrpQueue = MessageQueue_New(NULL);
|
||||
|
||||
if (!smartcard->IrpQueue)
|
||||
{
|
||||
WLog_ERR(TAG, "MessageQueue_New failed!");
|
||||
goto error_irp_queue;
|
||||
}
|
||||
|
||||
|
||||
smartcard->CompletedIrpQueue = Queue_New(TRUE, -1, -1);
|
||||
|
||||
if (!smartcard->CompletedIrpQueue)
|
||||
{
|
||||
WLog_ERR(TAG, "Queue_New failed!");
|
||||
@ -741,6 +758,7 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
}
|
||||
|
||||
smartcard->rgSCardContextList = ListDictionary_New(TRUE);
|
||||
|
||||
if (!smartcard->rgSCardContextList)
|
||||
{
|
||||
WLog_ERR(TAG, "ListDictionary_New failed!");
|
||||
@ -748,24 +766,26 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
}
|
||||
|
||||
ListDictionary_ValueObject(smartcard->rgSCardContextList)->fnObjectFree =
|
||||
(OBJECT_FREE_FN) smartcard_context_free;
|
||||
|
||||
(OBJECT_FREE_FN) smartcard_context_free;
|
||||
smartcard->rgOutstandingMessages = ListDictionary_New(TRUE);
|
||||
|
||||
if (!smartcard->rgOutstandingMessages)
|
||||
{
|
||||
WLog_ERR(TAG, "ListDictionary_New failed!");
|
||||
goto error_outstanding_messages;
|
||||
}
|
||||
|
||||
if ((error = pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*) smartcard)))
|
||||
if ((error = pEntryPoints->RegisterDevice(pEntryPoints->devman,
|
||||
(DEVICE*) smartcard)))
|
||||
{
|
||||
WLog_ERR(TAG, "RegisterDevice failed!");
|
||||
goto error_outstanding_messages;
|
||||
}
|
||||
|
||||
smartcard->thread = CreateThread(NULL, 0,
|
||||
(LPTHREAD_START_ROUTINE) smartcard_thread_func,
|
||||
smartcard, CREATE_SUSPENDED, NULL);
|
||||
|
||||
smartcard->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) smartcard_thread_func,
|
||||
smartcard, CREATE_SUSPENDED, NULL);
|
||||
if (!smartcard->thread)
|
||||
{
|
||||
WLog_ERR(TAG, "ListDictionary_New failed!");
|
||||
@ -774,9 +794,7 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
}
|
||||
|
||||
ResumeThread(smartcard->thread);
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
|
||||
error_thread:
|
||||
ListDictionary_Free(smartcard->rgOutstandingMessages);
|
||||
error_outstanding_messages:
|
||||
|
||||
@ -202,7 +202,7 @@ static LONG smartcard_EstablishContext_Decode(SMARTCARD_DEVICE* smartcard, SMART
|
||||
|
||||
if ((status = smartcard_unpack_establish_context_call(smartcard, irp->input, call)))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_unpack_establish_context_call failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_establish_context_call failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
smartcard_trace_establish_context_call(smartcard, call);
|
||||
@ -236,7 +236,7 @@ static LONG smartcard_EstablishContext_Call(SMARTCARD_DEVICE* smartcard, SMARTCA
|
||||
}
|
||||
else
|
||||
{
|
||||
WLog_ERR(TAG, "SCardEstablishContext failed with error %lu", status);
|
||||
WLog_ERR(TAG, "SCardEstablishContext failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -244,7 +244,7 @@ static LONG smartcard_EstablishContext_Call(SMARTCARD_DEVICE* smartcard, SMARTCA
|
||||
smartcard_trace_establish_context_return(smartcard, &ret);
|
||||
if ((status = smartcard_pack_establish_context_return(smartcard, irp->output, &ret)))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_pack_establish_context_return failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_pack_establish_context_return failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -260,7 +260,7 @@ static LONG smartcard_ReleaseContext_Decode(SMARTCARD_DEVICE* smartcard, SMARTCA
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
if ((status = smartcard_unpack_context_call(smartcard, irp->input, call)))
|
||||
WLog_ERR(TAG, "smartcard_unpack_context_call failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_context_call failed with error %ld", status);
|
||||
smartcard_trace_context_call(smartcard, call, "ReleaseContext");
|
||||
operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext));
|
||||
return status;
|
||||
@ -282,7 +282,7 @@ static LONG smartcard_ReleaseContext_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD
|
||||
}
|
||||
else
|
||||
{
|
||||
WLog_ERR(TAG, "SCardReleaseContext failed with error %lu", status);
|
||||
WLog_ERR(TAG, "SCardReleaseContext failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -299,7 +299,7 @@ static LONG smartcard_IsValidContext_Decode(SMARTCARD_DEVICE* smartcard, SMARTCA
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
if ((status = smartcard_unpack_context_call(smartcard, irp->input, call)))
|
||||
WLog_ERR(TAG, "smartcard_unpack_context_call failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_context_call failed with error %ld", status);
|
||||
smartcard_trace_context_call(smartcard, call, "IsValidContext");
|
||||
operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext));
|
||||
return status;
|
||||
@ -311,7 +311,7 @@ static LONG smartcard_IsValidContext_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD
|
||||
Long_Return ret;
|
||||
if ((status = ret.ReturnCode = SCardIsValidContext(operation->hContext)))
|
||||
{
|
||||
WLog_ERR(TAG, "SCardIsValidContext failed with error %lu", status);
|
||||
WLog_ERR(TAG, "SCardIsValidContext failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
smartcard_trace_long_return(smartcard, &ret, "IsValidContext");
|
||||
@ -327,7 +327,7 @@ static LONG smartcard_ListReadersA_Decode(SMARTCARD_DEVICE* smartcard, SMARTCARD
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
if ((status = smartcard_unpack_list_readers_call(smartcard, irp->input, call)))
|
||||
WLog_ERR(TAG, "smartcard_unpack_list_readers_call failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_list_readers_call failed with error %ld", status);
|
||||
smartcard_trace_list_readers_call(smartcard, call, FALSE);
|
||||
operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext));
|
||||
return status;
|
||||
@ -356,14 +356,14 @@ static LONG smartcard_ListReadersA_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_O
|
||||
|
||||
if (status)
|
||||
{
|
||||
WLog_ERR(TAG, "SCardListReadersA failed with error %lu", status);
|
||||
WLog_ERR(TAG, "SCardListReadersA failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
smartcard_trace_list_readers_return(smartcard, &ret, FALSE);
|
||||
if ((status = smartcard_pack_list_readers_return(smartcard, irp->output, &ret)))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_pack_list_readers_return failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_pack_list_readers_return failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -385,7 +385,7 @@ static LONG smartcard_ListReadersW_Decode(SMARTCARD_DEVICE* smartcard, SMARTCARD
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
if ((status = smartcard_unpack_list_readers_call(smartcard, irp->input, call)))
|
||||
WLog_ERR(TAG, "smartcard_unpack_list_readers_call failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_list_readers_call failed with error %ld", status);
|
||||
|
||||
smartcard_trace_list_readers_call(smartcard, call, TRUE);
|
||||
operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext));
|
||||
@ -417,7 +417,7 @@ static LONG smartcard_ListReadersW_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_O
|
||||
|
||||
if (status)
|
||||
{
|
||||
WLog_ERR(TAG, "SCardListReadersW failed with error %lu", status);
|
||||
WLog_ERR(TAG, "SCardListReadersW failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -425,7 +425,7 @@ static LONG smartcard_ListReadersW_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_O
|
||||
|
||||
if ((status = smartcard_pack_list_readers_return(smartcard, irp->output, &ret)))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_pack_list_readers_return failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_pack_list_readers_return failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -448,7 +448,7 @@ static LONG smartcard_GetStatusChangeA_Decode(SMARTCARD_DEVICE* smartcard, SMART
|
||||
|
||||
if ((status = smartcard_unpack_get_status_change_a_call(smartcard, irp->input, call)))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_unpack_get_status_change_a_call failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_get_status_change_a_call failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -492,7 +492,7 @@ static LONG smartcard_GetStatusChangeA_Call(SMARTCARD_DEVICE* smartcard, SMARTCA
|
||||
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 %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_pack_get_status_change_return failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -520,7 +520,7 @@ static LONG smartcard_GetStatusChangeW_Decode(SMARTCARD_DEVICE* smartcard, SMART
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
if ((status = smartcard_unpack_get_status_change_w_call(smartcard, irp->input, call)))
|
||||
WLog_ERR(TAG, "smartcard_unpack_get_status_change_w_call failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_get_status_change_w_call failed with error %ld", status);
|
||||
smartcard_trace_get_status_change_w_call(smartcard, call);
|
||||
operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext));
|
||||
return status;
|
||||
@ -559,7 +559,7 @@ static LONG smartcard_GetStatusChangeW_Call(SMARTCARD_DEVICE* smartcard, SMARTCA
|
||||
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 %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_pack_get_status_change_return failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -587,7 +587,7 @@ static LONG smartcard_Cancel_Decode(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERA
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
if ((status = smartcard_unpack_context_call(smartcard, irp->input, call)))
|
||||
WLog_ERR(TAG, "smartcard_unpack_context_call failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_context_call failed with error %ld", status);
|
||||
smartcard_trace_context_call(smartcard, call, "Cancel");
|
||||
operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext));
|
||||
return status;
|
||||
@ -600,7 +600,7 @@ static LONG smartcard_Cancel_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATI
|
||||
|
||||
if ((status = ret.ReturnCode = SCardCancel(operation->hContext)))
|
||||
{
|
||||
WLog_ERR(TAG, "SCardCancel failed with error %lu", status);
|
||||
WLog_ERR(TAG, "SCardCancel failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
smartcard_trace_long_return(smartcard, &ret, "Cancel");
|
||||
@ -616,7 +616,7 @@ static LONG smartcard_ConnectA_Decode(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPE
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
if ((status = smartcard_unpack_connect_a_call(smartcard, irp->input, call)))
|
||||
WLog_ERR(TAG, "smartcard_unpack_connect_a_call failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_connect_a_call failed with error %ld", status);
|
||||
smartcard_trace_connect_a_call(smartcard, call);
|
||||
operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->Common.hContext));
|
||||
return status;
|
||||
@ -644,14 +644,14 @@ static LONG smartcard_ConnectA_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERA
|
||||
|
||||
if (status)
|
||||
{
|
||||
WLog_ERR(TAG, "SCardConnectA failed with error %lu", status);
|
||||
WLog_ERR(TAG, "SCardConnectA failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
if ((status = smartcard_pack_connect_return(smartcard, irp->output, &ret)))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_pack_connect_return failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_pack_connect_return failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -669,7 +669,7 @@ static LONG smartcard_ConnectW_Decode(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPE
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
if ((status = smartcard_unpack_connect_w_call(smartcard, irp->input, call)))
|
||||
WLog_ERR(TAG, "smartcard_unpack_connect_w_call failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_connect_w_call failed with error %ld", status);
|
||||
|
||||
smartcard_trace_connect_w_call(smartcard, call);
|
||||
operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->Common.hContext));
|
||||
@ -699,13 +699,13 @@ static LONG smartcard_ConnectW_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERA
|
||||
|
||||
if (status)
|
||||
{
|
||||
WLog_ERR(TAG, "SCardConnectW failed with error %lu", status);
|
||||
WLog_ERR(TAG, "SCardConnectW failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
if ((status = smartcard_pack_connect_return(smartcard, irp->output, &ret)))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_pack_connect_return failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_pack_connect_return failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -723,7 +723,7 @@ static LONG smartcard_Reconnect_Decode(SMARTCARD_DEVICE* smartcard, SMARTCARD_OP
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
if ((status = smartcard_unpack_reconnect_call(smartcard, irp->input, call)))
|
||||
WLog_ERR(TAG, "smartcard_unpack_reconnect_call failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_reconnect_call failed with error %ld", status);
|
||||
smartcard_trace_reconnect_call(smartcard, call);
|
||||
operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext));
|
||||
operation->hCard = smartcard_scard_handle_native_from_redir(smartcard, &(call->hCard));
|
||||
@ -740,7 +740,7 @@ static LONG smartcard_Reconnect_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPER
|
||||
smartcard_trace_reconnect_return(smartcard, &ret);
|
||||
if ((status = smartcard_pack_reconnect_return(smartcard, irp->output, &ret)))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_pack_reconnect_return failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_pack_reconnect_return failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -756,7 +756,7 @@ static LONG smartcard_Disconnect_Decode(SMARTCARD_DEVICE* smartcard, SMARTCARD_O
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
if ((status = smartcard_unpack_hcard_and_disposition_call(smartcard, irp->input, call)))
|
||||
WLog_ERR(TAG, "smartcard_unpack_hcard_and_disposition_call failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_hcard_and_disposition_call failed with error %ld", status);
|
||||
smartcard_trace_hcard_and_disposition_call(smartcard, call, "Disconnect");
|
||||
operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext));
|
||||
operation->hCard = smartcard_scard_handle_native_from_redir(smartcard, &(call->hCard));
|
||||
@ -769,7 +769,7 @@ static LONG smartcard_Disconnect_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPE
|
||||
Long_Return ret;
|
||||
if ((status = ret.ReturnCode = SCardDisconnect(operation->hCard, call->dwDisposition)))
|
||||
{
|
||||
WLog_ERR(TAG, "SCardDisconnect failed with error %lu", status);
|
||||
WLog_ERR(TAG, "SCardDisconnect failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
smartcard_trace_long_return(smartcard, &ret, "Disconnect");
|
||||
@ -786,7 +786,7 @@ static LONG smartcard_BeginTransaction_Decode(SMARTCARD_DEVICE* smartcard, SMART
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
if ((status = smartcard_unpack_hcard_and_disposition_call(smartcard, irp->input, call)))
|
||||
WLog_ERR(TAG, "smartcard_unpack_hcard_and_disposition_call failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_hcard_and_disposition_call failed with error %ld", status);
|
||||
smartcard_trace_hcard_and_disposition_call(smartcard, call, "BeginTransaction");
|
||||
operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext));
|
||||
operation->hCard = smartcard_scard_handle_native_from_redir(smartcard, &(call->hCard));
|
||||
@ -798,7 +798,7 @@ static LONG smartcard_BeginTransaction_Call(SMARTCARD_DEVICE* smartcard, SMARTCA
|
||||
Long_Return ret;
|
||||
if ((ret.ReturnCode = SCardBeginTransaction(operation->hCard)))
|
||||
{
|
||||
WLog_ERR(TAG, "SCardBeginTransaction failed with error %lu", ret.ReturnCode);
|
||||
WLog_ERR(TAG, "SCardBeginTransaction failed with error %ld", ret.ReturnCode);
|
||||
return ret.ReturnCode;
|
||||
}
|
||||
smartcard_trace_long_return(smartcard, &ret, "BeginTransaction");
|
||||
@ -814,7 +814,7 @@ static LONG smartcard_EndTransaction_Decode(SMARTCARD_DEVICE* smartcard, SMARTCA
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
if ((status = smartcard_unpack_hcard_and_disposition_call(smartcard, irp->input, call)))
|
||||
WLog_ERR(TAG, "smartcard_unpack_hcard_and_disposition_call failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_hcard_and_disposition_call failed with error %ld", status);
|
||||
smartcard_trace_hcard_and_disposition_call(smartcard, call, "EndTransaction");
|
||||
operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext));
|
||||
operation->hCard = smartcard_scard_handle_native_from_redir(smartcard, &(call->hCard));
|
||||
@ -826,7 +826,7 @@ static LONG smartcard_EndTransaction_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD
|
||||
Long_Return ret;
|
||||
if ((ret.ReturnCode = SCardEndTransaction(operation->hCard, call->dwDisposition)))
|
||||
{
|
||||
WLog_ERR(TAG, "SCardEndTransaction failed with error %lu", ret.ReturnCode);
|
||||
WLog_ERR(TAG, "SCardEndTransaction failed with error %ld", ret.ReturnCode);
|
||||
return ret.ReturnCode;
|
||||
}
|
||||
smartcard_trace_long_return(smartcard, &ret, "EndTransaction");
|
||||
@ -842,7 +842,7 @@ static LONG smartcard_State_Decode(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERAT
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
if ((status = smartcard_unpack_state_call(smartcard, irp->input, call)))
|
||||
WLog_ERR(TAG, "smartcard_unpack_state_call failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_state_call failed with error %ld", status);
|
||||
operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext));
|
||||
operation->hCard = smartcard_scard_handle_native_from_redir(smartcard, &(call->hCard));
|
||||
return status;
|
||||
@ -857,7 +857,7 @@ static LONG smartcard_State_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATIO
|
||||
ret.ReturnCode = SCardState(operation->hCard, &ret.dwState, &ret.dwProtocol, (BYTE*) &ret.rgAtr, &ret.cbAtrLen);
|
||||
if ((status = smartcard_pack_state_return(smartcard, irp->output, &ret)))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_pack_state_return failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_pack_state_return failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -873,7 +873,7 @@ static LONG smartcard_StatusA_Decode(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPER
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
if ((status = smartcard_unpack_status_call(smartcard, irp->input, call)))
|
||||
WLog_ERR(TAG, "smartcard_unpack_status_call failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_status_call failed with error %ld", status);
|
||||
smartcard_trace_status_call(smartcard, call, FALSE);
|
||||
operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext));
|
||||
operation->hCard = smartcard_scard_handle_native_from_redir(smartcard, &(call->hCard));
|
||||
@ -904,7 +904,7 @@ static LONG smartcard_StatusA_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERAT
|
||||
smartcard_trace_status_return(smartcard, &ret, FALSE);
|
||||
if ((status = smartcard_pack_status_return(smartcard, irp->output, &ret)))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_pack_status_return failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_pack_status_return failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -923,7 +923,7 @@ static LONG smartcard_StatusW_Decode(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPER
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
if ((status = smartcard_unpack_status_call(smartcard, irp->input, call)))
|
||||
WLog_ERR(TAG, "smartcard_unpack_status_call failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_status_call failed with error %ld", status);
|
||||
smartcard_trace_status_call(smartcard, call, TRUE);
|
||||
operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext));
|
||||
operation->hCard = smartcard_scard_handle_native_from_redir(smartcard, &(call->hCard));
|
||||
@ -950,7 +950,7 @@ static LONG smartcard_StatusW_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERAT
|
||||
smartcard_trace_status_return(smartcard, &ret, TRUE);
|
||||
if ((status = smartcard_pack_status_return(smartcard, irp->output, &ret)))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_pack_status_return failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_pack_status_return failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -969,7 +969,7 @@ static LONG smartcard_Transmit_Decode(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPE
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
if ((status = smartcard_unpack_transmit_call(smartcard, irp->input, call)))
|
||||
WLog_ERR(TAG, "smartcard_unpack_transmit_call failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_transmit_call failed with error %ld", status);
|
||||
|
||||
smartcard_trace_transmit_call(smartcard, call);
|
||||
|
||||
@ -1007,7 +1007,7 @@ static LONG smartcard_Transmit_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERA
|
||||
smartcard_trace_transmit_return(smartcard, &ret);
|
||||
if ((status = smartcard_pack_transmit_return(smartcard, irp->output, &ret)))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_pack_transmit_return failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_pack_transmit_return failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -1028,7 +1028,7 @@ static LONG smartcard_Control_Decode(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPER
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
if ((status = smartcard_unpack_control_call(smartcard, irp->input, call)))
|
||||
WLog_ERR(TAG, "smartcard_unpack_control_call failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_control_call failed with error %ld", status);
|
||||
smartcard_trace_control_call(smartcard, call);
|
||||
operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext));
|
||||
operation->hCard = smartcard_scard_handle_native_from_redir(smartcard, &(call->hCard));
|
||||
@ -1053,7 +1053,7 @@ static LONG smartcard_Control_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERAT
|
||||
smartcard_trace_control_return(smartcard, &ret);
|
||||
if ((status = smartcard_pack_control_return(smartcard, irp->output, &ret)))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_pack_control_return failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_pack_control_return failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -1072,7 +1072,7 @@ static LONG smartcard_GetAttrib_Decode(SMARTCARD_DEVICE* smartcard, SMARTCARD_OP
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
if ((status = smartcard_unpack_get_attrib_call(smartcard, irp->input, call)))
|
||||
WLog_ERR(TAG, "smartcard_unpack_get_attrib_call failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_get_attrib_call failed with error %ld", status);
|
||||
smartcard_trace_get_attrib_call(smartcard, call);
|
||||
operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext));
|
||||
operation->hCard = smartcard_scard_handle_native_from_redir(smartcard, &(call->hCard));
|
||||
@ -1123,7 +1123,7 @@ static LONG smartcard_GetAttrib_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPER
|
||||
|
||||
if ((status = smartcard_pack_get_attrib_return(smartcard, irp->output, &ret)))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_pack_get_attrib_return failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_pack_get_attrib_return failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -1169,7 +1169,7 @@ static LONG smartcard_LocateCardsByATRA_Decode(SMARTCARD_DEVICE* smartcard, SMAR
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
if ((status = smartcard_unpack_locate_cards_by_atr_a_call(smartcard, irp->input, call)))
|
||||
WLog_ERR(TAG, "smartcard_unpack_locate_cards_by_atr_a_call failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_locate_cards_by_atr_a_call failed with error %ld", status);
|
||||
smartcard_trace_locate_cards_by_atr_a_call(smartcard, call);
|
||||
operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext));
|
||||
return status;
|
||||
@ -1249,7 +1249,7 @@ static LONG smartcard_LocateCardsByATRA_Call(SMARTCARD_DEVICE* smartcard, SMARTC
|
||||
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 %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_pack_get_status_change_return failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -1287,8 +1287,8 @@ LONG smartcard_irp_device_control_decode(SMARTCARD_DEVICE* smartcard, SMARTCARD_
|
||||
|
||||
if (Stream_GetRemainingLength(irp->input) < 32)
|
||||
{
|
||||
WLog_WARN(TAG, "Device Control Request is too short: %d",
|
||||
(int) Stream_GetRemainingLength(irp->input));
|
||||
WLog_WARN(TAG, "Device Control Request is too short: %lu",
|
||||
(unsigned long) Stream_GetRemainingLength(irp->input));
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
@ -1300,8 +1300,9 @@ LONG smartcard_irp_device_control_decode(SMARTCARD_DEVICE* smartcard, SMARTCARD_
|
||||
|
||||
if (Stream_Length(irp->input) != (Stream_GetPosition(irp->input) + inputBufferLength))
|
||||
{
|
||||
WLog_WARN(TAG, "InputBufferLength mismatch: Actual: %d Expected: %d",
|
||||
Stream_Length(irp->input), Stream_GetPosition(irp->input) + inputBufferLength);
|
||||
WLog_WARN(TAG, "InputBufferLength mismatch: Actual: %lu Expected: %lu",
|
||||
(unsigned long) Stream_Length(irp->input),
|
||||
(unsigned long) (Stream_GetPosition(irp->input) + inputBufferLength));
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
@ -1314,13 +1315,13 @@ LONG smartcard_irp_device_control_decode(SMARTCARD_DEVICE* smartcard, SMARTCARD_
|
||||
{
|
||||
if ((status = smartcard_unpack_common_type_header(smartcard, irp->input)))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_unpack_common_type_header failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_common_type_header failed with error %ld", status);
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
if ((status = smartcard_unpack_private_type_header(smartcard, irp->input)))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_unpack_common_type_header failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_common_type_header failed with error %ld", status);
|
||||
return SCARD_F_INTERNAL_ERROR;
|
||||
}
|
||||
}
|
||||
@ -1945,12 +1946,12 @@ LONG smartcard_irp_device_control_call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OP
|
||||
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 %lu", result);
|
||||
WLog_ERR(TAG, "smartcard_pack_common_type_header failed with error %ld", 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 %lu", result);
|
||||
WLog_ERR(TAG, "smartcard_pack_private_type_header failed with error %ld", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@ -109,8 +109,8 @@ LONG smartcard_unpack_private_type_header(SMARTCARD_DEVICE* smartcard, wStream*
|
||||
|
||||
if (objectBufferLength != Stream_GetRemainingLength(s))
|
||||
{
|
||||
WLog_WARN(TAG, "PrivateTypeHeader ObjectBufferLength mismatch: Actual: %d, Expected: %d",
|
||||
(int) objectBufferLength, Stream_GetRemainingLength(s));
|
||||
WLog_WARN(TAG, "PrivateTypeHeader ObjectBufferLength mismatch: Actual: %lu, Expected: %lu",
|
||||
(unsigned long) objectBufferLength, (unsigned long)Stream_GetRemainingLength(s));
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
@ -166,8 +166,8 @@ SCARDCONTEXT smartcard_scard_context_native_from_redir(SMARTCARD_DEVICE* smartca
|
||||
|
||||
if ((context->cbContext != sizeof(ULONG_PTR)) && (context->cbContext != 0))
|
||||
{
|
||||
WLog_WARN(TAG, "REDIR_SCARDCONTEXT does not match native size: Actual: %d, Expected: %d",
|
||||
context->cbContext, sizeof(ULONG_PTR));
|
||||
WLog_WARN(TAG, "REDIR_SCARDCONTEXT does not match native size: Actual: %lu, Expected: %lu",
|
||||
(unsigned long) context->cbContext, (unsigned long) sizeof(ULONG_PTR));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -192,8 +192,8 @@ SCARDHANDLE smartcard_scard_handle_native_from_redir(SMARTCARD_DEVICE* smartcard
|
||||
|
||||
if (handle->cbHandle != sizeof(ULONG_PTR))
|
||||
{
|
||||
WLog_WARN(TAG, "REDIR_SCARDHANDLE does not match native size: Actual: %d, Expected: %d",
|
||||
handle->cbHandle, sizeof(ULONG_PTR));
|
||||
WLog_WARN(TAG, "REDIR_SCARDHANDLE does not match native size: Actual: %lu, Expected: %lu",
|
||||
(unsigned long) handle->cbHandle, (unsigned long) sizeof(ULONG_PTR));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -446,12 +446,12 @@ LONG smartcard_pack_establish_context_return(SMARTCARD_DEVICE* smartcard, wStrea
|
||||
|
||||
if ((status = smartcard_pack_redir_scard_context(smartcard, s, &(ret->hContext))))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_pack_redir_scard_context failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_pack_redir_scard_context failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
if ((status = smartcard_pack_redir_scard_context_ref(smartcard, s, &(ret->hContext))))
|
||||
WLog_ERR(TAG, "smartcard_pack_redir_scard_context_ref failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_pack_redir_scard_context_ref failed with error %ld", status);
|
||||
|
||||
return status;
|
||||
}
|
||||
@ -490,12 +490,12 @@ LONG smartcard_unpack_context_call(SMARTCARD_DEVICE* smartcard, wStream* s, Cont
|
||||
|
||||
if ((status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->hContext))))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
if ((status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->hContext))))
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context_ref failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context_ref failed with error %ld", status);
|
||||
|
||||
return status;
|
||||
}
|
||||
@ -548,7 +548,7 @@ LONG smartcard_unpack_list_readers_call(SMARTCARD_DEVICE* smartcard, wStream* s,
|
||||
|
||||
if ((status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->hContext))))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -566,7 +566,7 @@ LONG smartcard_unpack_list_readers_call(SMARTCARD_DEVICE* smartcard, wStream* s,
|
||||
|
||||
if ((status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->hContext))))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context_ref failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context_ref failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -622,7 +622,7 @@ void smartcard_trace_list_readers_call(SMARTCARD_DEVICE* smartcard, ListReaders_
|
||||
if (unicode)
|
||||
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) call->mszGroups, call->cBytes / 2, &mszGroupsA, 0, NULL, NULL);
|
||||
|
||||
WLog_DBG(TAG, "ListReaders%S_Call {", unicode ? "W" : "A");
|
||||
WLog_DBG(TAG, "ListReaders%s_Call {", unicode ? "W" : "A");
|
||||
|
||||
pb = (BYTE*) &(call->hContext.pbContext);
|
||||
|
||||
@ -676,7 +676,7 @@ LONG smartcard_pack_list_readers_return(SMARTCARD_DEVICE* smartcard, wStream* s,
|
||||
|
||||
if ((error = smartcard_pack_write_size_align(smartcard, s, ret->cBytes, 4)))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_pack_write_size_align failed with error %lu", error);
|
||||
WLog_ERR(TAG, "smartcard_pack_write_size_align failed with error %ld", error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
@ -752,7 +752,7 @@ LONG smartcard_unpack_connect_common(SMARTCARD_DEVICE* smartcard, wStream* s, Co
|
||||
|
||||
if ((status = smartcard_unpack_redir_scard_context(smartcard, s, &(common->hContext))))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -780,7 +780,7 @@ LONG smartcard_unpack_connect_a_call(SMARTCARD_DEVICE* smartcard, wStream* s, Co
|
||||
|
||||
if ((status = smartcard_unpack_connect_common(smartcard, s, &(call->Common))))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_unpack_connect_common failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_connect_common failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -803,7 +803,7 @@ LONG smartcard_unpack_connect_a_call(SMARTCARD_DEVICE* smartcard, wStream* s, Co
|
||||
call->szReader[count] = '\0';
|
||||
|
||||
if ((status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->Common.hContext))))
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context_ref failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context_ref failed with error %ld", status);
|
||||
|
||||
return status;
|
||||
}
|
||||
@ -855,7 +855,7 @@ LONG smartcard_unpack_connect_w_call(SMARTCARD_DEVICE* smartcard, wStream* s, Co
|
||||
|
||||
if ((status = smartcard_unpack_connect_common(smartcard, s, &(call->Common))))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_unpack_connect_common failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_connect_common failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -878,7 +878,7 @@ LONG smartcard_unpack_connect_w_call(SMARTCARD_DEVICE* smartcard, wStream* s, Co
|
||||
call->szReader[count] = '\0';
|
||||
|
||||
if ((status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->Common.hContext))))
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context_ref failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context_ref failed with error %ld", status);
|
||||
|
||||
return status;
|
||||
}
|
||||
@ -923,13 +923,13 @@ LONG smartcard_pack_connect_return(SMARTCARD_DEVICE* smartcard, wStream* s, Conn
|
||||
|
||||
if ((status = smartcard_pack_redir_scard_context(smartcard, s, &(ret->hContext))))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_pack_redir_scard_context failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_pack_redir_scard_context failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
if ((status = smartcard_pack_redir_scard_handle(smartcard, s, &(ret->hCard))))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_pack_redir_scard_handle failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_pack_redir_scard_handle failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -937,12 +937,12 @@ LONG smartcard_pack_connect_return(SMARTCARD_DEVICE* smartcard, wStream* s, Conn
|
||||
|
||||
if ((status = smartcard_pack_redir_scard_context_ref(smartcard, s, &(ret->hContext))))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_pack_redir_scard_context_ref failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_pack_redir_scard_context_ref failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
if ((status = smartcard_pack_redir_scard_handle_ref(smartcard, s, &(ret->hCard))))
|
||||
WLog_ERR(TAG, "smartcard_pack_redir_scard_handle_ref failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_pack_redir_scard_handle_ref failed with error %ld", status);
|
||||
|
||||
return status;
|
||||
}
|
||||
@ -997,13 +997,13 @@ LONG smartcard_unpack_reconnect_call(SMARTCARD_DEVICE* smartcard, wStream* s, Re
|
||||
|
||||
if ((status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->hContext))))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
if ((status = smartcard_unpack_redir_scard_handle(smartcard, s, &(call->hCard))))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_handle failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_handle failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -1021,12 +1021,12 @@ LONG smartcard_unpack_reconnect_call(SMARTCARD_DEVICE* smartcard, wStream* s, Re
|
||||
|
||||
if ((status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->hContext))))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context_ref failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context_ref failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
if ((status = smartcard_unpack_redir_scard_handle_ref(smartcard, s, &(call->hCard))))
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_handle_ref failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_handle_ref failed with error %ld", status);
|
||||
|
||||
return status;
|
||||
}
|
||||
@ -1103,13 +1103,13 @@ LONG smartcard_unpack_hcard_and_disposition_call(SMARTCARD_DEVICE* smartcard, wS
|
||||
|
||||
if ((status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->hContext))))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
if ((status = smartcard_unpack_redir_scard_handle(smartcard, s, &(call->hCard))))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_handle failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_handle failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -1124,12 +1124,12 @@ LONG smartcard_unpack_hcard_and_disposition_call(SMARTCARD_DEVICE* smartcard, wS
|
||||
|
||||
if ((status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->hContext))))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context_ref failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context_ref failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
if ((status = smartcard_unpack_redir_scard_handle_ref(smartcard, s, &(call->hCard))))
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_handle_ref failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_handle_ref failed with error %ld", status);
|
||||
|
||||
return status;
|
||||
}
|
||||
@ -1190,7 +1190,7 @@ LONG smartcard_unpack_get_status_change_a_call(SMARTCARD_DEVICE* smartcard, wStr
|
||||
|
||||
if ((status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->hContext))))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -1207,7 +1207,7 @@ LONG smartcard_unpack_get_status_change_a_call(SMARTCARD_DEVICE* smartcard, wStr
|
||||
|
||||
if ((status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->hContext))))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context_ref failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context_ref failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -1368,7 +1368,7 @@ LONG smartcard_unpack_get_status_change_w_call(SMARTCARD_DEVICE* smartcard, wStr
|
||||
|
||||
if ((status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->hContext))))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -1385,7 +1385,7 @@ LONG smartcard_unpack_get_status_change_w_call(SMARTCARD_DEVICE* smartcard, wStr
|
||||
|
||||
if ((status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->hContext))))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context_ref failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context_ref failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -1601,13 +1601,13 @@ LONG smartcard_unpack_state_call(SMARTCARD_DEVICE* smartcard, wStream* s, State_
|
||||
|
||||
if ((status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->hContext))))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
if ((status = smartcard_unpack_redir_scard_handle(smartcard, s, &(call->hCard))))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_handle failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_handle failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -1623,12 +1623,12 @@ LONG smartcard_unpack_state_call(SMARTCARD_DEVICE* smartcard, wStream* s, State_
|
||||
|
||||
if ((status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->hContext))))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context_ref failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context_ref failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
if ((status = smartcard_unpack_redir_scard_handle_ref(smartcard, s, &(call->hCard))))
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_handle_ref failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_handle_ref failed with error %ld", status);
|
||||
|
||||
return status;
|
||||
}
|
||||
@ -1645,7 +1645,7 @@ LONG smartcard_pack_state_return(SMARTCARD_DEVICE* smartcard, wStream* s, State_
|
||||
Stream_Write(s, ret->rgAtr, ret->cbAtrLen); /* rgAtr */
|
||||
|
||||
if ((status = smartcard_pack_write_size_align(smartcard, s, ret->cbAtrLen, 4)))
|
||||
WLog_ERR(TAG, "smartcard_pack_write_size_align failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_pack_write_size_align failed with error %ld", status);
|
||||
|
||||
return status;
|
||||
}
|
||||
@ -1656,13 +1656,13 @@ LONG smartcard_unpack_status_call(SMARTCARD_DEVICE* smartcard, wStream* s, Statu
|
||||
|
||||
if ((status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->hContext))))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
if ((status = smartcard_unpack_redir_scard_handle(smartcard, s, &(call->hCard))))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_handle failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_handle failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -1679,12 +1679,12 @@ LONG smartcard_unpack_status_call(SMARTCARD_DEVICE* smartcard, wStream* s, Statu
|
||||
|
||||
if ((status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->hContext))))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context_ref failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context_ref failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
if ((status = smartcard_unpack_redir_scard_handle_ref(smartcard, s, &(call->hCard))))
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_handle_ref failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_handle_ref failed with error %ld", status);
|
||||
|
||||
return status;
|
||||
}
|
||||
@ -1754,7 +1754,7 @@ LONG smartcard_pack_status_return(SMARTCARD_DEVICE* smartcard, wStream* s, Statu
|
||||
Stream_Zero(s, ret->cBytes);
|
||||
|
||||
if ((status = smartcard_pack_write_size_align(smartcard, s, ret->cBytes, 4)))
|
||||
WLog_ERR(TAG, "smartcard_pack_write_size_align failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_pack_write_size_align failed with error %ld", status);
|
||||
|
||||
return status;
|
||||
}
|
||||
@ -1834,13 +1834,13 @@ LONG smartcard_unpack_get_attrib_call(SMARTCARD_DEVICE* smartcard, wStream* s, G
|
||||
|
||||
if ((status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->hContext))))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
if ((status = smartcard_unpack_redir_scard_handle(smartcard, s, &(call->hCard))))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_handle failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_handle failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -1857,12 +1857,12 @@ LONG smartcard_unpack_get_attrib_call(SMARTCARD_DEVICE* smartcard, wStream* s, G
|
||||
|
||||
if ((status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->hContext))))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context_ref failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context_ref failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
if ((status = smartcard_unpack_redir_scard_handle_ref(smartcard, s, &(call->hCard))))
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_handle_ref failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_handle_ref failed with error %ld", status);
|
||||
|
||||
return status;
|
||||
}
|
||||
@ -1927,7 +1927,7 @@ LONG smartcard_pack_get_attrib_return(SMARTCARD_DEVICE* smartcard, wStream* s, G
|
||||
Stream_Write(s, ret->pbAttr, ret->cbAttrLen); /* pbAttr */
|
||||
|
||||
if ((status = smartcard_pack_write_size_align(smartcard, s, ret->cbAttrLen, 4)))
|
||||
WLog_ERR(TAG, "smartcard_pack_write_size_align failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_pack_write_size_align failed with error %ld", status);
|
||||
|
||||
return status;
|
||||
}
|
||||
@ -1968,13 +1968,13 @@ LONG smartcard_unpack_control_call(SMARTCARD_DEVICE* smartcard, wStream* s, Cont
|
||||
|
||||
if ((status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->hContext))))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
if ((status = smartcard_unpack_redir_scard_handle(smartcard, s, &(call->hCard))))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_handle failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_handle failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -1993,13 +1993,13 @@ LONG smartcard_unpack_control_call(SMARTCARD_DEVICE* smartcard, wStream* s, Cont
|
||||
|
||||
if ((status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->hContext))))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context_ref failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context_ref failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
if ((status = smartcard_unpack_redir_scard_handle_ref(smartcard, s, &(call->hCard))))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context_ref failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context_ref failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -2107,7 +2107,7 @@ LONG smartcard_pack_control_return(SMARTCARD_DEVICE* smartcard, wStream* s, Cont
|
||||
Stream_Write(s, ret->pvOutBuffer, ret->cbOutBufferSize); /* pvOutBuffer */
|
||||
if ((error = smartcard_pack_write_size_align(smartcard, s, ret->cbOutBufferSize, 4)))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_pack_write_size_align failed with error %lu", error);
|
||||
WLog_ERR(TAG, "smartcard_pack_write_size_align failed with error %ld", error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
@ -2158,13 +2158,13 @@ LONG smartcard_unpack_transmit_call(SMARTCARD_DEVICE* smartcard, wStream* s, Tra
|
||||
|
||||
if ((status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->hContext))))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
if ((status = smartcard_unpack_redir_scard_handle(smartcard, s, &(call->hCard))))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_handle failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_handle failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -2200,13 +2200,13 @@ LONG smartcard_unpack_transmit_call(SMARTCARD_DEVICE* smartcard, wStream* s, Tra
|
||||
|
||||
if ((status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->hContext))))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context_ref failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context_ref failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
if ((status = smartcard_unpack_redir_scard_handle_ref(smartcard, s, &(call->hCard))))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_handle_ref failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_handle_ref failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -2528,7 +2528,7 @@ LONG smartcard_pack_transmit_return(SMARTCARD_DEVICE* smartcard, wStream* s, Tra
|
||||
Stream_Write(s, pbExtraBytes, cbExtraBytes);
|
||||
if ((error = smartcard_pack_write_size_align(smartcard, s, cbExtraBytes, 4)))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_pack_write_size_align failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "smartcard_pack_write_size_align failed with error %ld!", error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
@ -2546,7 +2546,7 @@ LONG smartcard_pack_transmit_return(SMARTCARD_DEVICE* smartcard, wStream* s, Tra
|
||||
Stream_Write(s, ret->pbRecvBuffer, ret->cbRecvLength);
|
||||
if ((error = smartcard_pack_write_size_align(smartcard, s, ret->cbRecvLength, 4)))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_pack_write_size_align failed with error %lu!", error);
|
||||
WLog_ERR(TAG, "smartcard_pack_write_size_align failed with error %ld!", error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
@ -2619,7 +2619,7 @@ LONG smartcard_unpack_locate_cards_by_atr_a_call(SMARTCARD_DEVICE* smartcard, wS
|
||||
|
||||
if ((status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->hContext))))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -2637,7 +2637,7 @@ LONG smartcard_unpack_locate_cards_by_atr_a_call(SMARTCARD_DEVICE* smartcard, wS
|
||||
|
||||
if ((status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->hContext))))
|
||||
{
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context_ref failed with error %lu", status);
|
||||
WLog_ERR(TAG, "smartcard_unpack_redir_scard_context_ref failed with error %ld", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
@ -42,7 +42,7 @@ add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE
|
||||
|
||||
target_link_libraries(${MODULE_NAME} freerdp winpr)
|
||||
|
||||
if (WITH_DEBUG_SYMBOLS AND MSVC AND NOT STATIC_CHANNELS AND BUILD_SHARED_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()
|
||||
|
||||
|
||||
@ -231,7 +231,7 @@ static void tsmf_alsa_free(ITSMFAudioDevice *audio)
|
||||
free(alsa);
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#ifdef BUILTIN_CHANNELS
|
||||
#define freerdp_tsmf_client_audio_subsystem_entry alsa_freerdp_tsmf_client_audio_subsystem_entry
|
||||
#else
|
||||
#define freerdp_tsmf_client_audio_subsystem_entry FREERDP_API freerdp_tsmf_client_audio_subsystem_entry
|
||||
|
||||
@ -39,7 +39,7 @@ else()
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
endif()
|
||||
|
||||
if (WITH_DEBUG_SYMBOLS AND MSVC AND NOT STATIC_CHANNELS AND BUILD_SHARED_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()
|
||||
|
||||
|
||||
@ -541,7 +541,7 @@ static void tsmf_ffmpeg_free(ITSMFDecoder* decoder)
|
||||
|
||||
static BOOL initialized = FALSE;
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#ifdef BUILTIN_CHANNELS
|
||||
#define freerdp_tsmf_client_subsystem_entry ffmpeg_freerdp_tsmf_client_decoder_subsystem_entry
|
||||
#else
|
||||
#define freerdp_tsmf_client_subsystem_entry FREERDP_API freerdp_tsmf_client_decoder_subsystem_entry
|
||||
|
||||
@ -1010,7 +1010,7 @@ BOOL tsmf_gstreamer_sync(ITSMFDecoder* decoder, void (*cb)(void *), void *stream
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#ifdef BUILTIN_CHANNELS
|
||||
#define freerdp_tsmf_client_subsystem_entry gstreamer_freerdp_tsmf_client_decoder_subsystem_entry
|
||||
#else
|
||||
#define freerdp_tsmf_client_subsystem_entry FREERDP_API freerdp_tsmf_client_decoder_subsystem_entry
|
||||
|
||||
@ -236,7 +236,7 @@ static void tsmf_oss_free(ITSMFAudioDevice* audio)
|
||||
free(oss);
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#ifdef BUILTIN_CHANNELS
|
||||
#define freerdp_tsmf_client_audio_subsystem_entry oss_freerdp_tsmf_client_audio_subsystem_entry
|
||||
#else
|
||||
#define freerdp_tsmf_client_audio_subsystem_entry FREERDP_API freerdp_tsmf_client_audio_subsystem_entry
|
||||
|
||||
@ -358,7 +358,7 @@ static void tsmf_pulse_free(ITSMFAudioDevice *audio)
|
||||
free(pulse);
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#ifdef BUILTIN_CHANNELS
|
||||
ITSMFAudioDevice *pulse_freerdp_tsmf_client_audio_subsystem_entry(void)
|
||||
#else
|
||||
FREERDP_API ITSMFAudioDevice *freerdp_tsmf_client_audio_subsystem_entry(void)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user