Merge pull request #1483 from awakecoding/master
FreeRDP, WinPR Various New Modules & Stubs
This commit is contained in:
commit
8a750f1858
9
.gitignore
vendored
9
.gitignore
vendored
@ -12,16 +12,25 @@ cmake_install.cmake
|
||||
CPackConfig.cmake
|
||||
CPackSourceConfig.cmake
|
||||
DartConfiguration.tcl
|
||||
CMakeCPackOptions.cmake
|
||||
_CPack_Packages
|
||||
LICENSE.txt
|
||||
external/*
|
||||
!external/README
|
||||
|
||||
*.a.objlist.cmake
|
||||
*.a.objlist
|
||||
*.a.objdir
|
||||
*_dummy.c
|
||||
*_dummy.c.base
|
||||
|
||||
# Packages
|
||||
*.zip
|
||||
*.exe
|
||||
*.sh
|
||||
*.deb
|
||||
*.rpm
|
||||
*.dmg
|
||||
*.tar.Z
|
||||
*.tar.gz
|
||||
|
||||
|
96
CMakeCPack.cmake
Normal file
96
CMakeCPack.cmake
Normal file
@ -0,0 +1,96 @@
|
||||
|
||||
# Generate .txt license file for CPack (PackageMaker requires a file extension)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/LICENSE ${CMAKE_CURRENT_BINARY_DIR}/LICENSE.txt @ONLY)
|
||||
|
||||
SET(CPACK_BINARY_ZIP "ON")
|
||||
|
||||
# Workaround to remove c++ compiler macros and defines for Eclipse.
|
||||
# If c++ macros/defines are set __cplusplus is also set which causes
|
||||
# problems when compiling freerdp/jni. To prevent this problem we set the macros to "".
|
||||
|
||||
if (ANDROID AND CMAKE_EXTRA_GENERATOR STREQUAL "Eclipse CDT4")
|
||||
set(CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_DEFINED_MACROS "")
|
||||
message(STATUS "Disabled CXX system defines for eclipse (workaround).")
|
||||
endif()
|
||||
|
||||
set(CPACK_SOURCE_IGNORE_FILES "/\\\\.git/;/\\\\.gitignore;/CMakeCache.txt")
|
||||
|
||||
if(NOT WIN32)
|
||||
if(APPLE AND (NOT IOS))
|
||||
|
||||
if(WITH_SERVER)
|
||||
set(CPACK_PACKAGE_EXECUTABLES ${CPACK_PACKAGE_EXECUTABLES} "mfreerdp-server")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_X11)
|
||||
set(CPACK_PACKAGE_EXECUTABLES "xfreerdp")
|
||||
|
||||
if(WITH_SERVER)
|
||||
set(CPACK_PACKAGE_EXECUTABLES ${CPACK_PACKAGE_EXECUTABLES} "xfreerdp-server")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(CPACK_SYSTEM_NAME "${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}")
|
||||
set(CPACK_TOPLEVEL_TAG "${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}")
|
||||
|
||||
string(TOLOWER ${CMAKE_PROJECT_NAME} CMAKE_PROJECT_NAME_lower)
|
||||
set(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME_lower}-${FREERDP_VERSION_FULL}-${CPACK_SYSTEM_NAME}")
|
||||
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME_lower}-${FREERDP_VERSION_FULL}-${CPACK_SYSTEM_NAME}")
|
||||
|
||||
set(CPACK_PACKAGE_NAME "FreeRDP")
|
||||
set(CPACK_PACKAGE_VENDOR "FreeRDP")
|
||||
set(CPACK_PACKAGE_VERSION ${FREERDP_VERSION_FULL})
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR ${FREERDP_VERSION_MAJOR})
|
||||
set(CPACK_PACKAGE_VERSION_MINOR ${FREERDP_VERSION_MINOR})
|
||||
set(CPACK_PACKAGE_VERSION_PATCH ${FREERDP_VERSION_REVISION})
|
||||
SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "FreeRDP: A Remote Desktop Protocol Implementation")
|
||||
|
||||
set(CPACK_PACKAGE_CONTACT "Marc-Andre Moreau")
|
||||
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "marcandre.moreau@gmail.com")
|
||||
set(CPACK_DEBIAN_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR})
|
||||
|
||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY "FreeRDP")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_BINARY_DIR}/LICENSE.txt")
|
||||
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_BINARY_DIR}/LICENSE.txt")
|
||||
|
||||
set(CPACK_NSIS_MODIFY_PATH ON)
|
||||
set(CPACK_PACKAGE_ICON "${CMAKE_SOURCE_DIR}/resources\\\\FreeRDP_Install.bmp")
|
||||
set(CPACK_NSIS_MUI_ICON "${CMAKE_SOURCE_DIR}/resources\\\\FreeRDP_Icon_96px.ico")
|
||||
set(CPACK_NSIS_MUI_UNICON "${CMAKE_SOURCE_DIR}/resource\\\\FreeRDP_Icon_96px.ico")
|
||||
|
||||
set(CPACK_COMPONENTS_ALL client server libraries headers)
|
||||
|
||||
if(MSVC)
|
||||
if(MSVC_RUNTIME STREQUAL "dynamic")
|
||||
set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP TRUE)
|
||||
include(InstallRequiredSystemLibraries)
|
||||
|
||||
install(PROGRAMS ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS}
|
||||
DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
COMPONENT libraries)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(CPACK_COMPONENT_CLIENT_DISPLAY_NAME "Client")
|
||||
set(CPACK_COMPONENT_CLIENT_GROUP "Applications")
|
||||
|
||||
set(CPACK_COMPONENT_SERVER_DISPLAY_NAME "Server")
|
||||
set(CPACK_COMPONENT_SERVER_GROUP "Applications")
|
||||
|
||||
set(CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME "Libraries")
|
||||
set(CPACK_COMPONENT_LIBRARIES_GROUP "Runtime")
|
||||
|
||||
set(CPACK_COMPONENT_HEADERS_DISPLAY_NAME "Headers")
|
||||
set(CPACK_COMPONENT_HEADERS_GROUP "Development")
|
||||
|
||||
set(CPACK_COMPONENT_GROUP_RUNTIME_DESCRIPTION "Runtime")
|
||||
set(CPACK_COMPONENT_GROUP_APPLICATIONS_DESCRIPTION "Applications")
|
||||
set(CPACK_COMPONENT_GROUP_DEVELOPMENT_DESCRIPTION "Development")
|
||||
|
||||
configure_file("${CMAKE_SOURCE_DIR}/CMakeCPackOptions.cmake.in"
|
||||
"${CMAKE_BINARY_DIR}/CMakeCPackOptions.cmake" @ONLY)
|
||||
set(CPACK_PROJECT_CONFIG_FILE "${CMAKE_BINARY_DIR}/CMakeCPackOptions.cmake")
|
||||
|
||||
include(CPack)
|
10
CMakeCPackOptions.cmake.in
Normal file
10
CMakeCPackOptions.cmake.in
Normal file
@ -0,0 +1,10 @@
|
||||
# This file is configured at cmake time, and loaded at cpack time.
|
||||
# To pass variables to cpack from cmake, they must be configured in this file.
|
||||
|
||||
if("${CPACK_GENERATOR}" STREQUAL "PackageMaker")
|
||||
if(CMAKE_PACKAGE_QTGUI)
|
||||
set(CPACK_PACKAGE_DEFAULT_LOCATION "/Applications")
|
||||
else()
|
||||
set(CPACK_PACKAGE_DEFAULT_LOCATION "/usr")
|
||||
endif()
|
||||
endif()
|
141
CMakeLists.txt
141
CMakeLists.txt
@ -22,8 +22,14 @@ cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
project(FreeRDP C)
|
||||
|
||||
if(NOT DEFINED VENDOR)
|
||||
set(VENDOR "FreeRDP" CACHE STRING "FreeRDP package vendor")
|
||||
endif()
|
||||
|
||||
set(CMAKE_COLOR_MAKEFILE ON)
|
||||
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
# Include our extra modules
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/)
|
||||
|
||||
@ -159,6 +165,10 @@ if("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
|
||||
if(WITH_SSE2)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mssse3")
|
||||
endif()
|
||||
CHECK_C_COMPILER_FLAG(-Wno-deprecated-declarations Wno-deprecated-declarations)
|
||||
if(Wno-deprecated-declarations)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated-declarations")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
@ -230,7 +240,9 @@ if(APPLE)
|
||||
set(CMAKE_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH} ${FREERDP_IOS_EXTERNAL_SSL_PATH})
|
||||
set_property(GLOBAL PROPERTY XCODE_ATTRIBUTE_SKIP_INSTALL YES)
|
||||
else()
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.6)
|
||||
if(NOT DEFINED CMAKE_OSX_DEPLOYMENT_TARGET OR CMAKE_OSX_DEPLOYMENT_TARGET MATCHES "")
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.6 CACHE STRING "OSX deployment target" FORCE)
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED CMAKE_OSX_ARCHITECTURES)
|
||||
set(CMAKE_OSX_ARCHITECTURES i386 x86_64)
|
||||
@ -242,9 +254,11 @@ if(APPLE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_CLANG)
|
||||
set(CMAKE_C_COMPILER "clang")
|
||||
endif()
|
||||
# Temporarily disabled, causes the cmake script to be reexecuted, causing the compilation to fail.
|
||||
# Workaround: specify the parameter in the command-line
|
||||
# if(WITH_CLANG)
|
||||
# set(CMAKE_C_COMPILER "clang")
|
||||
# endif()
|
||||
|
||||
if (WITH_VERBOSE)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -v")
|
||||
@ -273,6 +287,7 @@ if(NOT IOS AND NOT ANDROID)
|
||||
endif()
|
||||
|
||||
if(UNIX OR CYGWIN)
|
||||
check_include_files(sys/eventfd.h HAVE_AIO_H)
|
||||
check_include_files(sys/eventfd.h HAVE_EVENTFD_H)
|
||||
check_include_files(sys/timerfd.h HAVE_TIMERFD_H)
|
||||
set(X11_FEATURE_TYPE "RECOMMENDED")
|
||||
@ -475,9 +490,7 @@ if(WITH_THIRD_PARTY)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (NOT WITH_WAYK)
|
||||
add_subdirectory(include)
|
||||
endif()
|
||||
add_subdirectory(include)
|
||||
|
||||
add_subdirectory(libfreerdp)
|
||||
|
||||
@ -500,114 +513,16 @@ endif()
|
||||
|
||||
# Packaging
|
||||
|
||||
SET(CPACK_BINARY_ZIP "ON")
|
||||
set(CMAKE_CPACK_INCLUDE_FILE "CMakeCPack.cmake")
|
||||
|
||||
if(NOT WITH_WAYK)
|
||||
|
||||
set(CPACK_SOURCE_IGNORE_FILES "/\\\\.git/;/\\\\.gitignore;/CMakeCache.txt")
|
||||
|
||||
if(NOT WIN32)
|
||||
if(APPLE AND (NOT IOS))
|
||||
#set(CPACK_PACKAGE_EXECUTABLES "mfreerdp")
|
||||
|
||||
if(WITH_SERVER)
|
||||
set(CPACK_PACKAGE_EXECUTABLES ${CPACK_PACKAGE_EXECUTABLES} "mfreerdp-server")
|
||||
endif()
|
||||
if(NOT (VENDOR MATCHES "FreeRDP"))
|
||||
if(DEFINED CLIENT_VENDOR_PATH)
|
||||
if(EXISTS "${CMAKE_SOURCE_DIR}/${CLIENT_VENDOR_PATH}/CMakeCPack.cmake")
|
||||
set(CMAKE_CPACK_INCLUDE_FILE "${CLIENT_VENDOR_PATH}/CMakeCPack.cmake")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_X11)
|
||||
set(CPACK_PACKAGE_EXECUTABLES "xfreerdp")
|
||||
|
||||
if(WITH_SERVER)
|
||||
set(CPACK_PACKAGE_EXECUTABLES ${CPACK_PACKAGE_EXECUTABLES} "xfreerdp-server")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
set(CPACK_SYSTEM_NAME "${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}")
|
||||
set(CPACK_TOPLEVEL_TAG "${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}")
|
||||
#message("VENDOR: ${VENDOR} CLIENT_VENDOR_PATH: ${CLIENT_VENDOR_PATH} CMAKE_CPACK_INCLUDE_FILE: ${CMAKE_CPACK_INCLUDE_FILE}")
|
||||
|
||||
string(TOLOWER ${CMAKE_PROJECT_NAME} CMAKE_PROJECT_NAME_lower)
|
||||
set(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME_lower}-${FREERDP_VERSION_FULL}-${CPACK_SYSTEM_NAME}")
|
||||
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME_lower}-${FREERDP_VERSION_FULL}-${CPACK_SYSTEM_NAME}")
|
||||
|
||||
set(CPACK_PACKAGE_NAME "FreeRDP")
|
||||
set(CPACK_PACKAGE_VENDOR "FreeRDP")
|
||||
set(CPACK_PACKAGE_VERSION ${FREERDP_VERSION_FULL})
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR ${FREERDP_VERSION_MAJOR})
|
||||
set(CPACK_PACKAGE_VERSION_MINOR ${FREERDP_VERSION_MINOR})
|
||||
set(CPACK_PACKAGE_VERSION_PATCH ${FREERDP_VERSION_REVISION})
|
||||
SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "FreeRDP: A Remote Desktop Protocol Implementation")
|
||||
|
||||
set(CPACK_PACKAGE_CONTACT "Marc-Andre Moreau")
|
||||
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "marcandre.moreau@gmail.com")
|
||||
set(CPACK_DEBIAN_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR})
|
||||
|
||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY "FreeRDP")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_SOURCE_DIR}/LICENSE")
|
||||
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE")
|
||||
|
||||
set(CPACK_NSIS_MODIFY_PATH ON)
|
||||
set(CPACK_PACKAGE_ICON "${CMAKE_SOURCE_DIR}/resources\\\\FreeRDP_Install.bmp")
|
||||
set(CPACK_NSIS_MUI_ICON "${CMAKE_SOURCE_DIR}/resources\\\\FreeRDP_Icon_96px.ico")
|
||||
set(CPACK_NSIS_MUI_UNICON "${CMAKE_SOURCE_DIR}/resource\\\\FreeRDP_Icon_96px.ico")
|
||||
|
||||
set(CPACK_COMPONENTS_ALL client server libraries headers)
|
||||
|
||||
if(MSVC)
|
||||
if(MSVC_RUNTIME STREQUAL "dynamic")
|
||||
set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP TRUE)
|
||||
include(InstallRequiredSystemLibraries)
|
||||
|
||||
if(NOT WITH_WAYK)
|
||||
install(PROGRAMS ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS}
|
||||
DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
COMPONENT libraries)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(EXTRA_DATA_DIR "extra/")
|
||||
file(GLOB EXTRA_FILES "${CMAKE_SOURCE_DIR}/extra/*")
|
||||
install(FILES ${EXTRA_FILES}
|
||||
DESTINATION ${EXTRA_DATA_DIR}
|
||||
COMPONENT extra)
|
||||
|
||||
set(REV_DATA_DIR "REV/")
|
||||
file(GLOB REV_FILES "${CMAKE_SOURCE_DIR}/REV/*")
|
||||
install(FILES ${REV_FILES}
|
||||
DESTINATION ${REV_DATA_DIR}
|
||||
COMPONENT rev)
|
||||
|
||||
set(CPACK_COMPONENTS_AL ${CPACK_COMPONENTS_ALL} extra rev)
|
||||
endif()
|
||||
|
||||
|
||||
set(CPACK_COMPONENT_CLIENT_DISPLAY_NAME "Client")
|
||||
set(CPACK_COMPONENT_CLIENT_GROUP "Applications")
|
||||
|
||||
set(CPACK_COMPONENT_SERVER_DISPLAY_NAME "Server")
|
||||
set(CPACK_COMPONENT_SERVER_GROUP "Applications")
|
||||
|
||||
set(CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME "Libraries")
|
||||
set(CPACK_COMPONENT_LIBRARIES_GROUP "Runtime")
|
||||
|
||||
set(CPACK_COMPONENT_HEADERS_DISPLAY_NAME "Headers")
|
||||
set(CPACK_COMPONENT_HEADERS_GROUP "Development")
|
||||
|
||||
set(CPACK_COMPONENT_GROUP_RUNTIME_DESCRIPTION "Runtime")
|
||||
set(CPACK_COMPONENT_GROUP_APPLICATIONS_DESCRIPTION "Applications")
|
||||
set(CPACK_COMPONENT_GROUP_DEVELOPMENT_DESCRIPTION "Development")
|
||||
|
||||
# Workaround to remove c++ compiler macros and defines for Eclipse.
|
||||
# If c++ macros/defines are set __cplusplus is also set which causes
|
||||
# problems when compiling freerdp/jni. To prevent this problem
|
||||
# we set the macros to "".
|
||||
if (ANDROID AND CMAKE_EXTRA_GENERATOR STREQUAL "Eclipse CDT4")
|
||||
set(CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_DEFINED_MACROS "")
|
||||
message(STATUS "Disabled CXX system defines for eclipse (workaround).")
|
||||
endif()
|
||||
|
||||
include(CPack)
|
||||
|
||||
endif()
|
||||
include(${CMAKE_CPACK_INCLUDE_FILE})
|
||||
|
@ -30,7 +30,7 @@ set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
|
||||
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||
MODULE freerdp
|
||||
MODULES freerdp-utils)
|
||||
MODULES freerdp-codec freerdp-utils)
|
||||
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${ALSA_LIBRARIES})
|
||||
|
||||
|
@ -30,7 +30,7 @@ set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
|
||||
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||
MODULE freerdp
|
||||
MODULES freerdp-utils)
|
||||
MODULES freerdp-codec freerdp-utils)
|
||||
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${PULSE_LIBRARY})
|
||||
|
||||
|
@ -78,7 +78,7 @@ static void audin_server_send_version(audin_server* audin, wStream* s)
|
||||
{
|
||||
Stream_Write_UINT8(s, MSG_SNDIN_VERSION);
|
||||
Stream_Write_UINT32(s, 1); /* Version (4 bytes) */
|
||||
WTSVirtualChannelWrite(audin->audin_channel, Stream_Buffer(s), Stream_GetPosition(s), NULL);
|
||||
WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
|
||||
}
|
||||
|
||||
static BOOL audin_server_recv_version(audin_server* audin, wStream* s, UINT32 length)
|
||||
@ -130,7 +130,7 @@ static void audin_server_send_formats(audin_server* audin, wStream* s)
|
||||
}
|
||||
}
|
||||
|
||||
WTSVirtualChannelWrite(audin->audin_channel, Stream_Buffer(s), Stream_GetPosition(s), NULL);
|
||||
WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
|
||||
}
|
||||
|
||||
static BOOL audin_server_recv_formats(audin_server* audin, wStream* s, UINT32 length)
|
||||
@ -166,6 +166,7 @@ static BOOL audin_server_recv_formats(audin_server* audin, wStream* s, UINT32 le
|
||||
Stream_Read_UINT16(s, audin->context.client_formats[i].nBlockAlign);
|
||||
Stream_Read_UINT16(s, audin->context.client_formats[i].wBitsPerSample);
|
||||
Stream_Read_UINT16(s, audin->context.client_formats[i].cbSize);
|
||||
|
||||
if (audin->context.client_formats[i].cbSize > 0)
|
||||
{
|
||||
Stream_Seek(s, audin->context.client_formats[i].cbSize);
|
||||
@ -201,7 +202,7 @@ static void audin_server_send_open(audin_server* audin, wStream* s)
|
||||
Stream_Write_UINT16(s, 16); /* wBitsPerSample */
|
||||
Stream_Write_UINT16(s, 0); /* cbSize */
|
||||
|
||||
WTSVirtualChannelWrite(audin->audin_channel, Stream_Buffer(s), Stream_GetPosition(s), NULL);
|
||||
WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
|
||||
}
|
||||
|
||||
static BOOL audin_server_recv_open_reply(audin_server* audin, wStream* s, UINT32 length)
|
||||
@ -283,10 +284,10 @@ static void* audin_server_thread_func(void* arg)
|
||||
void* buffer;
|
||||
BYTE MessageId;
|
||||
BOOL ready = FALSE;
|
||||
UINT32 bytes_returned = 0;
|
||||
DWORD BytesReturned = 0;
|
||||
audin_server* audin = (audin_server*) arg;
|
||||
|
||||
if (WTSVirtualChannelQuery(audin->audin_channel, WTSVirtualFileHandle, &buffer, &bytes_returned) == TRUE)
|
||||
if (WTSVirtualChannelQuery(audin->audin_channel, WTSVirtualFileHandle, &buffer, &BytesReturned) == TRUE)
|
||||
{
|
||||
fd = *((void**) buffer);
|
||||
WTSFreeMemory(buffer);
|
||||
@ -303,7 +304,7 @@ static void* audin_server_thread_func(void* arg)
|
||||
if (WaitForSingleObject(audin->stopEvent, 0) == WAIT_OBJECT_0)
|
||||
break;
|
||||
|
||||
if (WTSVirtualChannelQuery(audin->audin_channel, WTSVirtualChannelReady, &buffer, &bytes_returned) == FALSE)
|
||||
if (WTSVirtualChannelQuery(audin->audin_channel, WTSVirtualChannelReady, &buffer, &BytesReturned) == FALSE)
|
||||
break;
|
||||
|
||||
ready = *((BOOL*) buffer);
|
||||
@ -330,46 +331,48 @@ static void* audin_server_thread_func(void* arg)
|
||||
|
||||
Stream_SetPosition(s, 0);
|
||||
|
||||
if (WTSVirtualChannelRead(audin->audin_channel, 0, Stream_Buffer(s),
|
||||
Stream_Capacity(s), &bytes_returned) == FALSE)
|
||||
if (WTSVirtualChannelRead(audin->audin_channel, 0, (PCHAR) Stream_Buffer(s),
|
||||
Stream_Capacity(s), &BytesReturned) == FALSE)
|
||||
{
|
||||
if (bytes_returned == 0)
|
||||
if (BytesReturned == 0)
|
||||
break;
|
||||
|
||||
Stream_EnsureRemainingCapacity(s, (int) bytes_returned);
|
||||
Stream_EnsureRemainingCapacity(s, BytesReturned);
|
||||
|
||||
if (WTSVirtualChannelRead(audin->audin_channel, 0, Stream_Buffer(s),
|
||||
Stream_Capacity(s), &bytes_returned) == FALSE)
|
||||
if (WTSVirtualChannelRead(audin->audin_channel, 0, (PCHAR) Stream_Buffer(s),
|
||||
Stream_Capacity(s), &BytesReturned) == FALSE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bytes_returned < 1)
|
||||
if (BytesReturned < 1)
|
||||
continue;
|
||||
|
||||
Stream_Read_UINT8(s, MessageId);
|
||||
bytes_returned--;
|
||||
BytesReturned--;
|
||||
|
||||
switch (MessageId)
|
||||
{
|
||||
case MSG_SNDIN_VERSION:
|
||||
if (audin_server_recv_version(audin, s, bytes_returned))
|
||||
if (audin_server_recv_version(audin, s, BytesReturned))
|
||||
audin_server_send_formats(audin, s);
|
||||
break;
|
||||
|
||||
case MSG_SNDIN_FORMATS:
|
||||
if (audin_server_recv_formats(audin, s, bytes_returned))
|
||||
if (audin_server_recv_formats(audin, s, BytesReturned))
|
||||
audin_server_send_open(audin, s);
|
||||
break;
|
||||
|
||||
case MSG_SNDIN_OPEN_REPLY:
|
||||
audin_server_recv_open_reply(audin, s, bytes_returned);
|
||||
audin_server_recv_open_reply(audin, s, BytesReturned);
|
||||
break;
|
||||
|
||||
case MSG_SNDIN_DATA_INCOMING:
|
||||
break;
|
||||
|
||||
case MSG_SNDIN_DATA:
|
||||
audin_server_recv_data(audin, s, bytes_returned);
|
||||
audin_server_recv_data(audin, s, BytesReturned);
|
||||
break;
|
||||
|
||||
case MSG_SNDIN_FORMATCHANGE:
|
||||
@ -394,7 +397,7 @@ static BOOL audin_server_open(audin_server_context* context)
|
||||
|
||||
if (!audin->thread)
|
||||
{
|
||||
audin->audin_channel = WTSVirtualChannelOpenEx(context->vcm, "AUDIO_INPUT", WTS_CHANNEL_OPTION_DYNAMIC);
|
||||
audin->audin_channel = WTSVirtualChannelManagerOpenEx(context->vcm, "AUDIO_INPUT", WTS_CHANNEL_OPTION_DYNAMIC);
|
||||
|
||||
if (!audin->audin_channel)
|
||||
return FALSE;
|
||||
|
@ -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()
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
set(OPTION_DEFAULT OFF)
|
||||
set(OPTION_CLIENT_DEFAULT ON)
|
||||
set(OPTION_SERVER_DEFAULT OFF)
|
||||
set(OPTION_SERVER_DEFAULT ON)
|
||||
|
||||
define_channel_options(NAME "cliprdr" TYPE "static"
|
||||
DESCRIPTION "Clipboard Virtual Channel Extension"
|
||||
|
@ -18,7 +18,6 @@
|
||||
define_channel_client("cliprdr")
|
||||
|
||||
set(${MODULE_PREFIX}_SRCS
|
||||
cliprdr_constants.h
|
||||
cliprdr_format.c
|
||||
cliprdr_format.h
|
||||
cliprdr_main.c
|
||||
|
@ -1,58 +0,0 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Clipboard Virtual Channel
|
||||
*
|
||||
* Copyright 2009-2011 Jay Sorg
|
||||
* Copyright 2010-2011 Vic Lee
|
||||
*
|
||||
* 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 __CLIPRDR_CONSTANTS
|
||||
#define __CLIPRDR_CONSTANTS
|
||||
|
||||
/* CLIPRDR_HEADER.msgType */
|
||||
#define CB_MONITOR_READY 0x0001
|
||||
#define CB_FORMAT_LIST 0x0002
|
||||
#define CB_FORMAT_LIST_RESPONSE 0x0003
|
||||
#define CB_FORMAT_DATA_REQUEST 0x0004
|
||||
#define CB_FORMAT_DATA_RESPONSE 0x0005
|
||||
#define CB_TEMP_DIRECTORY 0x0006
|
||||
#define CB_CLIP_CAPS 0x0007
|
||||
#define CB_FILECONTENTS_REQUEST 0x0008
|
||||
#define CB_FILECONTENTS_RESPONSE 0x0009
|
||||
#define CB_LOCK_CLIPDATA 0x000A
|
||||
#define CB_UNLOCK_CLIPDATA 0x000B
|
||||
|
||||
/* CLIPRDR_HEADER.msgFlags */
|
||||
#define CB_RESPONSE_OK 0x0001
|
||||
#define CB_RESPONSE_FAIL 0x0002
|
||||
#define CB_ASCII_NAMES 0x0004
|
||||
|
||||
/* CLIPRDR_CAPS_SET.capabilitySetType */
|
||||
#define CB_CAPSTYPE_GENERAL 0x0001
|
||||
|
||||
/* CLIPRDR_GENERAL_CAPABILITY.lengthCapability */
|
||||
#define CB_CAPSTYPE_GENERAL_LEN 12
|
||||
|
||||
/* CLIPRDR_GENERAL_CAPABILITY.version */
|
||||
#define CB_CAPS_VERSION_1 0x00000001
|
||||
#define CB_CAPS_VERSION_2 0x00000002
|
||||
|
||||
/* CLIPRDR_GENERAL_CAPABILITY.generalFlags */
|
||||
#define CB_USE_LONG_FORMAT_NAMES 0x00000002
|
||||
#define CB_STREAM_FILECLIP_ENABLED 0x00000004
|
||||
#define CB_FILECLIP_NO_FILE_PATHS 0x00000008
|
||||
#define CB_CAN_LOCK_CLIPDATA 0x00000010
|
||||
|
||||
#endif /* __CLIPRDR_CONSTANTS */
|
@ -34,7 +34,6 @@
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
#include <freerdp/client/cliprdr.h>
|
||||
|
||||
#include "cliprdr_constants.h"
|
||||
#include "cliprdr_main.h"
|
||||
#include "cliprdr_format.h"
|
||||
|
||||
|
@ -27,13 +27,13 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/print.h>
|
||||
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/constants.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
#include <freerdp/client/cliprdr.h>
|
||||
|
||||
#include "cliprdr_constants.h"
|
||||
#include "cliprdr_main.h"
|
||||
#include "cliprdr_format.h"
|
||||
|
||||
@ -77,6 +77,11 @@ void cliprdr_packet_send(cliprdrPlugin* cliprdr, wStream* s)
|
||||
Stream_Write_UINT32(s, dataLen);
|
||||
Stream_SetPosition(s, pos);
|
||||
|
||||
#ifdef WITH_DEBUG_CLIPRDR
|
||||
printf("Cliprdr Sending (%d bytes)\n", dataLen + 8);
|
||||
winpr_HexDump(Stream_Buffer(s), dataLen + 8);
|
||||
#endif
|
||||
|
||||
svc_plugin_send((rdpSvcPlugin*) cliprdr, s);
|
||||
}
|
||||
|
||||
@ -207,6 +212,10 @@ static void cliprdr_process_receive(rdpSvcPlugin* plugin, wStream* s)
|
||||
DEBUG_CLIPRDR("msgType: %s (%d), msgFlags: %d dataLen: %d",
|
||||
CB_MSG_TYPE_STRINGS[msgType], msgType, msgFlags, dataLen);
|
||||
|
||||
#ifdef WITH_DEBUG_CLIPRDR
|
||||
winpr_HexDump(Stream_Buffer(s), dataLen + 8);
|
||||
#endif
|
||||
|
||||
switch (msgType)
|
||||
{
|
||||
case CB_CLIP_CAPS:
|
||||
|
@ -25,14 +25,6 @@
|
||||
|
||||
#include <freerdp/utils/debug.h>
|
||||
|
||||
struct _CLIPRDR_FORMAT_NAME
|
||||
{
|
||||
UINT32 id;
|
||||
char* name;
|
||||
int length;
|
||||
};
|
||||
typedef struct _CLIPRDR_FORMAT_NAME CLIPRDR_FORMAT_NAME;
|
||||
|
||||
struct cliprdr_plugin
|
||||
{
|
||||
rdpSvcPlugin plugin;
|
||||
|
35
channels/cliprdr/server/CMakeLists.txt
Normal file
35
channels/cliprdr/server/CMakeLists.txt
Normal file
@ -0,0 +1,35 @@
|
||||
# FreeRDP: A Remote Desktop Protocol Implementation
|
||||
# FreeRDP cmake build script
|
||||
#
|
||||
# Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.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("cliprdr")
|
||||
|
||||
set(${MODULE_PREFIX}_SRCS
|
||||
cliprdr_main.c
|
||||
cliprdr_main.h)
|
||||
|
||||
add_channel_server_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntry")
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
|
||||
|
||||
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||
MODULE freerdp
|
||||
MODULES freerdp-utils)
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Server")
|
536
channels/cliprdr/server/cliprdr_main.c
Normal file
536
channels/cliprdr/server/cliprdr_main.c
Normal file
@ -0,0 +1,536 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Clipboard Virtual Channel Extension
|
||||
*
|
||||
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/stream.h>
|
||||
|
||||
#include "cliprdr_main.h"
|
||||
|
||||
/**
|
||||
* Initialization Sequence\n
|
||||
* Client Server\n
|
||||
* | |\n
|
||||
* |<----------------------Server Clipboard Capabilities PDU-----------------|\n
|
||||
* |<-----------------------------Monitor Ready PDU--------------------------|\n
|
||||
* |-----------------------Client Clipboard Capabilities PDU---------------->|\n
|
||||
* |---------------------------Temporary Directory PDU---------------------->|\n
|
||||
* |-------------------------------Format List PDU-------------------------->|\n
|
||||
* |<--------------------------Format List Response PDU----------------------|\n
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Data Transfer Sequences\n
|
||||
* Shared Local\n
|
||||
* Clipboard Owner Clipboard Owner\n
|
||||
* | |\n
|
||||
* |-------------------------------------------------------------------------|\n _
|
||||
* |-------------------------------Format List PDU-------------------------->|\n |
|
||||
* |<--------------------------Format List Response PDU----------------------|\n _| Copy Sequence
|
||||
* |<---------------------Lock Clipboard Data PDU (Optional)-----------------|\n
|
||||
* |-------------------------------------------------------------------------|\n
|
||||
* |-------------------------------------------------------------------------|\n _
|
||||
* |<--------------------------Format Data Request PDU-----------------------|\n | Paste Sequence Palette,
|
||||
* |---------------------------Format Data Response PDU--------------------->|\n _| Metafile, File List Data
|
||||
* |-------------------------------------------------------------------------|\n
|
||||
* |-------------------------------------------------------------------------|\n _
|
||||
* |<------------------------Format Contents Request PDU---------------------|\n | Paste Sequence
|
||||
* |-------------------------Format Contents Response PDU------------------->|\n _| File Stream Data
|
||||
* |<---------------------Lock Clipboard Data PDU (Optional)-----------------|\n
|
||||
* |-------------------------------------------------------------------------|\n
|
||||
*
|
||||
*/
|
||||
|
||||
static int cliprdr_server_send_capabilities(CliprdrServerContext* context)
|
||||
{
|
||||
wStream* s;
|
||||
BOOL status;
|
||||
UINT32 generalFlags;
|
||||
CLIPRDR_HEADER header;
|
||||
|
||||
printf("CliprdrServerSendCapabilities\n");
|
||||
|
||||
header.msgType = CB_CLIP_CAPS;
|
||||
header.msgFlags = 0;
|
||||
header.dataLen = 16;
|
||||
|
||||
generalFlags = 0;
|
||||
|
||||
if (context->priv->UseLongFormatNames)
|
||||
generalFlags |= CB_USE_LONG_FORMAT_NAMES;
|
||||
|
||||
s = Stream_New(NULL, header.dataLen + CLIPRDR_HEADER_LENGTH);
|
||||
|
||||
Stream_Write_UINT16(s, header.msgType); /* msgType (2 bytes) */
|
||||
Stream_Write_UINT16(s, header.msgFlags); /* msgFlags (2 bytes) */
|
||||
Stream_Write_UINT32(s, header.dataLen); /* dataLen (4 bytes) */
|
||||
|
||||
Stream_Write_UINT16(s, 1); /* cCapabilitiesSets (2 bytes) */
|
||||
Stream_Write_UINT16(s, 0); /* pad1 (2 bytes) */
|
||||
|
||||
Stream_Write_UINT16(s, CB_CAPSTYPE_GENERAL); /* capabilitySetType (2 bytes) */
|
||||
Stream_Write_UINT16(s, CB_CAPSTYPE_GENERAL_LEN); /* lengthCapability (2 bytes) */
|
||||
Stream_Write_UINT32(s, CB_CAPS_VERSION_2); /* version (4 bytes) */
|
||||
Stream_Write_UINT32(s, generalFlags); /* generalFlags (4 bytes) */
|
||||
|
||||
Stream_SealLength(s);
|
||||
|
||||
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL);
|
||||
|
||||
Stream_Free(s, TRUE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cliprdr_server_send_monitor_ready(CliprdrServerContext* context)
|
||||
{
|
||||
wStream* s;
|
||||
BOOL status;
|
||||
CLIPRDR_HEADER header;
|
||||
|
||||
printf("CliprdrServerSendMonitorReady\n");
|
||||
|
||||
header.msgType = CB_MONITOR_READY;
|
||||
header.msgFlags = 0;
|
||||
header.dataLen = 0;
|
||||
|
||||
s = Stream_New(NULL, header.dataLen + CLIPRDR_HEADER_LENGTH);
|
||||
|
||||
Stream_Write_UINT16(s, header.msgType); /* msgType (2 bytes) */
|
||||
Stream_Write_UINT16(s, header.msgFlags); /* msgFlags (2 bytes) */
|
||||
Stream_Write_UINT32(s, header.dataLen); /* dataLen (4 bytes) */
|
||||
|
||||
Stream_SealLength(s);
|
||||
|
||||
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL);
|
||||
|
||||
Stream_Free(s, TRUE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cliprdr_server_send_format_list_response(CliprdrServerContext* context)
|
||||
{
|
||||
wStream* s;
|
||||
BOOL status;
|
||||
CLIPRDR_HEADER header;
|
||||
|
||||
printf("CliprdrServerSendFormatListResponse\n");
|
||||
|
||||
header.msgType = CB_FORMAT_LIST_RESPONSE;
|
||||
header.msgFlags = CB_RESPONSE_OK;
|
||||
header.dataLen = 0;
|
||||
|
||||
s = Stream_New(NULL, header.dataLen + CLIPRDR_HEADER_LENGTH);
|
||||
|
||||
Stream_Write_UINT16(s, header.msgType); /* msgType (2 bytes) */
|
||||
Stream_Write_UINT16(s, header.msgFlags); /* msgFlags (2 bytes) */
|
||||
Stream_Write_UINT32(s, header.dataLen); /* dataLen (4 bytes) */
|
||||
|
||||
Stream_SealLength(s);
|
||||
|
||||
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL);
|
||||
|
||||
Stream_Free(s, TRUE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cliprdr_server_receive_capabilities(CliprdrServerContext* context, wStream* s, CLIPRDR_HEADER* header)
|
||||
{
|
||||
UINT32 version;
|
||||
UINT32 generalFlags;
|
||||
UINT16 cCapabilitiesSets;
|
||||
UINT16 capabilitySetType;
|
||||
UINT16 lengthCapability;
|
||||
|
||||
Stream_Read_UINT16(s, cCapabilitiesSets); /* cCapabilitiesSets (2 bytes) */
|
||||
Stream_Seek_UINT16(s); /* pad1 (2 bytes) */
|
||||
|
||||
Stream_Read_UINT16(s, capabilitySetType); /* capabilitySetType (2 bytes) */
|
||||
Stream_Read_UINT16(s, lengthCapability); /* lengthCapability (2 bytes) */
|
||||
|
||||
Stream_Read_UINT32(s, version); /* version (4 bytes) */
|
||||
Stream_Read_UINT32(s, generalFlags); /* generalFlags (4 bytes) */
|
||||
|
||||
if (generalFlags & CB_USE_LONG_FORMAT_NAMES)
|
||||
context->priv->UseLongFormatNames = TRUE;
|
||||
|
||||
if (generalFlags & CB_STREAM_FILECLIP_ENABLED)
|
||||
context->priv->StreamFileClipEnabled = TRUE;
|
||||
|
||||
if (generalFlags & CB_FILECLIP_NO_FILE_PATHS)
|
||||
context->priv->FileClipNoFilePaths = TRUE;
|
||||
|
||||
if (generalFlags & CB_CAN_LOCK_CLIPDATA)
|
||||
context->priv->CanLockClipData = TRUE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cliprdr_server_receive_temporary_directory(CliprdrServerContext* context, wStream* s, CLIPRDR_HEADER* header)
|
||||
{
|
||||
WCHAR* wszTempDir;
|
||||
|
||||
if (Stream_GetRemainingLength(s) < 520)
|
||||
return -1;
|
||||
|
||||
wszTempDir = (WCHAR*) Stream_Pointer(s);
|
||||
|
||||
if (wszTempDir[260] != 0)
|
||||
return -1;
|
||||
|
||||
ConvertFromUnicode(CP_UTF8, 0, wszTempDir, -1,
|
||||
&(context->priv->ClientTemporaryDirectory), 0, NULL, NULL);
|
||||
|
||||
printf("ClientTemporaryDirectory: %s\n", context->priv->ClientTemporaryDirectory);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cliprdr_wcslen(const WCHAR* str, const WCHAR* end)
|
||||
{
|
||||
WCHAR* p = (WCHAR*) str;
|
||||
|
||||
if (!p)
|
||||
return -1;
|
||||
|
||||
while (*p)
|
||||
{
|
||||
if (p == end)
|
||||
return -1;
|
||||
|
||||
p++;
|
||||
}
|
||||
|
||||
return (p - str);
|
||||
}
|
||||
|
||||
static void cliprdr_free_format_list(UINT32 count, CLIPRDR_FORMAT_NAME* formatNames)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (formatNames)
|
||||
{
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
free(formatNames[i].name);
|
||||
}
|
||||
|
||||
free(formatNames);
|
||||
}
|
||||
}
|
||||
|
||||
static int cliprdr_server_receive_long_format_list(CliprdrServerContext* context, wStream* s, CLIPRDR_HEADER* header)
|
||||
{
|
||||
int i;
|
||||
WCHAR* end;
|
||||
int length;
|
||||
int position;
|
||||
|
||||
printf("%s\n", __FUNCTION__);
|
||||
|
||||
position = Stream_GetPosition(s);
|
||||
Stream_SetPosition(s, Stream_Length(s));
|
||||
end = (WCHAR*) Stream_Pointer(s);
|
||||
Stream_SetPosition(s, position);
|
||||
|
||||
cliprdr_free_format_list(context->priv->ClientFormatNameCount, context->priv->ClientFormatNames);
|
||||
context->priv->ClientFormatNameCount = 0;
|
||||
context->priv->ClientFormatNames = NULL;
|
||||
|
||||
while (Stream_GetRemainingLength(s) >= 6)
|
||||
{
|
||||
Stream_Seek(s, 4); /* formatId (4 bytes) */
|
||||
|
||||
length = cliprdr_wcslen((WCHAR*) Stream_Pointer(s), end);
|
||||
|
||||
if (length < 0)
|
||||
return -1;
|
||||
|
||||
Stream_Seek(s, (length + 1) * 2); /* wszFormatName */
|
||||
|
||||
context->priv->ClientFormatNameCount++;
|
||||
}
|
||||
|
||||
context->priv->ClientFormatNames = (CLIPRDR_FORMAT_NAME*)
|
||||
malloc(sizeof(CLIPRDR_FORMAT_NAME) * context->priv->ClientFormatNameCount);
|
||||
|
||||
Stream_SetPosition(s, position);
|
||||
|
||||
for (i = 0; i < context->priv->ClientFormatNameCount; i++)
|
||||
{
|
||||
Stream_Read_UINT32(s, context->priv->ClientFormatNames[i].id); /* formatId (4 bytes) */
|
||||
|
||||
length = cliprdr_wcslen((WCHAR*) Stream_Pointer(s), end);
|
||||
|
||||
context->priv->ClientFormatNames[i].name = NULL;
|
||||
|
||||
if (length)
|
||||
{
|
||||
context->priv->ClientFormatNames[i].length = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s),
|
||||
-1, &(context->priv->ClientFormatNames[i].name), 0, NULL, NULL) - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
context->priv->ClientFormatNames[i].length = 0;
|
||||
}
|
||||
|
||||
Stream_Seek(s, (length + 1) * 2); /* wszFormatName */
|
||||
}
|
||||
|
||||
for (i = 0; i < context->priv->ClientFormatNameCount; i++)
|
||||
{
|
||||
printf("Format %d: Id: 0x%04X Name: %s Length: %d\n", i,
|
||||
context->priv->ClientFormatNames[i].id,
|
||||
context->priv->ClientFormatNames[i].name,
|
||||
context->priv->ClientFormatNames[i].length);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cliprdr_server_receive_short_format_list(CliprdrServerContext* context, wStream* s, CLIPRDR_HEADER* header)
|
||||
{
|
||||
printf("%s: unimplemented\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cliprdr_server_receive_format_list(CliprdrServerContext* context, wStream* s, CLIPRDR_HEADER* header)
|
||||
{
|
||||
int status;
|
||||
|
||||
if (context->priv->UseLongFormatNames)
|
||||
{
|
||||
status = cliprdr_server_receive_long_format_list(context, s, header);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = cliprdr_server_receive_short_format_list(context, s, header);
|
||||
}
|
||||
|
||||
cliprdr_server_send_format_list_response(context);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int cliprdr_server_receive_pdu(CliprdrServerContext* context, wStream* s, CLIPRDR_HEADER* header)
|
||||
{
|
||||
printf("CliprdrServerReceivePdu: msgType: %d msgFlags: 0x%08X dataLen: %d\n",
|
||||
header->msgType, header->msgFlags, header->dataLen);
|
||||
|
||||
switch (header->msgType)
|
||||
{
|
||||
case CB_CLIP_CAPS:
|
||||
cliprdr_server_receive_capabilities(context, s, header);
|
||||
break;
|
||||
|
||||
case CB_TEMP_DIRECTORY:
|
||||
cliprdr_server_receive_temporary_directory(context, s, header);
|
||||
break;
|
||||
|
||||
case CB_FORMAT_LIST:
|
||||
cliprdr_server_receive_format_list(context, s, header);
|
||||
break;
|
||||
|
||||
case CB_FORMAT_LIST_RESPONSE:
|
||||
break;
|
||||
|
||||
case CB_LOCK_CLIPDATA:
|
||||
break;
|
||||
|
||||
case CB_UNLOCK_CLIPDATA:
|
||||
break;
|
||||
|
||||
case CB_FORMAT_DATA_REQUEST:
|
||||
break;
|
||||
|
||||
case CB_FORMAT_DATA_RESPONSE:
|
||||
break;
|
||||
|
||||
case CB_FILECONTENTS_REQUEST:
|
||||
break;
|
||||
|
||||
case CB_FILECONTENTS_RESPONSE:
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Unexpected clipboard PDU type: %d\n", header->msgType);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void* cliprdr_server_thread(void* arg)
|
||||
{
|
||||
wStream* s;
|
||||
DWORD status;
|
||||
DWORD nCount;
|
||||
void* buffer;
|
||||
int position;
|
||||
HANDLE events[8];
|
||||
HANDLE ChannelEvent;
|
||||
DWORD BytesReturned;
|
||||
CLIPRDR_HEADER header;
|
||||
CliprdrServerContext* context;
|
||||
|
||||
context = (CliprdrServerContext*) arg;
|
||||
|
||||
buffer = NULL;
|
||||
BytesReturned = 0;
|
||||
ChannelEvent = NULL;
|
||||
|
||||
s = Stream_New(NULL, 4096);
|
||||
|
||||
if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE)
|
||||
{
|
||||
if (BytesReturned == sizeof(HANDLE))
|
||||
CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE));
|
||||
|
||||
WTSFreeMemory(buffer);
|
||||
}
|
||||
|
||||
nCount = 0;
|
||||
events[nCount++] = ChannelEvent;
|
||||
events[nCount++] = context->priv->StopEvent;
|
||||
|
||||
cliprdr_server_send_capabilities(context);
|
||||
cliprdr_server_send_monitor_ready(context);
|
||||
|
||||
while (1)
|
||||
{
|
||||
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
|
||||
|
||||
if (WaitForSingleObject(context->priv->StopEvent, 0) == WAIT_OBJECT_0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (WTSVirtualChannelRead(context->priv->ChannelHandle, 0,
|
||||
(PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned))
|
||||
{
|
||||
if (BytesReturned)
|
||||
Stream_Seek(s, BytesReturned);
|
||||
}
|
||||
else
|
||||
{
|
||||
Stream_EnsureRemainingCapacity(s, BytesReturned);
|
||||
}
|
||||
|
||||
if (Stream_GetPosition(s) >= CLIPRDR_HEADER_LENGTH)
|
||||
{
|
||||
position = Stream_GetPosition(s);
|
||||
Stream_SetPosition(s, 0);
|
||||
|
||||
Stream_Read_UINT16(s, header.msgType); /* msgType (2 bytes) */
|
||||
Stream_Read_UINT16(s, header.msgFlags); /* msgFlags (2 bytes) */
|
||||
Stream_Read_UINT32(s, header.dataLen); /* dataLen (4 bytes) */
|
||||
|
||||
Stream_SetPosition(s, position);
|
||||
|
||||
if (Stream_GetPosition(s) >= (header.dataLen + CLIPRDR_HEADER_LENGTH))
|
||||
{
|
||||
Stream_SealLength(s);
|
||||
Stream_SetPosition(s, CLIPRDR_HEADER_LENGTH);
|
||||
|
||||
cliprdr_server_receive_pdu(context, s, &header);
|
||||
Stream_SetPosition(s, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Stream_Free(s, TRUE);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int cliprdr_server_start(CliprdrServerContext* context)
|
||||
{
|
||||
context->priv->ChannelHandle = WTSVirtualChannelManagerOpenEx(context->vcm, "cliprdr", 0);
|
||||
|
||||
if (!context->priv->ChannelHandle)
|
||||
return -1;
|
||||
|
||||
context->priv->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
context->priv->Thread = CreateThread(NULL, 0,
|
||||
(LPTHREAD_START_ROUTINE) cliprdr_server_thread, (void*) context, 0, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cliprdr_server_stop(CliprdrServerContext* context)
|
||||
{
|
||||
SetEvent(context->priv->StopEvent);
|
||||
|
||||
WaitForSingleObject(context->priv->Thread, INFINITE);
|
||||
CloseHandle(context->priv->Thread);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CliprdrServerContext* cliprdr_server_context_new(WTSVirtualChannelManager* vcm)
|
||||
{
|
||||
CliprdrServerContext* context;
|
||||
|
||||
context = (CliprdrServerContext*) malloc(sizeof(CliprdrServerContext));
|
||||
|
||||
if (context)
|
||||
{
|
||||
ZeroMemory(context, sizeof(CliprdrServerContext));
|
||||
|
||||
context->vcm = vcm;
|
||||
|
||||
context->Start = cliprdr_server_start;
|
||||
context->Stop = cliprdr_server_stop;
|
||||
|
||||
context->priv = (CliprdrServerPrivate*) malloc(sizeof(CliprdrServerPrivate));
|
||||
|
||||
if (context->priv)
|
||||
{
|
||||
ZeroMemory(context->priv, sizeof(CliprdrServerPrivate));
|
||||
|
||||
context->priv->UseLongFormatNames = TRUE;
|
||||
context->priv->StreamFileClipEnabled = TRUE;
|
||||
context->priv->FileClipNoFilePaths = TRUE;
|
||||
context->priv->CanLockClipData = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
void cliprdr_server_context_free(CliprdrServerContext* context)
|
||||
{
|
||||
if (context)
|
||||
{
|
||||
if (context->priv)
|
||||
{
|
||||
free(context->priv);
|
||||
}
|
||||
|
||||
free(context);
|
||||
}
|
||||
}
|
56
channels/cliprdr/server/cliprdr_main.h
Normal file
56
channels/cliprdr/server/cliprdr_main.h
Normal file
@ -0,0 +1,56 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Clipboard Virtual Channel Extension
|
||||
*
|
||||
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.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_SERVER_CLIPRDR_MAIN_H
|
||||
#define FREERDP_CHANNEL_SERVER_CLIPRDR_MAIN_H
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/synch.h>
|
||||
#include <winpr/thread.h>
|
||||
|
||||
#include <freerdp/server/cliprdr.h>
|
||||
|
||||
#define CLIPRDR_HEADER_LENGTH 8
|
||||
|
||||
struct _CLIPRDR_HEADER
|
||||
{
|
||||
UINT16 msgType;
|
||||
UINT16 msgFlags;
|
||||
UINT32 dataLen;
|
||||
};
|
||||
typedef struct _CLIPRDR_HEADER CLIPRDR_HEADER;
|
||||
|
||||
struct _cliprdr_server_private
|
||||
{
|
||||
HANDLE Thread;
|
||||
HANDLE StopEvent;
|
||||
void* ChannelHandle;
|
||||
|
||||
BOOL UseLongFormatNames;
|
||||
BOOL StreamFileClipEnabled;
|
||||
BOOL FileClipNoFilePaths;
|
||||
BOOL CanLockClipData;
|
||||
|
||||
UINT32 ClientFormatNameCount;
|
||||
CLIPRDR_FORMAT_NAME* ClientFormatNames;
|
||||
|
||||
char* ClientTemporaryDirectory;
|
||||
};
|
||||
|
||||
#endif /* FREERDP_CHANNEL_SERVER_CLIPRDR_MAIN_H */
|
@ -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()
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
set(OPTION_DEFAULT OFF)
|
||||
set(OPTION_CLIENT_DEFAULT ON)
|
||||
set(OPTION_SERVER_DEFAULT OFF)
|
||||
set(OPTION_SERVER_DEFAULT ON)
|
||||
|
||||
define_channel_options(NAME "drdynvc" TYPE "static"
|
||||
DESCRIPTION "Dynamic Virtual Channel Extension"
|
||||
|
35
channels/drdynvc/server/CMakeLists.txt
Normal file
35
channels/drdynvc/server/CMakeLists.txt
Normal file
@ -0,0 +1,35 @@
|
||||
# FreeRDP: A Remote Desktop Protocol Implementation
|
||||
# FreeRDP cmake build script
|
||||
#
|
||||
# Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.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("drdynvc")
|
||||
|
||||
set(${MODULE_PREFIX}_SRCS
|
||||
drdynvc_main.c
|
||||
drdynvc_main.h)
|
||||
|
||||
add_channel_server_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntry")
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
|
||||
|
||||
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||
MODULE freerdp
|
||||
MODULES freerdp-utils)
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Server")
|
149
channels/drdynvc/server/drdynvc_main.c
Normal file
149
channels/drdynvc/server/drdynvc_main.c
Normal file
@ -0,0 +1,149 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Dynamic Virtual Channel Extension
|
||||
*
|
||||
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/stream.h>
|
||||
|
||||
#include "drdynvc_main.h"
|
||||
|
||||
static void* drdynvc_server_thread(void* arg)
|
||||
{
|
||||
wStream* s;
|
||||
DWORD status;
|
||||
DWORD nCount;
|
||||
void* buffer;
|
||||
HANDLE events[8];
|
||||
HANDLE ChannelEvent;
|
||||
DWORD BytesReturned;
|
||||
DrdynvcServerContext* context;
|
||||
|
||||
context = (DrdynvcServerContext*) arg;
|
||||
|
||||
buffer = NULL;
|
||||
BytesReturned = 0;
|
||||
ChannelEvent = NULL;
|
||||
|
||||
s = Stream_New(NULL, 4096);
|
||||
|
||||
if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE)
|
||||
{
|
||||
if (BytesReturned == sizeof(HANDLE))
|
||||
CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE));
|
||||
|
||||
WTSFreeMemory(buffer);
|
||||
}
|
||||
|
||||
nCount = 0;
|
||||
events[nCount++] = ChannelEvent;
|
||||
events[nCount++] = context->priv->StopEvent;
|
||||
|
||||
while (1)
|
||||
{
|
||||
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
|
||||
|
||||
if (WaitForSingleObject(context->priv->StopEvent, 0) == WAIT_OBJECT_0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (WTSVirtualChannelRead(context->priv->ChannelHandle, 0,
|
||||
(PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned))
|
||||
{
|
||||
if (BytesReturned)
|
||||
Stream_Seek(s, BytesReturned);
|
||||
}
|
||||
else
|
||||
{
|
||||
Stream_EnsureRemainingCapacity(s, BytesReturned);
|
||||
}
|
||||
}
|
||||
|
||||
Stream_Free(s, TRUE);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int drdynvc_server_start(DrdynvcServerContext* context)
|
||||
{
|
||||
context->priv->ChannelHandle = WTSVirtualChannelManagerOpenEx(context->vcm, "rdpdr", 0);
|
||||
|
||||
if (!context->priv->ChannelHandle)
|
||||
return -1;
|
||||
|
||||
context->priv->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
context->priv->Thread = CreateThread(NULL, 0,
|
||||
(LPTHREAD_START_ROUTINE) drdynvc_server_thread, (void*) context, 0, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int drdynvc_server_stop(DrdynvcServerContext* context)
|
||||
{
|
||||
SetEvent(context->priv->StopEvent);
|
||||
|
||||
WaitForSingleObject(context->priv->Thread, INFINITE);
|
||||
CloseHandle(context->priv->Thread);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DrdynvcServerContext* drdynvc_server_context_new(WTSVirtualChannelManager* vcm)
|
||||
{
|
||||
DrdynvcServerContext* context;
|
||||
|
||||
context = (DrdynvcServerContext*) malloc(sizeof(DrdynvcServerContext));
|
||||
|
||||
if (context)
|
||||
{
|
||||
ZeroMemory(context, sizeof(DrdynvcServerContext));
|
||||
|
||||
context->vcm = vcm;
|
||||
|
||||
context->Start = drdynvc_server_start;
|
||||
context->Stop = drdynvc_server_stop;
|
||||
|
||||
context->priv = (DrdynvcServerPrivate*) malloc(sizeof(DrdynvcServerPrivate));
|
||||
|
||||
if (context->priv)
|
||||
{
|
||||
ZeroMemory(context->priv, sizeof(DrdynvcServerPrivate));
|
||||
}
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
void drdynvc_server_context_free(DrdynvcServerContext* context)
|
||||
{
|
||||
if (context)
|
||||
{
|
||||
if (context->priv)
|
||||
{
|
||||
free(context->priv);
|
||||
}
|
||||
|
||||
free(context);
|
||||
}
|
||||
}
|
37
channels/drdynvc/server/drdynvc_main.h
Normal file
37
channels/drdynvc/server/drdynvc_main.h
Normal file
@ -0,0 +1,37 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Dynamic Virtual Channel Extension
|
||||
*
|
||||
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.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_SERVER_DRDYNVC_MAIN_H
|
||||
#define FREERDP_CHANNEL_SERVER_DRDYNVC_MAIN_H
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/synch.h>
|
||||
#include <winpr/thread.h>
|
||||
|
||||
#include <freerdp/settings.h>
|
||||
#include <freerdp/server/drdynvc.h>
|
||||
|
||||
struct _drdynvc_server_private
|
||||
{
|
||||
HANDLE Thread;
|
||||
HANDLE StopEvent;
|
||||
void* ChannelHandle;
|
||||
};
|
||||
|
||||
#endif /* FREERDP_CHANNEL_SERVER_DRDYNVC_MAIN_H */
|
@ -20,3 +20,7 @@ define_channel("rdpdr")
|
||||
if(WITH_CLIENT_CHANNELS)
|
||||
add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME})
|
||||
endif()
|
||||
|
||||
if(WITH_SERVER_CHANNELS)
|
||||
add_channel_server(${MODULE_PREFIX} ${CHANNEL_NAME})
|
||||
endif()
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
set(OPTION_DEFAULT OFF)
|
||||
set(OPTION_CLIENT_DEFAULT ON)
|
||||
set(OPTION_SERVER_DEFAULT OFF)
|
||||
set(OPTION_SERVER_DEFAULT ON)
|
||||
|
||||
define_channel_options(NAME "rdpdr" TYPE "static"
|
||||
DESCRIPTION "Device Redirection Virtual Channel Extension"
|
||||
|
@ -33,132 +33,132 @@
|
||||
#include "rdpdr_capabilities.h"
|
||||
|
||||
/* Output device redirection capability set header */
|
||||
static void rdpdr_write_capset_header(wStream* data_out, UINT16 capabilityType, UINT16 capabilityLength, UINT32 version)
|
||||
static void rdpdr_write_capset_header(wStream* s, UINT16 capabilityType, UINT16 capabilityLength, UINT32 version)
|
||||
{
|
||||
Stream_Write_UINT16(data_out, capabilityType);
|
||||
Stream_Write_UINT16(data_out, capabilityLength);
|
||||
Stream_Write_UINT32(data_out, version);
|
||||
Stream_Write_UINT16(s, capabilityType);
|
||||
Stream_Write_UINT16(s, capabilityLength);
|
||||
Stream_Write_UINT32(s, version);
|
||||
}
|
||||
|
||||
/* Output device direction general capability set */
|
||||
static void rdpdr_write_general_capset(rdpdrPlugin* rdpdr, wStream* data_out)
|
||||
static void rdpdr_write_general_capset(rdpdrPlugin* rdpdr, wStream* s)
|
||||
{
|
||||
rdpdr_write_capset_header(data_out, CAP_GENERAL_TYPE, 44, GENERAL_CAPABILITY_VERSION_02);
|
||||
rdpdr_write_capset_header(s, CAP_GENERAL_TYPE, 44, GENERAL_CAPABILITY_VERSION_02);
|
||||
|
||||
Stream_Write_UINT32(data_out, 0); /* osType, ignored on receipt */
|
||||
Stream_Write_UINT32(data_out, 0); /* osVersion, unused and must be set to zero */
|
||||
Stream_Write_UINT16(data_out, 1); /* protocolMajorVersion, must be set to 1 */
|
||||
Stream_Write_UINT16(data_out, RDPDR_MINOR_RDP_VERSION_5_2); /* protocolMinorVersion */
|
||||
Stream_Write_UINT32(data_out, 0x0000FFFF); /* ioCode1 */
|
||||
Stream_Write_UINT32(data_out, 0); /* ioCode2, must be set to zero, reserved for future use */
|
||||
Stream_Write_UINT32(data_out, RDPDR_DEVICE_REMOVE_PDUS | RDPDR_CLIENT_DISPLAY_NAME_PDU | RDPDR_USER_LOGGEDON_PDU); /* extendedPDU */
|
||||
Stream_Write_UINT32(data_out, ENABLE_ASYNCIO); /* extraFlags1 */
|
||||
Stream_Write_UINT32(data_out, 0); /* extraFlags2, must be set to zero, reserved for future use */
|
||||
Stream_Write_UINT32(data_out, 0); /* SpecialTypeDeviceCap, number of special devices to be redirected before logon */
|
||||
Stream_Write_UINT32(s, 0); /* osType, ignored on receipt */
|
||||
Stream_Write_UINT32(s, 0); /* osVersion, unused and must be set to zero */
|
||||
Stream_Write_UINT16(s, 1); /* protocolMajorVersion, must be set to 1 */
|
||||
Stream_Write_UINT16(s, RDPDR_MINOR_RDP_VERSION_5_2); /* protocolMinorVersion */
|
||||
Stream_Write_UINT32(s, 0x0000FFFF); /* ioCode1 */
|
||||
Stream_Write_UINT32(s, 0); /* ioCode2, must be set to zero, reserved for future use */
|
||||
Stream_Write_UINT32(s, RDPDR_DEVICE_REMOVE_PDUS | RDPDR_CLIENT_DISPLAY_NAME_PDU | RDPDR_USER_LOGGEDON_PDU); /* extendedPDU */
|
||||
Stream_Write_UINT32(s, ENABLE_ASYNCIO); /* extraFlags1 */
|
||||
Stream_Write_UINT32(s, 0); /* extraFlags2, must be set to zero, reserved for future use */
|
||||
Stream_Write_UINT32(s, 0); /* SpecialTypeDeviceCap, number of special devices to be redirected before logon */
|
||||
}
|
||||
|
||||
/* Process device direction general capability set */
|
||||
static void rdpdr_process_general_capset(rdpdrPlugin* rdpdr, wStream* data_in)
|
||||
static void rdpdr_process_general_capset(rdpdrPlugin* rdpdr, wStream* s)
|
||||
{
|
||||
UINT16 capabilityLength;
|
||||
|
||||
Stream_Read_UINT16(data_in, capabilityLength);
|
||||
Stream_Seek(data_in, capabilityLength - 4);
|
||||
Stream_Read_UINT16(s, capabilityLength);
|
||||
Stream_Seek(s, capabilityLength - 4);
|
||||
}
|
||||
|
||||
/* Output printer direction capability set */
|
||||
static void rdpdr_write_printer_capset(rdpdrPlugin* rdpdr, wStream* data_out)
|
||||
static void rdpdr_write_printer_capset(rdpdrPlugin* rdpdr, wStream* s)
|
||||
{
|
||||
rdpdr_write_capset_header(data_out, CAP_PRINTER_TYPE, 8, PRINT_CAPABILITY_VERSION_01);
|
||||
rdpdr_write_capset_header(s, CAP_PRINTER_TYPE, 8, PRINT_CAPABILITY_VERSION_01);
|
||||
}
|
||||
|
||||
/* Process printer direction capability set */
|
||||
static void rdpdr_process_printer_capset(rdpdrPlugin* rdpdr, wStream* data_in)
|
||||
static void rdpdr_process_printer_capset(rdpdrPlugin* rdpdr, wStream* s)
|
||||
{
|
||||
UINT16 capabilityLength;
|
||||
|
||||
Stream_Read_UINT16(data_in, capabilityLength);
|
||||
Stream_Seek(data_in, capabilityLength - 4);
|
||||
Stream_Read_UINT16(s, capabilityLength);
|
||||
Stream_Seek(s, capabilityLength - 4);
|
||||
}
|
||||
|
||||
/* Output port redirection capability set */
|
||||
static void rdpdr_write_port_capset(rdpdrPlugin* rdpdr, wStream* data_out)
|
||||
static void rdpdr_write_port_capset(rdpdrPlugin* rdpdr, wStream* s)
|
||||
{
|
||||
rdpdr_write_capset_header(data_out, CAP_PORT_TYPE, 8, PORT_CAPABILITY_VERSION_01);
|
||||
rdpdr_write_capset_header(s, CAP_PORT_TYPE, 8, PORT_CAPABILITY_VERSION_01);
|
||||
}
|
||||
|
||||
/* Process port redirection capability set */
|
||||
static void rdpdr_process_port_capset(rdpdrPlugin* rdpdr, wStream* data_in)
|
||||
static void rdpdr_process_port_capset(rdpdrPlugin* rdpdr, wStream* s)
|
||||
{
|
||||
UINT16 capabilityLength;
|
||||
|
||||
Stream_Read_UINT16(data_in, capabilityLength);
|
||||
Stream_Seek(data_in, capabilityLength - 4);
|
||||
Stream_Read_UINT16(s, capabilityLength);
|
||||
Stream_Seek(s, capabilityLength - 4);
|
||||
}
|
||||
|
||||
/* Output drive redirection capability set */
|
||||
static void rdpdr_write_drive_capset(rdpdrPlugin* rdpdr, wStream* data_out)
|
||||
static void rdpdr_write_drive_capset(rdpdrPlugin* rdpdr, wStream* s)
|
||||
{
|
||||
rdpdr_write_capset_header(data_out, CAP_DRIVE_TYPE, 8, DRIVE_CAPABILITY_VERSION_02);
|
||||
rdpdr_write_capset_header(s, CAP_DRIVE_TYPE, 8, DRIVE_CAPABILITY_VERSION_02);
|
||||
}
|
||||
|
||||
/* Process drive redirection capability set */
|
||||
static void rdpdr_process_drive_capset(rdpdrPlugin* rdpdr, wStream* data_in)
|
||||
static void rdpdr_process_drive_capset(rdpdrPlugin* rdpdr, wStream* s)
|
||||
{
|
||||
UINT16 capabilityLength;
|
||||
|
||||
Stream_Read_UINT16(data_in, capabilityLength);
|
||||
Stream_Seek(data_in, capabilityLength - 4);
|
||||
Stream_Read_UINT16(s, capabilityLength);
|
||||
Stream_Seek(s, capabilityLength - 4);
|
||||
}
|
||||
|
||||
/* Output smart card redirection capability set */
|
||||
static void rdpdr_write_smartcard_capset(rdpdrPlugin* rdpdr, wStream* data_out)
|
||||
static void rdpdr_write_smartcard_capset(rdpdrPlugin* rdpdr, wStream* s)
|
||||
{
|
||||
rdpdr_write_capset_header(data_out, CAP_SMARTCARD_TYPE, 8, SMARTCARD_CAPABILITY_VERSION_01);
|
||||
rdpdr_write_capset_header(s, CAP_SMARTCARD_TYPE, 8, SMARTCARD_CAPABILITY_VERSION_01);
|
||||
}
|
||||
|
||||
/* Process smartcard redirection capability set */
|
||||
static void rdpdr_process_smartcard_capset(rdpdrPlugin* rdpdr, wStream* data_in)
|
||||
static void rdpdr_process_smartcard_capset(rdpdrPlugin* rdpdr, wStream* s)
|
||||
{
|
||||
UINT16 capabilityLength;
|
||||
|
||||
Stream_Read_UINT16(data_in, capabilityLength);
|
||||
Stream_Seek(data_in, capabilityLength - 4);
|
||||
Stream_Read_UINT16(s, capabilityLength);
|
||||
Stream_Seek(s, capabilityLength - 4);
|
||||
}
|
||||
|
||||
void rdpdr_process_capability_request(rdpdrPlugin* rdpdr, wStream* data_in)
|
||||
void rdpdr_process_capability_request(rdpdrPlugin* rdpdr, wStream* s)
|
||||
{
|
||||
UINT16 i;
|
||||
UINT16 numCapabilities;
|
||||
UINT16 capabilityType;
|
||||
|
||||
Stream_Read_UINT16(data_in, numCapabilities);
|
||||
Stream_Seek(data_in, 2); /* pad (2 bytes) */
|
||||
Stream_Read_UINT16(s, numCapabilities);
|
||||
Stream_Seek(s, 2); /* pad (2 bytes) */
|
||||
|
||||
for(i = 0; i < numCapabilities; i++)
|
||||
for (i = 0; i < numCapabilities; i++)
|
||||
{
|
||||
Stream_Read_UINT16(data_in, capabilityType);
|
||||
Stream_Read_UINT16(s, capabilityType);
|
||||
|
||||
switch (capabilityType)
|
||||
{
|
||||
case CAP_GENERAL_TYPE:
|
||||
rdpdr_process_general_capset(rdpdr, data_in);
|
||||
rdpdr_process_general_capset(rdpdr, s);
|
||||
break;
|
||||
|
||||
case CAP_PRINTER_TYPE:
|
||||
rdpdr_process_printer_capset(rdpdr, data_in);
|
||||
rdpdr_process_printer_capset(rdpdr, s);
|
||||
break;
|
||||
|
||||
case CAP_PORT_TYPE:
|
||||
rdpdr_process_port_capset(rdpdr, data_in);
|
||||
rdpdr_process_port_capset(rdpdr, s);
|
||||
break;
|
||||
|
||||
case CAP_DRIVE_TYPE:
|
||||
rdpdr_process_drive_capset(rdpdr, data_in);
|
||||
rdpdr_process_drive_capset(rdpdr, s);
|
||||
break;
|
||||
|
||||
case CAP_SMARTCARD_TYPE:
|
||||
rdpdr_process_smartcard_capset(rdpdr, data_in);
|
||||
rdpdr_process_smartcard_capset(rdpdr, s);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -170,21 +170,21 @@ void rdpdr_process_capability_request(rdpdrPlugin* rdpdr, wStream* data_in)
|
||||
|
||||
void rdpdr_send_capability_response(rdpdrPlugin* rdpdr)
|
||||
{
|
||||
wStream* data_out;
|
||||
wStream* s;
|
||||
|
||||
data_out = Stream_New(NULL, 256);
|
||||
s = Stream_New(NULL, 256);
|
||||
|
||||
Stream_Write_UINT16(data_out, RDPDR_CTYP_CORE);
|
||||
Stream_Write_UINT16(data_out, PAKID_CORE_CLIENT_CAPABILITY);
|
||||
Stream_Write_UINT16(s, RDPDR_CTYP_CORE);
|
||||
Stream_Write_UINT16(s, PAKID_CORE_CLIENT_CAPABILITY);
|
||||
|
||||
Stream_Write_UINT16(data_out, 5); /* numCapabilities */
|
||||
Stream_Write_UINT16(data_out, 0); /* pad */
|
||||
Stream_Write_UINT16(s, 5); /* numCapabilities */
|
||||
Stream_Write_UINT16(s, 0); /* pad */
|
||||
|
||||
rdpdr_write_general_capset(rdpdr, data_out);
|
||||
rdpdr_write_printer_capset(rdpdr, data_out);
|
||||
rdpdr_write_port_capset(rdpdr, data_out);
|
||||
rdpdr_write_drive_capset(rdpdr, data_out);
|
||||
rdpdr_write_smartcard_capset(rdpdr, data_out);
|
||||
rdpdr_write_general_capset(rdpdr, s);
|
||||
rdpdr_write_printer_capset(rdpdr, s);
|
||||
rdpdr_write_port_capset(rdpdr, s);
|
||||
rdpdr_write_drive_capset(rdpdr, s);
|
||||
rdpdr_write_smartcard_capset(rdpdr, s);
|
||||
|
||||
svc_plugin_send((rdpSvcPlugin*)rdpdr, data_out);
|
||||
svc_plugin_send((rdpSvcPlugin*)rdpdr, s);
|
||||
}
|
||||
|
35
channels/rdpdr/server/CMakeLists.txt
Normal file
35
channels/rdpdr/server/CMakeLists.txt
Normal file
@ -0,0 +1,35 @@
|
||||
# FreeRDP: A Remote Desktop Protocol Implementation
|
||||
# FreeRDP cmake build script
|
||||
#
|
||||
# Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.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("rdpdr")
|
||||
|
||||
set(${MODULE_PREFIX}_SRCS
|
||||
rdpdr_main.c
|
||||
rdpdr_main.h)
|
||||
|
||||
add_channel_server_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntry")
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
|
||||
|
||||
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||
MODULE freerdp
|
||||
MODULES freerdp-utils)
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Server")
|
699
channels/rdpdr/server/rdpdr_main.c
Normal file
699
channels/rdpdr/server/rdpdr_main.c
Normal file
@ -0,0 +1,699 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Device Redirection Virtual Channel Extension
|
||||
*
|
||||
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/stream.h>
|
||||
|
||||
#include "rdpdr_main.h"
|
||||
|
||||
static UINT32 g_ClientId = 0;
|
||||
|
||||
static int rdpdr_server_send_announce_request(RdpdrServerContext* context)
|
||||
{
|
||||
wStream* s;
|
||||
BOOL status;
|
||||
RDPDR_HEADER header;
|
||||
|
||||
printf("RdpdrServerSendAnnounceRequest\n");
|
||||
|
||||
header.Component = RDPDR_CTYP_CORE;
|
||||
header.PacketId = PAKID_CORE_SERVER_ANNOUNCE;
|
||||
|
||||
s = Stream_New(NULL, RDPDR_HEADER_LENGTH + 8);
|
||||
|
||||
Stream_Write_UINT16(s, header.Component); /* Component (2 bytes) */
|
||||
Stream_Write_UINT16(s, header.PacketId); /* PacketId (2 bytes) */
|
||||
|
||||
Stream_Write_UINT16(s, context->priv->VersionMajor); /* VersionMajor (2 bytes) */
|
||||
Stream_Write_UINT16(s, context->priv->VersionMinor); /* VersionMinor (2 bytes) */
|
||||
Stream_Write_UINT32(s, context->priv->ClientId); /* ClientId (4 bytes) */
|
||||
|
||||
Stream_SealLength(s);
|
||||
|
||||
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL);
|
||||
|
||||
Stream_Free(s, TRUE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rdpdr_server_receive_announce_response(RdpdrServerContext* context, wStream* s, RDPDR_HEADER* header)
|
||||
{
|
||||
UINT32 ClientId;
|
||||
UINT16 VersionMajor;
|
||||
UINT16 VersionMinor;
|
||||
|
||||
Stream_Read_UINT16(s, VersionMajor); /* VersionMajor (2 bytes) */
|
||||
Stream_Read_UINT16(s, VersionMinor); /* VersionMinor (2 bytes) */
|
||||
Stream_Read_UINT32(s, ClientId); /* ClientId (4 bytes) */
|
||||
|
||||
printf("Client Announce Response: VersionMajor: 0x%04X VersionMinor: 0x%04X ClientId: 0x%04X\n",
|
||||
VersionMajor, VersionMinor, ClientId);
|
||||
|
||||
context->priv->ClientId = ClientId;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rdpdr_server_receive_client_name_request(RdpdrServerContext* context, wStream* s, RDPDR_HEADER* header)
|
||||
{
|
||||
UINT32 UnicodeFlag;
|
||||
UINT32 ComputerNameLen;
|
||||
|
||||
Stream_Read_UINT32(s, UnicodeFlag); /* UnicodeFlag (4 bytes) */
|
||||
Stream_Seek_UINT32(s); /* CodePage (4 bytes), MUST be set to zero */
|
||||
Stream_Read_UINT32(s, ComputerNameLen); /* ComputerNameLen (4 bytes) */
|
||||
|
||||
/**
|
||||
* Caution: ComputerNameLen is given *bytes*,
|
||||
* not in characters, including the NULL terminator!
|
||||
*/
|
||||
|
||||
if (context->priv->ClientComputerName)
|
||||
{
|
||||
free(context->priv->ClientComputerName);
|
||||
context->priv->ClientComputerName = NULL;
|
||||
}
|
||||
|
||||
if (UnicodeFlag)
|
||||
{
|
||||
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s),
|
||||
-1, &(context->priv->ClientComputerName), 0, NULL, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
context->priv->ClientComputerName = _strdup((char*) Stream_Pointer(s));
|
||||
}
|
||||
|
||||
Stream_Seek(s, ComputerNameLen);
|
||||
|
||||
printf("ClientComputerName: %s\n", context->priv->ClientComputerName);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rdpdr_server_read_capability_set_header(wStream* s, RDPDR_CAPABILITY_HEADER* header)
|
||||
{
|
||||
Stream_Read_UINT16(s, header->CapabilityType); /* CapabilityType (2 bytes) */
|
||||
Stream_Read_UINT16(s, header->CapabilityLength); /* CapabilityLength (2 bytes) */
|
||||
Stream_Read_UINT32(s, header->Version); /* Version (4 bytes) */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rdpdr_server_write_capability_set_header(wStream* s, RDPDR_CAPABILITY_HEADER* header)
|
||||
{
|
||||
Stream_Write_UINT16(s, header->CapabilityType); /* CapabilityType (2 bytes) */
|
||||
Stream_Write_UINT16(s, header->CapabilityLength); /* CapabilityLength (2 bytes) */
|
||||
Stream_Write_UINT32(s, header->Version); /* Version (4 bytes) */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rdpdr_server_read_general_capability_set(RdpdrServerContext* context, wStream* s, RDPDR_CAPABILITY_HEADER* header)
|
||||
{
|
||||
UINT32 ioCode1;
|
||||
UINT32 extraFlags1;
|
||||
UINT32 extendedPdu;
|
||||
UINT16 VersionMajor;
|
||||
UINT16 VersionMinor;
|
||||
UINT32 SpecialTypeDeviceCap;
|
||||
|
||||
Stream_Seek_UINT32(s); /* osType (4 bytes), ignored on receipt */
|
||||
Stream_Seek_UINT32(s); /* osVersion (4 bytes), unused and must be set to zero */
|
||||
Stream_Read_UINT16(s, VersionMajor); /* protocolMajorVersion (2 bytes) */
|
||||
Stream_Read_UINT16(s, VersionMinor); /* protocolMinorVersion (2 bytes) */
|
||||
Stream_Read_UINT32(s, ioCode1); /* ioCode1 (4 bytes) */
|
||||
Stream_Seek_UINT32(s); /* ioCode2 (4 bytes), must be set to zero, reserved for future use */
|
||||
Stream_Read_UINT32(s, extendedPdu); /* extendedPdu (4 bytes) */
|
||||
Stream_Read_UINT32(s, extraFlags1); /* extraFlags1 (4 bytes) */
|
||||
Stream_Seek_UINT32(s); /* extraFlags2 (4 bytes), must be set to zero, reserved for future use */
|
||||
Stream_Read_UINT32(s, SpecialTypeDeviceCap); /* SpecialTypeDeviceCap (4 bytes) */
|
||||
|
||||
context->priv->UserLoggedOnPdu = (extendedPdu & RDPDR_USER_LOGGEDON_PDU) ? TRUE : FALSE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rdpdr_server_write_general_capability_set(RdpdrServerContext* context, wStream* s)
|
||||
{
|
||||
UINT32 ioCode1;
|
||||
UINT32 extendedPdu;
|
||||
UINT32 extraFlags1;
|
||||
UINT32 SpecialTypeDeviceCap;
|
||||
RDPDR_CAPABILITY_HEADER header;
|
||||
|
||||
header.CapabilityType = CAP_GENERAL_TYPE;
|
||||
header.CapabilityLength = RDPDR_CAPABILITY_HEADER_LENGTH + 36;
|
||||
header.Version = GENERAL_CAPABILITY_VERSION_02;
|
||||
|
||||
ioCode1 = 0;
|
||||
ioCode1 |= RDPDR_IRP_MJ_CREATE; /* always set */
|
||||
ioCode1 |= RDPDR_IRP_MJ_CLEANUP; /* always set */
|
||||
ioCode1 |= RDPDR_IRP_MJ_CLOSE; /* always set */
|
||||
ioCode1 |= RDPDR_IRP_MJ_READ; /* always set */
|
||||
ioCode1 |= RDPDR_IRP_MJ_WRITE; /* always set */
|
||||
ioCode1 |= RDPDR_IRP_MJ_FLUSH_BUFFERS; /* always set */
|
||||
ioCode1 |= RDPDR_IRP_MJ_SHUTDOWN; /* always set */
|
||||
ioCode1 |= RDPDR_IRP_MJ_DEVICE_CONTROL; /* always set */
|
||||
ioCode1 |= RDPDR_IRP_MJ_QUERY_VOLUME_INFORMATION; /* always set */
|
||||
ioCode1 |= RDPDR_IRP_MJ_SET_VOLUME_INFORMATION; /* always set */
|
||||
ioCode1 |= RDPDR_IRP_MJ_QUERY_INFORMATION; /* always set */
|
||||
ioCode1 |= RDPDR_IRP_MJ_SET_INFORMATION; /* always set */
|
||||
ioCode1 |= RDPDR_IRP_MJ_DIRECTORY_CONTROL; /* always set */
|
||||
ioCode1 |= RDPDR_IRP_MJ_LOCK_CONTROL; /* always set */
|
||||
ioCode1 |= RDPDR_IRP_MJ_QUERY_SECURITY; /* optional */
|
||||
ioCode1 |= RDPDR_IRP_MJ_SET_SECURITY; /* optional */
|
||||
|
||||
extendedPdu = 0;
|
||||
extendedPdu |= RDPDR_CLIENT_DISPLAY_NAME_PDU; /* always set */
|
||||
extendedPdu |= RDPDR_DEVICE_REMOVE_PDUS; /* optional */
|
||||
|
||||
if (context->priv->UserLoggedOnPdu)
|
||||
extendedPdu |= RDPDR_USER_LOGGEDON_PDU; /* optional */
|
||||
|
||||
extraFlags1 = 0;
|
||||
extraFlags1 |= ENABLE_ASYNCIO; /* optional */
|
||||
|
||||
SpecialTypeDeviceCap = 0;
|
||||
|
||||
Stream_EnsureRemainingCapacity(s, header.CapabilityLength);
|
||||
rdpdr_server_write_capability_set_header(s, &header);
|
||||
|
||||
Stream_Write_UINT32(s, 0); /* osType (4 bytes), ignored on receipt */
|
||||
Stream_Write_UINT32(s, 0); /* osVersion (4 bytes), unused and must be set to zero */
|
||||
Stream_Write_UINT16(s, context->priv->VersionMajor); /* protocolMajorVersion (2 bytes) */
|
||||
Stream_Write_UINT16(s, context->priv->VersionMinor); /* protocolMinorVersion (2 bytes) */
|
||||
Stream_Write_UINT32(s, ioCode1); /* ioCode1 (4 bytes) */
|
||||
Stream_Write_UINT32(s, 0); /* ioCode2 (4 bytes), must be set to zero, reserved for future use */
|
||||
Stream_Write_UINT32(s, extendedPdu); /* extendedPdu (4 bytes) */
|
||||
Stream_Write_UINT32(s, extraFlags1); /* extraFlags1 (4 bytes) */
|
||||
Stream_Write_UINT32(s, 0); /* extraFlags2 (4 bytes), must be set to zero, reserved for future use */
|
||||
Stream_Write_UINT32(s, SpecialTypeDeviceCap); /* SpecialTypeDeviceCap (4 bytes) */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rdpdr_server_read_printer_capability_set(RdpdrServerContext* context, wStream* s, RDPDR_CAPABILITY_HEADER* header)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rdpdr_server_write_printer_capability_set(RdpdrServerContext* context, wStream* s)
|
||||
{
|
||||
RDPDR_CAPABILITY_HEADER header;
|
||||
|
||||
header.CapabilityType = CAP_PRINTER_TYPE;
|
||||
header.CapabilityLength = RDPDR_CAPABILITY_HEADER_LENGTH;
|
||||
header.Version = PRINT_CAPABILITY_VERSION_01;
|
||||
|
||||
Stream_EnsureRemainingCapacity(s, header.CapabilityLength);
|
||||
rdpdr_server_write_capability_set_header(s, &header);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rdpdr_server_read_port_capability_set(RdpdrServerContext* context, wStream* s, RDPDR_CAPABILITY_HEADER* header)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rdpdr_server_write_port_capability_set(RdpdrServerContext* context, wStream* s)
|
||||
{
|
||||
RDPDR_CAPABILITY_HEADER header;
|
||||
|
||||
header.CapabilityType = CAP_PORT_TYPE;
|
||||
header.CapabilityLength = RDPDR_CAPABILITY_HEADER_LENGTH;
|
||||
header.Version = PORT_CAPABILITY_VERSION_01;
|
||||
|
||||
Stream_EnsureRemainingCapacity(s, header.CapabilityLength);
|
||||
rdpdr_server_write_capability_set_header(s, &header);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rdpdr_server_read_drive_capability_set(RdpdrServerContext* context, wStream* s, RDPDR_CAPABILITY_HEADER* header)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rdpdr_server_write_drive_capability_set(RdpdrServerContext* context, wStream* s)
|
||||
{
|
||||
RDPDR_CAPABILITY_HEADER header;
|
||||
|
||||
header.CapabilityType = CAP_DRIVE_TYPE;
|
||||
header.CapabilityLength = RDPDR_CAPABILITY_HEADER_LENGTH;
|
||||
header.Version = DRIVE_CAPABILITY_VERSION_02;
|
||||
|
||||
Stream_EnsureRemainingCapacity(s, header.CapabilityLength);
|
||||
rdpdr_server_write_capability_set_header(s, &header);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rdpdr_server_read_smartcard_capability_set(RdpdrServerContext* context, wStream* s, RDPDR_CAPABILITY_HEADER* header)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rdpdr_server_write_smartcard_capability_set(RdpdrServerContext* context, wStream* s)
|
||||
{
|
||||
RDPDR_CAPABILITY_HEADER header;
|
||||
|
||||
header.CapabilityType = CAP_SMARTCARD_TYPE;
|
||||
header.CapabilityLength = RDPDR_CAPABILITY_HEADER_LENGTH;
|
||||
header.Version = SMARTCARD_CAPABILITY_VERSION_01;
|
||||
|
||||
Stream_EnsureRemainingCapacity(s, header.CapabilityLength);
|
||||
rdpdr_server_write_capability_set_header(s, &header);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rdpdr_server_send_core_capability_request(RdpdrServerContext* context)
|
||||
{
|
||||
wStream* s;
|
||||
BOOL status;
|
||||
RDPDR_HEADER header;
|
||||
UINT16 numCapabilities;
|
||||
|
||||
printf("RdpdrServerSendCoreCapabilityRequest\n");
|
||||
|
||||
header.Component = RDPDR_CTYP_CORE;
|
||||
header.PacketId = PAKID_CORE_SERVER_CAPABILITY;
|
||||
|
||||
numCapabilities = 5;
|
||||
|
||||
s = Stream_New(NULL, RDPDR_HEADER_LENGTH + 512);
|
||||
|
||||
Stream_Write_UINT16(s, header.Component); /* Component (2 bytes) */
|
||||
Stream_Write_UINT16(s, header.PacketId); /* PacketId (2 bytes) */
|
||||
|
||||
Stream_Write_UINT16(s, numCapabilities); /* numCapabilities (2 bytes) */
|
||||
Stream_Write_UINT16(s, 0); /* Padding (2 bytes) */
|
||||
|
||||
rdpdr_server_write_general_capability_set(context, s);
|
||||
rdpdr_server_write_printer_capability_set(context, s);
|
||||
rdpdr_server_write_port_capability_set(context, s);
|
||||
rdpdr_server_write_drive_capability_set(context, s);
|
||||
rdpdr_server_write_smartcard_capability_set(context, s);
|
||||
|
||||
Stream_SealLength(s);
|
||||
|
||||
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL);
|
||||
|
||||
Stream_Free(s, TRUE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rdpdr_server_receive_core_capability_response(RdpdrServerContext* context, wStream* s, RDPDR_HEADER* header)
|
||||
{
|
||||
int i;
|
||||
UINT16 numCapabilities;
|
||||
RDPDR_CAPABILITY_HEADER capabilityHeader;
|
||||
|
||||
Stream_Read_UINT16(s, numCapabilities); /* numCapabilities (2 bytes) */
|
||||
Stream_Seek_UINT16(s); /* Padding (2 bytes) */
|
||||
|
||||
for (i = 0; i < numCapabilities; i++)
|
||||
{
|
||||
rdpdr_server_read_capability_set_header(s, &capabilityHeader);
|
||||
|
||||
switch (capabilityHeader.CapabilityType)
|
||||
{
|
||||
case CAP_GENERAL_TYPE:
|
||||
rdpdr_server_read_general_capability_set(context, s, &capabilityHeader);
|
||||
break;
|
||||
|
||||
case CAP_PRINTER_TYPE:
|
||||
rdpdr_server_read_printer_capability_set(context, s, &capabilityHeader);
|
||||
break;
|
||||
|
||||
case CAP_PORT_TYPE:
|
||||
rdpdr_server_read_port_capability_set(context, s, &capabilityHeader);
|
||||
break;
|
||||
|
||||
case CAP_DRIVE_TYPE:
|
||||
rdpdr_server_read_drive_capability_set(context, s, &capabilityHeader);
|
||||
break;
|
||||
|
||||
case CAP_SMARTCARD_TYPE:
|
||||
rdpdr_server_read_smartcard_capability_set(context, s, &capabilityHeader);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Unknown capabilityType %d\n", capabilityHeader.CapabilityType);
|
||||
Stream_Seek(s, capabilityHeader.CapabilityLength - RDPDR_CAPABILITY_HEADER_LENGTH);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rdpdr_server_send_client_id_confirm(RdpdrServerContext* context)
|
||||
{
|
||||
wStream* s;
|
||||
BOOL status;
|
||||
RDPDR_HEADER header;
|
||||
|
||||
printf("RdpdrServerSendClientIdConfirm\n");
|
||||
|
||||
header.Component = RDPDR_CTYP_CORE;
|
||||
header.PacketId = PAKID_CORE_CLIENTID_CONFIRM;
|
||||
|
||||
s = Stream_New(NULL, RDPDR_HEADER_LENGTH + 8);
|
||||
|
||||
Stream_Write_UINT16(s, header.Component); /* Component (2 bytes) */
|
||||
Stream_Write_UINT16(s, header.PacketId); /* PacketId (2 bytes) */
|
||||
|
||||
Stream_Write_UINT16(s, context->priv->VersionMajor); /* VersionMajor (2 bytes) */
|
||||
Stream_Write_UINT16(s, context->priv->VersionMinor); /* VersionMinor (2 bytes) */
|
||||
Stream_Write_UINT32(s, context->priv->ClientId); /* ClientId (4 bytes) */
|
||||
|
||||
Stream_SealLength(s);
|
||||
|
||||
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL);
|
||||
|
||||
Stream_Free(s, TRUE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rdpdr_server_receive_device_list_announce_request(RdpdrServerContext* context, wStream* s, RDPDR_HEADER* header)
|
||||
{
|
||||
int i;
|
||||
UINT32 DeviceCount;
|
||||
UINT32 DeviceType;
|
||||
UINT32 DeviceId;
|
||||
char PreferredDosName[9];
|
||||
UINT32 DeviceDataLength;
|
||||
|
||||
PreferredDosName[8] = 0;
|
||||
|
||||
Stream_Read_UINT32(s, DeviceCount); /* DeviceCount (4 bytes) */
|
||||
|
||||
printf("%s: DeviceCount: %d\n", __FUNCTION__, DeviceCount);
|
||||
|
||||
for (i = 0; i < DeviceCount; i++)
|
||||
{
|
||||
Stream_Read_UINT32(s, DeviceType); /* DeviceType (4 bytes) */
|
||||
Stream_Read_UINT32(s, DeviceId); /* DeviceId (4 bytes) */
|
||||
Stream_Read(s, PreferredDosName, 8); /* PreferredDosName (8 bytes) */
|
||||
Stream_Read_UINT32(s, DeviceDataLength); /* DeviceDataLength (4 bytes) */
|
||||
|
||||
printf("Device %d Name: %s Id: 0x%04X DataLength: %d\n",
|
||||
i, PreferredDosName, DeviceId, DeviceDataLength);
|
||||
|
||||
switch (DeviceId)
|
||||
{
|
||||
case RDPDR_DTYP_FILESYSTEM:
|
||||
break;
|
||||
|
||||
case RDPDR_DTYP_PRINT:
|
||||
break;
|
||||
|
||||
case RDPDR_DTYP_SERIAL:
|
||||
break;
|
||||
|
||||
case RDPDR_DTYP_PARALLEL:
|
||||
break;
|
||||
|
||||
case RDPDR_DTYP_SMARTCARD:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Stream_Seek(s, DeviceDataLength);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rdpdr_server_send_user_logged_on(RdpdrServerContext* context)
|
||||
{
|
||||
wStream* s;
|
||||
BOOL status;
|
||||
RDPDR_HEADER header;
|
||||
|
||||
printf("%s\n", __FUNCTION__);
|
||||
|
||||
header.Component = RDPDR_CTYP_CORE;
|
||||
header.PacketId = PAKID_CORE_USER_LOGGEDON;
|
||||
|
||||
s = Stream_New(NULL, RDPDR_HEADER_LENGTH);
|
||||
|
||||
Stream_Write_UINT16(s, header.Component); /* Component (2 bytes) */
|
||||
Stream_Write_UINT16(s, header.PacketId); /* PacketId (2 bytes) */
|
||||
|
||||
Stream_SealLength(s);
|
||||
|
||||
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL);
|
||||
|
||||
Stream_Free(s, TRUE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rdpdr_server_receive_pdu(RdpdrServerContext* context, wStream* s, RDPDR_HEADER* header)
|
||||
{
|
||||
printf("RdpdrServerReceivePdu: Component: 0x%04X PacketId: 0x%04X\n",
|
||||
header->Component, header->PacketId);
|
||||
|
||||
winpr_HexDump(Stream_Buffer(s), Stream_Length(s));
|
||||
|
||||
if (header->Component == RDPDR_CTYP_CORE)
|
||||
{
|
||||
switch (header->PacketId)
|
||||
{
|
||||
case PAKID_CORE_CLIENTID_CONFIRM:
|
||||
rdpdr_server_receive_announce_response(context, s, header);
|
||||
break;
|
||||
|
||||
case PAKID_CORE_CLIENT_NAME:
|
||||
rdpdr_server_receive_client_name_request(context, s, header);
|
||||
rdpdr_server_send_core_capability_request(context);
|
||||
break;
|
||||
|
||||
case PAKID_CORE_CLIENT_CAPABILITY:
|
||||
rdpdr_server_receive_core_capability_response(context, s, header);
|
||||
rdpdr_server_send_client_id_confirm(context);
|
||||
|
||||
if (context->priv->UserLoggedOnPdu)
|
||||
rdpdr_server_send_user_logged_on(context);
|
||||
break;
|
||||
|
||||
case PAKID_CORE_DEVICELIST_ANNOUNCE:
|
||||
rdpdr_server_receive_device_list_announce_request(context, s, header);
|
||||
break;
|
||||
|
||||
case PAKID_CORE_DEVICE_REPLY:
|
||||
break;
|
||||
|
||||
case PAKID_CORE_DEVICE_IOREQUEST:
|
||||
break;
|
||||
|
||||
case PAKID_CORE_DEVICE_IOCOMPLETION:
|
||||
break;
|
||||
|
||||
case PAKID_CORE_DEVICELIST_REMOVE:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (header->Component == RDPDR_CTYP_PRN)
|
||||
{
|
||||
switch (header->PacketId)
|
||||
{
|
||||
case PAKID_PRN_CACHE_DATA:
|
||||
break;
|
||||
|
||||
case PAKID_PRN_USING_XPS:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Unknown RDPDR_HEADER.Component: 0x%04X\n", header->Component);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void* rdpdr_server_thread(void* arg)
|
||||
{
|
||||
wStream* s;
|
||||
DWORD status;
|
||||
DWORD nCount;
|
||||
void* buffer;
|
||||
int position;
|
||||
HANDLE events[8];
|
||||
RDPDR_HEADER header;
|
||||
HANDLE ChannelEvent;
|
||||
DWORD BytesReturned;
|
||||
RdpdrServerContext* context;
|
||||
|
||||
context = (RdpdrServerContext*) arg;
|
||||
|
||||
buffer = NULL;
|
||||
BytesReturned = 0;
|
||||
ChannelEvent = NULL;
|
||||
|
||||
s = Stream_New(NULL, 4096);
|
||||
|
||||
if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE)
|
||||
{
|
||||
if (BytesReturned == sizeof(HANDLE))
|
||||
CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE));
|
||||
|
||||
WTSFreeMemory(buffer);
|
||||
}
|
||||
|
||||
nCount = 0;
|
||||
events[nCount++] = ChannelEvent;
|
||||
events[nCount++] = context->priv->StopEvent;
|
||||
|
||||
rdpdr_server_send_announce_request(context);
|
||||
|
||||
while (1)
|
||||
{
|
||||
BytesReturned = 0;
|
||||
|
||||
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
|
||||
|
||||
if (WaitForSingleObject(context->priv->StopEvent, 0) == WAIT_OBJECT_0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (WTSVirtualChannelRead(context->priv->ChannelHandle, 0, (PCHAR) Stream_Pointer(s),
|
||||
Stream_Capacity(s) - Stream_GetPosition(s), &BytesReturned))
|
||||
{
|
||||
if (BytesReturned)
|
||||
Stream_Seek(s, BytesReturned);
|
||||
}
|
||||
else
|
||||
{
|
||||
Stream_EnsureRemainingCapacity(s, BytesReturned);
|
||||
}
|
||||
|
||||
if (Stream_GetPosition(s) >= RDPDR_HEADER_LENGTH)
|
||||
{
|
||||
position = Stream_GetPosition(s);
|
||||
Stream_SetPosition(s, 0);
|
||||
|
||||
Stream_Read_UINT16(s, header.Component); /* Component (2 bytes) */
|
||||
Stream_Read_UINT16(s, header.PacketId); /* PacketId (2 bytes) */
|
||||
|
||||
Stream_SetPosition(s, position);
|
||||
|
||||
Stream_SealLength(s);
|
||||
Stream_SetPosition(s, RDPDR_HEADER_LENGTH);
|
||||
|
||||
rdpdr_server_receive_pdu(context, s, &header);
|
||||
Stream_SetPosition(s, 0);
|
||||
}
|
||||
}
|
||||
|
||||
Stream_Free(s, TRUE);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int rdpdr_server_start(RdpdrServerContext* context)
|
||||
{
|
||||
context->priv->ChannelHandle = WTSVirtualChannelManagerOpenEx(context->vcm, "rdpdr", 0);
|
||||
|
||||
if (!context->priv->ChannelHandle)
|
||||
return -1;
|
||||
|
||||
context->priv->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
context->priv->Thread = CreateThread(NULL, 0,
|
||||
(LPTHREAD_START_ROUTINE) rdpdr_server_thread, (void*) context, 0, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rdpdr_server_stop(RdpdrServerContext* context)
|
||||
{
|
||||
SetEvent(context->priv->StopEvent);
|
||||
|
||||
WaitForSingleObject(context->priv->Thread, INFINITE);
|
||||
CloseHandle(context->priv->Thread);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
RdpdrServerContext* rdpdr_server_context_new(WTSVirtualChannelManager* vcm)
|
||||
{
|
||||
RdpdrServerContext* context;
|
||||
|
||||
context = (RdpdrServerContext*) malloc(sizeof(RdpdrServerContext));
|
||||
|
||||
if (context)
|
||||
{
|
||||
ZeroMemory(context, sizeof(RdpdrServerContext));
|
||||
|
||||
context->vcm = vcm;
|
||||
|
||||
context->Start = rdpdr_server_start;
|
||||
context->Stop = rdpdr_server_stop;
|
||||
|
||||
context->priv = (RdpdrServerPrivate*) malloc(sizeof(RdpdrServerPrivate));
|
||||
|
||||
if (context->priv)
|
||||
{
|
||||
ZeroMemory(context->priv, sizeof(RdpdrServerPrivate));
|
||||
|
||||
context->priv->VersionMajor = RDPDR_VERSION_MAJOR;
|
||||
context->priv->VersionMinor = RDPDR_VERSION_MINOR_RDP6X;
|
||||
context->priv->ClientId = g_ClientId++;
|
||||
|
||||
context->priv->UserLoggedOnPdu = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
void rdpdr_server_context_free(RdpdrServerContext* context)
|
||||
{
|
||||
if (context)
|
||||
{
|
||||
if (context->priv)
|
||||
{
|
||||
free(context->priv);
|
||||
}
|
||||
|
||||
free(context);
|
||||
}
|
||||
}
|
70
channels/rdpdr/server/rdpdr_main.h
Normal file
70
channels/rdpdr/server/rdpdr_main.h
Normal file
@ -0,0 +1,70 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Device Redirection Virtual Channel Extension
|
||||
*
|
||||
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.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_SERVER_RDPDR_MAIN_H
|
||||
#define FREERDP_CHANNEL_SERVER_RDPDR_MAIN_H
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/synch.h>
|
||||
#include <winpr/thread.h>
|
||||
|
||||
#include <freerdp/settings.h>
|
||||
#include <freerdp/server/rdpdr.h>
|
||||
|
||||
struct _rdpdr_server_private
|
||||
{
|
||||
HANDLE Thread;
|
||||
HANDLE StopEvent;
|
||||
void* ChannelHandle;
|
||||
|
||||
UINT32 ClientId;
|
||||
UINT16 VersionMajor;
|
||||
UINT16 VersionMinor;
|
||||
char* ClientComputerName;
|
||||
|
||||
BOOL UserLoggedOnPdu;
|
||||
};
|
||||
|
||||
#define RDPDR_HEADER_LENGTH 4
|
||||
|
||||
struct _RDPDR_HEADER
|
||||
{
|
||||
UINT16 Component;
|
||||
UINT16 PacketId;
|
||||
};
|
||||
typedef struct _RDPDR_HEADER RDPDR_HEADER;
|
||||
|
||||
#define RDPDR_VERSION_MAJOR 0x0001
|
||||
|
||||
#define RDPDR_VERSION_MINOR_RDP50 0x0002
|
||||
#define RDPDR_VERSION_MINOR_RDP51 0x0005
|
||||
#define RDPDR_VERSION_MINOR_RDP52 0x000A
|
||||
#define RDPDR_VERSION_MINOR_RDP6X 0x000C
|
||||
|
||||
#define RDPDR_CAPABILITY_HEADER_LENGTH 8
|
||||
|
||||
struct _RDPDR_CAPABILITY_HEADER
|
||||
{
|
||||
UINT16 CapabilityType;
|
||||
UINT16 CapabilityLength;
|
||||
UINT32 Version;
|
||||
};
|
||||
typedef struct _RDPDR_CAPABILITY_HEADER RDPDR_CAPABILITY_HEADER;
|
||||
|
||||
#endif /* FREERDP_CHANNEL_SERVER_RDPDR_MAIN_H */
|
@ -28,7 +28,7 @@ set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
|
||||
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||
MODULE freerdp
|
||||
MODULES freerdp-utils)
|
||||
MODULES freerdp-codec freerdp-utils)
|
||||
|
||||
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||
@ -43,6 +43,10 @@ if(WITH_ALSA)
|
||||
add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "alsa" "")
|
||||
endif()
|
||||
|
||||
if(WITH_IOSAUDIO)
|
||||
add_channel_client_subsystem($(MODULE_PREFIX) $(CHANNEL_NAME) "ios" "")
|
||||
endif()
|
||||
|
||||
if(WITH_PULSE)
|
||||
add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "pulse" "")
|
||||
endif()
|
||||
|
@ -30,7 +30,7 @@ set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
|
||||
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||
MODULE freerdp
|
||||
MODULES freerdp-utils)
|
||||
MODULES freerdp-codec freerdp-utils)
|
||||
|
||||
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||
|
52
channels/rdpsnd/client/ios/CMakeLists.txt
Normal file
52
channels/rdpsnd/client/ios/CMakeLists.txt
Normal file
@ -0,0 +1,52 @@
|
||||
# FreeRDP: A Remote Desktop Protocol Implementation
|
||||
# FreeRDP cmake build script
|
||||
#
|
||||
# Copyright 2012 Laxmikant Rashinkar <LK.Rashinkar@gmail.com>
|
||||
# Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
# Copyright 2013 Corey Clayton <can.of.tuna@gmail.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
define_channel_client_subsystem("rdpsnd" "ios" "")
|
||||
|
||||
FIND_LIBRARY(CORE_AUDIO CoreAudio)
|
||||
FIND_LIBRARY(AUDIO_TOOL AudioToolbox)
|
||||
FIND_LIBRARY(CORE_FOUNDATION CoreFoundation)
|
||||
|
||||
set(${MODULE_PREFIX}_SRCS
|
||||
rdpsnd_ios.c
|
||||
TPCircularBuffer.c)
|
||||
|
||||
include_directories(..)
|
||||
|
||||
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
|
||||
|
||||
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||
MODULE freerdp
|
||||
MODULES freerdp-utils)
|
||||
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS}
|
||||
${AUDIO_TOOL}
|
||||
${CORE_AUDIO}
|
||||
${CORE_FOUNDATION})
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
if(NOT STATIC_CHANNELS)
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH})
|
||||
endif()
|
||||
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client/ios")
|
136
channels/rdpsnd/client/ios/TPCircularBuffer.c
Normal file
136
channels/rdpsnd/client/ios/TPCircularBuffer.c
Normal file
@ -0,0 +1,136 @@
|
||||
//
|
||||
// TPCircularBuffer.c
|
||||
// Circular/Ring buffer implementation
|
||||
//
|
||||
// https://github.com/michaeltyson/TPCircularBuffer
|
||||
//
|
||||
// Created by Michael Tyson on 10/12/2011.
|
||||
//
|
||||
// Copyright (C) 2012-2013 A Tasty Pixel
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
|
||||
#include "TPCircularBuffer.h"
|
||||
#include <mach/mach.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define reportResult(result,operation) (_reportResult((result),(operation),strrchr(__FILE__, '/')+1,__LINE__))
|
||||
static inline bool _reportResult(kern_return_t result, const char *operation, const char* file, int line) {
|
||||
if ( result != ERR_SUCCESS ) {
|
||||
printf("%s:%d: %s: %s\n", file, line, operation, mach_error_string(result));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TPCircularBufferInit(TPCircularBuffer *buffer, int length) {
|
||||
|
||||
// Keep trying until we get our buffer, needed to handle race conditions
|
||||
int retries = 3;
|
||||
while ( true ) {
|
||||
|
||||
buffer->length = round_page(length); // We need whole page sizes
|
||||
|
||||
// Temporarily allocate twice the length, so we have the contiguous address space to
|
||||
// support a second instance of the buffer directly after
|
||||
vm_address_t bufferAddress;
|
||||
kern_return_t result = vm_allocate(mach_task_self(),
|
||||
&bufferAddress,
|
||||
buffer->length * 2,
|
||||
VM_FLAGS_ANYWHERE); // allocate anywhere it'll fit
|
||||
if ( result != ERR_SUCCESS ) {
|
||||
if ( retries-- == 0 ) {
|
||||
reportResult(result, "Buffer allocation");
|
||||
return false;
|
||||
}
|
||||
// Try again if we fail
|
||||
continue;
|
||||
}
|
||||
|
||||
// Now replace the second half of the allocation with a virtual copy of the first half. Deallocate the second half...
|
||||
result = vm_deallocate(mach_task_self(),
|
||||
bufferAddress + buffer->length,
|
||||
buffer->length);
|
||||
if ( result != ERR_SUCCESS ) {
|
||||
if ( retries-- == 0 ) {
|
||||
reportResult(result, "Buffer deallocation");
|
||||
return false;
|
||||
}
|
||||
// If this fails somehow, deallocate the whole region and try again
|
||||
vm_deallocate(mach_task_self(), bufferAddress, buffer->length);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Re-map the buffer to the address space immediately after the buffer
|
||||
vm_address_t virtualAddress = bufferAddress + buffer->length;
|
||||
vm_prot_t cur_prot, max_prot;
|
||||
result = vm_remap(mach_task_self(),
|
||||
&virtualAddress, // mirror target
|
||||
buffer->length, // size of mirror
|
||||
0, // auto alignment
|
||||
0, // force remapping to virtualAddress
|
||||
mach_task_self(), // same task
|
||||
bufferAddress, // mirror source
|
||||
0, // MAP READ-WRITE, NOT COPY
|
||||
&cur_prot, // unused protection struct
|
||||
&max_prot, // unused protection struct
|
||||
VM_INHERIT_DEFAULT);
|
||||
if ( result != ERR_SUCCESS ) {
|
||||
if ( retries-- == 0 ) {
|
||||
reportResult(result, "Remap buffer memory");
|
||||
return false;
|
||||
}
|
||||
// If this remap failed, we hit a race condition, so deallocate and try again
|
||||
vm_deallocate(mach_task_self(), bufferAddress, buffer->length);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( virtualAddress != bufferAddress+buffer->length ) {
|
||||
// If the memory is not contiguous, clean up both allocated buffers and try again
|
||||
if ( retries-- == 0 ) {
|
||||
printf("Couldn't map buffer memory to end of buffer\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
vm_deallocate(mach_task_self(), virtualAddress, buffer->length);
|
||||
vm_deallocate(mach_task_self(), bufferAddress, buffer->length);
|
||||
continue;
|
||||
}
|
||||
|
||||
buffer->buffer = (void*)bufferAddress;
|
||||
buffer->fillCount = 0;
|
||||
buffer->head = buffer->tail = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void TPCircularBufferCleanup(TPCircularBuffer *buffer) {
|
||||
vm_deallocate(mach_task_self(), (vm_address_t)buffer->buffer, buffer->length * 2);
|
||||
memset(buffer, 0, sizeof(TPCircularBuffer));
|
||||
}
|
||||
|
||||
void TPCircularBufferClear(TPCircularBuffer *buffer) {
|
||||
int32_t fillCount;
|
||||
if ( TPCircularBufferTail(buffer, &fillCount) ) {
|
||||
TPCircularBufferConsume(buffer, fillCount);
|
||||
}
|
||||
}
|
195
channels/rdpsnd/client/ios/TPCircularBuffer.h
Normal file
195
channels/rdpsnd/client/ios/TPCircularBuffer.h
Normal file
@ -0,0 +1,195 @@
|
||||
//
|
||||
// TPCircularBuffer.h
|
||||
// Circular/Ring buffer implementation
|
||||
//
|
||||
// https://github.com/michaeltyson/TPCircularBuffer
|
||||
//
|
||||
// Created by Michael Tyson on 10/12/2011.
|
||||
//
|
||||
//
|
||||
// This implementation makes use of a virtual memory mapping technique that inserts a virtual copy
|
||||
// of the buffer memory directly after the buffer's end, negating the need for any buffer wrap-around
|
||||
// logic. Clients can simply use the returned memory address as if it were contiguous space.
|
||||
//
|
||||
// The implementation is thread-safe in the case of a single producer and single consumer.
|
||||
//
|
||||
// Virtual memory technique originally proposed by Philip Howard (http://vrb.slashusr.org/), and
|
||||
// adapted to Darwin by Kurt Revis (http://www.snoize.com,
|
||||
// http://www.snoize.com/Code/PlayBufferedSoundFile.tar.gz)
|
||||
//
|
||||
//
|
||||
// Copyright (C) 2012-2013 A Tasty Pixel
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
|
||||
#ifndef TPCircularBuffer_h
|
||||
#define TPCircularBuffer_h
|
||||
|
||||
#include <libkern/OSAtomic.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
void *buffer;
|
||||
int32_t length;
|
||||
int32_t tail;
|
||||
int32_t head;
|
||||
volatile int32_t fillCount;
|
||||
} TPCircularBuffer;
|
||||
|
||||
/*!
|
||||
* Initialise buffer
|
||||
*
|
||||
* Note that the length is advisory only: Because of the way the
|
||||
* memory mirroring technique works, the true buffer length will
|
||||
* be multiples of the device page size (e.g. 4096 bytes)
|
||||
*
|
||||
* @param buffer Circular buffer
|
||||
* @param length Length of buffer
|
||||
*/
|
||||
bool TPCircularBufferInit(TPCircularBuffer *buffer, int32_t length);
|
||||
|
||||
/*!
|
||||
* Cleanup buffer
|
||||
*
|
||||
* Releases buffer resources.
|
||||
*/
|
||||
void TPCircularBufferCleanup(TPCircularBuffer *buffer);
|
||||
|
||||
/*!
|
||||
* Clear buffer
|
||||
*
|
||||
* Resets buffer to original, empty state.
|
||||
*
|
||||
* This is safe for use by consumer while producer is accessing
|
||||
* buffer.
|
||||
*/
|
||||
void TPCircularBufferClear(TPCircularBuffer *buffer);
|
||||
|
||||
// Reading (consuming)
|
||||
|
||||
/*!
|
||||
* Access end of buffer
|
||||
*
|
||||
* This gives you a pointer to the end of the buffer, ready
|
||||
* for reading, and the number of available bytes to read.
|
||||
*
|
||||
* @param buffer Circular buffer
|
||||
* @param availableBytes On output, the number of bytes ready for reading
|
||||
* @return Pointer to the first bytes ready for reading, or NULL if buffer is empty
|
||||
*/
|
||||
static __inline__ __attribute__((always_inline)) void* TPCircularBufferTail(TPCircularBuffer *buffer, int32_t* availableBytes) {
|
||||
*availableBytes = buffer->fillCount;
|
||||
if ( *availableBytes == 0 ) return NULL;
|
||||
return (void*)((char*)buffer->buffer + buffer->tail);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Consume bytes in buffer
|
||||
*
|
||||
* This frees up the just-read bytes, ready for writing again.
|
||||
*
|
||||
* @param buffer Circular buffer
|
||||
* @param amount Number of bytes to consume
|
||||
*/
|
||||
static __inline__ __attribute__((always_inline)) void TPCircularBufferConsume(TPCircularBuffer *buffer, int32_t amount) {
|
||||
buffer->tail = (buffer->tail + amount) % buffer->length;
|
||||
OSAtomicAdd32Barrier(-amount, &buffer->fillCount);
|
||||
assert(buffer->fillCount >= 0);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Version of TPCircularBufferConsume without the memory barrier, for more optimal use in single-threaded contexts
|
||||
*/
|
||||
static __inline__ __attribute__((always_inline)) void TPCircularBufferConsumeNoBarrier(TPCircularBuffer *buffer, int32_t amount) {
|
||||
buffer->tail = (buffer->tail + amount) % buffer->length;
|
||||
buffer->fillCount -= amount;
|
||||
assert(buffer->fillCount >= 0);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Access front of buffer
|
||||
*
|
||||
* This gives you a pointer to the front of the buffer, ready
|
||||
* for writing, and the number of available bytes to write.
|
||||
*
|
||||
* @param buffer Circular buffer
|
||||
* @param availableBytes On output, the number of bytes ready for writing
|
||||
* @return Pointer to the first bytes ready for writing, or NULL if buffer is full
|
||||
*/
|
||||
static __inline__ __attribute__((always_inline)) void* TPCircularBufferHead(TPCircularBuffer *buffer, int32_t* availableBytes) {
|
||||
*availableBytes = (buffer->length - buffer->fillCount);
|
||||
if ( *availableBytes == 0 ) return NULL;
|
||||
return (void*)((char*)buffer->buffer + buffer->head);
|
||||
}
|
||||
|
||||
// Writing (producing)
|
||||
|
||||
/*!
|
||||
* Produce bytes in buffer
|
||||
*
|
||||
* This marks the given section of the buffer ready for reading.
|
||||
*
|
||||
* @param buffer Circular buffer
|
||||
* @param amount Number of bytes to produce
|
||||
*/
|
||||
static __inline__ __attribute__((always_inline)) void TPCircularBufferProduce(TPCircularBuffer *buffer, int amount) {
|
||||
buffer->head = (buffer->head + amount) % buffer->length;
|
||||
OSAtomicAdd32Barrier(amount, &buffer->fillCount);
|
||||
assert(buffer->fillCount <= buffer->length);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Version of TPCircularBufferProduce without the memory barrier, for more optimal use in single-threaded contexts
|
||||
*/
|
||||
static __inline__ __attribute__((always_inline)) void TPCircularBufferProduceNoBarrier(TPCircularBuffer *buffer, int amount) {
|
||||
buffer->head = (buffer->head + amount) % buffer->length;
|
||||
buffer->fillCount += amount;
|
||||
assert(buffer->fillCount <= buffer->length);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Helper routine to copy bytes to buffer
|
||||
*
|
||||
* This copies the given bytes to the buffer, and marks them ready for writing.
|
||||
*
|
||||
* @param buffer Circular buffer
|
||||
* @param src Source buffer
|
||||
* @param len Number of bytes in source buffer
|
||||
* @return true if bytes copied, false if there was insufficient space
|
||||
*/
|
||||
static __inline__ __attribute__((always_inline)) bool TPCircularBufferProduceBytes(TPCircularBuffer *buffer, const void* src, int32_t len) {
|
||||
int32_t space;
|
||||
void *ptr = TPCircularBufferHead(buffer, &space);
|
||||
if ( space < len ) return false;
|
||||
memcpy(ptr, src, len);
|
||||
TPCircularBufferProduce(buffer, len);
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
299
channels/rdpsnd/client/ios/rdpsnd_ios.c
Normal file
299
channels/rdpsnd/client/ios/rdpsnd_ios.c
Normal file
@ -0,0 +1,299 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Audio Output Virtual Channel
|
||||
*
|
||||
* Copyright 2013 Dell Software <Mike.McDonald@software.dell.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <winpr/wtypes.h>
|
||||
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/codec/dsp.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
|
||||
#import <AudioToolbox/AudioToolbox.h>
|
||||
|
||||
#include "rdpsnd_main.h"
|
||||
#include "TPCircularBuffer.h"
|
||||
|
||||
#define INPUT_BUFFER_SIZE 32768
|
||||
#define CIRCULAR_BUFFER_SIZE (INPUT_BUFFER_SIZE * 4)
|
||||
|
||||
typedef struct rdpsnd_ios_plugin
|
||||
{
|
||||
rdpsndDevicePlugin device;
|
||||
AudioComponentInstance audio_unit;
|
||||
TPCircularBuffer buffer;
|
||||
BOOL is_opened;
|
||||
BOOL is_playing;
|
||||
} rdpsndIOSPlugin;
|
||||
|
||||
#define THIS(__ptr) ((rdpsndIOSPlugin*)__ptr)
|
||||
|
||||
static OSStatus rdpsnd_ios_render_cb(
|
||||
void *inRefCon,
|
||||
AudioUnitRenderActionFlags __unused *ioActionFlags,
|
||||
const AudioTimeStamp __unused *inTimeStamp,
|
||||
UInt32 inBusNumber,
|
||||
UInt32 __unused inNumberFrames,
|
||||
AudioBufferList *ioData
|
||||
)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (inBusNumber != 0)
|
||||
{
|
||||
return noErr;
|
||||
}
|
||||
|
||||
rdpsndIOSPlugin *p = THIS(inRefCon);
|
||||
|
||||
for (i = 0; i < ioData->mNumberBuffers; i++)
|
||||
{
|
||||
AudioBuffer* target_buffer = &ioData->mBuffers[i];
|
||||
|
||||
int32_t available_bytes = 0;
|
||||
const void *buffer = TPCircularBufferTail(&p->buffer, &available_bytes);
|
||||
if (buffer != NULL && available_bytes > 0)
|
||||
{
|
||||
const int bytes_to_copy = MIN((int32_t)target_buffer->mDataByteSize, available_bytes);
|
||||
|
||||
memcpy(target_buffer->mData, buffer, bytes_to_copy);
|
||||
target_buffer->mDataByteSize = bytes_to_copy;
|
||||
|
||||
TPCircularBufferConsume(&p->buffer, bytes_to_copy);
|
||||
}
|
||||
else
|
||||
{
|
||||
target_buffer->mDataByteSize = 0;
|
||||
AudioOutputUnitStop(p->audio_unit);
|
||||
p->is_playing = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
static BOOL rdpsnd_ios_format_supported(rdpsndDevicePlugin* __unused device, AUDIO_FORMAT* format)
|
||||
{
|
||||
if (format->wFormatTag == WAVE_FORMAT_PCM)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rdpsnd_ios_set_format(rdpsndDevicePlugin* __unused device, AUDIO_FORMAT* __unused format, int __unused latency)
|
||||
{
|
||||
}
|
||||
|
||||
static void rdpsnd_ios_set_volume(rdpsndDevicePlugin* __unused device, UINT32 __unused value)
|
||||
{
|
||||
}
|
||||
|
||||
static void rdpsnd_ios_start(rdpsndDevicePlugin* device)
|
||||
{
|
||||
rdpsndIOSPlugin *p = THIS(device);
|
||||
|
||||
/* If this device is not playing... */
|
||||
if (!p->is_playing)
|
||||
{
|
||||
/* Start the device. */
|
||||
int32_t available_bytes = 0;
|
||||
TPCircularBufferTail(&p->buffer, &available_bytes);
|
||||
if (available_bytes > 0)
|
||||
{
|
||||
p->is_playing = 1;
|
||||
AudioOutputUnitStart(p->audio_unit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void rdpsnd_ios_stop(rdpsndDevicePlugin* __unused device)
|
||||
{
|
||||
rdpsndIOSPlugin *p = THIS(device);
|
||||
|
||||
/* If the device is playing... */
|
||||
if (p->is_playing)
|
||||
{
|
||||
/* Stop the device. */
|
||||
AudioOutputUnitStop(p->audio_unit);
|
||||
p->is_playing = 0;
|
||||
|
||||
/* Free all buffers. */
|
||||
TPCircularBufferClear(&p->buffer);
|
||||
}
|
||||
}
|
||||
|
||||
static void rdpsnd_ios_play(rdpsndDevicePlugin* device, BYTE* data, int size)
|
||||
{
|
||||
rdpsndIOSPlugin *p = THIS(device);
|
||||
|
||||
const BOOL ok = TPCircularBufferProduceBytes(&p->buffer, data, size);
|
||||
if (!ok)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
rdpsnd_ios_start(device);
|
||||
}
|
||||
|
||||
static void rdpsnd_ios_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int __unused latency)
|
||||
{
|
||||
rdpsndIOSPlugin *p = THIS(device);
|
||||
|
||||
if (p->is_opened)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Find the output audio unit. */
|
||||
AudioComponentDescription desc;
|
||||
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
|
||||
desc.componentType = kAudioUnitType_Output;
|
||||
desc.componentSubType = kAudioUnitSubType_RemoteIO;
|
||||
desc.componentFlags = 0;
|
||||
desc.componentFlagsMask = 0;
|
||||
|
||||
AudioComponent audioComponent = AudioComponentFindNext(NULL, &desc);
|
||||
if (audioComponent == NULL) return;
|
||||
|
||||
/* Open the audio unit. */
|
||||
OSStatus status = AudioComponentInstanceNew(audioComponent, &p->audio_unit);
|
||||
if (status != 0) return;
|
||||
|
||||
/* Set the format for the AudioUnit. */
|
||||
AudioStreamBasicDescription audioFormat = {0};
|
||||
audioFormat.mSampleRate = format->nSamplesPerSec;
|
||||
audioFormat.mFormatID = kAudioFormatLinearPCM;
|
||||
audioFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
|
||||
audioFormat.mFramesPerPacket = 1; /* imminent property of the Linear PCM */
|
||||
audioFormat.mChannelsPerFrame = format->nChannels;
|
||||
audioFormat.mBitsPerChannel = format->wBitsPerSample;
|
||||
audioFormat.mBytesPerFrame = (format->wBitsPerSample * format->nChannels) / 8;
|
||||
audioFormat.mBytesPerPacket = audioFormat.mBytesPerFrame * audioFormat.mFramesPerPacket;
|
||||
|
||||
status = AudioUnitSetProperty(
|
||||
p->audio_unit,
|
||||
kAudioUnitProperty_StreamFormat,
|
||||
kAudioUnitScope_Input,
|
||||
0,
|
||||
&audioFormat,
|
||||
sizeof(audioFormat));
|
||||
if (status != 0)
|
||||
{
|
||||
AudioComponentInstanceDispose(p->audio_unit);
|
||||
p->audio_unit = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set up the AudioUnit callback. */
|
||||
AURenderCallbackStruct callbackStruct = {0};
|
||||
callbackStruct.inputProc = rdpsnd_ios_render_cb;
|
||||
callbackStruct.inputProcRefCon = p;
|
||||
status = AudioUnitSetProperty(
|
||||
p->audio_unit,
|
||||
kAudioUnitProperty_SetRenderCallback,
|
||||
kAudioUnitScope_Input,
|
||||
0,
|
||||
&callbackStruct,
|
||||
sizeof(callbackStruct));
|
||||
if (status != 0)
|
||||
{
|
||||
AudioComponentInstanceDispose(p->audio_unit);
|
||||
p->audio_unit = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Initialize the AudioUnit. */
|
||||
status = AudioUnitInitialize(p->audio_unit);
|
||||
if (status != 0)
|
||||
{
|
||||
AudioComponentInstanceDispose(p->audio_unit);
|
||||
p->audio_unit = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Allocate the circular buffer. */
|
||||
const BOOL ok = TPCircularBufferInit(&p->buffer, CIRCULAR_BUFFER_SIZE);
|
||||
if (!ok)
|
||||
{
|
||||
AudioUnitUninitialize(p->audio_unit);
|
||||
AudioComponentInstanceDispose(p->audio_unit);
|
||||
p->audio_unit = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
p->is_opened = 1;
|
||||
}
|
||||
|
||||
static void rdpsnd_ios_close(rdpsndDevicePlugin* device)
|
||||
{
|
||||
rdpsndIOSPlugin *p = THIS(device);
|
||||
|
||||
/* Make sure the device is stopped. */
|
||||
rdpsnd_ios_stop(device);
|
||||
|
||||
/* If the device is open... */
|
||||
if (p->is_opened)
|
||||
{
|
||||
/* Close the device. */
|
||||
AudioUnitUninitialize(p->audio_unit);
|
||||
AudioComponentInstanceDispose(p->audio_unit);
|
||||
p->audio_unit = NULL;
|
||||
p->is_opened = 0;
|
||||
|
||||
/* Destroy the circular buffer. */
|
||||
TPCircularBufferCleanup(&p->buffer);
|
||||
}
|
||||
}
|
||||
|
||||
static void rdpsnd_ios_free(rdpsndDevicePlugin* device)
|
||||
{
|
||||
rdpsndIOSPlugin *p = THIS(device);
|
||||
|
||||
/* Ensure the device is closed. */
|
||||
rdpsnd_ios_close(device);
|
||||
|
||||
/* Free memory associated with the device. */
|
||||
free(p);
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define freerdp_rdpsnd_client_subsystem_entry ios_freerdp_rdpsnd_client_subsystem_entry
|
||||
#endif
|
||||
|
||||
int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints)
|
||||
{
|
||||
rdpsndIOSPlugin *p = (rdpsndIOSPlugin*)malloc(sizeof(rdpsndIOSPlugin));
|
||||
memset(p, 0, sizeof(rdpsndIOSPlugin));
|
||||
|
||||
p->device.Open = rdpsnd_ios_open;
|
||||
p->device.FormatSupported = rdpsnd_ios_format_supported;
|
||||
p->device.SetFormat = rdpsnd_ios_set_format;
|
||||
p->device.SetVolume = rdpsnd_ios_set_volume;
|
||||
p->device.Play = rdpsnd_ios_play;
|
||||
p->device.Start = rdpsnd_ios_start;
|
||||
p->device.Close = rdpsnd_ios_close;
|
||||
p->device.Free = rdpsnd_ios_free;
|
||||
|
||||
pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*)p);
|
||||
|
||||
return 0;
|
||||
}
|
@ -30,7 +30,7 @@ set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
|
||||
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||
MODULE freerdp
|
||||
MODULES freerdp-utils)
|
||||
MODULES freerdp-codec freerdp-utils)
|
||||
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${PULSE_LIBRARY})
|
||||
|
||||
|
@ -18,7 +18,8 @@
|
||||
define_channel_server("rdpsnd")
|
||||
|
||||
set(${MODULE_PREFIX}_SRCS
|
||||
rdpsnd.c)
|
||||
rdpsnd_main.c
|
||||
rdpsnd_main.h)
|
||||
|
||||
add_channel_server_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntry")
|
||||
|
||||
|
572
channels/rdpsnd/server/rdpsnd_main.c
Normal file
572
channels/rdpsnd/server/rdpsnd_main.c
Normal file
@ -0,0 +1,572 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Server Audio Virtual Channel
|
||||
*
|
||||
* Copyright 2012 Vic Lee
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/stream.h>
|
||||
|
||||
#include "rdpsnd_main.h"
|
||||
|
||||
static BOOL rdpsnd_server_send_formats(RdpsndServerContext* context, wStream* s)
|
||||
{
|
||||
int pos;
|
||||
UINT16 i;
|
||||
BOOL status;
|
||||
|
||||
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 */
|
||||
Stream_Write_UINT16(s, 0); /* wDGramPort */
|
||||
Stream_Write_UINT16(s, context->num_server_formats); /* wNumberOfFormats */
|
||||
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].nChannels); /* nChannels */
|
||||
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 */
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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), NULL);
|
||||
Stream_SetPosition(s, 0);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void rdpsnd_server_recv_waveconfirm(RdpsndServerContext* context, wStream* s)
|
||||
{
|
||||
UINT16 timestamp = 0;
|
||||
BYTE confirmBlockNum = 0;
|
||||
Stream_Read_UINT16(s, timestamp);
|
||||
Stream_Read_UINT8(s, confirmBlockNum);
|
||||
Stream_Seek_UINT8(s);
|
||||
}
|
||||
|
||||
static void rdpsnd_server_recv_quality_mode(RdpsndServerContext* context, wStream* s)
|
||||
{
|
||||
UINT16 quality;
|
||||
|
||||
Stream_Read_UINT16(s, quality);
|
||||
Stream_Seek_UINT16(s); // reserved
|
||||
|
||||
fprintf(stderr, "Client requested sound quality: %#0X\n", quality);
|
||||
}
|
||||
|
||||
static BOOL rdpsnd_server_recv_formats(RdpsndServerContext* context, wStream* s)
|
||||
{
|
||||
int i, num_known_format = 0;
|
||||
UINT32 flags, vol, pitch;
|
||||
UINT16 udpPort, version;
|
||||
BYTE lastblock;
|
||||
|
||||
Stream_Read_UINT32(s, flags); /* dwFlags */
|
||||
Stream_Read_UINT32(s, vol); /* dwVolume */
|
||||
Stream_Read_UINT32(s, pitch); /* dwPitch */
|
||||
Stream_Read_UINT16(s, udpPort); /* wDGramPort */
|
||||
Stream_Read_UINT16(s, context->num_client_formats); /* wNumberOfFormats */
|
||||
Stream_Read_UINT8(s, lastblock); /* cLastBlockConfirmed */
|
||||
Stream_Read_UINT16(s, version); /* wVersion */
|
||||
Stream_Seek_UINT8(s); /* bPad */
|
||||
|
||||
if (context->num_client_formats > 0)
|
||||
{
|
||||
context->client_formats = (AUDIO_FORMAT*) malloc(context->num_client_formats * sizeof(AUDIO_FORMAT));
|
||||
ZeroMemory(context->client_formats, sizeof(AUDIO_FORMAT));
|
||||
|
||||
for (i = 0; i < context->num_client_formats; i++)
|
||||
{
|
||||
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);
|
||||
Stream_Read_UINT32(s, context->client_formats[i].nAvgBytesPerSec);
|
||||
Stream_Read_UINT16(s, context->client_formats[i].nBlockAlign);
|
||||
Stream_Read_UINT16(s, context->client_formats[i].wBitsPerSample);
|
||||
Stream_Read_UINT16(s, context->client_formats[i].cbSize);
|
||||
|
||||
if (context->client_formats[i].cbSize > 0)
|
||||
{
|
||||
Stream_Seek(s, context->client_formats[i].cbSize);
|
||||
}
|
||||
|
||||
if (context->client_formats[i].wFormatTag != 0)
|
||||
{
|
||||
//lets call this a known format
|
||||
//TODO: actually look through our own list of known formats
|
||||
num_known_format++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (num_known_format == 0)
|
||||
{
|
||||
fprintf(stderr, "Client doesn't support any known formats!\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void* rdpsnd_server_thread(void* arg)
|
||||
{
|
||||
wStream* s;
|
||||
DWORD status;
|
||||
DWORD nCount;
|
||||
void* buffer;
|
||||
BYTE msgType;
|
||||
UINT16 BodySize;
|
||||
HANDLE events[8];
|
||||
HANDLE ChannelEvent;
|
||||
DWORD BytesReturned;
|
||||
RdpsndServerContext* context;
|
||||
|
||||
context = (RdpsndServerContext*) arg;
|
||||
|
||||
buffer = NULL;
|
||||
BytesReturned = 0;
|
||||
ChannelEvent = NULL;
|
||||
|
||||
s = Stream_New(NULL, 4096);
|
||||
|
||||
if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE)
|
||||
{
|
||||
if (BytesReturned == sizeof(HANDLE))
|
||||
CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE));
|
||||
|
||||
WTSFreeMemory(buffer);
|
||||
}
|
||||
|
||||
nCount = 0;
|
||||
events[nCount++] = ChannelEvent;
|
||||
events[nCount++] = context->priv->StopEvent;
|
||||
|
||||
s = Stream_New(NULL, 4096);
|
||||
rdpsnd_server_send_formats(context, s);
|
||||
|
||||
while (1)
|
||||
{
|
||||
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
|
||||
|
||||
if (WaitForSingleObject(context->priv->StopEvent, 0) == WAIT_OBJECT_0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
Stream_SetPosition(s, 0);
|
||||
|
||||
if (WTSVirtualChannelRead(context->priv->ChannelHandle, 0,
|
||||
(PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned))
|
||||
{
|
||||
if (BytesReturned)
|
||||
Stream_Seek(s, BytesReturned);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!BytesReturned)
|
||||
break;
|
||||
|
||||
Stream_EnsureRemainingCapacity(s, BytesReturned);
|
||||
|
||||
if (WTSVirtualChannelRead(context->priv->ChannelHandle, 0,
|
||||
(PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned) == FALSE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Stream_Read_UINT8(s, msgType);
|
||||
Stream_Seek_UINT8(s); /* bPad */
|
||||
Stream_Read_UINT16(s, BodySize);
|
||||
|
||||
switch (msgType)
|
||||
{
|
||||
case SNDC_WAVECONFIRM:
|
||||
rdpsnd_server_recv_waveconfirm(context, s);
|
||||
break;
|
||||
|
||||
case SNDC_QUALITYMODE:
|
||||
rdpsnd_server_recv_quality_mode(context, s);
|
||||
break;
|
||||
|
||||
case SNDC_FORMATS:
|
||||
if (rdpsnd_server_recv_formats(context, s))
|
||||
{
|
||||
IFCALL(context->Activated, context);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "UNKOWN MESSAGE TYPE!! (%#0X)\n\n", msgType);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Stream_Free(s, TRUE);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static BOOL rdpsnd_server_initialize(RdpsndServerContext* context)
|
||||
{
|
||||
context->Start(context);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void rdpsnd_server_select_format(RdpsndServerContext* context, int client_format_index)
|
||||
{
|
||||
int bs;
|
||||
int out_buffer_size;
|
||||
AUDIO_FORMAT *format;
|
||||
|
||||
if (client_format_index < 0 || client_format_index >= context->num_client_formats)
|
||||
{
|
||||
fprintf(stderr, "rdpsnd_server_select_format: index %d is not correct.\n", client_format_index);
|
||||
return;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
fprintf(stderr, "Invalid Client Sound Format!!\n\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (format->wFormatTag == 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);
|
||||
}
|
||||
else if (format->wFormatTag == WAVE_FORMAT_ADPCM)
|
||||
{
|
||||
bs = (format->nBlockAlign - 7 * format->nChannels) * 2 / format->nChannels + 2;
|
||||
context->priv->out_frames = bs * 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
context->priv->out_frames = 0x4000 / context->priv->src_bytes_per_frame;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (context->priv->out_buffer_size < out_buffer_size)
|
||||
{
|
||||
context->priv->out_buffer = (BYTE*) realloc(context->priv->out_buffer, out_buffer_size);
|
||||
context->priv->out_buffer_size = out_buffer_size;
|
||||
}
|
||||
|
||||
freerdp_dsp_context_reset_adpcm(context->priv->dsp_context);
|
||||
}
|
||||
|
||||
static BOOL rdpsnd_server_send_audio_pdu(RdpsndServerContext* context)
|
||||
{
|
||||
int size;
|
||||
BYTE* src;
|
||||
int frames;
|
||||
int fill_size;
|
||||
BOOL status;
|
||||
AUDIO_FORMAT* format;
|
||||
int tbytes_per_frame;
|
||||
wStream* s = context->priv->rdpsnd_pdu;
|
||||
|
||||
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))
|
||||
{
|
||||
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);
|
||||
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 = 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 = 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))
|
||||
{
|
||||
fill_size = format->nBlockAlign - (size % format->nBlockAlign);
|
||||
}
|
||||
|
||||
/* WaveInfo PDU */
|
||||
Stream_SetPosition(s, 0);
|
||||
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, 0); /* 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);
|
||||
|
||||
WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
|
||||
Stream_SetPosition(s, 0);
|
||||
|
||||
/* Wave PDU */
|
||||
Stream_EnsureRemainingCapacity(s, size + fill_size);
|
||||
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), NULL);
|
||||
Stream_SetPosition(s, 0);
|
||||
|
||||
context->priv->out_pending_frames = 0;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static BOOL rdpsnd_server_send_samples(RdpsndServerContext* context, const void* buf, int nframes)
|
||||
{
|
||||
int cframes;
|
||||
int cframesize;
|
||||
|
||||
if (context->selected_client_format < 0)
|
||||
return FALSE;
|
||||
|
||||
while (nframes > 0)
|
||||
{
|
||||
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);
|
||||
buf = (BYTE*) buf + cframesize;
|
||||
nframes -= cframes;
|
||||
context->priv->out_pending_frames += cframes;
|
||||
|
||||
if (context->priv->out_pending_frames >= context->priv->out_frames)
|
||||
{
|
||||
if (!rdpsnd_server_send_audio_pdu(context))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL rdpsnd_server_set_volume(RdpsndServerContext* context, int left, int right)
|
||||
{
|
||||
int pos;
|
||||
BOOL status;
|
||||
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), NULL);
|
||||
Stream_SetPosition(s, 0);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static BOOL rdpsnd_server_close(RdpsndServerContext* context)
|
||||
{
|
||||
int pos;
|
||||
BOOL status;
|
||||
wStream* s = context->priv->rdpsnd_pdu;
|
||||
|
||||
if (context->selected_client_format < 0)
|
||||
return FALSE;
|
||||
|
||||
if (context->priv->out_pending_frames > 0)
|
||||
{
|
||||
if (!rdpsnd_server_send_audio_pdu(context))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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), NULL);
|
||||
Stream_SetPosition(s, 0);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int rdpsnd_server_start(RdpsndServerContext* context)
|
||||
{
|
||||
context->priv->ChannelHandle = WTSVirtualChannelManagerOpenEx(context->vcm, "rdpsnd", 0);
|
||||
|
||||
if (!context->priv->ChannelHandle)
|
||||
return -1;
|
||||
|
||||
context->priv->rdpsnd_pdu = Stream_New(NULL, 4096);
|
||||
|
||||
context->priv->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
context->priv->Thread = CreateThread(NULL, 0,
|
||||
(LPTHREAD_START_ROUTINE) rdpsnd_server_thread, (void*) context, 0, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rdpsnd_server_stop(RdpsndServerContext* context)
|
||||
{
|
||||
SetEvent(context->priv->StopEvent);
|
||||
|
||||
WaitForSingleObject(context->priv->Thread, INFINITE);
|
||||
CloseHandle(context->priv->Thread);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
RdpsndServerContext* rdpsnd_server_context_new(WTSVirtualChannelManager* vcm)
|
||||
{
|
||||
RdpsndServerContext* context;
|
||||
|
||||
context = (RdpsndServerContext*) malloc(sizeof(RdpsndServerContext));
|
||||
|
||||
if (context)
|
||||
{
|
||||
ZeroMemory(context, sizeof(RdpsndServerContext));
|
||||
|
||||
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 = (RdpsndServerPrivate*) malloc(sizeof(RdpsndServerPrivate));
|
||||
|
||||
if (context->priv)
|
||||
{
|
||||
ZeroMemory(context->priv, sizeof(RdpsndServerPrivate));
|
||||
|
||||
context->priv->dsp_context = freerdp_dsp_context_new();
|
||||
}
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
void rdpsnd_server_context_free(RdpsndServerContext* context)
|
||||
{
|
||||
SetEvent(context->priv->StopEvent);
|
||||
WaitForSingleObject(context->priv->Thread, INFINITE);
|
||||
|
||||
if (context->priv->ChannelHandle)
|
||||
WTSVirtualChannelClose(context->priv->ChannelHandle);
|
||||
|
||||
if (context->priv->rdpsnd_pdu)
|
||||
Stream_Free(context->priv->rdpsnd_pdu, TRUE);
|
||||
|
||||
if (context->priv->out_buffer)
|
||||
free(context->priv->out_buffer);
|
||||
|
||||
if (context->priv->dsp_context)
|
||||
freerdp_dsp_context_free(context->priv->dsp_context);
|
||||
|
||||
if (context->client_formats)
|
||||
free(context->client_formats);
|
||||
|
||||
free(context);
|
||||
}
|
48
channels/rdpsnd/server/rdpsnd_main.h
Normal file
48
channels/rdpsnd/server/rdpsnd_main.h
Normal file
@ -0,0 +1,48 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Server Audio Virtual Channel
|
||||
*
|
||||
* Copyright 2012 Vic Lee
|
||||
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.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_SERVER_RDPSND_MAIN_H
|
||||
#define FREERDP_CHANNEL_SERVER_RDPSND_MAIN_H
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/synch.h>
|
||||
#include <winpr/thread.h>
|
||||
|
||||
#include <freerdp/codec/dsp.h>
|
||||
#include <freerdp/channels/wtsvc.h>
|
||||
#include <freerdp/server/rdpsnd.h>
|
||||
|
||||
struct _rdpsnd_server_private
|
||||
{
|
||||
HANDLE Thread;
|
||||
HANDLE StopEvent;
|
||||
void* ChannelHandle;
|
||||
|
||||
wStream* rdpsnd_pdu;
|
||||
BYTE* out_buffer;
|
||||
int out_buffer_size;
|
||||
int out_frames;
|
||||
int out_pending_frames;
|
||||
UINT32 src_bytes_per_sample;
|
||||
UINT32 src_bytes_per_frame;
|
||||
FREERDP_DSP_CONTEXT* dsp_context;
|
||||
};
|
||||
|
||||
#endif /* FREERDP_CHANNEL_SERVER_RDPSND_MAIN_H */
|
@ -42,6 +42,9 @@
|
||||
|
||||
#include <freerdp/server/audin.h>
|
||||
#include <freerdp/server/rdpsnd.h>
|
||||
#include <freerdp/server/cliprdr.h>
|
||||
#include <freerdp/server/rdpdr.h>
|
||||
#include <freerdp/server/drdynvc.h>
|
||||
|
||||
void freerdp_channels_dummy()
|
||||
{
|
||||
@ -50,6 +53,15 @@ void freerdp_channels_dummy()
|
||||
|
||||
rdpsnd_server_context_new(NULL);
|
||||
rdpsnd_server_context_free(NULL);
|
||||
|
||||
cliprdr_server_context_new(NULL);
|
||||
cliprdr_server_context_free(NULL);
|
||||
|
||||
rdpdr_server_context_new(NULL);
|
||||
rdpdr_server_context_free(NULL);
|
||||
|
||||
drdynvc_server_context_new(NULL);
|
||||
drdynvc_server_context_free(NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -420,7 +432,7 @@ WTSVirtualChannelManager* WTSCreateVirtualChannelManager(freerdp_peer* client)
|
||||
|
||||
vcm = (WTSVirtualChannelManager*) malloc(sizeof(WTSVirtualChannelManager));
|
||||
|
||||
if (vcm != NULL)
|
||||
if (vcm)
|
||||
{
|
||||
ZeroMemory(vcm, sizeof(WTSVirtualChannelManager));
|
||||
|
||||
@ -470,8 +482,7 @@ void WTSDestroyVirtualChannelManager(WTSVirtualChannelManager* vcm)
|
||||
}
|
||||
}
|
||||
|
||||
void WTSVirtualChannelManagerGetFileDescriptor(WTSVirtualChannelManager* vcm,
|
||||
void** fds, int* fds_count)
|
||||
void WTSVirtualChannelManagerGetFileDescriptor(WTSVirtualChannelManager* vcm, void** fds, int* fds_count)
|
||||
{
|
||||
void* fd;
|
||||
|
||||
@ -507,13 +518,13 @@ BOOL WTSVirtualChannelManagerCheckFileDescriptor(WTSVirtualChannelManager* vcm)
|
||||
/* Initialize drdynvc channel once and only once. */
|
||||
vcm->drdynvc_state = DRDYNVC_STATE_INITIALIZED;
|
||||
|
||||
channel = WTSVirtualChannelOpenEx(vcm, "drdynvc", 0);
|
||||
channel = WTSVirtualChannelManagerOpenEx(vcm, "drdynvc", 0);
|
||||
|
||||
if (channel)
|
||||
{
|
||||
vcm->drdynvc_channel = channel;
|
||||
dynvc_caps = 0x00010050; /* DYNVC_CAPS_VERSION1 (4 bytes) */
|
||||
WTSVirtualChannelWrite(channel, (BYTE*) &dynvc_caps, sizeof(dynvc_caps), NULL);
|
||||
WTSVirtualChannelWrite(channel, (PCHAR) &dynvc_caps, sizeof(dynvc_caps), NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -539,10 +550,12 @@ BOOL WTSVirtualChannelManagerCheckFileDescriptor(WTSVirtualChannelManager* vcm)
|
||||
return result;
|
||||
}
|
||||
|
||||
void* WTSVirtualChannelOpenEx(
|
||||
/* __in */ WTSVirtualChannelManager* vcm,
|
||||
/* __in */ const char* pVirtualName,
|
||||
/* __in */ UINT32 flags)
|
||||
HANDLE WTSVirtualChannelManagerGetEventHandle(WTSVirtualChannelManager* vcm)
|
||||
{
|
||||
return vcm->send_event;
|
||||
}
|
||||
|
||||
HANDLE WTSVirtualChannelManagerOpenEx(WTSVirtualChannelManager* vcm, LPSTR pVirtualName, DWORD flags)
|
||||
{
|
||||
int i;
|
||||
int len;
|
||||
@ -592,7 +605,7 @@ void* WTSVirtualChannelOpenEx(
|
||||
|
||||
s = Stream_New(NULL, 64);
|
||||
wts_write_drdynvc_create_request(s, channel->channel_id, pVirtualName);
|
||||
WTSVirtualChannelWrite(vcm->drdynvc_channel, Stream_Buffer(s), Stream_GetPosition(s), NULL);
|
||||
WTSVirtualChannelWrite(vcm->drdynvc_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
|
||||
Stream_Free(s, TRUE);
|
||||
|
||||
DEBUG_DVC("ChannelId %d.%s (total %d)", channel->channel_id, pVirtualName, list_size(vcm->dvc_channel_list));
|
||||
@ -646,11 +659,7 @@ void* WTSVirtualChannelOpenEx(
|
||||
return channel;
|
||||
}
|
||||
|
||||
BOOL WTSVirtualChannelQuery(
|
||||
/* __in */ void* hChannelHandle,
|
||||
/* __in */ WTS_VIRTUAL_CLASS WtsVirtualClass,
|
||||
/* __out */ void** ppBuffer,
|
||||
/* __out */ UINT32* pBytesReturned)
|
||||
BOOL WTSVirtualChannelQuery(HANDLE hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass, PVOID* ppBuffer, DWORD* pBytesReturned)
|
||||
{
|
||||
void* pfd;
|
||||
BOOL bval;
|
||||
@ -659,6 +668,7 @@ BOOL WTSVirtualChannelQuery(
|
||||
BOOL result = FALSE;
|
||||
rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle;
|
||||
ZeroMemory(fds, sizeof(fds));
|
||||
|
||||
switch (WtsVirtualClass)
|
||||
{
|
||||
case WTSVirtualFileHandle:
|
||||
@ -677,6 +687,13 @@ BOOL WTSVirtualChannelQuery(
|
||||
result = TRUE;
|
||||
break;
|
||||
|
||||
case WTSVirtualEventHandle:
|
||||
*ppBuffer = malloc(sizeof(HANDLE));
|
||||
CopyMemory(*ppBuffer, &(channel->receive_event), sizeof(HANDLE));
|
||||
*pBytesReturned = sizeof(void*);
|
||||
result = TRUE;
|
||||
break;
|
||||
|
||||
case WTSVirtualChannelReady:
|
||||
if (channel->channel_type == RDP_PEER_CHANNEL_TYPE_SVC)
|
||||
{
|
||||
@ -715,25 +732,19 @@ BOOL WTSVirtualChannelQuery(
|
||||
return result;
|
||||
}
|
||||
|
||||
void WTSFreeMemory(
|
||||
/* __in */ void* pMemory)
|
||||
VOID WTSFreeMemory(PVOID pMemory)
|
||||
{
|
||||
free(pMemory);
|
||||
}
|
||||
|
||||
BOOL WTSVirtualChannelRead(
|
||||
/* __in */ void* hChannelHandle,
|
||||
/* __in */ UINT32 TimeOut,
|
||||
/* __out */ BYTE* Buffer,
|
||||
/* __in */ UINT32 BufferSize,
|
||||
/* __out */ UINT32* pBytesRead)
|
||||
BOOL WTSVirtualChannelRead(HANDLE hChannelHandle, ULONG TimeOut, PCHAR Buffer, ULONG BufferSize, PULONG pBytesRead)
|
||||
{
|
||||
wts_data_item* item;
|
||||
rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle;
|
||||
|
||||
item = (wts_data_item*) list_peek(channel->receive_queue);
|
||||
|
||||
if (item == NULL)
|
||||
if (!item)
|
||||
{
|
||||
ResetEvent(channel->receive_event);
|
||||
*pBytesRead = 0;
|
||||
@ -755,16 +766,12 @@ BOOL WTSVirtualChannelRead(
|
||||
ReleaseMutex(channel->mutex);
|
||||
|
||||
CopyMemory(Buffer, item->buffer, item->length);
|
||||
wts_data_item_free(item) ;
|
||||
wts_data_item_free(item);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WTSVirtualChannelWrite(
|
||||
/* __in */ void* hChannelHandle,
|
||||
/* __in */ BYTE* Buffer,
|
||||
/* __in */ UINT32 Length,
|
||||
/* __out */ UINT32* pBytesWritten)
|
||||
BOOL WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer, ULONG Length, PULONG pBytesWritten)
|
||||
{
|
||||
rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle;
|
||||
wts_data_item* item;
|
||||
@ -774,7 +781,7 @@ BOOL WTSVirtualChannelWrite(
|
||||
int first;
|
||||
UINT32 written;
|
||||
|
||||
if (channel == NULL)
|
||||
if (!channel)
|
||||
return FALSE;
|
||||
|
||||
if (channel->channel_type == RDP_PEER_CHANNEL_TYPE_SVC)
|
||||
@ -841,8 +848,7 @@ BOOL WTSVirtualChannelWrite(
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WTSVirtualChannelClose(
|
||||
/* __in */ void* hChannelHandle)
|
||||
BOOL WTSVirtualChannelClose(HANDLE hChannelHandle)
|
||||
{
|
||||
wStream* s;
|
||||
wts_data_item* item;
|
||||
@ -868,7 +874,7 @@ BOOL WTSVirtualChannelClose(
|
||||
{
|
||||
s = Stream_New(NULL, 8);
|
||||
wts_write_drdynvc_header(s, CLOSE_REQUEST_PDU, channel->channel_id);
|
||||
WTSVirtualChannelWrite(vcm->drdynvc_channel, Stream_Buffer(s), Stream_GetPosition(s), NULL);
|
||||
WTSVirtualChannelWrite(vcm->drdynvc_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
|
||||
Stream_Free(s, TRUE);
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
|
||||
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||
MODULE freerdp
|
||||
MODULES freerdp-utils)
|
||||
MODULES freerdp-codec freerdp-utils)
|
||||
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${ALSA_LIBRARIES})
|
||||
|
||||
|
@ -30,7 +30,7 @@ set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
|
||||
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||
MODULE freerdp
|
||||
MODULES freerdp-utils)
|
||||
MODULES freerdp-codec freerdp-utils)
|
||||
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${PULSE_LIBRARY})
|
||||
|
||||
|
14
client/.gitignore
vendored
14
client/.gitignore
vendored
@ -1,4 +1,10 @@
|
||||
WaykClient
|
||||
|
||||
|
||||
DotNetClient
|
||||
/*
|
||||
!/Android
|
||||
!/common
|
||||
!/DirectFB
|
||||
!/iOS
|
||||
!/Mac
|
||||
!/Sample
|
||||
!/Windows
|
||||
!/X11
|
||||
!/CMakeLists.txt
|
||||
|
4
client/Android/ModuleOptions.cmake
Normal file
4
client/Android/ModuleOptions.cmake
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
set(FREERDP_CLIENT_NAME "afreerdp")
|
||||
set(FREERDP_CLIENT_PLATFORM "Android")
|
||||
set(FREERDP_CLIENT_VENDOR "FreeRDP")
|
@ -51,10 +51,29 @@ if(ANDROID)
|
||||
add_subdirectory(Android)
|
||||
endif()
|
||||
|
||||
if(WITH_WAYK)
|
||||
add_subdirectory(WaykClient)
|
||||
endif()
|
||||
# Pick up other clients
|
||||
|
||||
set(FILENAME "ModuleOptions.cmake")
|
||||
file(GLOB FILEPATHS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*/${FILENAME}")
|
||||
|
||||
foreach(FILEPATH ${FILEPATHS})
|
||||
if(${FILEPATH} MATCHES "^([^/]*)//${FILENAME}")
|
||||
string(REGEX REPLACE "^([^/]*)//${FILENAME}" "\\1" FREERDP_CLIENT ${FILEPATH})
|
||||
set(FREERDP_CLIENT_ENABLED 0)
|
||||
include(${FILEPATH})
|
||||
if(FREERDP_CLIENT_ENABLED)
|
||||
if(NOT (${FREERDP_CLIENT_VENDOR} MATCHES "FreeRDP"))
|
||||
list(APPEND FREERDP_EXTRA_CLIENTS ${FREERDP_CLIENT})
|
||||
if(${FREERDP_CLIENT_VENDOR} MATCHES "${VENDOR}")
|
||||
set(CLIENT_VENDOR_PATH "client/${FREERDP_CLIENT}" PARENT_SCOPE)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
foreach(FREERDP_CLIENT ${FREERDP_EXTRA_CLIENTS})
|
||||
add_subdirectory(${FREERDP_CLIENT})
|
||||
endforeach()
|
||||
|
||||
|
||||
if (WITH_DOTNET)
|
||||
add_subdirectory(DotNetClient)
|
||||
endif()
|
||||
|
4
client/DirectFB/ModuleOptions.cmake
Normal file
4
client/DirectFB/ModuleOptions.cmake
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
set(FREERDP_CLIENT_NAME "dfreerdp")
|
||||
set(FREERDP_CLIENT_PLATFORM "DirectFB")
|
||||
set(FREERDP_CLIENT_VENDOR "FreeRDP")
|
@ -85,7 +85,6 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHI
|
||||
MODULE winpr
|
||||
MODULES winpr-input winpr-crt winpr-utils)
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES LINK_INTERFACE_LIBRARIES "")
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
# Set a list of the dependent targets used by the application. There should be a way to get this list automatically
|
||||
|
4
client/Mac/ModuleOptions.cmake
Normal file
4
client/Mac/ModuleOptions.cmake
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
set(FREERDP_CLIENT_NAME "mfreerdp")
|
||||
set(FREERDP_CLIENT_PLATFORM "MacOSX")
|
||||
set(FREERDP_CLIENT_VENDOR "FreeRDP")
|
4
client/Sample/ModuleOptions.cmake
Normal file
4
client/Sample/ModuleOptions.cmake
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
set(FREERDP_CLIENT_NAME "sfreerdp")
|
||||
set(FREERDP_CLIENT_PLATFORM "Sample")
|
||||
set(FREERDP_CLIENT_VENDOR "FreeRDP")
|
@ -63,10 +63,8 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
if(WITH_CLIENT_INTERFACE)
|
||||
if (NOT WITH_WAYK)
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libraries)
|
||||
add_subdirectory(cli)
|
||||
endif()
|
||||
else()
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT client)
|
||||
endif()
|
||||
|
4
client/Windows/ModuleOptions.cmake
Normal file
4
client/Windows/ModuleOptions.cmake
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
set(FREERDP_CLIENT_NAME "wfreerdp")
|
||||
set(FREERDP_CLIENT_PLATFORM "Windows")
|
||||
set(FREERDP_CLIENT_VENDOR "FreeRDP")
|
@ -371,7 +371,7 @@ BOOL wf_post_connect(freerdp* instance)
|
||||
if (settings->RemoteFxCodec)
|
||||
{
|
||||
wfc->tile = wf_image_new(wfc, 64, 64, 32, NULL);
|
||||
wfc->rfx_context = rfx_context_new();
|
||||
wfc->rfx_context = rfx_context_new(FALSE);
|
||||
}
|
||||
|
||||
if (settings->NSCodec)
|
||||
|
@ -92,8 +92,6 @@ if(WITH_MANPAGES)
|
||||
MODULE freerdp
|
||||
MODULES freerdp-core freerdp-utils)
|
||||
|
||||
message(WARNING "GAD_LIBS: ${GAD_LIBS}")
|
||||
|
||||
target_link_libraries(generate_argument_docbook ${GAD_LIBS})
|
||||
|
||||
add_custom_command(OUTPUT xfreerdp.1
|
||||
|
4
client/X11/ModuleOptions.cmake
Normal file
4
client/X11/ModuleOptions.cmake
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
set(FREERDP_CLIENT_NAME "xfreerdp")
|
||||
set(FREERDP_CLIENT_PLATFORM "X11")
|
||||
set(FREERDP_CLIENT_VENDOR "FreeRDP")
|
@ -155,12 +155,12 @@ int main(int argc, char *argv[])
|
||||
const COMMAND_LINE_ARGUMENT_A *arg = &args[x];
|
||||
|
||||
fprintf(fp, "\t\t\t<varlistentry>\n");
|
||||
if( COMMAND_LINE_VALUE_REQUIRED == arg->Flags )
|
||||
fprintf(fp, "\t\t\t\t<term><option>/%s</option> <replaceable>%s</replaceable></term>\n", tr_esc_str(arg->Name), tr_esc_str(arg->Format) );
|
||||
if ( COMMAND_LINE_VALUE_REQUIRED == arg->Flags)
|
||||
fprintf(fp, "\t\t\t\t<term><option>/%s</option> <replaceable>%s</replaceable></term>\n", tr_esc_str((LPSTR) arg->Name), tr_esc_str(arg->Format) );
|
||||
else
|
||||
fprintf(fp, "\t\t\t\t<term><option>/%s</option></term>\n", tr_esc_str(arg->Name) );
|
||||
fprintf(fp, "\t\t\t\t<term><option>/%s</option></term>\n", tr_esc_str((LPSTR) arg->Name));
|
||||
fprintf(fp, "\t\t\t\t<listitem>\n");
|
||||
fprintf(fp, "\t\t\t\t\t<para>%s</para>\n", tr_esc_str(arg->Text));
|
||||
fprintf(fp, "\t\t\t\t\t<para>%s</para>\n", tr_esc_str((LPSTR) arg->Text));
|
||||
|
||||
fprintf(fp, "\t\t\t\t</listitem>\n");
|
||||
fprintf(fp, "\t\t\t</varlistentry>\n");
|
||||
|
@ -908,7 +908,7 @@ BOOL xf_post_connect(freerdp* instance)
|
||||
|
||||
if (instance->settings->RemoteFxCodec)
|
||||
{
|
||||
rfx_context = (void*) rfx_context_new();
|
||||
rfx_context = (void*) rfx_context_new(FALSE);
|
||||
xfc->rfx_context = rfx_context;
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
#ifndef __XF_MONITOR_H
|
||||
#define __XF_MONITOR_H
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/rail/rail.h>
|
||||
|
||||
@ -43,8 +44,8 @@ typedef struct _VIRTUAL_SCREEN VIRTUAL_SCREEN;
|
||||
#include "xf_client.h"
|
||||
#include "xfreerdp.h"
|
||||
|
||||
int xf_list_monitors(xfContext* xfc);
|
||||
BOOL xf_detect_monitors(xfContext* xfc, rdpSettings* settings);
|
||||
void xf_monitors_free(xfContext *xfc, rdpSettings *settings);
|
||||
FREERDP_API int xf_list_monitors(xfContext* xfc);
|
||||
FREERDP_API BOOL xf_detect_monitors(xfContext* xfc, rdpSettings* settings);
|
||||
FREERDP_API void xf_monitors_free(xfContext *xfc, rdpSettings *settings);
|
||||
|
||||
#endif /* __XF_MONITOR_H */
|
||||
|
@ -22,6 +22,8 @@
|
||||
|
||||
typedef struct xf_context xfContext;
|
||||
|
||||
#include <freerdp/api.h>
|
||||
|
||||
#include "xf_window.h"
|
||||
#include "xf_monitor.h"
|
||||
#include "xf_channels.h"
|
||||
@ -215,7 +217,7 @@ void xf_unlock_x11(xfContext* xfc, BOOL display);
|
||||
void xf_draw_screen_scaled(xfContext* xfc, int x, int y, int w, int h, BOOL scale);
|
||||
void xf_transform_window(xfContext* xfc);
|
||||
|
||||
DWORD xf_exit_code_from_disconnect_reason(DWORD reason);
|
||||
FREERDP_API DWORD xf_exit_code_from_disconnect_reason(DWORD reason);
|
||||
|
||||
#endif /* __XFREERDP_H */
|
||||
|
||||
|
@ -52,11 +52,7 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHI
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES LINK_INTERFACE_LIBRARIES "")
|
||||
|
||||
if (NOT WITH_WAYK)
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libraries)
|
||||
endif()
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libraries)
|
||||
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Client/Common")
|
||||
|
||||
|
@ -23,8 +23,8 @@
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/freerdp.h>
|
||||
|
||||
int freerdp_detect_old_command_line_syntax(int argc, char** argv, int* count);
|
||||
int freerdp_client_parse_old_command_line_arguments(int argc, char** argv, rdpSettings* settings);
|
||||
FREERDP_API int freerdp_detect_old_command_line_syntax(int argc, char** argv, int* count);
|
||||
FREERDP_API int freerdp_client_parse_old_command_line_arguments(int argc, char** argv, rdpSettings* settings);
|
||||
|
||||
#endif /* FREERDP_CLIENT_COMPATIBILITY */
|
||||
|
||||
|
4
client/iOS/ModuleOptions.cmake
Normal file
4
client/iOS/ModuleOptions.cmake
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
set(FREERDP_CLIENT_NAME "ifreerdp")
|
||||
set(FREERDP_CLIENT_PLATFORM "iOS")
|
||||
set(FREERDP_CLIENT_VENDOR "FreeRDP")
|
@ -1,4 +1,6 @@
|
||||
|
||||
|
||||
include(EchoTarget)
|
||||
include(CMakeParseArguments)
|
||||
|
||||
macro(set_complex_link_libraries)
|
||||
@ -46,3 +48,32 @@ macro(add_complex_library)
|
||||
endif()
|
||||
|
||||
endmacro(add_complex_library)
|
||||
|
||||
if(${CMAKE_VERSION} VERSION_GREATER 2.8.8)
|
||||
set(CMAKE_OBJECT_TARGET_SUPPORT 1)
|
||||
endif()
|
||||
|
||||
function(create_object_cotarget target)
|
||||
|
||||
set(cotarget "${target}-objects")
|
||||
|
||||
get_target_property(${target}_TYPE ${target} TYPE)
|
||||
|
||||
if(NOT ((${target}_TYPE MATCHES "SHARED_LIBRARY") OR (${target}_TYPE MATCHES "SHARED_LIBRARY")))
|
||||
return()
|
||||
endif()
|
||||
|
||||
get_target_property(${target}_SOURCES ${target} SOURCES)
|
||||
get_target_property(${target}_LINK_LIBRARIES ${target} LINK_LIBRARIES)
|
||||
get_target_property(${target}_INCLUDE_DIRECTORIES ${target} INCLUDE_DIRECTORIES)
|
||||
|
||||
add_library(${cotarget} "OBJECT" ${${target}_SOURCES})
|
||||
|
||||
set_target_properties(${cotarget} PROPERTIES LINK_LIBRARIES "${${target}_LINK_LIBRARIES}")
|
||||
set_target_properties(${cotarget} PROPERTIES INCLUDE_DIRECTORIES "${${target}_INCLUDE_DIRECTORIES}")
|
||||
|
||||
echo_target(${target})
|
||||
echo_target(${cotarget})
|
||||
|
||||
endfunction()
|
||||
|
||||
|
178
cmake/EchoTarget.cmake
Normal file
178
cmake/EchoTarget.cmake
Normal file
@ -0,0 +1,178 @@
|
||||
function(echo_target_property tgt prop)
|
||||
# v for value, d for defined, s for set
|
||||
get_property(v TARGET ${tgt} PROPERTY ${prop})
|
||||
get_property(d TARGET ${tgt} PROPERTY ${prop} DEFINED)
|
||||
get_property(s TARGET ${tgt} PROPERTY ${prop} SET)
|
||||
|
||||
# only produce output for values that are set
|
||||
if(s)
|
||||
message("tgt='${tgt}' prop='${prop}'")
|
||||
message(" value='${v}'")
|
||||
message(" defined='${d}'")
|
||||
message(" set='${s}'")
|
||||
message("")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(echo_target tgt)
|
||||
if(NOT TARGET ${tgt})
|
||||
message("There is no target named '${tgt}'")
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(props
|
||||
DEBUG_OUTPUT_NAME
|
||||
RELEASE_OUTPUT_NAME
|
||||
DEBUG_POSTFIX
|
||||
RELEASE_POSTFIX
|
||||
ARCHIVE_OUTPUT_DIRECTORY
|
||||
ARCHIVE_OUTPUT_DIRECTORY_DEBUG
|
||||
ARCHIVE_OUTPUT_DIRECTORY_RELEASE
|
||||
ARCHIVE_OUTPUT_NAME
|
||||
ARCHIVE_OUTPUT_NAME_DEBUG
|
||||
ARCHIVE_OUTPUT_NAME_RELEASE
|
||||
AUTOMOC
|
||||
AUTOMOC_MOC_OPTIONS
|
||||
BUILD_WITH_INSTALL_RPATH
|
||||
BUNDLE
|
||||
BUNDLE_EXTENSION
|
||||
COMPILE_DEFINITIONS
|
||||
COMPILE_DEFINITIONS_DEBUG
|
||||
COMPILE_DEFINITIONS_RELEASE
|
||||
COMPILE_FLAGS
|
||||
DEBUG_POSTFIX
|
||||
DEFINE_SYMBOL
|
||||
ENABLE_EXPORTS
|
||||
EXCLUDE_FROM_ALL
|
||||
EchoString
|
||||
FOLDER
|
||||
FRAMEWORK
|
||||
Fortran_FORMAT
|
||||
Fortran_MODULE_DIRECTORY
|
||||
GENERATOR_FILE_NAME
|
||||
GNUtoMS
|
||||
HAS_CXX
|
||||
IMPLICIT_DEPENDS_INCLUDE_TRANSFORM
|
||||
IMPORTED
|
||||
IMPORTED_CONFIGURATIONS
|
||||
IMPORTED_IMPLIB
|
||||
IMPORTED_IMPLIB_RELEASE
|
||||
IMPORTED_IMPLIB_RELEASE
|
||||
IMPORTED_LINK_DEPENDENT_LIBRARIES
|
||||
IMPORTED_LINK_DEPENDENT_LIBRARIES_DEBUG
|
||||
IMPORTED_LINK_DEPENDENT_LIBRARIES_RELEASE
|
||||
IMPORTED_LINK_INTERFACE_LANGUAGES
|
||||
IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG
|
||||
IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE
|
||||
IMPORTED_LINK_INTERFACE_LIBRARIES
|
||||
IMPORTED_LINK_INTERFACE_LIBRARIES_DEBUG
|
||||
IMPORTED_LINK_INTERFACE_LIBRARIES_RELEASE
|
||||
IMPORTED_LINK_INTERFACE_MULTIPLICITY
|
||||
IMPORTED_LINK_INTERFACE_MULTIPLICITY_DEBUG
|
||||
IMPORTED_LINK_INTERFACE_MULTIPLICITY_RELEASE
|
||||
IMPORTED_LOCATION
|
||||
IMPORTED_LOCATION_DEBUG
|
||||
IMPORTED_LOCATION_RELEASE
|
||||
IMPORTED_NO_SONAME
|
||||
IMPORTED_NO_SONAME_DEBUG
|
||||
IMPORTED_NO_SONAME_RELEASE
|
||||
IMPORTED_SONAME
|
||||
IMPORTED_SONAME_DEBUG
|
||||
IMPORTED_SONAME_RELEASE
|
||||
IMPORT_PREFIX
|
||||
IMPORT_SUFFIX
|
||||
INCLUDE_DIRECTORIES
|
||||
INSTALL_NAME_DIR
|
||||
INSTALL_RPATH
|
||||
INSTALL_RPATH_USE_LINK_PATH
|
||||
INTERPROCEDURAL_OPTIMIZATION
|
||||
INTERPROCEDURAL_OPTIMIZATION_DEBUG
|
||||
INTERPROCEDURAL_OPTIMIZATION_RELEASE
|
||||
LABELS
|
||||
LIBRARY_OUTPUT_DIRECTORY
|
||||
LIBRARY_OUTPUT_DIRECTORY_DEBUG
|
||||
LIBRARY_OUTPUT_DIRECTORY_RELEASE
|
||||
LIBRARY_OUTPUT_NAME
|
||||
LIBRARY_OUTPUT_NAME_DEBUG
|
||||
LIBRARY_OUTPUT_NAME_RELEASE
|
||||
LINKER_LANGUAGE
|
||||
LINK_DEPENDS
|
||||
LINK_LIBRARIES
|
||||
LINK_FLAGS
|
||||
LINK_FLAGS_DEBUG
|
||||
LINK_FLAGS_RELEASE
|
||||
LINK_INTERFACE_LIBRARIES
|
||||
LINK_INTERFACE_LIBRARIES_DEBUG
|
||||
LINK_INTERFACE_LIBRARIES_RELEASE
|
||||
LINK_INTERFACE_MULTIPLICITY
|
||||
LINK_INTERFACE_MULTIPLICITY_DEBUG
|
||||
LINK_INTERFACE_MULTIPLICITY_RELEASE
|
||||
LINK_SEARCH_END_STATIC
|
||||
LINK_SEARCH_START_STATIC
|
||||
LOCATION
|
||||
LOCATION_DEBUG
|
||||
LOCATION_RELEASE
|
||||
MACOSX_BUNDLE
|
||||
MACOSX_BUNDLE_INFO_PLIST
|
||||
MACOSX_FRAMEWORK_INFO_PLIST
|
||||
MAP_IMPORTED_CONFIG_DEBUG
|
||||
MAP_IMPORTED_CONFIG_RELEASE
|
||||
OSX_ARCHITECTURES
|
||||
OSX_ARCHITECTURES_DEBUG
|
||||
OSX_ARCHITECTURES_RELEASE
|
||||
OUTPUT_NAME
|
||||
OUTPUT_NAME_DEBUG
|
||||
OUTPUT_NAME_RELEASE
|
||||
POST_INSTALL_SCRIPT
|
||||
PREFIX
|
||||
PRE_INSTALL_SCRIPT
|
||||
PRIVATE_HEADER
|
||||
PROJECT_LABEL
|
||||
PUBLIC_HEADER
|
||||
RESOURCE
|
||||
RULE_LAUNCH_COMPILE
|
||||
RULE_LAUNCH_CUSTOM
|
||||
RULE_LAUNCH_LINK
|
||||
RUNTIME_OUTPUT_DIRECTORY
|
||||
RUNTIME_OUTPUT_DIRECTORY_DEBUG
|
||||
RUNTIME_OUTPUT_DIRECTORY_RELEASE
|
||||
RUNTIME_OUTPUT_NAME
|
||||
RUNTIME_OUTPUT_NAME_DEBUG
|
||||
RUNTIME_OUTPUT_NAME_RELEASE
|
||||
SKIP_BUILD_RPATH
|
||||
SOURCES
|
||||
SOVERSION
|
||||
STATIC_LIBRARY_FLAGS
|
||||
STATIC_LIBRARY_FLAGS_DEBUG
|
||||
STATIC_LIBRARY_FLAGS_RELEASE
|
||||
SUFFIX
|
||||
TYPE
|
||||
VERSION
|
||||
VS_DOTNET_REFERENCES
|
||||
VS_GLOBAL_KEYWORD
|
||||
VS_GLOBAL_PROJECT_TYPES
|
||||
VS_KEYWORD
|
||||
VS_SCC_AUXPATH
|
||||
VS_SCC_LOCALPATH
|
||||
VS_SCC_PROJECTNAME
|
||||
VS_SCC_PROVIDER
|
||||
VS_WINRT_EXTENSIONS
|
||||
VS_WINRT_REFERENCES
|
||||
WIN32_EXECUTABLE
|
||||
)
|
||||
|
||||
message("======================== ${tgt} ========================")
|
||||
foreach(p ${props})
|
||||
echo_target_property("${tgt}" "${p}")
|
||||
endforeach()
|
||||
message("")
|
||||
|
||||
endfunction()
|
||||
|
||||
function(echo_targets)
|
||||
set(tgts ${ARGV})
|
||||
foreach(t ${tgts})
|
||||
echo_target("${t}")
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
@ -12,16 +12,19 @@
|
||||
# You should have received a copy of the FMILIB_License.txt file
|
||||
# along with this program. If not, contact Modelon AB <http://www.modelon.com>.
|
||||
|
||||
# Merge_static_libs(outlib lib1 lib2 ... libn) merges a number of static
|
||||
# Merge_static_libs(output_library lib1 lib2 ... libn) merges a number of static
|
||||
# libs into a single static library
|
||||
function(merge_static_libs outlib)
|
||||
function(merge_static_libs output_library)
|
||||
set(output_target "${output_library}")
|
||||
string(REGEX REPLACE "-" "_" output_library ${output_library})
|
||||
set(libs ${ARGV})
|
||||
list(REMOVE_AT libs 0)
|
||||
# Create a dummy file that the target will depend on
|
||||
set(dummyfile ${CMAKE_CURRENT_BINARY_DIR}/${outlib}_dummy.c)
|
||||
|
||||
# Create a dummy file that the target will depend on
|
||||
set(dummyfile ${CMAKE_CURRENT_BINARY_DIR}/${output_library}_dummy.c)
|
||||
file(WRITE ${dummyfile} "const char * dummy = \"${dummyfile}\";")
|
||||
|
||||
add_library(${outlib} STATIC ${dummyfile})
|
||||
add_library(${output_target} STATIC ${dummyfile})
|
||||
|
||||
if("${CMAKE_CFG_INTDIR}" STREQUAL ".")
|
||||
set(multiconfig FALSE)
|
||||
@ -29,7 +32,7 @@ function(merge_static_libs outlib)
|
||||
set(multiconfig TRUE)
|
||||
endif()
|
||||
|
||||
# First get the file names of the libraries to be merged
|
||||
# First get the file names of the libraries to be merged
|
||||
foreach(lib ${libs})
|
||||
get_target_property(libtype ${lib} TYPE)
|
||||
if(NOT libtype STREQUAL "STATIC_LIBRARY")
|
||||
@ -45,8 +48,8 @@ function(merge_static_libs outlib)
|
||||
list(APPEND libfiles "${libfile}")
|
||||
endif(multiconfig)
|
||||
endforeach()
|
||||
#message(STATUS "will be merging ${libfiles}")
|
||||
# Just to be sure: cleanup from duplicates
|
||||
|
||||
# Just to be sure: cleanup from duplicates
|
||||
if(multiconfig)
|
||||
foreach(CONFIG_TYPE ${CMAKE_CONFIGURATION_TYPES})
|
||||
list(REMOVE_DUPLICATES libfiles_${CONFIG_TYPE})
|
||||
@ -55,7 +58,7 @@ function(merge_static_libs outlib)
|
||||
endif()
|
||||
list(REMOVE_DUPLICATES libfiles)
|
||||
|
||||
# Now the easy part for MSVC and for MAC
|
||||
# Now the easy part for MSVC and for MAC
|
||||
if(MSVC)
|
||||
# lib.exe does the merging of libraries just need to conver the list into string
|
||||
foreach(CONFIG_TYPE ${CMAKE_CONFIGURATION_TYPES})
|
||||
@ -64,7 +67,7 @@ function(merge_static_libs outlib)
|
||||
set(flags "${flags} ${lib}")
|
||||
endforeach()
|
||||
string(TOUPPER "STATIC_LIBRARY_FLAGS_${CONFIG_TYPE}" PROPNAME)
|
||||
set_target_properties(${outlib} PROPERTIES ${PROPNAME} "${flags}")
|
||||
set_target_properties(${output_target} PROPERTIES ${PROPNAME} "${flags}")
|
||||
endforeach()
|
||||
|
||||
elseif(APPLE)
|
||||
@ -72,8 +75,8 @@ function(merge_static_libs outlib)
|
||||
if(multiconfig)
|
||||
message(FATAL_ERROR "Multiple configurations are not supported")
|
||||
endif()
|
||||
get_target_property(outfile ${outlib} LOCATION)
|
||||
add_custom_command(TARGET ${outlib} POST_BUILD
|
||||
get_target_property(outfile ${output_target} LOCATION)
|
||||
add_custom_command(TARGET ${output_target} POST_BUILD
|
||||
COMMAND rm ${outfile}
|
||||
COMMAND /usr/bin/libtool -static -o ${outfile}
|
||||
${libfiles}
|
||||
@ -83,48 +86,66 @@ function(merge_static_libs outlib)
|
||||
if(multiconfig)
|
||||
message(FATAL_ERROR "Multiple configurations are not supported")
|
||||
endif()
|
||||
get_target_property(outfile ${outlib} LOCATION)
|
||||
message(STATUS "outfile location is ${outfile}")
|
||||
get_target_property(outfile ${output_target} LOCATION)
|
||||
message(STATUS "output file location is ${outfile}")
|
||||
foreach(lib ${libfiles})
|
||||
# objlistfile will contain the list of object files for the library
|
||||
# objlistfile will contain the list of object files for the library
|
||||
set(objlistfile ${lib}.objlist)
|
||||
set(objdir ${lib}.objdir)
|
||||
set(objlistcmake ${objlistfile}.cmake)
|
||||
# we only need to extract files once
|
||||
get_filename_component(libname ${lib} NAME_WE)
|
||||
|
||||
if(${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/cmake.check_cache IS_NEWER_THAN ${objlistcmake})
|
||||
#---------------------------------
|
||||
FILE(WRITE ${objlistcmake}
|
||||
"# Extract object files from the library
|
||||
message(STATUS \"Extracting object files from ${lib}\")
|
||||
EXECUTE_PROCESS(COMMAND ${CMAKE_AR} -x ${lib}
|
||||
WORKING_DIRECTORY ${objdir})
|
||||
# save the list of object files
|
||||
EXECUTE_PROCESS(COMMAND ls .
|
||||
OUTPUT_FILE ${objlistfile}
|
||||
WORKING_DIRECTORY ${objdir})")
|
||||
#---------------------------------
|
||||
|
||||
file(WRITE ${objlistcmake} "
|
||||
# delete previous object files
|
||||
message(STATUS \"Removing previous object files from ${lib}\")
|
||||
EXECUTE_PROCESS(COMMAND ls .
|
||||
WORKING_DIRECTORY ${objdir}
|
||||
COMMAND xargs -I {} rm {}
|
||||
WORKING_DIRECTORY ${objdir})
|
||||
# Extract object files from the library
|
||||
message(STATUS \"Extracting object files from ${lib}\")
|
||||
EXECUTE_PROCESS(COMMAND ${CMAKE_AR} -x ${lib}
|
||||
WORKING_DIRECTORY ${objdir})
|
||||
# Prefixing object files to avoid conflicts
|
||||
message(STATUS \"Prefixing object files to avoid conflicts\")
|
||||
EXECUTE_PROCESS(COMMAND ls .
|
||||
WORKING_DIRECTORY ${objdir}
|
||||
COMMAND xargs -I {} mv {} ${libname}_{}
|
||||
WORKING_DIRECTORY ${objdir})
|
||||
# save the list of object files
|
||||
EXECUTE_PROCESS(COMMAND ls .
|
||||
OUTPUT_FILE ${objlistfile}
|
||||
WORKING_DIRECTORY ${objdir})
|
||||
")
|
||||
|
||||
file(MAKE_DIRECTORY ${objdir})
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${objlistfile}
|
||||
COMMAND ${CMAKE_COMMAND} -P ${objlistcmake}
|
||||
DEPENDS ${lib})
|
||||
|
||||
endif()
|
||||
|
||||
list(APPEND extrafiles "${objlistfile}")
|
||||
# relative path is needed by ar under MSYS
|
||||
file(RELATIVE_PATH objlistfilerpath ${objdir} ${objlistfile})
|
||||
add_custom_command(TARGET ${outlib} POST_BUILD
|
||||
add_custom_command(TARGET ${output_target} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Running: ${CMAKE_AR} ru ${outfile} @${objlistfilerpath}"
|
||||
COMMAND ${CMAKE_AR} ru "${outfile}" @"${objlistfilerpath}"
|
||||
WORKING_DIRECTORY ${objdir})
|
||||
#COMMAND ld -r -static -o "${outfile}" --whole-archive @"${objlistfilerpath}"
|
||||
WORKING_DIRECTORY ${objdir})
|
||||
endforeach()
|
||||
add_custom_command(TARGET ${outlib} POST_BUILD
|
||||
add_custom_command(TARGET ${output_target} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Running: ${CMAKE_RANLIB} ${outfile}"
|
||||
COMMAND ${CMAKE_RANLIB} ${outfile})
|
||||
endif()
|
||||
file(WRITE ${dummyfile}.base "const char* ${outlib}_sublibs=\"${libs}\";")
|
||||
file(WRITE ${dummyfile}.base "const char* ${output_library}_sublibs=\"${libs}\";")
|
||||
add_custom_command(
|
||||
OUTPUT ${dummyfile}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${dummyfile}.base ${dummyfile}
|
||||
OUTPUT ${dummyfile}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${dummyfile}.base ${dummyfile}
|
||||
DEPENDS ${libs} ${extrafiles})
|
||||
|
||||
endfunction()
|
||||
|
@ -32,6 +32,7 @@
|
||||
#cmakedefine HAVE_EVENTFD_H
|
||||
#cmakedefine HAVE_TIMERFD_H
|
||||
#cmakedefine HAVE_TM_GMTOFF
|
||||
#cmakedefine HAVE_AIO_H
|
||||
|
||||
|
||||
/* Options */
|
||||
|
@ -21,6 +21,7 @@
|
||||
#ifndef FREERDP_CHANNEL_RDPDR_H
|
||||
#define FREERDP_CHANNEL_RDPDR_H
|
||||
|
||||
#include <winpr/nt.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/file.h>
|
||||
#include <winpr/synch.h>
|
||||
@ -113,43 +114,14 @@ enum FILE_CREATE_DISPOSITION
|
||||
};
|
||||
|
||||
/* DR_CREATE_REQ.CreateOptions [MS-SMB2] */
|
||||
enum FILE_CREATE_OPTION
|
||||
{
|
||||
FILE_DIRECTORY_FILE = 0x00000001,
|
||||
FILE_NON_DIRECTORY_FILE = 0x00000040,
|
||||
FILE_COMPLETE_IF_OPLOCKED = 0x00000100,
|
||||
FILE_DELETE_ON_CLOSE = 0x00001000,
|
||||
FILE_OPEN_REPARSE_POINT = 0x00200000,
|
||||
FILE_OPEN_FOR_FREE_SPACE_QUERY = 0x00800000
|
||||
};
|
||||
|
||||
/* DR_CREATE_REQ.DesiredAccess [MS-SMB2] */
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#if 0
|
||||
#define FILE_READ_DATA 0x00000001
|
||||
#define FILE_WRITE_DATA 0x00000002
|
||||
#define FILE_APPEND_DATA 0x00000004
|
||||
#define FILE_READ_EA 0x00000008
|
||||
#define FILE_WRITE_EA 0x00000010
|
||||
#define FILE_EXECUTE 0x00000020
|
||||
#define FILE_READ_ATTRIBUTES 0x00000080
|
||||
#define FILE_WRITE_ATTRIBUTES 0x00000100
|
||||
#endif
|
||||
|
||||
#include <winpr/io.h>
|
||||
|
||||
#endif
|
||||
|
||||
/* DR_CREATE_RSP.Information */
|
||||
/* DR_DRIVE_CREATE_RSP.DeviceCreateResponse */
|
||||
enum FILE_RESPONSE
|
||||
{
|
||||
FILE_SUPERSEDED = 0x00000000,
|
||||
FILE_OPENED = 0x00000001,
|
||||
FILE_OVERWRITTEN = 0x00000003
|
||||
};
|
||||
|
||||
#define FILE_OPENED 0x00000001
|
||||
#define FILE_OVERWRITTEN 0x00000003
|
||||
|
||||
/* DR_CORE_CLIENT_ANNOUNCE_RSP.VersionMinor */
|
||||
enum RDPDR_MINOR_RDP_VERSION
|
||||
@ -211,73 +183,6 @@ enum RDP_LOWIO_OP
|
||||
RDP_LOWIO_OP_UNLOCK_MULTIPLE = 0x00000005
|
||||
};
|
||||
|
||||
/* NTSTATUS values */
|
||||
/* http://msdn.microsoft.com/en-us/library/cc704588.aspx */
|
||||
enum NTSTATUS
|
||||
{
|
||||
STATUS_SUCCESS = 0x00000000,
|
||||
#ifndef _WIN32
|
||||
STATUS_TIMEOUT = 0x00000102,
|
||||
STATUS_PENDING = 0x00000103,
|
||||
#endif
|
||||
STATUS_REPARSE = 0x00000104,
|
||||
STATUS_MORE_ENTRIES = 0x00000105,
|
||||
STATUS_NOT_ALL_ASSIGNED = 0x00000106,
|
||||
STATUS_OPLOCK_BREAK_IN_PROGRESS = 0x00000108,
|
||||
STATUS_VOLUME_MOUNTED = 0x00000109,
|
||||
STATUS_NOTIFY_CLEANUP = 0x0000010B,
|
||||
STATUS_NOTIFY_ENUM_DIR = 0x0000010C,
|
||||
STATUS_NO_QUOTAS_FOR_ACCOUNT = 0x0000010D,
|
||||
STATUS_FILE_LOCKED_WITH_ONLY_READERS = 0x0000012A,
|
||||
STATUS_FILE_LOCKED_WITH_WRITERS = 0x0000012B,
|
||||
STATUS_WAIT_FOR_OPLOCK = 0x00000367,
|
||||
STATUS_OBJECT_NAME_EXISTS = 0x40000000,
|
||||
STATUS_BAD_CURRENT_DIRECTORY = 0x40000007,
|
||||
STATUS_NO_MORE_FILES = 0x80000006,
|
||||
STATUS_DEVICE_PAPER_EMPTY = 0x8000000E,
|
||||
STATUS_DEVICE_POWERED_OFF = 0x8000000F,
|
||||
STATUS_DEVICE_OFF_LINE = 0x80000010,
|
||||
STATUS_DEVICE_BUSY = 0x80000011,
|
||||
STATUS_NO_MORE_ENTRIES = 0x8000001A,
|
||||
STATUS_UNSUCCESSFUL = 0xC0000001,
|
||||
STATUS_NOT_IMPLEMENTED = 0xC0000002,
|
||||
STATUS_INVALID_INFO_CLASS = 0xC0000003,
|
||||
#ifndef _WIN32
|
||||
STATUS_INVALID_HANDLE = 0xC0000008,
|
||||
STATUS_INVALID_PARAMETER = 0xC000000D,
|
||||
#endif
|
||||
STATUS_NO_SUCH_DEVICE = 0xC000000E,
|
||||
STATUS_NO_SUCH_FILE = 0xC000000F,
|
||||
STATUS_INVALID_DEVICE_REQUEST = 0xC0000010,
|
||||
STATUS_END_OF_FILE = 0xC0000011,
|
||||
STATUS_NO_MEDIA_IN_DEVICE = 0xC0000013,
|
||||
STATUS_UNRECOGNIZED_MEDIA = 0xC0000014,
|
||||
STATUS_ACCESS_DENIED = 0xc0000022,
|
||||
STATUS_OBJECT_NAME_INVALID = 0xC0000033,
|
||||
STATUS_OBJECT_NAME_NOT_FOUND = 0xC0000034,
|
||||
STATUS_OBJECT_NAME_COLLISION = 0xc0000035,
|
||||
STATUS_PORT_DISCONNECTED = 0xC0000037,
|
||||
STATUS_OBJECT_PATH_INVALID = 0xC0000039,
|
||||
STATUS_OBJECT_PATH_NOT_FOUND = 0xC000003A,
|
||||
STATUS_INVALID_PORT_HANDLE = 0xC0000042,
|
||||
STATUS_DELETE_PENDING = 0xC0000056,
|
||||
STATUS_DISK_FULL = 0xC000007F,
|
||||
STATUS_DEVICE_NOT_READY = 0xC00000A3,
|
||||
STATUS_IO_TIMEOUT = 0xC00000B5,
|
||||
STATUS_FILE_IS_A_DIRECTORY = 0xC00000BA,
|
||||
STATUS_NOT_SUPPORTED = 0xC00000BB,
|
||||
STATUS_PRINT_QUEUE_FULL = 0xC00000C6,
|
||||
STATUS_PRINT_CANCELLED = 0xC00000C8,
|
||||
STATUS_DIRECTORY_NOT_EMPTY = 0xC0000101,
|
||||
STATUS_FILE_CORRUPT_ERROR = 0xC0000102,
|
||||
STATUS_NOT_A_DIRECTORY = 0xC0000103,
|
||||
STATUS_NAME_TOO_LONG = 0xC0000106,
|
||||
STATUS_CANCELLED = 0xC0000120,
|
||||
STATUS_CANNOT_DELETE = 0xC0000121,
|
||||
STATUS_FILE_DELETED = 0xC0000123,
|
||||
STATUS_FILE_CLOSED = 0xC0000128
|
||||
};
|
||||
|
||||
enum RDPDR_PRINTER_ANNOUNCE_FLAG
|
||||
{
|
||||
RDPDR_PRINTER_ANNOUNCE_FLAG_ASCII = 0x00000001,
|
||||
|
@ -35,17 +35,27 @@
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/peer.h>
|
||||
|
||||
typedef struct WTSVirtualChannelManager WTSVirtualChannelManager;
|
||||
|
||||
#define WTS_CHANNEL_OPTION_DYNAMIC 0x00000001
|
||||
#include <winpr/winpr.h>
|
||||
#include <winpr/wtypes.h>
|
||||
//#include <winpr/wtsapi.h>
|
||||
|
||||
typedef enum _WTS_VIRTUAL_CLASS
|
||||
{
|
||||
WTSVirtualClientData,
|
||||
WTSVirtualFileHandle,
|
||||
WTSVirtualChannelReady
|
||||
WTSVirtualEventHandle, /* Extended */
|
||||
WTSVirtualChannelReady /* Extended */
|
||||
} WTS_VIRTUAL_CLASS;
|
||||
|
||||
#define WTS_CHANNEL_OPTION_DYNAMIC 0x00000001
|
||||
#define WTS_CHANNEL_OPTION_DYNAMIC_PRI_LOW 0x00000000
|
||||
#define WTS_CHANNEL_OPTION_DYNAMIC_PRI_MED 0x00000002
|
||||
#define WTS_CHANNEL_OPTION_DYNAMIC_PRI_HIGH 0x00000004
|
||||
#define WTS_CHANNEL_OPTION_DYNAMIC_PRI_REAL 0x00000006
|
||||
#define WTS_CHANNEL_OPTION_DYNAMIC_NO_COMPRESS 0x00000008
|
||||
|
||||
typedef struct WTSVirtualChannelManager WTSVirtualChannelManager;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -55,9 +65,10 @@ extern "C" {
|
||||
*/
|
||||
FREERDP_API WTSVirtualChannelManager* WTSCreateVirtualChannelManager(freerdp_peer* client);
|
||||
FREERDP_API void WTSDestroyVirtualChannelManager(WTSVirtualChannelManager* vcm);
|
||||
FREERDP_API void WTSVirtualChannelManagerGetFileDescriptor(WTSVirtualChannelManager* vcm,
|
||||
void** fds, int* fds_count);
|
||||
|
||||
FREERDP_API void WTSVirtualChannelManagerGetFileDescriptor(WTSVirtualChannelManager* vcm, void** fds, int* fds_count);
|
||||
FREERDP_API BOOL WTSVirtualChannelManagerCheckFileDescriptor(WTSVirtualChannelManager* vcm);
|
||||
FREERDP_API HANDLE WTSVirtualChannelManagerGetEventHandle(WTSVirtualChannelManager* vcm);
|
||||
|
||||
/**
|
||||
* Opens a static or dynamic virtual channel and return the handle. If the
|
||||
@ -69,10 +80,10 @@ FREERDP_API BOOL WTSVirtualChannelManagerCheckFileDescriptor(WTSVirtualChannelMa
|
||||
* Static virtual channels must be opened from the main thread. Dynamic virtual channels
|
||||
* can be opened from any thread.
|
||||
*/
|
||||
FREERDP_API void* WTSVirtualChannelOpenEx(
|
||||
/* __in */ WTSVirtualChannelManager* vcm,
|
||||
/* __in */ const char* pVirtualName,
|
||||
/* __in */ UINT32 flags);
|
||||
|
||||
// WINPR_API HANDLE WTSVirtualChannelOpenEx(DWORD SessionId, LPSTR pVirtualName, DWORD flags);
|
||||
|
||||
WINPR_API HANDLE WTSVirtualChannelManagerOpenEx(WTSVirtualChannelManager* vcm, LPSTR pVirtualName, DWORD flags);
|
||||
|
||||
/**
|
||||
* Returns information about a specified virtual channel.
|
||||
@ -80,17 +91,14 @@ FREERDP_API void* WTSVirtualChannelOpenEx(
|
||||
* Servers use this function to gain access to a virtual channel file handle
|
||||
* that can be used for asynchronous I/O.
|
||||
*/
|
||||
FREERDP_API BOOL WTSVirtualChannelQuery(
|
||||
/* __in */ void* hChannelHandle,
|
||||
/* __in */ WTS_VIRTUAL_CLASS WtsVirtualClass,
|
||||
/* __out */ void** ppBuffer,
|
||||
/* __out */ UINT32* pBytesReturned);
|
||||
|
||||
WINPR_API BOOL WTSVirtualChannelQuery(HANDLE hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass, PVOID* ppBuffer, DWORD* pBytesReturned);
|
||||
|
||||
/**
|
||||
* Frees memory allocated by WTSVirtualChannelQuery
|
||||
*/
|
||||
FREERDP_API void WTSFreeMemory(
|
||||
/* __in */ void* pMemory);
|
||||
|
||||
WINPR_API VOID WTSFreeMemory(PVOID pMemory);
|
||||
|
||||
/**
|
||||
* Reads data from the server end of a virtual channel.
|
||||
@ -109,27 +117,20 @@ FREERDP_API void WTSFreeMemory(
|
||||
* The caller should use the file handle returned by WTSVirtualChannelQuery to
|
||||
* determine whether a packet has arrived.
|
||||
*/
|
||||
FREERDP_API BOOL WTSVirtualChannelRead(
|
||||
/* __in */ void* hChannelHandle,
|
||||
/* __in */ UINT32 TimeOut,
|
||||
/* __out */ BYTE* Buffer,
|
||||
/* __in */ UINT32 BufferSize,
|
||||
/* __out */ UINT32* pBytesRead);
|
||||
|
||||
WINPR_API BOOL WTSVirtualChannelRead(HANDLE hChannelHandle, ULONG TimeOut, PCHAR Buffer, ULONG BufferSize, PULONG pBytesRead);
|
||||
|
||||
/**
|
||||
* Writes data to the server end of a virtual channel.
|
||||
*/
|
||||
FREERDP_API BOOL WTSVirtualChannelWrite(
|
||||
/* __in */ void* hChannelHandle,
|
||||
/* __in */ BYTE* Buffer,
|
||||
/* __in */ UINT32 Length,
|
||||
/* __out */ UINT32* pBytesWritten);
|
||||
|
||||
WINPR_API BOOL WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer, ULONG Length, PULONG pBytesWritten);
|
||||
|
||||
/**
|
||||
* Closes an open virtual channel handle.
|
||||
*/
|
||||
FREERDP_API BOOL WTSVirtualChannelClose(
|
||||
/* __in */ void* hChannelHandle);
|
||||
|
||||
WINPR_API BOOL WTSVirtualChannelClose(HANDLE hChannelHandle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -20,6 +20,8 @@
|
||||
#ifndef FREERDP_CHANNEL_CLIENT_CLIPRDR_H
|
||||
#define FREERDP_CHANNEL_CLIENT_CLIPRDR_H
|
||||
|
||||
#include <freerdp/types.h>
|
||||
|
||||
/**
|
||||
* Client Interface
|
||||
*/
|
||||
@ -52,6 +54,48 @@ struct _cliprdr_client_context
|
||||
#define CB_FORMAT_JPEG 0xD012
|
||||
#define CB_FORMAT_GIF 0xD013
|
||||
|
||||
/* CLIPRDR_HEADER.msgType */
|
||||
#define CB_MONITOR_READY 0x0001
|
||||
#define CB_FORMAT_LIST 0x0002
|
||||
#define CB_FORMAT_LIST_RESPONSE 0x0003
|
||||
#define CB_FORMAT_DATA_REQUEST 0x0004
|
||||
#define CB_FORMAT_DATA_RESPONSE 0x0005
|
||||
#define CB_TEMP_DIRECTORY 0x0006
|
||||
#define CB_CLIP_CAPS 0x0007
|
||||
#define CB_FILECONTENTS_REQUEST 0x0008
|
||||
#define CB_FILECONTENTS_RESPONSE 0x0009
|
||||
#define CB_LOCK_CLIPDATA 0x000A
|
||||
#define CB_UNLOCK_CLIPDATA 0x000B
|
||||
|
||||
/* CLIPRDR_HEADER.msgFlags */
|
||||
#define CB_RESPONSE_OK 0x0001
|
||||
#define CB_RESPONSE_FAIL 0x0002
|
||||
#define CB_ASCII_NAMES 0x0004
|
||||
|
||||
/* CLIPRDR_CAPS_SET.capabilitySetType */
|
||||
#define CB_CAPSTYPE_GENERAL 0x0001
|
||||
|
||||
/* CLIPRDR_GENERAL_CAPABILITY.lengthCapability */
|
||||
#define CB_CAPSTYPE_GENERAL_LEN 12
|
||||
|
||||
/* CLIPRDR_GENERAL_CAPABILITY.version */
|
||||
#define CB_CAPS_VERSION_1 0x00000001
|
||||
#define CB_CAPS_VERSION_2 0x00000002
|
||||
|
||||
/* CLIPRDR_GENERAL_CAPABILITY.generalFlags */
|
||||
#define CB_USE_LONG_FORMAT_NAMES 0x00000002
|
||||
#define CB_STREAM_FILECLIP_ENABLED 0x00000004
|
||||
#define CB_FILECLIP_NO_FILE_PATHS 0x00000008
|
||||
#define CB_CAN_LOCK_CLIPDATA 0x00000010
|
||||
|
||||
struct _CLIPRDR_FORMAT_NAME
|
||||
{
|
||||
UINT32 id;
|
||||
char* name;
|
||||
int length;
|
||||
};
|
||||
typedef struct _CLIPRDR_FORMAT_NAME CLIPRDR_FORMAT_NAME;
|
||||
|
||||
/**
|
||||
* Clipboard Events
|
||||
*/
|
||||
|
@ -50,6 +50,7 @@ struct _NSC_MESSAGE
|
||||
UINT32 height;
|
||||
BYTE* data;
|
||||
int scanline;
|
||||
BYTE* PlaneBuffer;
|
||||
UINT32 MaxPlaneSize;
|
||||
BYTE* PlaneBuffers[5];
|
||||
UINT32 OrgByteCount[4];
|
||||
|
@ -56,7 +56,6 @@ struct _RFX_TILE
|
||||
BYTE* data;
|
||||
int scanline;
|
||||
BOOL allocated;
|
||||
|
||||
BYTE quantIdxY;
|
||||
BYTE quantIdxCb;
|
||||
BYTE quantIdxCr;
|
||||
@ -68,6 +67,7 @@ struct _RFX_TILE
|
||||
BYTE* YData;
|
||||
BYTE* CbData;
|
||||
BYTE* CrData;
|
||||
BYTE* YCbCrData;
|
||||
};
|
||||
typedef struct _RFX_TILE RFX_TILE;
|
||||
|
||||
@ -118,6 +118,7 @@ struct _RFX_CONTEXT
|
||||
{
|
||||
RFX_STATE state;
|
||||
|
||||
BOOL encoder;
|
||||
UINT16 flags;
|
||||
UINT16 properties;
|
||||
UINT16 width;
|
||||
@ -153,7 +154,7 @@ struct _RFX_CONTEXT
|
||||
};
|
||||
typedef struct _RFX_CONTEXT RFX_CONTEXT;
|
||||
|
||||
FREERDP_API RFX_CONTEXT* rfx_context_new(void);
|
||||
FREERDP_API RFX_CONTEXT* rfx_context_new(BOOL encoder);
|
||||
FREERDP_API void rfx_context_free(RFX_CONTEXT* context);
|
||||
FREERDP_API void rfx_context_set_pixel_format(RFX_CONTEXT* context, RDP_PIXEL_FORMAT pixel_format);
|
||||
FREERDP_API void rfx_context_reset(RFX_CONTEXT* context);
|
||||
|
51
include/freerdp/server/cliprdr.h
Normal file
51
include/freerdp/server/cliprdr.h
Normal file
@ -0,0 +1,51 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Clipboard Virtual Channel Server Interface
|
||||
*
|
||||
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.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_SERVER_CLIPRDR_H
|
||||
#define FREERDP_CHANNEL_SERVER_CLIPRDR_H
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/channels/wtsvc.h>
|
||||
#include <freerdp/client/cliprdr.h>
|
||||
|
||||
/**
|
||||
* Server Interface
|
||||
*/
|
||||
|
||||
typedef struct _cliprdr_server_context CliprdrServerContext;
|
||||
typedef struct _cliprdr_server_private CliprdrServerPrivate;
|
||||
|
||||
typedef int (*psCliprdrStart)(CliprdrServerContext* context);
|
||||
typedef int (*psCliprdrStop)(CliprdrServerContext* context);
|
||||
|
||||
struct _cliprdr_server_context
|
||||
{
|
||||
WTSVirtualChannelManager* vcm;
|
||||
|
||||
psCliprdrStart Start;
|
||||
psCliprdrStop Stop;
|
||||
|
||||
CliprdrServerPrivate* priv;
|
||||
};
|
||||
|
||||
FREERDP_API CliprdrServerContext* cliprdr_server_context_new(WTSVirtualChannelManager* vcm);
|
||||
FREERDP_API void cliprdr_server_context_free(CliprdrServerContext* context);
|
||||
|
||||
#endif /* FREERDP_CHANNEL_SERVER_CLIPRDR_H */
|
50
include/freerdp/server/drdynvc.h
Normal file
50
include/freerdp/server/drdynvc.h
Normal file
@ -0,0 +1,50 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Dynamic Virtual Channel Extension
|
||||
*
|
||||
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.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_SERVER_DRDYNVC_H
|
||||
#define FREERDP_CHANNEL_SERVER_DRDYNVC_H
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/channels/wtsvc.h>
|
||||
|
||||
/**
|
||||
* Server Interface
|
||||
*/
|
||||
|
||||
typedef struct _drdynvc_client_context DrdynvcServerContext;
|
||||
typedef struct _drdynvc_server_private DrdynvcServerPrivate;
|
||||
|
||||
typedef int (*psDrdynvcStart)(DrdynvcServerContext* context);
|
||||
typedef int (*psDrdynvcStop)(DrdynvcServerContext* context);
|
||||
|
||||
struct _drdynvc_client_context
|
||||
{
|
||||
WTSVirtualChannelManager* vcm;
|
||||
|
||||
psDrdynvcStart Start;
|
||||
psDrdynvcStop Stop;
|
||||
|
||||
DrdynvcServerPrivate* priv;
|
||||
};
|
||||
|
||||
FREERDP_API DrdynvcServerContext* drdynvc_server_context_new(WTSVirtualChannelManager* vcm);
|
||||
FREERDP_API void drdynvc_server_context_free(DrdynvcServerContext* context);
|
||||
|
||||
#endif /* FREERDP_CHANNEL_SERVER_DRDYNVC_H */
|
51
include/freerdp/server/rdpdr.h
Normal file
51
include/freerdp/server/rdpdr.h
Normal file
@ -0,0 +1,51 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Device Redirection Virtual Channel Server Interface
|
||||
*
|
||||
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.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_SERVER_RDPDR_H
|
||||
#define FREERDP_CHANNEL_SERVER_RDPDR_H
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/channels/wtsvc.h>
|
||||
#include <freerdp/channels/rdpdr.h>
|
||||
|
||||
/**
|
||||
* Server Interface
|
||||
*/
|
||||
|
||||
typedef struct _rdpdr_server_context RdpdrServerContext;
|
||||
typedef struct _rdpdr_server_private RdpdrServerPrivate;
|
||||
|
||||
typedef int (*psRdpdrStart)(RdpdrServerContext* context);
|
||||
typedef int (*psRdpdrStop)(RdpdrServerContext* context);
|
||||
|
||||
struct _rdpdr_server_context
|
||||
{
|
||||
WTSVirtualChannelManager* vcm;
|
||||
|
||||
psRdpdrStart Start;
|
||||
psRdpdrStop Stop;
|
||||
|
||||
RdpdrServerPrivate* priv;
|
||||
};
|
||||
|
||||
FREERDP_API RdpdrServerContext* rdpdr_server_context_new(WTSVirtualChannelManager* vcm);
|
||||
FREERDP_API void rdpdr_server_context_free(RdpdrServerContext* context);
|
||||
|
||||
#endif /* FREERDP_CHANNEL_SERVER_RDPDR_H */
|
@ -23,20 +23,30 @@
|
||||
#include <freerdp/channels/wtsvc.h>
|
||||
#include <freerdp/channels/rdpsnd.h>
|
||||
|
||||
typedef struct _rdpsnd_server_context RdpsndServerContext;
|
||||
typedef struct _rdpsnd_server_context rdpsnd_server_context;
|
||||
typedef struct _rdpsnd_server_private RdpsndServerPrivate;
|
||||
|
||||
typedef BOOL (*psRdpsndServerInitialize)(rdpsnd_server_context* context);
|
||||
typedef void (*psRdpsndServerSelectFormat)(rdpsnd_server_context* context, int client_format_index);
|
||||
typedef BOOL (*psRdpsndServerSendSamples)(rdpsnd_server_context* context, const void* buf, int nframes);
|
||||
typedef BOOL (*psRdpsndServerSetVolume)(rdpsnd_server_context* context, int left, int right);
|
||||
typedef BOOL (*psRdpsndServerClose)(rdpsnd_server_context* context);
|
||||
typedef int (*psRdpsndStart)(RdpsndServerContext* context);
|
||||
typedef int (*psRdpsndStop)(RdpsndServerContext* context);
|
||||
|
||||
typedef void (*psRdpsndServerActivated)(rdpsnd_server_context* context);
|
||||
typedef BOOL (*psRdpsndServerInitialize)(RdpsndServerContext* context);
|
||||
typedef void (*psRdpsndServerSelectFormat)(RdpsndServerContext* context, int client_format_index);
|
||||
typedef BOOL (*psRdpsndServerSendSamples)(RdpsndServerContext* context, const void* buf, int nframes);
|
||||
typedef BOOL (*psRdpsndServerSetVolume)(RdpsndServerContext* context, int left, int right);
|
||||
typedef BOOL (*psRdpsndServerClose)(RdpsndServerContext* context);
|
||||
|
||||
typedef void (*psRdpsndServerActivated)(RdpsndServerContext* context);
|
||||
|
||||
struct _rdpsnd_server_context
|
||||
{
|
||||
WTSVirtualChannelManager* vcm;
|
||||
|
||||
psRdpsndStart Start;
|
||||
psRdpsndStop Stop;
|
||||
|
||||
RdpsndServerPrivate* priv;
|
||||
|
||||
/* Server self-defined pointer. */
|
||||
void* data;
|
||||
|
||||
@ -95,8 +105,8 @@ struct _rdpsnd_server_context
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
FREERDP_API rdpsnd_server_context* rdpsnd_server_context_new(WTSVirtualChannelManager* vcm);
|
||||
FREERDP_API void rdpsnd_server_context_free(rdpsnd_server_context* context);
|
||||
FREERDP_API RdpsndServerContext* rdpsnd_server_context_new(WTSVirtualChannelManager* vcm);
|
||||
FREERDP_API void rdpsnd_server_context_free(RdpsndServerContext* context);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -59,11 +59,7 @@ if(MONOLITHIC_BUILD)
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
if(NOT WITH_WAYK)
|
||||
install(TARGETS ${MODULE_NAME}
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
COMPONENT libraries)
|
||||
endif()
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libraries)
|
||||
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "FreeRDP/libfreerdp")
|
||||
endif()
|
||||
|
@ -390,6 +390,7 @@ NSC_MESSAGE* nsc_encode_messages(NSC_CONTEXT* context, BYTE* data, int x, int y,
|
||||
UINT32 MaxPlaneSize;
|
||||
UINT32 MaxMessageSize;
|
||||
NSC_MESSAGE* messages;
|
||||
UINT32 PaddedMaxPlaneSize;
|
||||
|
||||
k = 0;
|
||||
MaxRegionWidth = 64 * 4;
|
||||
@ -430,11 +431,15 @@ NSC_MESSAGE* nsc_encode_messages(NSC_CONTEXT* context, BYTE* data, int x, int y,
|
||||
|
||||
for (i = 0; i < *numMessages; i++)
|
||||
{
|
||||
messages[i].PlaneBuffers[0] = (BYTE*) BufferPool_Take(context->priv->PlanePool, messages[i].MaxPlaneSize);
|
||||
messages[i].PlaneBuffers[1] = (BYTE*) BufferPool_Take(context->priv->PlanePool, messages[i].MaxPlaneSize);
|
||||
messages[i].PlaneBuffers[2] = (BYTE*) BufferPool_Take(context->priv->PlanePool, messages[i].MaxPlaneSize);
|
||||
messages[i].PlaneBuffers[3] = (BYTE*) BufferPool_Take(context->priv->PlanePool, messages[i].MaxPlaneSize);
|
||||
messages[i].PlaneBuffers[4] = (BYTE*) BufferPool_Take(context->priv->PlanePool, messages[i].MaxPlaneSize);
|
||||
PaddedMaxPlaneSize = messages[i].MaxPlaneSize + 32;
|
||||
|
||||
messages[i].PlaneBuffer = (BYTE*) BufferPool_Take(context->priv->PlanePool, PaddedMaxPlaneSize * 5);
|
||||
|
||||
messages[i].PlaneBuffers[0] = (BYTE*) &(messages[i].PlaneBuffer[(PaddedMaxPlaneSize * 0) + 16]);
|
||||
messages[i].PlaneBuffers[1] = (BYTE*) &(messages[i].PlaneBuffer[(PaddedMaxPlaneSize * 1) + 16]);
|
||||
messages[i].PlaneBuffers[2] = (BYTE*) &(messages[i].PlaneBuffer[(PaddedMaxPlaneSize * 2) + 16]);
|
||||
messages[i].PlaneBuffers[3] = (BYTE*) &(messages[i].PlaneBuffer[(PaddedMaxPlaneSize * 3) + 16]);
|
||||
messages[i].PlaneBuffers[4] = (BYTE*) &(messages[i].PlaneBuffer[(PaddedMaxPlaneSize * 4) + 16]);
|
||||
}
|
||||
|
||||
for (i = 0; i < *numMessages; i++)
|
||||
@ -504,11 +509,7 @@ int nsc_write_message(NSC_CONTEXT* context, wStream* s, NSC_MESSAGE* message)
|
||||
|
||||
int nsc_message_free(NSC_CONTEXT* context, NSC_MESSAGE* message)
|
||||
{
|
||||
BufferPool_Return(context->priv->PlanePool, message->PlaneBuffers[0]);
|
||||
BufferPool_Return(context->priv->PlanePool, message->PlaneBuffers[1]);
|
||||
BufferPool_Return(context->priv->PlanePool, message->PlaneBuffers[2]);
|
||||
BufferPool_Return(context->priv->PlanePool, message->PlaneBuffers[3]);
|
||||
BufferPool_Return(context->priv->PlanePool, message->PlaneBuffers[4]);
|
||||
BufferPool_Return(context->priv->PlanePool, message->PlaneBuffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -154,7 +154,7 @@ void rfx_tile_init(RFX_TILE* tile)
|
||||
}
|
||||
}
|
||||
|
||||
RFX_TILE* rfx_tile_new()
|
||||
RFX_TILE* rfx_decoder_tile_new()
|
||||
{
|
||||
RFX_TILE* tile = NULL;
|
||||
|
||||
@ -171,7 +171,7 @@ RFX_TILE* rfx_tile_new()
|
||||
return tile;
|
||||
}
|
||||
|
||||
void rfx_tile_free(RFX_TILE* tile)
|
||||
void rfx_decoder_tile_free(RFX_TILE* tile)
|
||||
{
|
||||
if (tile)
|
||||
{
|
||||
@ -181,7 +181,29 @@ void rfx_tile_free(RFX_TILE* tile)
|
||||
}
|
||||
}
|
||||
|
||||
RFX_CONTEXT* rfx_context_new(void)
|
||||
RFX_TILE* rfx_encoder_tile_new()
|
||||
{
|
||||
RFX_TILE* tile = NULL;
|
||||
|
||||
tile = (RFX_TILE*) malloc(sizeof(RFX_TILE));
|
||||
|
||||
if (tile)
|
||||
{
|
||||
ZeroMemory(tile, sizeof(RFX_TILE));
|
||||
}
|
||||
|
||||
return tile;
|
||||
}
|
||||
|
||||
void rfx_encoder_tile_free(RFX_TILE* tile)
|
||||
{
|
||||
if (tile)
|
||||
{
|
||||
free(tile);
|
||||
}
|
||||
}
|
||||
|
||||
RFX_CONTEXT* rfx_context_new(BOOL encoder)
|
||||
{
|
||||
HKEY hKey;
|
||||
LONG status;
|
||||
@ -194,13 +216,24 @@ RFX_CONTEXT* rfx_context_new(void)
|
||||
context = (RFX_CONTEXT*) malloc(sizeof(RFX_CONTEXT));
|
||||
ZeroMemory(context, sizeof(RFX_CONTEXT));
|
||||
|
||||
context->encoder = encoder;
|
||||
|
||||
context->priv = (RFX_CONTEXT_PRIV*) malloc(sizeof(RFX_CONTEXT_PRIV));
|
||||
ZeroMemory(context->priv, sizeof(RFX_CONTEXT_PRIV));
|
||||
|
||||
context->priv->TilePool = ObjectPool_New(TRUE);
|
||||
ObjectPool_Object(context->priv->TilePool)->fnObjectNew = (OBJECT_NEW_FN) rfx_tile_new;
|
||||
ObjectPool_Object(context->priv->TilePool)->fnObjectInit = (OBJECT_INIT_FN) rfx_tile_init;
|
||||
ObjectPool_Object(context->priv->TilePool)->fnObjectFree = (OBJECT_FREE_FN) rfx_tile_free;
|
||||
|
||||
if (context->encoder)
|
||||
{
|
||||
ObjectPool_Object(context->priv->TilePool)->fnObjectNew = (OBJECT_NEW_FN) rfx_encoder_tile_new;
|
||||
ObjectPool_Object(context->priv->TilePool)->fnObjectFree = (OBJECT_FREE_FN) rfx_encoder_tile_free;
|
||||
}
|
||||
else
|
||||
{
|
||||
ObjectPool_Object(context->priv->TilePool)->fnObjectNew = (OBJECT_NEW_FN) rfx_decoder_tile_new;
|
||||
ObjectPool_Object(context->priv->TilePool)->fnObjectFree = (OBJECT_FREE_FN) rfx_decoder_tile_free;
|
||||
}
|
||||
|
||||
/*
|
||||
* align buffers to 16 byte boundary (needed for SSE/NEON instructions)
|
||||
@ -212,9 +245,11 @@ RFX_CONTEXT* rfx_context_new(void)
|
||||
* in order to allow optimized functions (SEE, NEON) to read from positions
|
||||
* that are actually in front/beyond the buffer. Offset calculations are
|
||||
* performed at the BufferPool_Take function calls in rfx_encode/decode.c.
|
||||
*
|
||||
* We then multiply by 3 to use a single, partioned buffer for all 3 channels.
|
||||
*/
|
||||
|
||||
context->priv->BufferPool = BufferPool_New(TRUE, 8192 + 32, 16);
|
||||
context->priv->BufferPool = BufferPool_New(TRUE, (8192 + 32) * 3, 16);
|
||||
|
||||
#ifdef _WIN32
|
||||
{
|
||||
@ -937,14 +972,11 @@ void rfx_message_free(RFX_CONTEXT* context, RFX_MESSAGE* message)
|
||||
{
|
||||
tile = message->tiles[i];
|
||||
|
||||
if (tile->YData)
|
||||
BufferPool_Return(context->priv->BufferPool, tile->YData);
|
||||
|
||||
if (tile->CbData)
|
||||
BufferPool_Return(context->priv->BufferPool, tile->CbData);
|
||||
|
||||
if (tile->CrData)
|
||||
BufferPool_Return(context->priv->BufferPool, tile->CrData);
|
||||
if (tile->YCbCrData)
|
||||
{
|
||||
BufferPool_Return(context->priv->BufferPool, tile->YCbCrData);
|
||||
tile->YCbCrData = NULL;
|
||||
}
|
||||
|
||||
ObjectPool_Return(context->priv->TilePool, (void*) tile);
|
||||
}
|
||||
@ -1105,7 +1137,7 @@ RFX_MESSAGE* rfx_encode_message(RFX_CONTEXT* context, const RFX_RECT* rects,
|
||||
{
|
||||
context->numQuant = 1;
|
||||
context->quants = (UINT32*) malloc(sizeof(rfx_default_quantization_values));
|
||||
memcpy(context->quants, rfx_default_quantization_values, sizeof(rfx_default_quantization_values));
|
||||
CopyMemory(context->quants, &rfx_default_quantization_values, sizeof(rfx_default_quantization_values));
|
||||
context->quantIdxY = 0;
|
||||
context->quantIdxCb = 0;
|
||||
context->quantIdxCr = 0;
|
||||
@ -1186,9 +1218,12 @@ RFX_MESSAGE* rfx_encode_message(RFX_CONTEXT* context, const RFX_RECT* rects,
|
||||
tile->YLen = 0;
|
||||
tile->CbLen = 0;
|
||||
tile->CrLen = 0;
|
||||
tile->YData = (BYTE*) BufferPool_Take(context->priv->BufferPool, -1);
|
||||
tile->CbData = (BYTE*) BufferPool_Take(context->priv->BufferPool, -1);
|
||||
tile->CrData = (BYTE*) BufferPool_Take(context->priv->BufferPool, -1);
|
||||
|
||||
tile->YCbCrData = (BYTE*) BufferPool_Take(context->priv->BufferPool, -1);
|
||||
|
||||
tile->YData = (BYTE*) &(tile->YCbCrData[((8192 + 32) * 0) + 16]);
|
||||
tile->CbData = (BYTE*) &(tile->YCbCrData[((8192 + 32) * 1) + 16]);
|
||||
tile->CrData = (BYTE*) &(tile->YCbCrData[((8192 + 32) * 2) + 16]);
|
||||
|
||||
if (context->priv->UseThreads)
|
||||
{
|
||||
@ -1294,9 +1329,6 @@ RFX_MESSAGE* rfx_encode_messages(RFX_CONTEXT* context, const RFX_RECT* rects, in
|
||||
RFX_MESSAGE* message;
|
||||
RFX_MESSAGE* messages;
|
||||
|
||||
printf("rfx_encode_messages: numRects: %d maxDataSize: %d x: %d y: %d w: %d/%d h: %d/%d\n", numRects, maxDataSize,
|
||||
rects[0].x, rects[0].y, rects[0].width, width, rects[0].height, height);
|
||||
|
||||
message = rfx_encode_message(context, rects, numRects, data, width, height, scanline);
|
||||
messages = rfx_split_message(context, message, numMessages, maxDataSize);
|
||||
rfx_message_free(context, message);
|
||||
|
@ -128,6 +128,7 @@ static void rfx_decode_component(RFX_CONTEXT* context, const UINT32* quantizatio
|
||||
/* stride is bytes between rows in the output buffer. */
|
||||
BOOL rfx_decode_rgb(RFX_CONTEXT* context, RFX_TILE* tile, BYTE* rgb_buffer, int stride)
|
||||
{
|
||||
BYTE* pBuffer;
|
||||
INT16* pSrcDst[3];
|
||||
UINT32 *y_quants, *cb_quants, *cr_quants;
|
||||
static const prim_size_t roi_64x64 = { 64, 64 };
|
||||
@ -139,9 +140,10 @@ BOOL rfx_decode_rgb(RFX_CONTEXT* context, RFX_TILE* tile, BYTE* rgb_buffer, int
|
||||
cb_quants = context->quants + (tile->quantIdxCb * 10);
|
||||
cr_quants = context->quants + (tile->quantIdxCr * 10);
|
||||
|
||||
pSrcDst[0] = (INT16*)((BYTE*)BufferPool_Take(context->priv->BufferPool, -1) + 16); /* y_r_buffer */
|
||||
pSrcDst[1] = (INT16*)((BYTE*)BufferPool_Take(context->priv->BufferPool, -1) + 16); /* cb_g_buffer */
|
||||
pSrcDst[2] = (INT16*)((BYTE*)BufferPool_Take(context->priv->BufferPool, -1) + 16); /* cr_b_buffer */
|
||||
pBuffer = (BYTE*) BufferPool_Take(context->priv->BufferPool, -1);
|
||||
pSrcDst[0] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 0) + 16])); /* y_r_buffer */
|
||||
pSrcDst[1] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 1) + 16])); /* cb_g_buffer */
|
||||
pSrcDst[2] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 2) + 16])); /* cr_b_buffer */
|
||||
|
||||
rfx_decode_component(context, y_quants, tile->YData, tile->YLen, pSrcDst[0]); /* YData */
|
||||
|
||||
@ -161,9 +163,7 @@ BOOL rfx_decode_rgb(RFX_CONTEXT* context, RFX_TILE* tile, BYTE* rgb_buffer, int
|
||||
|
||||
PROFILER_EXIT(context->priv->prof_rfx_decode_rgb);
|
||||
|
||||
BufferPool_Return(context->priv->BufferPool, (BYTE*)pSrcDst[0] - 16);
|
||||
BufferPool_Return(context->priv->BufferPool, (BYTE*)pSrcDst[1] - 16);
|
||||
BufferPool_Return(context->priv->BufferPool, (BYTE*)pSrcDst[2] - 16);
|
||||
BufferPool_Return(context->priv->BufferPool, pBuffer);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -219,6 +219,7 @@ static void rfx_encode_component(RFX_CONTEXT* context, const UINT32* quantizatio
|
||||
|
||||
void rfx_encode_rgb(RFX_CONTEXT* context, RFX_TILE* tile)
|
||||
{
|
||||
BYTE* pBuffer;
|
||||
INT16* pSrcDst[3];
|
||||
int YLen, CbLen, CrLen;
|
||||
UINT32 *YQuant, *CbQuant, *CrQuant;
|
||||
@ -230,9 +231,10 @@ void rfx_encode_rgb(RFX_CONTEXT* context, RFX_TILE* tile)
|
||||
CbQuant = context->quants + (tile->quantIdxCb * 10);
|
||||
CrQuant = context->quants + (tile->quantIdxCr * 10);
|
||||
|
||||
pSrcDst[0] = (INT16*)((BYTE*)BufferPool_Take(context->priv->BufferPool, -1) + 16); /* y_r_buffer */
|
||||
pSrcDst[1] = (INT16*)((BYTE*)BufferPool_Take(context->priv->BufferPool, -1) + 16); /* cb_g_buffer */
|
||||
pSrcDst[2] = (INT16*)((BYTE*)BufferPool_Take(context->priv->BufferPool, -1) + 16); /* cr_b_buffer */
|
||||
pBuffer = (BYTE*) BufferPool_Take(context->priv->BufferPool, -1);
|
||||
pSrcDst[0] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 0) + 16])); /* y_r_buffer */
|
||||
pSrcDst[1] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 1) + 16])); /* cb_g_buffer */
|
||||
pSrcDst[2] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 2) + 16])); /* cr_b_buffer */
|
||||
|
||||
PROFILER_ENTER(context->priv->prof_rfx_encode_rgb);
|
||||
|
||||
@ -265,7 +267,5 @@ void rfx_encode_rgb(RFX_CONTEXT* context, RFX_TILE* tile)
|
||||
|
||||
PROFILER_EXIT(context->priv->prof_rfx_encode_rgb);
|
||||
|
||||
BufferPool_Return(context->priv->BufferPool, (BYTE*)pSrcDst[0] - 16);
|
||||
BufferPool_Return(context->priv->BufferPool, (BYTE*)pSrcDst[1] - 16);
|
||||
BufferPool_Return(context->priv->BufferPool, (BYTE*)pSrcDst[2] - 16);
|
||||
BufferPool_Return(context->priv->BufferPool, pBuffer);
|
||||
}
|
||||
|
@ -136,7 +136,7 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||
MODULE winpr
|
||||
MODULES winpr-registry winpr-utils winpr-interlocked winpr-dsparse winpr-sspi winpr-rpc winpr-crt)
|
||||
MODULES winpr-registry winpr-utils winpr-interlocked winpr-dsparse winpr-sspi winpr-rpc winpr-handle winpr-crt)
|
||||
|
||||
if(MONOLITHIC_BUILD)
|
||||
set(FREERDP_LIBS ${FREERDP_LIBS} ${${MODULE_PREFIX}_LIBS} PARENT_SCOPE)
|
||||
|
@ -120,6 +120,7 @@ BOOL rdp_read_extended_info_packet(wStream* s, rdpSettings* settings)
|
||||
|
||||
if (Stream_GetRemainingLength(s) < 4)
|
||||
return FALSE;
|
||||
|
||||
Stream_Read_UINT16(s, clientAddressFamily); /* clientAddressFamily */
|
||||
Stream_Read_UINT16(s, cbClientAddress); /* cbClientAddress */
|
||||
|
||||
@ -149,6 +150,7 @@ BOOL rdp_read_extended_info_packet(wStream* s, rdpSettings* settings)
|
||||
|
||||
if (Stream_GetRemainingLength(s) < 10)
|
||||
return FALSE;
|
||||
|
||||
Stream_Seek_UINT32(s); /* clientSessionId, should be set to 0 */
|
||||
Stream_Read_UINT32(s, settings->PerformanceFlags); /* performanceFlags */
|
||||
|
||||
|
@ -191,11 +191,15 @@ BOOL license_send(rdpLicense* license, wStream* s, BYTE type)
|
||||
sec_flags = SEC_LICENSE_PKT;
|
||||
wMsgSize = length - LICENSE_PACKET_HEADER_MAX_LENGTH + 4;
|
||||
|
||||
flags = PREAMBLE_VERSION_3_0;
|
||||
|
||||
/**
|
||||
* Using EXTENDED_ERROR_MSG_SUPPORTED here would cause mstsc to crash when
|
||||
* running in server mode! This flag seems to be incorrectly documented.
|
||||
*/
|
||||
flags = PREAMBLE_VERSION_3_0 | EXTENDED_ERROR_MSG_SUPPORTED;
|
||||
|
||||
if (!license->rdp->settings->ServerMode)
|
||||
flags |= EXTENDED_ERROR_MSG_SUPPORTED;
|
||||
|
||||
rdp_write_header(license->rdp, s, length, MCS_GLOBAL_CHANNEL_ID);
|
||||
rdp_write_security_header(s, sec_flags);
|
||||
|
@ -30,6 +30,10 @@
|
||||
|
||||
#include "peer.h"
|
||||
|
||||
#ifdef WITH_DEBUG_RDP
|
||||
extern const char* DATA_PDU_TYPE_STRINGS[80];
|
||||
#endif
|
||||
|
||||
static BOOL freerdp_peer_initialize(freerdp_peer* client)
|
||||
{
|
||||
client->context->rdp->settings->ServerMode = TRUE;
|
||||
@ -85,6 +89,11 @@ static BOOL peer_recv_data_pdu(freerdp_peer* client, wStream* s)
|
||||
if (!rdp_read_share_data_header(s, &length, &type, &share_id, &compressed_type, &compressed_len))
|
||||
return FALSE;
|
||||
|
||||
#ifdef WITH_DEBUG_RDP
|
||||
printf("recv %s Data PDU (0x%02X), length: %d\n",
|
||||
type < ARRAYSIZE(DATA_PDU_TYPE_STRINGS) ? DATA_PDU_TYPE_STRINGS[type] : "???", type, length);
|
||||
#endif
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case DATA_PDU_TYPE_SYNCHRONIZE:
|
||||
|
@ -31,7 +31,7 @@
|
||||
#include <freerdp/crypto/per.h>
|
||||
|
||||
#ifdef WITH_DEBUG_RDP
|
||||
static const char* const DATA_PDU_TYPE_STRINGS[] =
|
||||
const char* DATA_PDU_TYPE_STRINGS[80] =
|
||||
{
|
||||
"?", "?", /* 0x00 - 0x01 */
|
||||
"Update", /* 0x02 */
|
||||
@ -65,7 +65,7 @@ static const char* const DATA_PDU_TYPE_STRINGS[] =
|
||||
"?", "?", "?", /* 0x33 - 0x35 */
|
||||
"Status Info", /* 0x36 */
|
||||
"Monitor Layout" /* 0x37 */
|
||||
"?", "?", "?", /* 0x38 - 0x40 */
|
||||
"FrameAcknowledge", "?", "?", /* 0x38 - 0x40 */
|
||||
"?", "?", "?", "?", "?", "?" /* 0x41 - 0x46 */
|
||||
};
|
||||
#endif
|
||||
@ -133,20 +133,21 @@ void rdp_write_share_control_header(wStream* s, UINT16 length, UINT16 type, UINT
|
||||
Stream_Write_UINT16(s, channel_id); /* pduSource */
|
||||
}
|
||||
|
||||
BOOL rdp_read_share_data_header(wStream* s, UINT16* length, BYTE* type, UINT32* share_id,
|
||||
BYTE *compressed_type, UINT16 *compressed_len)
|
||||
BOOL rdp_read_share_data_header(wStream* s, UINT16* length, BYTE* type, UINT32* shareId,
|
||||
BYTE *compressedType, UINT16 *compressedLen)
|
||||
{
|
||||
if (Stream_GetRemainingLength(s) < 12)
|
||||
return FALSE;
|
||||
|
||||
/* Share Data Header */
|
||||
Stream_Read_UINT32(s, *share_id); /* shareId (4 bytes) */
|
||||
Stream_Read_UINT32(s, *shareId); /* shareId (4 bytes) */
|
||||
Stream_Seek_UINT8(s); /* pad1 (1 byte) */
|
||||
Stream_Seek_UINT8(s); /* streamId (1 byte) */
|
||||
Stream_Read_UINT16(s, *length); /* uncompressedLength (2 bytes) */
|
||||
Stream_Read_UINT8(s, *type); /* pduType2, Data PDU Type (1 byte) */
|
||||
Stream_Read_UINT8(s, *compressed_type); /* compressedType (1 byte) */
|
||||
Stream_Read_UINT16(s, *compressed_len); /* compressedLength (2 bytes) */
|
||||
Stream_Read_UINT8(s, *compressedType); /* compressedType (1 byte) */
|
||||
Stream_Read_UINT16(s, *compressedLen); /* compressedLength (2 bytes) */
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -567,9 +568,8 @@ int rdp_recv_data_pdu(rdpRdp* rdp, wStream* s)
|
||||
}
|
||||
|
||||
#ifdef WITH_DEBUG_RDP
|
||||
/* if (type != DATA_PDU_TYPE_UPDATE) */
|
||||
DEBUG_RDP("recv %s Data PDU (0x%02X), length:%d",
|
||||
type < ARRAYSIZE(DATA_PDU_TYPE_STRINGS) ? DATA_PDU_TYPE_STRINGS[type] : "???", type, length);
|
||||
printf("recv %s Data PDU (0x%02X), length: %d\n",
|
||||
type < ARRAYSIZE(DATA_PDU_TYPE_STRINGS) ? DATA_PDU_TYPE_STRINGS[type] : "???", type, length);
|
||||
#endif
|
||||
|
||||
switch (type)
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
int dummy()
|
||||
int freerdp_dummy()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -917,10 +917,20 @@ void gdi_register_update_callbacks(rdpUpdate* update)
|
||||
|
||||
void gdi_init_primary(rdpGdi* gdi)
|
||||
{
|
||||
gdi->primary = gdi_bitmap_new_ex(gdi, gdi->width, gdi->height, gdi->dstBpp, gdi->primary_buffer);
|
||||
gdi->primary = (gdiBitmap*) malloc(sizeof(gdiBitmap));
|
||||
gdi->primary->hdc = gdi_CreateCompatibleDC(gdi->hdc);
|
||||
|
||||
if (!gdi->primary_buffer)
|
||||
gdi->primary->bitmap = gdi_CreateCompatibleBitmap(gdi->hdc, gdi->width, gdi->height);
|
||||
else
|
||||
gdi->primary->bitmap = gdi_CreateBitmap(gdi->width, gdi->height, gdi->dstBpp, gdi->primary_buffer);
|
||||
|
||||
gdi_SelectObject(gdi->primary->hdc, (HGDIOBJECT) gdi->primary->bitmap);
|
||||
gdi->primary->org_bitmap = NULL;
|
||||
|
||||
gdi->primary_buffer = gdi->primary->bitmap->data;
|
||||
|
||||
if (gdi->drawing == NULL)
|
||||
if (!gdi->drawing)
|
||||
gdi->drawing = gdi->primary;
|
||||
|
||||
gdi->primary->hdc->hwnd = (HGDI_WND) malloc(sizeof(GDI_WND));
|
||||
@ -1042,7 +1052,7 @@ int gdi_init(freerdp* instance, UINT32 flags, BYTE* buffer)
|
||||
|
||||
gdi_register_graphics(instance->context->graphics);
|
||||
|
||||
gdi->rfx_context = rfx_context_new();
|
||||
gdi->rfx_context = rfx_context_new(FALSE);
|
||||
gdi->nsc_context = nsc_context_new();
|
||||
|
||||
return 0;
|
||||
|
@ -134,6 +134,7 @@ static void svc_plugin_process_received(rdpSvcPlugin* plugin, void* pData, UINT3
|
||||
}
|
||||
|
||||
plugin->data_in = NULL;
|
||||
Stream_SealLength(data_in);
|
||||
Stream_SetPosition(data_in, 0);
|
||||
|
||||
MessageQueue_Post(plugin->MsgPipe->In, NULL, 0, (void*) data_in, NULL);
|
||||
|
10
server/.gitignore
vendored
10
server/.gitignore
vendored
@ -1,3 +1,7 @@
|
||||
WaykServer
|
||||
xrdp-ng
|
||||
|
||||
/*
|
||||
!/common
|
||||
!/Mac
|
||||
!/Sample
|
||||
!/Windows
|
||||
!/X11
|
||||
!/CmakeLists.txt
|
||||
|
@ -35,13 +35,28 @@ else()
|
||||
add_subdirectory(Windows)
|
||||
endif()
|
||||
|
||||
if(WITH_WAYK)
|
||||
if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/WaykServer")
|
||||
add_subdirectory(WaykServer)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/xrdp-ng")
|
||||
add_subdirectory("xrdp-ng")
|
||||
endif()
|
||||
|
||||
# Pick up other clients
|
||||
|
||||
set(FILENAME "ModuleOptions.cmake")
|
||||
file(GLOB FILEPATHS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*/${FILENAME}")
|
||||
|
||||
foreach(FILEPATH ${FILEPATHS})
|
||||
if(${FILEPATH} MATCHES "^([^/]*)//${FILENAME}")
|
||||
string(REGEX REPLACE "^([^/]*)//${FILENAME}" "\\1" FREERDP_SERVER ${FILEPATH})
|
||||
set(FREERDP_SERVER_ENABLED 0)
|
||||
include(${FILEPATH})
|
||||
if(FREERDP_SERVER_ENABLED)
|
||||
if(NOT (${FREERDP_SERVER_VENDOR} MATCHES "FreeRDP"))
|
||||
list(APPEND FREERDP_EXTRA_SERVERS ${FREERDP_SERVER})
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
foreach(FREERDP_SERVER ${FREERDP_EXTRA_SERVERS})
|
||||
add_subdirectory(${FREERDP_SERVER})
|
||||
endforeach()
|
||||
|
4
server/Mac/ModuleOptions.cmake
Normal file
4
server/Mac/ModuleOptions.cmake
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
set(FREERDP_SERVER_NAME "mfreerdp-server")
|
||||
set(FREERDP_SERVER_PLATFORM "X11")
|
||||
set(FREERDP_SERVER_VENDOR "FreeRDP")
|
@ -66,7 +66,7 @@ struct mf_peer_context
|
||||
//#endif
|
||||
|
||||
//#ifdef CHANNEL_RDPSND_SERVER
|
||||
rdpsnd_server_context* rdpsnd;
|
||||
RdpsndServerContext* rdpsnd;
|
||||
//#endif
|
||||
};
|
||||
|
||||
|
@ -175,7 +175,7 @@ void mf_peer_rfx_update(freerdp_peer* client)
|
||||
int mf_peer_context_new(freerdp_peer* client, mfPeerContext* context)
|
||||
{
|
||||
context->info = mf_info_get_instance();
|
||||
context->rfx_context = rfx_context_new();
|
||||
context->rfx_context = rfx_context_new(TRUE);
|
||||
context->rfx_context->mode = RLGR3;
|
||||
context->rfx_context->width = client->settings->DesktopWidth;
|
||||
context->rfx_context->height = client->settings->DesktopHeight;
|
||||
|
@ -34,7 +34,7 @@ static const AUDIO_FORMAT supported_audio_formats[] =
|
||||
{ WAVE_FORMAT_ALAW, 2, 22050, 44100, 2, 8, NULL }
|
||||
};
|
||||
|
||||
static void mf_peer_rdpsnd_activated(rdpsnd_server_context* context)
|
||||
static void mf_peer_rdpsnd_activated(RdpsndServerContext* context)
|
||||
{
|
||||
OSStatus status;
|
||||
int i, j;
|
||||
|
@ -53,7 +53,7 @@ struct _AQRecorderState
|
||||
UInt32 bufferByteSize;
|
||||
SInt64 currentPacket;
|
||||
bool isRunning;
|
||||
rdpsnd_server_context* snd_context;
|
||||
RdpsndServerContext* snd_context;
|
||||
|
||||
};
|
||||
|
||||
|
4
server/Sample/ModuleOptions.cmake
Normal file
4
server/Sample/ModuleOptions.cmake
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
set(FREERDP_SERVER_NAME "sfreerdp-server")
|
||||
set(FREERDP_SERVER_PLATFORM "Sample")
|
||||
set(FREERDP_SERVER_VENDOR "FreeRDP")
|
@ -31,7 +31,7 @@ static const AUDIO_FORMAT test_audio_formats[] =
|
||||
{ WAVE_FORMAT_ALAW, 2, 22050, 44100, 2, 8, 0, NULL }
|
||||
};
|
||||
|
||||
static void sf_peer_rdpsnd_activated(rdpsnd_server_context* context)
|
||||
static void sf_peer_rdpsnd_activated(RdpsndServerContext* context)
|
||||
{
|
||||
printf("RDPSND Activated\n");
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ static BOOL test_dump_rfx_realtime = TRUE;
|
||||
|
||||
void test_peer_context_new(freerdp_peer* client, testPeerContext* context)
|
||||
{
|
||||
context->rfx_context = rfx_context_new();
|
||||
context->rfx_context = rfx_context_new(TRUE);
|
||||
context->rfx_context->mode = RLGR3;
|
||||
context->rfx_context->width = SAMPLE_SERVER_DEFAULT_WIDTH;
|
||||
context->rfx_context->height = SAMPLE_SERVER_DEFAULT_HEIGHT;
|
||||
@ -398,10 +398,10 @@ static void* tf_debug_channel_thread_func(void* arg)
|
||||
void* fd;
|
||||
wStream* s;
|
||||
void* buffer;
|
||||
UINT32 bytes_returned = 0;
|
||||
DWORD BytesReturned = 0;
|
||||
testPeerContext* context = (testPeerContext*) arg;
|
||||
|
||||
if (WTSVirtualChannelQuery(context->debug_channel, WTSVirtualFileHandle, &buffer, &bytes_returned) == TRUE)
|
||||
if (WTSVirtualChannelQuery(context->debug_channel, WTSVirtualFileHandle, &buffer, &BytesReturned) == TRUE)
|
||||
{
|
||||
fd = *((void**) buffer);
|
||||
WTSFreeMemory(buffer);
|
||||
@ -411,7 +411,7 @@ static void* tf_debug_channel_thread_func(void* arg)
|
||||
|
||||
s = Stream_New(NULL, 4096);
|
||||
|
||||
WTSVirtualChannelWrite(context->debug_channel, (BYTE*) "test1", 5, NULL);
|
||||
WTSVirtualChannelWrite(context->debug_channel, (PCHAR) "test1", 5, NULL);
|
||||
|
||||
while (1)
|
||||
{
|
||||
@ -422,25 +422,25 @@ static void* tf_debug_channel_thread_func(void* arg)
|
||||
|
||||
Stream_SetPosition(s, 0);
|
||||
|
||||
if (WTSVirtualChannelRead(context->debug_channel, 0, Stream_Buffer(s),
|
||||
Stream_Capacity(s), &bytes_returned) == FALSE)
|
||||
if (WTSVirtualChannelRead(context->debug_channel, 0, (PCHAR) Stream_Buffer(s),
|
||||
Stream_Capacity(s), &BytesReturned) == FALSE)
|
||||
{
|
||||
if (bytes_returned == 0)
|
||||
if (BytesReturned == 0)
|
||||
break;
|
||||
|
||||
Stream_EnsureRemainingCapacity(s, bytes_returned);
|
||||
Stream_EnsureRemainingCapacity(s, BytesReturned);
|
||||
|
||||
if (WTSVirtualChannelRead(context->debug_channel, 0, Stream_Buffer(s),
|
||||
Stream_Capacity(s), &bytes_returned) == FALSE)
|
||||
if (WTSVirtualChannelRead(context->debug_channel, 0, (PCHAR) Stream_Buffer(s),
|
||||
Stream_Capacity(s), &BytesReturned) == FALSE)
|
||||
{
|
||||
/* should not happen */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Stream_SetPosition(s, bytes_returned);
|
||||
Stream_SetPosition(s, BytesReturned);
|
||||
|
||||
printf("got %d bytes\n", bytes_returned);
|
||||
printf("got %d bytes\n", BytesReturned);
|
||||
}
|
||||
|
||||
Stream_Free(s, TRUE);
|
||||
@ -498,7 +498,7 @@ BOOL tf_peer_post_connect(freerdp_peer* client)
|
||||
{
|
||||
if (strncmp(client->settings->ChannelDefArray[i].Name, "rdpdbg", 6) == 0)
|
||||
{
|
||||
context->debug_channel = WTSVirtualChannelOpenEx(context->vcm, "rdpdbg", 0);
|
||||
context->debug_channel = WTSVirtualChannelManagerOpenEx(context->vcm, "rdpdbg", 0);
|
||||
|
||||
if (context->debug_channel != NULL)
|
||||
{
|
||||
@ -580,7 +580,7 @@ void tf_peer_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
|
||||
{
|
||||
if (context->debug_channel)
|
||||
{
|
||||
WTSVirtualChannelWrite(context->debug_channel, (BYTE*) "test2", 5, NULL);
|
||||
WTSVirtualChannelWrite(context->debug_channel, (PCHAR) "test2", 5, NULL);
|
||||
}
|
||||
}
|
||||
else if ((flags & 0x4000) && code == 0x2D) /* 'x' key */
|
||||
|
@ -54,7 +54,7 @@ struct test_peer_context
|
||||
audin_server_context* audin;
|
||||
BOOL audin_open;
|
||||
UINT32 frame_id;
|
||||
rdpsnd_server_context* rdpsnd;
|
||||
RdpsndServerContext* rdpsnd;
|
||||
};
|
||||
typedef struct test_peer_context testPeerContext;
|
||||
|
||||
|
4
server/Windows/ModuleOptions.cmake
Normal file
4
server/Windows/ModuleOptions.cmake
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
set(FREERDP_SERVER_NAME "wfreerdp-server")
|
||||
set(FREERDP_SERVER_PLATFORM "Windows")
|
||||
set(FREERDP_SERVER_VENDOR "FreeRDP")
|
@ -26,7 +26,7 @@ int wf_rdpsnd_set_latest_peer(wfPeerContext* peer)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wf_directsound_activate(rdpsnd_server_context* context)
|
||||
int wf_directsound_activate(RdpsndServerContext* context)
|
||||
{
|
||||
HRESULT hr;
|
||||
wfInfo* wfi;
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
int wf_rdpsnd_set_latest_peer(wfPeerContext* peer);
|
||||
|
||||
int wf_directsound_activate(rdpsnd_server_context* context);
|
||||
int wf_directsound_activate(RdpsndServerContext* context);
|
||||
|
||||
DWORD WINAPI wf_rdpsnd_directsound_thread(LPVOID lpParam);
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user