Merge pull request #1483 from awakecoding/master

FreeRDP, WinPR Various New Modules & Stubs
This commit is contained in:
Marc-André Moreau 2013-09-16 14:59:56 -07:00
commit 8a750f1858
168 changed files with 9652 additions and 865 deletions

9
.gitignore vendored
View File

@ -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
View 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)

View 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()

View File

@ -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})

View 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})

View 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} ${PULSE_LIBRARY})

View File

@ -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;

View File

@ -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()

View File

@ -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"

View File

@ -18,7 +18,6 @@
define_channel_client("cliprdr")
set(${MODULE_PREFIX}_SRCS
cliprdr_constants.h
cliprdr_format.c
cliprdr_format.h
cliprdr_main.c

View File

@ -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 */

View File

@ -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"

View File

@ -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:

View File

@ -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;

View 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")

View 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);
}
}

View 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 */

View File

@ -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()

View File

@ -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"

View 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")

View 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);
}
}

View 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 */

View File

@ -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()

View File

@ -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"

View File

@ -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);
}

View 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")

View 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);
}
}

View 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 */

View File

@ -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()

View 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_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD}

View 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")

View 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);
}
}

View 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

View 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;
}

View 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} ${PULSE_LIBRARY})

View File

@ -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")

View 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);
}

View 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 */

View File

@ -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);
}
}

View 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})

View 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} ${PULSE_LIBRARY})

14
client/.gitignore vendored
View File

@ -1,4 +1,10 @@
WaykClient
DotNetClient
/*
!/Android
!/common
!/DirectFB
!/iOS
!/Mac
!/Sample
!/Windows
!/X11
!/CMakeLists.txt

View File

@ -0,0 +1,4 @@
set(FREERDP_CLIENT_NAME "afreerdp")
set(FREERDP_CLIENT_PLATFORM "Android")
set(FREERDP_CLIENT_VENDOR "FreeRDP")

View File

@ -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()

View File

@ -0,0 +1,4 @@
set(FREERDP_CLIENT_NAME "dfreerdp")
set(FREERDP_CLIENT_PLATFORM "DirectFB")
set(FREERDP_CLIENT_VENDOR "FreeRDP")

View File

@ -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

View File

@ -0,0 +1,4 @@
set(FREERDP_CLIENT_NAME "mfreerdp")
set(FREERDP_CLIENT_PLATFORM "MacOSX")
set(FREERDP_CLIENT_VENDOR "FreeRDP")

View File

@ -0,0 +1,4 @@
set(FREERDP_CLIENT_NAME "sfreerdp")
set(FREERDP_CLIENT_PLATFORM "Sample")
set(FREERDP_CLIENT_VENDOR "FreeRDP")

View File

@ -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()

View File

@ -0,0 +1,4 @@
set(FREERDP_CLIENT_NAME "wfreerdp")
set(FREERDP_CLIENT_PLATFORM "Windows")
set(FREERDP_CLIENT_VENDOR "FreeRDP")

View File

@ -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)

View File

@ -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

View File

@ -0,0 +1,4 @@
set(FREERDP_CLIENT_NAME "xfreerdp")
set(FREERDP_CLIENT_PLATFORM "X11")
set(FREERDP_CLIENT_VENDOR "FreeRDP")

View File

@ -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");

View File

@ -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;
}

View File

@ -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 */

View File

@ -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 */

View File

@ -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")

View File

@ -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 */

View File

@ -0,0 +1,4 @@
set(FREERDP_CLIENT_NAME "ifreerdp")
set(FREERDP_CLIENT_PLATFORM "iOS")
set(FREERDP_CLIENT_VENDOR "FreeRDP")

View File

@ -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
View 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()

View File

@ -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()

View File

@ -32,6 +32,7 @@
#cmakedefine HAVE_EVENTFD_H
#cmakedefine HAVE_TIMERFD_H
#cmakedefine HAVE_TM_GMTOFF
#cmakedefine HAVE_AIO_H
/* Options */

View File

@ -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,

View File

@ -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
}

View File

@ -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
*/

View File

@ -50,6 +50,7 @@ struct _NSC_MESSAGE
UINT32 height;
BYTE* data;
int scanline;
BYTE* PlaneBuffer;
UINT32 MaxPlaneSize;
BYTE* PlaneBuffers[5];
UINT32 OrgByteCount[4];

View File

@ -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);

View 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 */

View 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 */

View 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 */

View File

@ -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
}

View File

@ -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()

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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)

View File

@ -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 */

View File

@ -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);

View File

@ -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:

View File

@ -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)

View File

@ -1,5 +1,5 @@
int dummy()
int freerdp_dummy()
{
return 0;
}

View File

@ -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;

View File

@ -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
View File

@ -1,3 +1,7 @@
WaykServer
xrdp-ng
/*
!/common
!/Mac
!/Sample
!/Windows
!/X11
!/CmakeLists.txt

View File

@ -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()

View File

@ -0,0 +1,4 @@
set(FREERDP_SERVER_NAME "mfreerdp-server")
set(FREERDP_SERVER_PLATFORM "X11")
set(FREERDP_SERVER_VENDOR "FreeRDP")

View File

@ -66,7 +66,7 @@ struct mf_peer_context
//#endif
//#ifdef CHANNEL_RDPSND_SERVER
rdpsnd_server_context* rdpsnd;
RdpsndServerContext* rdpsnd;
//#endif
};

View File

@ -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;

View File

@ -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;

View File

@ -53,7 +53,7 @@ struct _AQRecorderState
UInt32 bufferByteSize;
SInt64 currentPacket;
bool isRunning;
rdpsnd_server_context* snd_context;
RdpsndServerContext* snd_context;
};

View File

@ -0,0 +1,4 @@
set(FREERDP_SERVER_NAME "sfreerdp-server")
set(FREERDP_SERVER_PLATFORM "Sample")
set(FREERDP_SERVER_VENDOR "FreeRDP")

View File

@ -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");
}

View File

@ -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 */

View File

@ -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;

View File

@ -0,0 +1,4 @@
set(FREERDP_SERVER_NAME "wfreerdp-server")
set(FREERDP_SERVER_PLATFORM "Windows")
set(FREERDP_SERVER_VENDOR "FreeRDP")

View File

@ -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;

View File

@ -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