mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-15 00:44:19 +09:00
wfreerdp-server: merge upstream
This commit is contained in:
@@ -24,6 +24,12 @@ project(FreeRDP C)
|
||||
|
||||
set(CMAKE_COLOR_MAKEFILE ON)
|
||||
|
||||
# Include our extra modules
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/)
|
||||
|
||||
# Check for cmake compatibility (enable/disable features)
|
||||
include(CheckCmakeCompat)
|
||||
|
||||
# Include cmake modules
|
||||
include(CheckIncludeFiles)
|
||||
include(CheckLibraryExists)
|
||||
@@ -32,12 +38,6 @@ include(CMakeDetermineSystem)
|
||||
include(FindPkgConfig)
|
||||
include(TestBigEndian)
|
||||
|
||||
# Include our extra modules
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/)
|
||||
|
||||
# Check for cmake compatibility (enable/disable features)
|
||||
include(CheckCmakeCompat)
|
||||
|
||||
include(FindFeature)
|
||||
include(AutoVersioning)
|
||||
include(ConfigOptions)
|
||||
@@ -50,8 +50,14 @@ include(GNUInstallDirsWrapper)
|
||||
set(FREERDP_VERSION_MAJOR "1")
|
||||
set(FREERDP_VERSION_MINOR "1")
|
||||
set(FREERDP_VERSION_REVISION "0")
|
||||
set(FREERDP_VERSION "${FREERDP_VERSION_MAJOR}.${FREERDP_VERSION_MINOR}")
|
||||
set(FREERDP_VERSION_FULL "${FREERDP_VERSION}.${FREERDP_VERSION_REVISION}")
|
||||
set(FREERDP_VERSION_SUFFIX "dev")
|
||||
set(FREERDP_API_VERSION "${FREERDP_VERSION_MAJOR}.${FREERDP_VERSION_MINOR}")
|
||||
set(FREERDP_VERSION "${FREERDP_API_VERSION}.${FREERDP_VERSION_REVISION}")
|
||||
if (FREERDP_VERSION_SUFFIX)
|
||||
set(FREERDP_VERSION_FULL "${FREERDP_VERSION}-${FREERDP_VERSION_SUFFIX}")
|
||||
else()
|
||||
set(FREERDP_VERSION_FULL "${FREERDP_VERSION}")
|
||||
endif()
|
||||
include(GetGitRevisionDescription)
|
||||
git_describe(GIT_REVISION --match "[0-9]*" --abbrev=4 --tags --always)
|
||||
message(STATUS "Git Revision ${GIT_REVISION}")
|
||||
@@ -73,7 +79,7 @@ if(NOT DEFINED BUILD_SHARED_LIBS)
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED EXPORT_ALL_SYMBOLS)
|
||||
set(EXPORT_ALL_SYMBOLS FALSE)
|
||||
set(EXPORT_ALL_SYMBOLS TRUE)
|
||||
endif()
|
||||
|
||||
# Configure MSVC Runtime
|
||||
@@ -92,6 +98,9 @@ endif()
|
||||
|
||||
# Compiler-specific flags
|
||||
if(CMAKE_COMPILER_IS_GNUCC)
|
||||
if(NOT CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT ANDROID)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=i686")
|
||||
endif()
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
|
||||
CHECK_C_COMPILER_FLAG (-Wno-unused-result Wno-unused-result)
|
||||
if(Wno-unused-result)
|
||||
@@ -173,7 +182,9 @@ if(APPLE)
|
||||
endif()
|
||||
|
||||
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
|
||||
find_package(Threads REQUIRED)
|
||||
if(NOT ANDROID)
|
||||
find_package(Threads REQUIRED)
|
||||
endif()
|
||||
|
||||
if(UNIX OR CYGWIN)
|
||||
set(X11_FEATURE_TYPE "RECOMMENDED")
|
||||
@@ -286,6 +297,8 @@ set(FREERDP_KEYMAP_PATH "${FREERDP_DATA_PATH}/keymaps")
|
||||
|
||||
# Path to put plugins
|
||||
|
||||
set(FREERDP_LIBRARY_PATH "${CMAKE_INSTALL_LIBDIR}")
|
||||
|
||||
set(FREERDP_PLUGIN_PATH "${CMAKE_INSTALL_LIBDIR}/freerdp")
|
||||
set(FREERDP_ADDIN_PATH "${FREERDP_PLUGIN_PATH}")
|
||||
|
||||
|
||||
@@ -22,14 +22,35 @@ include(CMakeDependentOption)
|
||||
|
||||
macro(define_channel_options)
|
||||
set(PREFIX "CHANNEL")
|
||||
|
||||
|
||||
cmake_parse_arguments(${PREFIX}
|
||||
""
|
||||
"NAME;TYPE;DESCRIPTION;SPECIFICATIONS;DEFAULT"
|
||||
""
|
||||
${ARGN})
|
||||
|
||||
|
||||
string(TOUPPER "CHANNEL_${CHANNEL_NAME}" CHANNEL_OPTION)
|
||||
string(TOUPPER "CHANNEL_${CHANNEL_NAME}_CLIENT" CHANNEL_CLIENT_OPTION)
|
||||
string(TOUPPER "CHANNEL_${CHANNEL_NAME}_SERVER" CHANNEL_SERVER_OPTION)
|
||||
|
||||
if(${${CHANNEL_CLIENT_OPTION}})
|
||||
set(OPTION_CLIENT_DEFAULT ${${CHANNEL_CLIENT_OPTION}})
|
||||
endif()
|
||||
|
||||
if(${${CHANNEL_SERVER_OPTION}})
|
||||
set(OPTION_SERVER_DEFAULT ${${CHANNEL_SERVER_OPTION}})
|
||||
endif()
|
||||
|
||||
if(${${CHANNEL_OPTION}})
|
||||
set(OPTION_DEFAULT ${${CHANNEL_OPTION}})
|
||||
endif()
|
||||
|
||||
if(${OPTION_CLIENT_DEFAULT} OR ${OPTION_SERVER_DEFAULT})
|
||||
set(OPTION_DEFAULT "ON")
|
||||
endif()
|
||||
|
||||
set(CHANNEL_DEFAULT ${OPTION_DEFAULT})
|
||||
|
||||
set(CHANNEL_OPTION_DOC "Build ${CHANNEL_NAME} ${CHANNEL_TYPE} channel")
|
||||
option(${CHANNEL_OPTION} "${CHANNEL_OPTION_DOC}" ${CHANNEL_DEFAULT})
|
||||
|
||||
@@ -77,7 +98,7 @@ macro(define_channel_client_subsystem _channel_name _subsystem _type)
|
||||
if(_type_length GREATER 0)
|
||||
set(SUBSYSTEM_TYPE ${_type})
|
||||
set(MODULE_NAME "${CHANNEL_NAME}-client-${CHANNEL_SUBSYSTEM}-${SUBSYSTEM_TYPE}")
|
||||
string(TOUPPER "CHANNEL_${CHANNEL_NAME}_CLIENT_${CHANNEL_SUBSYSTEM}-${SUBSYSTEM_TYPE}" MODULE_PREFIX)
|
||||
string(TOUPPER "CHANNEL_${CHANNEL_NAME}_CLIENT_${CHANNEL_SUBSYSTEM}_${SUBSYSTEM_TYPE}" MODULE_PREFIX)
|
||||
else()
|
||||
set(MODULE_NAME "${CHANNEL_NAME}-client-${CHANNEL_SUBSYSTEM}")
|
||||
string(TOUPPER "CHANNEL_${CHANNEL_NAME}_CLIENT_${CHANNEL_SUBSYSTEM}" MODULE_PREFIX)
|
||||
@@ -116,11 +137,19 @@ endmacro(add_channel_server)
|
||||
macro(add_channel_client_subsystem _channel_prefix _channel_name _subsystem _type)
|
||||
add_subdirectory(${_subsystem})
|
||||
set(_channel_module_name "${_channel_name}-client")
|
||||
string(TOUPPER "CHANNEL_${_channel_name}_CLIENT_${_subsystem}" _subsystem_prefix)
|
||||
string(LENGTH "${_type}" _type_length)
|
||||
if(_type_length GREATER 0)
|
||||
string(TOUPPER "CHANNEL_${_channel_name}_CLIENT_${_subsystem}_${_type}" _subsystem_prefix)
|
||||
else()
|
||||
string(TOUPPER "CHANNEL_${_channel_name}_CLIENT_${_subsystem}" _subsystem_prefix)
|
||||
endif()
|
||||
if(${${_subsystem_prefix}_STATIC})
|
||||
message(STATUS "Static Subsystem: ${_subsystem_prefix} / ${_subsystem}")
|
||||
get_target_property(CHANNEL_SUBSYSTEMS ${_channel_module_name} SUBSYSTEMS)
|
||||
set(SUBSYSTEMS ${SUBSYSTEMS} ${_subsystem})
|
||||
if(_type_length GREATER 0)
|
||||
set(SUBSYSTEMS ${SUBSYSTEMS} "${_subsystem}-${_type}")
|
||||
else()
|
||||
set(SUBSYSTEMS ${SUBSYSTEMS} ${_subsystem})
|
||||
endif()
|
||||
set_target_properties(${_channel_module_name} PROPERTIES SUBSYSTEMS "${SUBSYSTEMS}")
|
||||
endif()
|
||||
endmacro(add_channel_client_subsystem)
|
||||
@@ -140,7 +169,7 @@ macro(add_channel_client_library _module_prefix _module_name _channel_name _dyna
|
||||
endif()
|
||||
endmacro(add_channel_client_library)
|
||||
|
||||
macro(add_channel_client_subsystem_library _module_prefix _module_name _channel_name _dynamic _entry)
|
||||
macro(add_channel_client_subsystem_library _module_prefix _module_name _channel_name _type _dynamic _entry)
|
||||
if(${_dynamic} AND MSVC AND (NOT STATIC_CHANNELS))
|
||||
set(${_module_prefix}_SRCS ${${_module_prefix}_SRCS} module.def)
|
||||
endif()
|
||||
@@ -149,6 +178,7 @@ macro(add_channel_client_subsystem_library _module_prefix _module_name _channel_
|
||||
else()
|
||||
set(${_module_prefix}_STATIC ON PARENT_SCOPE)
|
||||
set(${_module_prefix}_NAME ${_module_name} PARENT_SCOPE)
|
||||
set(${_module_prefix}_TYPE ${_type} PARENT_SCOPE)
|
||||
add_library(${_module_name} STATIC ${${_module_prefix}_SRCS})
|
||||
endif()
|
||||
endmacro(add_channel_client_subsystem_library)
|
||||
|
||||
@@ -8,10 +8,6 @@ if(ANDROID)
|
||||
set(OPTION_SERVER_DEFAULT OFF)
|
||||
endif()
|
||||
|
||||
if(${OPTION_CLIENT_DEFAULT} OR ${OPTION_SERVER_DEFAULT})
|
||||
set(OPTION_DEFAULT ON)
|
||||
endif()
|
||||
|
||||
define_channel_options(NAME "audin" TYPE "dynamic"
|
||||
DESCRIPTION "Audio Input Redirection Virtual Channel Extension"
|
||||
SPECIFICATIONS "[MS-RDPEAI]"
|
||||
@@ -19,3 +15,4 @@ define_channel_options(NAME "audin" TYPE "dynamic"
|
||||
|
||||
define_channel_client_options(${OPTION_CLIENT_DEFAULT})
|
||||
define_channel_server_options(${OPTION_SERVER_DEFAULT})
|
||||
|
||||
|
||||
@@ -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-common freerdp-utils)
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ set(${MODULE_PREFIX}_SRCS
|
||||
include_directories(..)
|
||||
include_directories(${ALSA_INCLUDE_DIRS})
|
||||
|
||||
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE "")
|
||||
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
|
||||
|
||||
|
||||
@@ -25,10 +25,14 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/cmdline.h>
|
||||
|
||||
#include <alsa/asoundlib.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/thread.h>
|
||||
|
||||
#include <freerdp/addin.h>
|
||||
#include <freerdp/utils/dsp.h>
|
||||
#include <freerdp/utils/thread.h>
|
||||
|
||||
#include "audin_main.h"
|
||||
|
||||
@@ -36,7 +40,7 @@ typedef struct _AudinALSADevice
|
||||
{
|
||||
IAudinDevice iface;
|
||||
|
||||
char device_name[32];
|
||||
char* device_name;
|
||||
UINT32 frames_per_packet;
|
||||
UINT32 target_rate;
|
||||
UINT32 actual_rate;
|
||||
@@ -183,10 +187,13 @@ static void* audin_alsa_thread_func(void* arg)
|
||||
|
||||
rbytes_per_frame = alsa->actual_channels * alsa->bytes_per_channel;
|
||||
tbytes_per_frame = alsa->target_channels * alsa->bytes_per_channel;
|
||||
alsa->buffer = (BYTE*) xzalloc(tbytes_per_frame * alsa->frames_per_packet);
|
||||
alsa->buffer = (BYTE*) malloc(tbytes_per_frame * alsa->frames_per_packet);
|
||||
ZeroMemory(alsa->buffer, tbytes_per_frame * alsa->frames_per_packet);
|
||||
alsa->buffer_frames = 0;
|
||||
buffer = (BYTE*) xzalloc(rbytes_per_frame * alsa->frames_per_packet);
|
||||
buffer = (BYTE*) malloc(rbytes_per_frame * alsa->frames_per_packet);
|
||||
ZeroMemory(buffer, rbytes_per_frame * alsa->frames_per_packet);
|
||||
freerdp_dsp_context_reset_adpcm(alsa->dsp_context);
|
||||
|
||||
do
|
||||
{
|
||||
if ((error = snd_pcm_open(&capture_handle, alsa->device_name, SND_PCM_STREAM_CAPTURE, 0)) < 0)
|
||||
@@ -236,6 +243,9 @@ static void audin_alsa_free(IAudinDevice* device)
|
||||
|
||||
freerdp_thread_free(alsa->thread);
|
||||
freerdp_dsp_context_free(alsa->dsp_context);
|
||||
|
||||
free(alsa->device_name);
|
||||
|
||||
free(alsa);
|
||||
}
|
||||
|
||||
@@ -328,40 +338,66 @@ static void audin_alsa_close(IAudinDevice* device)
|
||||
alsa->user_data = NULL;
|
||||
}
|
||||
|
||||
COMMAND_LINE_ARGUMENT_A audin_alsa_args[] =
|
||||
{
|
||||
{ "audio-dev", COMMAND_LINE_VALUE_REQUIRED, "<device>", NULL, NULL, -1, NULL, "audio device name" },
|
||||
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
|
||||
};
|
||||
|
||||
static void audin_alsa_parse_addin_args(AudinALSADevice* device, ADDIN_ARGV* args)
|
||||
{
|
||||
int status;
|
||||
DWORD flags;
|
||||
COMMAND_LINE_ARGUMENT_A* arg;
|
||||
AudinALSADevice* alsa = (AudinALSADevice*) device;
|
||||
|
||||
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON;
|
||||
|
||||
status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv, audin_alsa_args, flags, alsa, NULL, NULL);
|
||||
|
||||
arg = audin_alsa_args;
|
||||
|
||||
do
|
||||
{
|
||||
if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT))
|
||||
continue;
|
||||
|
||||
CommandLineSwitchStart(arg)
|
||||
|
||||
CommandLineSwitchCase(arg, "audio-dev")
|
||||
{
|
||||
alsa->device_name = _strdup(arg->Value);
|
||||
}
|
||||
|
||||
CommandLineSwitchEnd(arg)
|
||||
}
|
||||
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define freerdp_audin_client_subsystem_entry alsa_freerdp_audin_client_subsystem_entry
|
||||
#endif
|
||||
|
||||
int freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints)
|
||||
{
|
||||
ADDIN_ARGV* args;
|
||||
AudinALSADevice* alsa;
|
||||
RDP_PLUGIN_DATA* data;
|
||||
|
||||
alsa = xnew(AudinALSADevice);
|
||||
alsa = (AudinALSADevice*) malloc(sizeof(AudinALSADevice));
|
||||
ZeroMemory(alsa, sizeof(AudinALSADevice));
|
||||
|
||||
alsa->iface.Open = audin_alsa_open;
|
||||
alsa->iface.FormatSupported = audin_alsa_format_supported;
|
||||
alsa->iface.SetFormat = audin_alsa_set_format;
|
||||
alsa->iface.Close = audin_alsa_close;
|
||||
alsa->iface.Free = audin_alsa_free;
|
||||
alsa->device_name[0] = '\0';
|
||||
|
||||
data = pEntryPoints->plugin_data;
|
||||
if (data)
|
||||
{
|
||||
char *data2 = (char *) (data->data[2]);
|
||||
if (data->data[0] && (strcmp(data->data[0], "audin") == 0) &&
|
||||
data->data[1] && (strcmp(data->data[1], "alsa") == 0) &&
|
||||
data2 && (*data2 != '\0'))
|
||||
{
|
||||
strncpy(alsa->device_name, data2, sizeof(alsa->device_name));
|
||||
}
|
||||
}
|
||||
args = pEntryPoints->args;
|
||||
|
||||
if (alsa->device_name[0] == '\0')
|
||||
{
|
||||
strcpy(alsa->device_name, "default");
|
||||
}
|
||||
audin_alsa_parse_addin_args(alsa, args);
|
||||
|
||||
if (!alsa->device_name)
|
||||
alsa->device_name = _strdup("default");
|
||||
|
||||
alsa->frames_per_packet = 128;
|
||||
alsa->target_rate = 22050;
|
||||
@@ -378,4 +414,3 @@ int freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEnt
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,9 +25,12 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/cmdline.h>
|
||||
|
||||
#include <freerdp/addin.h>
|
||||
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/load_plugin.h>
|
||||
|
||||
#include "audin_main.h"
|
||||
|
||||
@@ -77,6 +80,8 @@ struct _AUDIN_PLUGIN
|
||||
UINT16 fixed_format;
|
||||
UINT16 fixed_channel;
|
||||
UINT32 fixed_rate;
|
||||
char* subsystem;
|
||||
char* device_name;
|
||||
|
||||
/* Device interface */
|
||||
IAudinDevice* device;
|
||||
@@ -132,7 +137,8 @@ static int audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback, S
|
||||
}
|
||||
stream_seek_UINT32(s); /* cbSizeFormatsPacket */
|
||||
|
||||
callback->formats = (audinFormat*) xzalloc(NumFormats * sizeof(audinFormat));
|
||||
callback->formats = (audinFormat*) malloc(NumFormats * sizeof(audinFormat));
|
||||
ZeroMemory(callback->formats, NumFormats * sizeof(audinFormat));
|
||||
|
||||
out = stream_new(9);
|
||||
stream_seek(out, 9);
|
||||
@@ -373,7 +379,8 @@ static int audin_on_new_channel_connection(IWTSListenerCallback* pListenerCallba
|
||||
|
||||
DEBUG_DVC("");
|
||||
|
||||
callback = xnew(AUDIN_CHANNEL_CALLBACK);
|
||||
callback = (AUDIN_CHANNEL_CALLBACK*) malloc(sizeof(AUDIN_CHANNEL_CALLBACK));
|
||||
ZeroMemory(callback, sizeof(AUDIN_CHANNEL_CALLBACK));
|
||||
|
||||
callback->iface.OnDataReceived = audin_on_data_received;
|
||||
callback->iface.OnClose = audin_on_close;
|
||||
@@ -392,7 +399,8 @@ static int audin_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManage
|
||||
|
||||
DEBUG_DVC("");
|
||||
|
||||
audin->listener_callback = xnew(AUDIN_LISTENER_CALLBACK);
|
||||
audin->listener_callback = (AUDIN_LISTENER_CALLBACK*) malloc(sizeof(AUDIN_LISTENER_CALLBACK));
|
||||
ZeroMemory(audin->listener_callback, sizeof(AUDIN_LISTENER_CALLBACK));
|
||||
|
||||
audin->listener_callback->iface.OnNewChannelConnection = audin_on_new_channel_connection;
|
||||
audin->listener_callback->plugin = pPlugin;
|
||||
@@ -436,31 +444,19 @@ static void audin_register_device_plugin(IWTSPlugin* pPlugin, IAudinDevice* devi
|
||||
audin->device = device;
|
||||
}
|
||||
|
||||
static BOOL audin_load_device_plugin(IWTSPlugin* pPlugin, const char* name, RDP_PLUGIN_DATA* data)
|
||||
static BOOL audin_load_device_plugin(IWTSPlugin* pPlugin, const char* name, ADDIN_ARGV* args)
|
||||
{
|
||||
char* fullname;
|
||||
PFREERDP_AUDIN_DEVICE_ENTRY entry;
|
||||
FREERDP_AUDIN_DEVICE_ENTRY_POINTS entryPoints;
|
||||
|
||||
if (strrchr(name, '.') != NULL)
|
||||
{
|
||||
entry = (PFREERDP_AUDIN_DEVICE_ENTRY) freerdp_load_plugin(name, AUDIN_DEVICE_EXPORT_FUNC_NAME);
|
||||
}
|
||||
else
|
||||
{
|
||||
fullname = xzalloc(strlen(name) + 8);
|
||||
strcpy(fullname, "audin_");
|
||||
strcat(fullname, name);
|
||||
entry = (PFREERDP_AUDIN_DEVICE_ENTRY) freerdp_load_plugin(fullname, AUDIN_DEVICE_EXPORT_FUNC_NAME);
|
||||
free(fullname);
|
||||
}
|
||||
entry = (PFREERDP_AUDIN_DEVICE_ENTRY) freerdp_load_channel_addin_entry("audin", (LPSTR) name, NULL, 0);
|
||||
|
||||
if (entry == NULL)
|
||||
return FALSE;
|
||||
|
||||
entryPoints.plugin = pPlugin;
|
||||
entryPoints.pRegisterAudinDevice = audin_register_device_plugin;
|
||||
entryPoints.plugin_data = data;
|
||||
entryPoints.args = args;
|
||||
|
||||
if (entry(&entryPoints) != 0)
|
||||
{
|
||||
@@ -471,54 +467,81 @@ static BOOL audin_load_device_plugin(IWTSPlugin* pPlugin, const char* name, RDP_
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL audin_process_plugin_data(IWTSPlugin* pPlugin, RDP_PLUGIN_DATA* data)
|
||||
void audin_set_subsystem(AUDIN_PLUGIN* audin, char* subsystem)
|
||||
{
|
||||
BOOL ret;
|
||||
if (audin->subsystem)
|
||||
free(audin->subsystem);
|
||||
|
||||
audin->subsystem = _strdup(subsystem);
|
||||
}
|
||||
|
||||
void audin_set_device_name(AUDIN_PLUGIN* audin, char* device_name)
|
||||
{
|
||||
if (audin->device_name)
|
||||
free(audin->device_name);
|
||||
|
||||
audin->device_name = _strdup(device_name);
|
||||
}
|
||||
|
||||
COMMAND_LINE_ARGUMENT_A audin_args[] =
|
||||
{
|
||||
{ "sys", COMMAND_LINE_VALUE_REQUIRED, "<subsystem>", NULL, NULL, -1, NULL, "subsystem" },
|
||||
{ "dev", COMMAND_LINE_VALUE_REQUIRED, "<device>", NULL, NULL, -1, NULL, "device" },
|
||||
{ "format", COMMAND_LINE_VALUE_REQUIRED, "<format>", NULL, NULL, -1, NULL, "format" },
|
||||
{ "rate", COMMAND_LINE_VALUE_REQUIRED, "<rate>", NULL, NULL, -1, NULL, "rate" },
|
||||
{ "channel", COMMAND_LINE_VALUE_REQUIRED, "<channel>", NULL, NULL, -1, NULL, "channel" },
|
||||
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
|
||||
};
|
||||
|
||||
static BOOL audin_process_addin_args(IWTSPlugin* pPlugin, ADDIN_ARGV* args)
|
||||
{
|
||||
int status;
|
||||
DWORD flags;
|
||||
COMMAND_LINE_ARGUMENT_A* arg;
|
||||
AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) pPlugin;
|
||||
RDP_PLUGIN_DATA default_data[2] = { { 0 }, { 0 } };
|
||||
|
||||
if (data->data[0] && (strcmp((char*)data->data[0], "audin") == 0 || strstr((char*) data->data[0], "/audin.") != NULL))
|
||||
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON;
|
||||
|
||||
status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv,
|
||||
audin_args, flags, audin, NULL, NULL);
|
||||
|
||||
arg = audin_args;
|
||||
|
||||
do
|
||||
{
|
||||
if (data->data[1] && strcmp((char*)data->data[1], "format") == 0)
|
||||
{
|
||||
audin->fixed_format = atoi(data->data[2]);
|
||||
return TRUE;
|
||||
}
|
||||
else if (data->data[1] && strcmp((char*)data->data[1], "rate") == 0)
|
||||
{
|
||||
audin->fixed_rate = atoi(data->data[2]);
|
||||
return TRUE;
|
||||
}
|
||||
else if (data->data[1] && strcmp((char*)data->data[1], "channel") == 0)
|
||||
{
|
||||
audin->fixed_channel = atoi(data->data[2]);
|
||||
return TRUE;
|
||||
}
|
||||
else if (data->data[1] && ((char*)data->data[1])[0])
|
||||
{
|
||||
return audin_load_device_plugin(pPlugin, (char*) data->data[1], data);
|
||||
}
|
||||
else
|
||||
{
|
||||
default_data[0].size = sizeof(RDP_PLUGIN_DATA);
|
||||
default_data[0].data[0] = "audin";
|
||||
default_data[0].data[1] = "pulse";
|
||||
default_data[0].data[2] = "";
|
||||
if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT))
|
||||
continue;
|
||||
|
||||
ret = audin_load_device_plugin(pPlugin, "pulse", default_data);
|
||||
CommandLineSwitchStart(arg)
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
default_data[0].size = sizeof(RDP_PLUGIN_DATA);
|
||||
default_data[0].data[0] = "audin";
|
||||
default_data[0].data[1] = "alsa";
|
||||
default_data[0].data[2] = "default";
|
||||
ret = audin_load_device_plugin(pPlugin, "alsa", default_data);
|
||||
}
|
||||
|
||||
return ret;
|
||||
CommandLineSwitchCase(arg, "sys")
|
||||
{
|
||||
audin_set_subsystem(audin, arg->Value);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "dev")
|
||||
{
|
||||
audin_set_device_name(audin, arg->Value);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "format")
|
||||
{
|
||||
audin->fixed_format = atoi(arg->Value);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "rate")
|
||||
{
|
||||
audin->fixed_rate = atoi(arg->Value);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "channel")
|
||||
{
|
||||
audin->fixed_channel = atoi(arg->Value);
|
||||
}
|
||||
CommandLineSwitchDefault(arg)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CommandLineSwitchEnd(arg)
|
||||
}
|
||||
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -530,23 +553,50 @@ static BOOL audin_process_plugin_data(IWTSPlugin* pPlugin, RDP_PLUGIN_DATA* data
|
||||
int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
|
||||
{
|
||||
int error = 0;
|
||||
ADDIN_ARGV* args;
|
||||
AUDIN_PLUGIN* audin;
|
||||
|
||||
audin = (AUDIN_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "audin");
|
||||
|
||||
if (audin == NULL)
|
||||
{
|
||||
audin = xnew(AUDIN_PLUGIN);
|
||||
audin = (AUDIN_PLUGIN*) malloc(sizeof(AUDIN_PLUGIN));
|
||||
ZeroMemory(audin, sizeof(AUDIN_PLUGIN));
|
||||
|
||||
audin->iface.Initialize = audin_plugin_initialize;
|
||||
audin->iface.Connected = NULL;
|
||||
audin->iface.Disconnected = NULL;
|
||||
audin->iface.Terminated = audin_plugin_terminated;
|
||||
|
||||
error = pEntryPoints->RegisterPlugin(pEntryPoints, "audin", (IWTSPlugin*) audin);
|
||||
}
|
||||
|
||||
args = pEntryPoints->GetPluginData(pEntryPoints);
|
||||
|
||||
if (error == 0)
|
||||
audin_process_plugin_data((IWTSPlugin*) audin, pEntryPoints->GetPluginData(pEntryPoints));
|
||||
audin_process_addin_args((IWTSPlugin*) audin, args);
|
||||
|
||||
if (audin->subsystem)
|
||||
audin_load_device_plugin((IWTSPlugin*) audin, audin->subsystem, args);
|
||||
|
||||
if (!audin->device)
|
||||
{
|
||||
audin_set_subsystem(audin, "pulse");
|
||||
audin_set_device_name(audin, "");
|
||||
audin_load_device_plugin((IWTSPlugin*) audin, audin->subsystem, args);
|
||||
}
|
||||
|
||||
if (!audin->device)
|
||||
{
|
||||
audin_set_subsystem(audin, "alsa");
|
||||
audin_set_device_name(audin, "default");
|
||||
audin_load_device_plugin((IWTSPlugin*) audin, audin->subsystem, args);
|
||||
}
|
||||
|
||||
if (audin->device == NULL)
|
||||
{
|
||||
DEBUG_WARN("no sound device.");
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
#include <freerdp/dvc.h>
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/addin.h>
|
||||
#include <freerdp/utils/debug.h>
|
||||
|
||||
#ifdef WITH_DEBUG_DVC
|
||||
@@ -66,7 +67,7 @@ struct _FREERDP_AUDIN_DEVICE_ENTRY_POINTS
|
||||
{
|
||||
IWTSPlugin* plugin;
|
||||
PREGISTERAUDINDEVICE pRegisterAudinDevice;
|
||||
RDP_PLUGIN_DATA* plugin_data;
|
||||
ADDIN_ARGV* args;
|
||||
};
|
||||
typedef struct _FREERDP_AUDIN_DEVICE_ENTRY_POINTS FREERDP_AUDIN_DEVICE_ENTRY_POINTS;
|
||||
typedef FREERDP_AUDIN_DEVICE_ENTRY_POINTS* PFREERDP_AUDIN_DEVICE_ENTRY_POINTS;
|
||||
|
||||
@@ -23,7 +23,7 @@ set(${MODULE_PREFIX}_SRCS
|
||||
include_directories(..)
|
||||
include_directories(${PULSE_INCLUDE_DIR})
|
||||
|
||||
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE "")
|
||||
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
|
||||
|
||||
|
||||
@@ -25,9 +25,13 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/cmdline.h>
|
||||
|
||||
#include <pulse/pulseaudio.h>
|
||||
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/addin.h>
|
||||
#include <freerdp/utils/dsp.h>
|
||||
|
||||
#include "audin_main.h"
|
||||
@@ -36,7 +40,7 @@ typedef struct _AudinPulseDevice
|
||||
{
|
||||
IAudinDevice iface;
|
||||
|
||||
char device_name[32];
|
||||
char* device_name;
|
||||
UINT32 frames_per_packet;
|
||||
pa_threaded_mainloop* mainloop;
|
||||
pa_context* context;
|
||||
@@ -420,7 +424,8 @@ static void audin_pulse_open(IAudinDevice* device, AudinReceive receive, void* u
|
||||
if (state == PA_STREAM_READY)
|
||||
{
|
||||
freerdp_dsp_context_reset_adpcm(pulse->dsp_context);
|
||||
pulse->buffer = xzalloc(pulse->bytes_per_frame * pulse->frames_per_packet);
|
||||
pulse->buffer = malloc(pulse->bytes_per_frame * pulse->frames_per_packet);
|
||||
ZeroMemory(pulse->buffer, pulse->bytes_per_frame * pulse->frames_per_packet);
|
||||
pulse->buffer_frames = 0;
|
||||
DEBUG_DVC("connected");
|
||||
}
|
||||
@@ -430,16 +435,53 @@ static void audin_pulse_open(IAudinDevice* device, AudinReceive receive, void* u
|
||||
}
|
||||
}
|
||||
|
||||
COMMAND_LINE_ARGUMENT_A audin_pulse_args[] =
|
||||
{
|
||||
{ "audio-dev", COMMAND_LINE_VALUE_REQUIRED, "<device>", NULL, NULL, -1, NULL, "audio device name" },
|
||||
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
|
||||
};
|
||||
|
||||
static void audin_pulse_parse_addin_args(AudinPulseDevice* device, ADDIN_ARGV* args)
|
||||
{
|
||||
int status;
|
||||
DWORD flags;
|
||||
COMMAND_LINE_ARGUMENT_A* arg;
|
||||
AudinPulseDevice* pulse = (AudinPulseDevice*) device;
|
||||
|
||||
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON;
|
||||
|
||||
status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv, audin_pulse_args, flags, pulse, NULL, NULL);
|
||||
|
||||
arg = audin_pulse_args;
|
||||
|
||||
do
|
||||
{
|
||||
if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT))
|
||||
continue;
|
||||
|
||||
CommandLineSwitchStart(arg)
|
||||
|
||||
CommandLineSwitchCase(arg, "audio-dev")
|
||||
{
|
||||
pulse->device_name = _strdup(arg->Value);
|
||||
}
|
||||
|
||||
CommandLineSwitchEnd(arg)
|
||||
}
|
||||
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define freerdp_audin_client_subsystem_entry pulse_freerdp_audin_client_subsystem_entry
|
||||
#endif
|
||||
|
||||
int freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints)
|
||||
{
|
||||
ADDIN_ARGV* args;
|
||||
AudinPulseDevice* pulse;
|
||||
RDP_PLUGIN_DATA * data;
|
||||
|
||||
pulse = xnew(AudinPulseDevice);
|
||||
pulse = (AudinPulseDevice*) malloc(sizeof(AudinPulseDevice));
|
||||
ZeroMemory(pulse, sizeof(AudinPulseDevice));
|
||||
|
||||
pulse->iface.Open = audin_pulse_open;
|
||||
pulse->iface.FormatSupported = audin_pulse_format_supported;
|
||||
@@ -447,30 +489,35 @@ int freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEnt
|
||||
pulse->iface.Close = audin_pulse_close;
|
||||
pulse->iface.Free = audin_pulse_free;
|
||||
|
||||
data = pEntryPoints->plugin_data;
|
||||
if (data && data->data[0] && strcmp(data->data[0], "audin") == 0 &&
|
||||
data->data[1] && strcmp(data->data[1], "pulse") == 0)
|
||||
{
|
||||
strncpy(pulse->device_name, (char*)data->data[2], sizeof(pulse->device_name));
|
||||
}
|
||||
args = pEntryPoints->args;
|
||||
|
||||
audin_pulse_parse_addin_args(pulse, args);
|
||||
|
||||
if (!pulse->device_name)
|
||||
pulse->device_name = _strdup("default");
|
||||
|
||||
pulse->dsp_context = freerdp_dsp_context_new();
|
||||
|
||||
pulse->mainloop = pa_threaded_mainloop_new();
|
||||
|
||||
if (!pulse->mainloop)
|
||||
{
|
||||
DEBUG_WARN("pa_threaded_mainloop_new failed");
|
||||
audin_pulse_free((IAudinDevice*) pulse);
|
||||
return 1;
|
||||
}
|
||||
|
||||
pulse->context = pa_context_new(pa_threaded_mainloop_get_api(pulse->mainloop), "freerdp");
|
||||
|
||||
if (!pulse->context)
|
||||
{
|
||||
DEBUG_WARN("pa_context_new failed");
|
||||
audin_pulse_free((IAudinDevice*) pulse);
|
||||
return 1;
|
||||
}
|
||||
|
||||
pa_context_set_state_callback(pulse->context, audin_pulse_context_state_callback, pulse);
|
||||
|
||||
if (!audin_pulse_connect((IAudinDevice*) pulse))
|
||||
{
|
||||
audin_pulse_free((IAudinDevice*) pulse);
|
||||
@@ -481,4 +528,3 @@ int freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEnt
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,11 +25,11 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <freerdp/utils/dsp.h>
|
||||
#include <freerdp/utils/thread.h>
|
||||
#include <freerdp/utils/wait_obj.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/channels/wtsvc.h>
|
||||
#include <freerdp/server/audin.h>
|
||||
|
||||
@@ -134,7 +134,9 @@ static BOOL audin_server_recv_formats(audin_server* audin, STREAM* s, UINT32 len
|
||||
if (audin->context.num_client_formats <= 0)
|
||||
return FALSE;
|
||||
|
||||
audin->context.client_formats = xzalloc(audin->context.num_client_formats * sizeof(rdpsndFormat));
|
||||
audin->context.client_formats = malloc(audin->context.num_client_formats * sizeof(rdpsndFormat));
|
||||
ZeroMemory(audin->context.client_formats, audin->context.num_client_formats * sizeof(rdpsndFormat));
|
||||
|
||||
for (i = 0; i < audin->context.num_client_formats; i++)
|
||||
{
|
||||
if (length < 18)
|
||||
@@ -273,22 +275,27 @@ static void* audin_server_thread_func(void* arg)
|
||||
|
||||
if (WTSVirtualChannelQuery(audin->audin_channel, WTSVirtualFileHandle, &buffer, &bytes_returned) == TRUE)
|
||||
{
|
||||
fd = *((void**)buffer);
|
||||
fd = *((void**) buffer);
|
||||
WTSFreeMemory(buffer);
|
||||
thread->signals[thread->num_signals++] = wait_obj_new_with_fd(fd);
|
||||
|
||||
thread->signals[thread->num_signals++] = CreateWaitObjectEvent(NULL, TRUE, FALSE, fd);
|
||||
}
|
||||
|
||||
/* Wait for the client to confirm that the Audio Input dynamic channel is ready */
|
||||
while (1)
|
||||
{
|
||||
freerdp_thread_wait(thread);
|
||||
|
||||
if (freerdp_thread_is_stopped(thread))
|
||||
break;
|
||||
|
||||
if (WTSVirtualChannelQuery(audin->audin_channel, WTSVirtualChannelReady, &buffer, &bytes_returned) == FALSE)
|
||||
break;
|
||||
ready = *((BOOL*)buffer);
|
||||
|
||||
ready = *((BOOL*) buffer);
|
||||
|
||||
WTSFreeMemory(buffer);
|
||||
|
||||
if (ready)
|
||||
break;
|
||||
}
|
||||
@@ -410,7 +417,9 @@ audin_server_context* audin_server_context_new(WTSVirtualChannelManager* vcm)
|
||||
{
|
||||
audin_server* audin;
|
||||
|
||||
audin = xnew(audin_server);
|
||||
audin = (audin_server*) malloc(sizeof(audin_server));
|
||||
ZeroMemory(audin, sizeof(audin_server));
|
||||
|
||||
audin->context.vcm = vcm;
|
||||
audin->context.selected_client_format = -1;
|
||||
audin->context.frames_per_packet = 4096;
|
||||
@@ -428,9 +437,12 @@ void audin_server_context_free(audin_server_context* context)
|
||||
audin_server* audin = (audin_server*) context;
|
||||
|
||||
audin_server_close(context);
|
||||
|
||||
if (audin->dsp_context)
|
||||
freerdp_dsp_context_free(audin->dsp_context);
|
||||
|
||||
if (audin->context.client_formats)
|
||||
free(audin->context.client_formats);
|
||||
|
||||
free(audin);
|
||||
}
|
||||
|
||||
@@ -63,12 +63,22 @@ foreach(STATIC_MODULE ${CHANNEL_STATIC_CLIENT_MODULES})
|
||||
set(CHANNEL_SUBSYSTEMS "")
|
||||
endif()
|
||||
foreach(STATIC_SUBSYSTEM ${CHANNEL_SUBSYSTEMS})
|
||||
message(STATUS "STATIC_SUBSYSTEM: ${STATIC_SUBSYSTEM}")
|
||||
string(TOUPPER "${STATIC_MODULE}_CLIENT_${STATIC_SUBSYSTEM}" SUBSYSTEM_PREFIX)
|
||||
if(${STATIC_SUBSYSTEM} MATCHES "^([^-]*)-(.*)")
|
||||
string(REGEX REPLACE "^([^-]*)-(.*)" "\\1" STATIC_SUBSYSTEM_NAME ${STATIC_SUBSYSTEM})
|
||||
string(REGEX REPLACE "^([^-]*)-(.*)" "\\2" STATIC_SUBSYSTEM_TYPE ${STATIC_SUBSYSTEM})
|
||||
else()
|
||||
set(STATIC_SUBSYSTEM_NAME "${STATIC_SUBSYSTEM}")
|
||||
set(STATIC_SUBSYSTEM_TYPE "")
|
||||
endif()
|
||||
string(LENGTH "${STATIC_SUBSYSTEM_TYPE}" _type_length)
|
||||
set(SUBSYSTEM_MODULE_NAME "${STATIC_MODULE_NAME}-${STATIC_SUBSYSTEM}")
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${SUBSYSTEM_MODULE_NAME})
|
||||
set(STATIC_SUBSYSTEM_ENTRY "${STATIC_SUBSYSTEM}_freerdp_${STATIC_MODULE_CHANNEL}_client_subsystem_entry")
|
||||
set(SUBSYSTEM_TABLE "${SUBSYSTEM_TABLE}\n\t{ \"${STATIC_SUBSYSTEM}\", \"\", ${STATIC_SUBSYSTEM_ENTRY} },")
|
||||
if(_type_length GREATER 0)
|
||||
set(STATIC_SUBSYSTEM_ENTRY "${STATIC_SUBSYSTEM_NAME}_freerdp_${STATIC_MODULE_CHANNEL}_client_${STATIC_SUBSYSTEM_TYPE}_subsystem_entry")
|
||||
else()
|
||||
set(STATIC_SUBSYSTEM_ENTRY "${STATIC_SUBSYSTEM_NAME}_freerdp_${STATIC_MODULE_CHANNEL}_client_subsystem_entry")
|
||||
endif()
|
||||
set(SUBSYSTEM_TABLE "${SUBSYSTEM_TABLE}\n\t{ \"${STATIC_SUBSYSTEM_NAME}\", \"${STATIC_SUBSYSTEM_TYPE}\", ${STATIC_SUBSYSTEM_ENTRY} },")
|
||||
set(SUBSYSTEM_IMPORT "extern void ${STATIC_SUBSYSTEM_ENTRY}();")
|
||||
set(CLIENT_STATIC_SUBSYSTEM_IMPORTS "${CLIENT_STATIC_SUBSYSTEM_IMPORTS}\n${SUBSYSTEM_IMPORT}")
|
||||
endforeach()
|
||||
|
||||
@@ -34,9 +34,7 @@
|
||||
#include <freerdp/client/channels.h>
|
||||
#include <freerdp/channels/channels.h>
|
||||
#include <freerdp/svc.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/wait_obj.h>
|
||||
#include <freerdp/utils/load_plugin.h>
|
||||
#include <freerdp/addin.h>
|
||||
#include <freerdp/utils/file.h>
|
||||
#include <freerdp/utils/event.h>
|
||||
#include <freerdp/utils/debug.h>
|
||||
@@ -112,40 +110,9 @@ void* freerdp_channels_client_find_static_entry(const char* name, const char* id
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* freerdp_channels_client_find_dynamic_entry(const char* name, const char* identifier)
|
||||
{
|
||||
char* path;
|
||||
void* entry;
|
||||
char* module;
|
||||
|
||||
module = freerdp_append_shared_library_suffix((char*) identifier);
|
||||
path = freerdp_construct_path(FREERDP_PLUGIN_PATH, module);
|
||||
|
||||
entry = freerdp_load_library_symbol(path, module);
|
||||
|
||||
free(module);
|
||||
free(path);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
void* freerdp_channels_client_find_entry(const char* name, const char* identifier)
|
||||
{
|
||||
void* pChannelEntry = NULL;
|
||||
|
||||
pChannelEntry = freerdp_channels_client_find_static_entry(name, identifier);
|
||||
|
||||
if (!pChannelEntry)
|
||||
{
|
||||
pChannelEntry = freerdp_channels_client_find_dynamic_entry(name, identifier);
|
||||
}
|
||||
|
||||
return pChannelEntry;
|
||||
}
|
||||
|
||||
extern const STATIC_ADDIN_TABLE CLIENT_STATIC_ADDIN_TABLE[];
|
||||
|
||||
FREERDP_ADDIN** freerdp_channels_list_client_static_addins(LPSTR lpName, LPSTR lpSubsystem, LPSTR lpType, DWORD dwFlags)
|
||||
FREERDP_ADDIN** freerdp_channels_list_client_static_addins(LPSTR pszName, LPSTR pszSubsystem, LPSTR pszType, DWORD dwFlags)
|
||||
{
|
||||
int i, j;
|
||||
DWORD nAddins;
|
||||
@@ -194,64 +161,63 @@ FREERDP_ADDIN** freerdp_channels_list_client_static_addins(LPSTR lpName, LPSTR l
|
||||
return ppAddins;
|
||||
}
|
||||
|
||||
LPCSTR gAddinPath = FREERDP_ADDIN_PATH;
|
||||
LPCSTR gInstallPrefix = FREERDP_INSTALL_PREFIX;
|
||||
|
||||
FREERDP_ADDIN** freerdp_channels_list_client_dynamic_addins(LPSTR lpName, LPSTR lpSubsystem, LPSTR lpType, DWORD dwFlags)
|
||||
FREERDP_ADDIN** freerdp_channels_list_dynamic_addins(LPSTR pszName, LPSTR pszSubsystem, LPSTR pszType, DWORD dwFlags)
|
||||
{
|
||||
int index;
|
||||
int nDashes;
|
||||
HANDLE hFind;
|
||||
DWORD nAddins;
|
||||
LPSTR lpPattern;
|
||||
LPSTR pszPattern;
|
||||
size_t cchPattern;
|
||||
LPCSTR lpExtension;
|
||||
LPSTR lpSearchPath;
|
||||
LPCSTR pszAddinPath = FREERDP_ADDIN_PATH;
|
||||
LPCSTR pszInstallPrefix = FREERDP_INSTALL_PREFIX;
|
||||
LPCSTR pszExtension;
|
||||
LPSTR pszSearchPath;
|
||||
size_t cchSearchPath;
|
||||
size_t cchAddinPath;
|
||||
size_t cchInstallPrefix;
|
||||
FREERDP_ADDIN** ppAddins;
|
||||
WIN32_FIND_DATAA FindData;
|
||||
|
||||
cchAddinPath = strlen(gAddinPath);
|
||||
cchInstallPrefix = strlen(gInstallPrefix);
|
||||
cchAddinPath = strlen(pszAddinPath);
|
||||
cchInstallPrefix = strlen(pszInstallPrefix);
|
||||
|
||||
lpExtension = PathGetSharedLibraryExtensionA(0);
|
||||
pszExtension = PathGetSharedLibraryExtensionA(0);
|
||||
|
||||
cchPattern = 128 + strlen(lpExtension) + 2;
|
||||
lpPattern = (LPSTR) malloc(cchPattern + 1);
|
||||
cchPattern = 128 + strlen(pszExtension) + 2;
|
||||
pszPattern = (LPSTR) malloc(cchPattern + 1);
|
||||
|
||||
if (lpName && lpSubsystem && lpType)
|
||||
if (pszName && pszSubsystem && pszType)
|
||||
{
|
||||
sprintf_s(lpPattern, cchPattern, "%s-client-%s-%s.%s", lpName, lpSubsystem, lpType, lpExtension);
|
||||
sprintf_s(pszPattern, cchPattern, "%s-client-%s-%s.%s", pszName, pszSubsystem, pszType, pszExtension);
|
||||
}
|
||||
else if (lpName && lpType)
|
||||
else if (pszName && pszType)
|
||||
{
|
||||
sprintf_s(lpPattern, cchPattern, "%s-client-?-%s.%s", lpName, lpType, lpExtension);
|
||||
sprintf_s(pszPattern, cchPattern, "%s-client-?-%s.%s", pszName, pszType, pszExtension);
|
||||
}
|
||||
else if (lpName)
|
||||
else if (pszName)
|
||||
{
|
||||
sprintf_s(lpPattern, cchPattern, "%s-client*.%s", lpName, lpExtension);
|
||||
sprintf_s(pszPattern, cchPattern, "%s-client*.%s", pszName, pszExtension);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf_s(lpPattern, cchPattern, "?-client*.%s", lpExtension);
|
||||
sprintf_s(pszPattern, cchPattern, "?-client*.%s", pszExtension);
|
||||
}
|
||||
|
||||
cchPattern = strlen(lpPattern);
|
||||
cchPattern = strlen(pszPattern);
|
||||
|
||||
cchSearchPath = cchInstallPrefix + cchAddinPath + cchPattern + 3;
|
||||
lpSearchPath = (LPSTR) malloc(cchSearchPath + 1);
|
||||
pszSearchPath = (LPSTR) malloc(cchSearchPath + 1);
|
||||
|
||||
CopyMemory(lpSearchPath, gInstallPrefix, cchInstallPrefix);
|
||||
lpSearchPath[cchInstallPrefix] = '\0';
|
||||
CopyMemory(pszSearchPath, pszInstallPrefix, cchInstallPrefix);
|
||||
pszSearchPath[cchInstallPrefix] = '\0';
|
||||
|
||||
NativePathCchAppendA(lpSearchPath, cchSearchPath + 1, gAddinPath);
|
||||
NativePathCchAppendA(lpSearchPath, cchSearchPath + 1, lpPattern);
|
||||
NativePathCchAppendA(pszSearchPath, cchSearchPath + 1, pszAddinPath);
|
||||
NativePathCchAppendA(pszSearchPath, cchSearchPath + 1, pszPattern);
|
||||
|
||||
cchSearchPath = strlen(lpSearchPath);
|
||||
cchSearchPath = strlen(pszSearchPath);
|
||||
|
||||
hFind = FindFirstFileA(lpSearchPath, &FindData);
|
||||
hFind = FindFirstFileA(pszSearchPath, &FindData);
|
||||
|
||||
nAddins = 0;
|
||||
ppAddins = (FREERDP_ADDIN**) malloc(sizeof(FREERDP_ADDIN*) * 128);
|
||||
@@ -342,12 +308,12 @@ FREERDP_ADDIN** freerdp_channels_list_client_dynamic_addins(LPSTR lpName, LPSTR
|
||||
return ppAddins;
|
||||
}
|
||||
|
||||
FREERDP_ADDIN** freerdp_channels_list_client_addins(LPSTR lpName, LPSTR lpSubsystem, LPSTR lpType, DWORD dwFlags)
|
||||
FREERDP_ADDIN** freerdp_channels_list_addins(LPSTR pszName, LPSTR pszSubsystem, LPSTR pszType, DWORD dwFlags)
|
||||
{
|
||||
if (dwFlags & FREERDP_ADDIN_STATIC)
|
||||
return freerdp_channels_list_client_static_addins(lpName, lpSubsystem, lpType, dwFlags);
|
||||
return freerdp_channels_list_client_static_addins(pszName, pszSubsystem, pszType, dwFlags);
|
||||
else if (dwFlags & FREERDP_ADDIN_DYNAMIC)
|
||||
return freerdp_channels_list_client_dynamic_addins(lpName, lpSubsystem, lpType, dwFlags);
|
||||
return freerdp_channels_list_dynamic_addins(pszName, pszSubsystem, pszType, dwFlags);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -362,139 +328,43 @@ void freerdp_channels_addin_list_free(FREERDP_ADDIN** ppAddins)
|
||||
free(ppAddins);
|
||||
}
|
||||
|
||||
void* freerdp_channels_load_static_addin_entry(LPCSTR lpName, LPSTR lpSubsystem, LPSTR lpType, DWORD dwFlags)
|
||||
void* freerdp_channels_load_static_addin_entry(LPCSTR pszName, LPSTR pszSubsystem, LPSTR pszType, DWORD dwFlags)
|
||||
{
|
||||
int i, j;
|
||||
STATIC_SUBSYSTEM_ENTRY* subsystems;
|
||||
|
||||
for (i = 0; CLIENT_STATIC_ADDIN_TABLE[i].name != NULL; i++)
|
||||
{
|
||||
if ((lpSubsystem == NULL) && (lpType == NULL))
|
||||
if (strcmp(CLIENT_STATIC_ADDIN_TABLE[i].name, pszName) == 0)
|
||||
{
|
||||
return (void*) CLIENT_STATIC_ADDIN_TABLE[i].entry;
|
||||
}
|
||||
|
||||
subsystems = (STATIC_SUBSYSTEM_ENTRY*) CLIENT_STATIC_ADDIN_TABLE[i].table;
|
||||
|
||||
for (j = 0; subsystems[j].name != NULL; j++)
|
||||
{
|
||||
if (strcmp(subsystems[j].name, lpSubsystem) == 0)
|
||||
if (pszSubsystem != NULL)
|
||||
{
|
||||
if (lpType)
|
||||
subsystems = (STATIC_SUBSYSTEM_ENTRY*) CLIENT_STATIC_ADDIN_TABLE[i].table;
|
||||
|
||||
for (j = 0; subsystems[j].name != NULL; j++)
|
||||
{
|
||||
if (strcmp(subsystems[j].type, lpType) == 0)
|
||||
return (void*) subsystems[j].entry;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (void*) subsystems[j].entry;
|
||||
if (strcmp(subsystems[j].name, pszSubsystem) == 0)
|
||||
{
|
||||
if (pszType)
|
||||
{
|
||||
if (strcmp(subsystems[j].type, pszType) == 0)
|
||||
return (void*) subsystems[j].entry;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (void*) subsystems[j].entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
return (void*) CLIENT_STATIC_ADDIN_TABLE[i].entry;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* freerdp_channels_load_dynamic_addin_entry(LPCSTR lpName, LPSTR lpSubsystem, LPSTR lpType, DWORD dwFlags)
|
||||
{
|
||||
void* entry;
|
||||
LPSTR lpFileName;
|
||||
LPSTR lpFilePath;
|
||||
size_t cchFileName;
|
||||
size_t cchFilePath;
|
||||
size_t cchAddinPath;
|
||||
size_t cchInstallPrefix;
|
||||
LPCSTR lpExtension;
|
||||
HINSTANCE library;
|
||||
|
||||
cchAddinPath = strlen(gAddinPath);
|
||||
cchInstallPrefix = strlen(gInstallPrefix);
|
||||
|
||||
lpExtension = PathGetSharedLibraryExtensionA(0);
|
||||
|
||||
if (lpName && lpSubsystem && lpType)
|
||||
{
|
||||
cchFileName = strlen(lpName) + strlen(lpSubsystem) + strlen(lpType) + strlen(lpExtension) + 32;
|
||||
lpFileName = (LPSTR) malloc(cchFileName);
|
||||
sprintf_s(lpFileName, cchFileName, "%s-client-%s-%s.%s", lpName, lpSubsystem, lpType, lpExtension);
|
||||
cchFileName = strlen(lpFileName);
|
||||
}
|
||||
else if (lpName && lpSubsystem)
|
||||
{
|
||||
cchFileName = strlen(lpName) + strlen(lpSubsystem) + strlen(lpExtension) + 32;
|
||||
lpFileName = (LPSTR) malloc(cchFileName);
|
||||
sprintf_s(lpFileName, cchFileName, "%s-client-%s.%s", lpName, lpSubsystem, lpExtension);
|
||||
cchFileName = strlen(lpFileName);
|
||||
}
|
||||
else if (lpName)
|
||||
{
|
||||
cchFileName = strlen(lpName) + strlen(lpExtension) + 32;
|
||||
lpFileName = (LPSTR) malloc(cchFileName);
|
||||
sprintf_s(lpFileName, cchFileName, "%s-client.%s", lpName, lpExtension);
|
||||
cchFileName = strlen(lpFileName);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cchFilePath = cchInstallPrefix + cchAddinPath + cchFileName + 32;
|
||||
lpFilePath = (LPSTR) malloc(cchFilePath + 1);
|
||||
|
||||
CopyMemory(lpFilePath, gInstallPrefix, cchInstallPrefix);
|
||||
lpFilePath[cchInstallPrefix] = '\0';
|
||||
|
||||
NativePathCchAppendA(lpFilePath, cchFilePath + 1, gAddinPath);
|
||||
NativePathCchAppendA(lpFilePath, cchFilePath + 1, lpFileName);
|
||||
cchFilePath = strlen(lpFilePath);
|
||||
|
||||
library = LoadLibraryA(lpFilePath);
|
||||
|
||||
if (!library)
|
||||
return NULL;
|
||||
|
||||
if (lpSubsystem)
|
||||
{
|
||||
LPSTR lpEntryName;
|
||||
size_t cchEntryName;
|
||||
|
||||
/* subsystem add-in */
|
||||
|
||||
cchEntryName = 64 + strlen(lpName);
|
||||
lpEntryName = (LPSTR) malloc(cchEntryName + 1);
|
||||
sprintf_s(lpEntryName, cchEntryName + 1, "freerdp_%s_client_subsystem_entry", lpName);
|
||||
|
||||
entry = GetProcAddress(library, lpEntryName);
|
||||
|
||||
if (entry)
|
||||
return entry;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* channel add-in */
|
||||
|
||||
entry = GetProcAddress(library, lpType);
|
||||
|
||||
if (entry)
|
||||
return entry;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* freerdp_channels_load_addin_entry(LPCSTR lpName, LPSTR lpSubsystem, LPSTR lpType, DWORD dwFlags)
|
||||
{
|
||||
void* entry = NULL;
|
||||
|
||||
entry = freerdp_channels_load_static_addin_entry(lpName, lpSubsystem, lpType, dwFlags);
|
||||
|
||||
if (!entry)
|
||||
entry = freerdp_channels_load_dynamic_addin_entry(lpName, lpSubsystem, lpType, dwFlags);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
struct lib_data
|
||||
{
|
||||
PVIRTUALCHANNELENTRY entry; /* the one and only exported function */
|
||||
@@ -559,7 +429,7 @@ struct rdp_channels
|
||||
freerdp* instance;
|
||||
|
||||
/* signal for incoming data or event */
|
||||
struct wait_obj* signal;
|
||||
HANDLE signal;
|
||||
|
||||
/* used for sync write */
|
||||
PSLIST_HEADER pSyncDataList;
|
||||
@@ -966,7 +836,7 @@ static UINT32 FREERDP_CC MyVirtualChannelWrite(UINT32 openHandle, void* pData, U
|
||||
InterlockedPushEntrySList(channels->pSyncDataList, &(item->ItemEntry));
|
||||
|
||||
/* set the event */
|
||||
wait_obj_set(channels->signal);
|
||||
SetEvent(channels->signal);
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
@@ -1017,7 +887,7 @@ static UINT32 FREERDP_CC MyVirtualChannelEventPush(UINT32 openHandle, RDP_EVENT*
|
||||
|
||||
channels->event = event;
|
||||
/* set the event */
|
||||
wait_obj_set(channels->signal);
|
||||
SetEvent(channels->signal);
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
@@ -1054,16 +924,18 @@ rdpChannels* freerdp_channels_new(void)
|
||||
rdpChannels* channels;
|
||||
rdpChannelsList* channels_list;
|
||||
|
||||
channels = xnew(rdpChannels);
|
||||
channels = (rdpChannels*) malloc(sizeof(rdpChannels));
|
||||
ZeroMemory(channels, sizeof(rdpChannels));
|
||||
|
||||
channels->pSyncDataList = (PSLIST_HEADER) _aligned_malloc(sizeof(SLIST_HEADER), MEMORY_ALLOCATION_ALIGNMENT);
|
||||
InitializeSListHead(channels->pSyncDataList);
|
||||
|
||||
channels->event_sem = CreateSemaphore(NULL, 1, 16, NULL);
|
||||
channels->signal = wait_obj_new();
|
||||
channels->signal = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
/* Add it to the global list */
|
||||
channels_list = xnew(rdpChannelsList);
|
||||
channels_list = (rdpChannelsList*) malloc(sizeof(rdpChannelsList));
|
||||
ZeroMemory(channels_list, sizeof(rdpChannelsList));
|
||||
channels_list->channels = channels;
|
||||
|
||||
WaitForSingleObject(g_mutex_list, INFINITE);
|
||||
@@ -1083,7 +955,7 @@ void freerdp_channels_free(rdpChannels* channels)
|
||||
_aligned_free(channels->pSyncDataList);
|
||||
|
||||
CloseHandle(channels->event_sem);
|
||||
wait_obj_free(channels->signal);
|
||||
CloseHandle(channels->signal);
|
||||
|
||||
/* Remove from global list */
|
||||
|
||||
@@ -1117,7 +989,7 @@ int freerdp_channels_client_load(rdpChannels* channels, rdpSettings* settings, v
|
||||
|
||||
if (channels->num_libs_data + 1 >= CHANNEL_MAX_COUNT)
|
||||
{
|
||||
DEBUG_CHANNELS("too many channels");
|
||||
printf("error: too many channels\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1151,7 +1023,7 @@ int freerdp_channels_client_load(rdpChannels* channels, rdpSettings* settings, v
|
||||
|
||||
if (!status)
|
||||
{
|
||||
DEBUG_CHANNELS("export function call failed");
|
||||
printf("error: channel export function call failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1166,9 +1038,9 @@ int freerdp_channels_load_plugin(rdpChannels* channels, rdpSettings* settings, c
|
||||
{
|
||||
void* entry;
|
||||
|
||||
DEBUG_CHANNELS("%s", Name);
|
||||
DEBUG_CHANNELS("%s", name);
|
||||
|
||||
entry = (PVIRTUALCHANNELENTRY) freerdp_load_plugin(name, CHANNEL_EXPORT_FUNC_NAME);
|
||||
entry = (PVIRTUALCHANNELENTRY) freerdp_load_channel_addin_entry(name, NULL, NULL, FREERDP_ADDIN_CHANNEL_STATIC);
|
||||
|
||||
if (entry == NULL)
|
||||
{
|
||||
@@ -1244,7 +1116,7 @@ int freerdp_channels_post_connect(rdpChannels* channels, freerdp* instance)
|
||||
hostname = instance->settings->ServerHostname;
|
||||
hostname_len = strlen(hostname);
|
||||
|
||||
DEBUG_CHANNELS("hostname [%s] channels->num_libs [%d]", Hostname, channels->num_libs_data);
|
||||
DEBUG_CHANNELS("hostname [%s] channels->num_libs [%d]", hostname, channels->num_libs_data);
|
||||
|
||||
for (index = 0; index < channels->num_libs_data; index++)
|
||||
{
|
||||
@@ -1335,7 +1207,7 @@ FREERDP_API int freerdp_channels_send_event(rdpChannels* channels, RDP_EVENT* ev
|
||||
|
||||
if (lchannel_data == NULL)
|
||||
{
|
||||
DEBUG_CHANNELS("could not find channel name %s", Name);
|
||||
DEBUG_CHANNELS("could not find channel name %s", name);
|
||||
freerdp_event_free(event);
|
||||
return 1;
|
||||
}
|
||||
@@ -1390,7 +1262,16 @@ static void freerdp_channels_process_sync(rdpChannels* channels, freerdp* instan
|
||||
BOOL freerdp_channels_get_fds(rdpChannels* channels, freerdp* instance, void** read_fds,
|
||||
int* read_count, void** write_fds, int* write_count)
|
||||
{
|
||||
wait_obj_get_fds(channels->signal, read_fds, read_count);
|
||||
void* pfd;
|
||||
|
||||
pfd = GetEventWaitObject(channels->signal);
|
||||
|
||||
if (pfd)
|
||||
{
|
||||
read_fds[*read_count] = pfd;
|
||||
(*read_count)++;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -1399,9 +1280,9 @@ BOOL freerdp_channels_get_fds(rdpChannels* channels, freerdp* instance, void** r
|
||||
*/
|
||||
BOOL freerdp_channels_check_fds(rdpChannels* channels, freerdp* instance)
|
||||
{
|
||||
if (wait_obj_is_set(channels->signal))
|
||||
if (WaitForSingleObject(channels->signal, 0) == WAIT_OBJECT_0)
|
||||
{
|
||||
wait_obj_clear(channels->signal);
|
||||
ResetEvent(channels->signal);
|
||||
freerdp_channels_process_sync(channels, instance);
|
||||
}
|
||||
|
||||
@@ -1443,3 +1324,7 @@ void freerdp_channels_close(rdpChannels* channels, freerdp* instance)
|
||||
}
|
||||
}
|
||||
|
||||
/* Local variables: */
|
||||
/* c-basic-offset: 8 */
|
||||
/* c-file-style: "linux" */
|
||||
/* End: */
|
||||
|
||||
@@ -3,10 +3,6 @@ set(OPTION_DEFAULT OFF)
|
||||
set(OPTION_CLIENT_DEFAULT ON)
|
||||
set(OPTION_SERVER_DEFAULT OFF)
|
||||
|
||||
if(${OPTION_CLIENT_DEFAULT} OR ${OPTION_SERVER_DEFAULT})
|
||||
set(OPTION_DEFAULT ON)
|
||||
endif()
|
||||
|
||||
define_channel_options(NAME "cliprdr" TYPE "static"
|
||||
DESCRIPTION "Clipboard Virtual Channel Extension"
|
||||
SPECIFICATIONS "[MS-RDPECLIP]"
|
||||
|
||||
@@ -27,12 +27,10 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/print.h>
|
||||
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/constants.h>
|
||||
#include <freerdp/utils/hexdump.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/unicode.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
#include <freerdp/client/cliprdr.h>
|
||||
|
||||
@@ -146,7 +144,7 @@ void cliprdr_process_short_format_names(cliprdrPlugin* cliprdr, STREAM* s, UINT3
|
||||
}
|
||||
else
|
||||
{
|
||||
format_name->length = freerdp_UnicodeToAsciiAlloc((WCHAR*) s->p, &format_name->name, 32 / 2);
|
||||
format_name->length = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) s->p, 32 / 2, &format_name->name, 0, NULL, NULL);
|
||||
}
|
||||
|
||||
stream_seek(s, 32);
|
||||
@@ -189,7 +187,8 @@ void cliprdr_process_long_format_names(cliprdrPlugin* cliprdr, STREAM* s, UINT32
|
||||
break;
|
||||
}
|
||||
|
||||
format_name->length = freerdp_UnicodeToAsciiAlloc((WCHAR*) stream_get_tail(s), &format_name->name, name_len / 2);
|
||||
format_name->length = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) stream_get_tail(s), name_len / 2, &format_name->name, 0, NULL, NULL);
|
||||
|
||||
stream_seek(s, name_len + 2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,8 +30,6 @@
|
||||
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/constants.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/unicode.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
#include <freerdp/client/cliprdr.h>
|
||||
|
||||
|
||||
@@ -3,10 +3,6 @@ set(OPTION_DEFAULT OFF)
|
||||
set(OPTION_CLIENT_DEFAULT ON)
|
||||
set(OPTION_SERVER_DEFAULT OFF)
|
||||
|
||||
if(${OPTION_CLIENT_DEFAULT} OR ${OPTION_SERVER_DEFAULT})
|
||||
set(OPTION_DEFAULT ON)
|
||||
endif()
|
||||
|
||||
define_channel_options(NAME "drdynvc" TYPE "static"
|
||||
DESCRIPTION "Dynamic Virtual Channel Extension"
|
||||
SPECIFICATIONS "[MS-RDPEDYC]"
|
||||
|
||||
@@ -28,20 +28,18 @@
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <freerdp/constants.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
#include <freerdp/utils/wait_obj.h>
|
||||
|
||||
#include "dvcman.h"
|
||||
#include "drdynvc_types.h"
|
||||
#include "drdynvc_main.h"
|
||||
|
||||
#define CREATE_REQUEST_PDU 0x01
|
||||
#define DATA_FIRST_PDU 0x02
|
||||
#define DATA_PDU 0x03
|
||||
#define CLOSE_REQUEST_PDU 0x04
|
||||
#define CAPABILITY_REQUEST_PDU 0x05
|
||||
#define CREATE_REQUEST_PDU 0x01
|
||||
#define DATA_FIRST_PDU 0x02
|
||||
#define DATA_PDU 0x03
|
||||
#define CLOSE_REQUEST_PDU 0x04
|
||||
#define CAPABILITY_REQUEST_PDU 0x05
|
||||
|
||||
struct drdynvc_plugin
|
||||
{
|
||||
@@ -76,6 +74,7 @@ static int drdynvc_write_variable_uint(STREAM* stream, UINT32 val)
|
||||
cb = 2;
|
||||
stream_write_UINT32(stream, val);
|
||||
}
|
||||
|
||||
return cb;
|
||||
}
|
||||
|
||||
@@ -97,13 +96,13 @@ int drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, BYTE* data, UIN
|
||||
stream_set_pos(data_out, 1);
|
||||
cbChId = drdynvc_write_variable_uint(data_out, ChannelId);
|
||||
|
||||
if(data_size == 0)
|
||||
if (data_size == 0)
|
||||
{
|
||||
pos = stream_get_pos(data_out);
|
||||
stream_set_pos(data_out, 0);
|
||||
stream_write_BYTE(data_out, 0x40 | cbChId);
|
||||
stream_set_pos(data_out, pos);
|
||||
error = svc_plugin_send((rdpSvcPlugin*)drdynvc, data_out);
|
||||
error = svc_plugin_send((rdpSvcPlugin*) drdynvc, data_out);
|
||||
}
|
||||
else if (data_size <= CHANNEL_CHUNK_LENGTH - pos)
|
||||
{
|
||||
@@ -112,7 +111,7 @@ int drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, BYTE* data, UIN
|
||||
stream_write_BYTE(data_out, 0x30 | cbChId);
|
||||
stream_set_pos(data_out, pos);
|
||||
stream_write(data_out, data, data_size);
|
||||
error = svc_plugin_send((rdpSvcPlugin*)drdynvc, data_out);
|
||||
error = svc_plugin_send((rdpSvcPlugin*) drdynvc, data_out);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -126,7 +125,7 @@ int drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, BYTE* data, UIN
|
||||
stream_write(data_out, data, chunk_len);
|
||||
data += chunk_len;
|
||||
data_size -= chunk_len;
|
||||
error = svc_plugin_send((rdpSvcPlugin*)drdynvc, data_out);
|
||||
error = svc_plugin_send((rdpSvcPlugin*) drdynvc, data_out);
|
||||
|
||||
while (error == CHANNEL_RC_OK && data_size > 0)
|
||||
{
|
||||
@@ -148,12 +147,14 @@ int drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, BYTE* data, UIN
|
||||
error = svc_plugin_send((rdpSvcPlugin*)drdynvc, data_out);
|
||||
}
|
||||
}
|
||||
|
||||
if (error != CHANNEL_RC_OK)
|
||||
{
|
||||
drdynvc->channel_error = error;
|
||||
DEBUG_WARN("VirtualChannelWrite failed %d", error);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -161,12 +162,14 @@ int drdynvc_push_event(drdynvcPlugin* drdynvc, RDP_EVENT* event)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = svc_plugin_send_event((rdpSvcPlugin*)drdynvc, event);
|
||||
error = svc_plugin_send_event((rdpSvcPlugin*) drdynvc, event);
|
||||
|
||||
if (error != CHANNEL_RC_OK)
|
||||
{
|
||||
DEBUG_WARN("pVirtualChannelEventPush failed %d", error);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -178,6 +181,7 @@ static int drdynvc_process_capability_request(drdynvcPlugin* drdynvc, int Sp, in
|
||||
DEBUG_DVC("Sp=%d cbChId=%d", Sp, cbChId);
|
||||
stream_seek(s, 1); /* pad */
|
||||
stream_read_UINT16(s, drdynvc->version);
|
||||
|
||||
if (drdynvc->version == 2)
|
||||
{
|
||||
stream_read_UINT16(s, drdynvc->PriorityCharge0);
|
||||
@@ -185,15 +189,18 @@ static int drdynvc_process_capability_request(drdynvcPlugin* drdynvc, int Sp, in
|
||||
stream_read_UINT16(s, drdynvc->PriorityCharge2);
|
||||
stream_read_UINT16(s, drdynvc->PriorityCharge3);
|
||||
}
|
||||
|
||||
data_out = stream_new(4);
|
||||
stream_write_UINT16(data_out, 0x0050); /* Cmd+Sp+cbChId+Pad. Note: MSTSC sends 0x005c */
|
||||
stream_write_UINT16(data_out, drdynvc->version);
|
||||
error = svc_plugin_send((rdpSvcPlugin*)drdynvc, data_out);
|
||||
error = svc_plugin_send((rdpSvcPlugin*) drdynvc, data_out);
|
||||
|
||||
if (error != CHANNEL_RC_OK)
|
||||
{
|
||||
DEBUG_WARN("VirtualChannelWrite failed %d", error);
|
||||
return 1;
|
||||
}
|
||||
|
||||
drdynvc->channel_error = error;
|
||||
|
||||
return 0;
|
||||
@@ -208,28 +215,31 @@ static UINT32 drdynvc_read_variable_uint(STREAM* stream, int cbLen)
|
||||
case 0:
|
||||
stream_read_BYTE(stream, val);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
stream_read_UINT16(stream, val);
|
||||
break;
|
||||
|
||||
default:
|
||||
stream_read_UINT32(stream, val);
|
||||
break;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static int drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, int cbChId, STREAM* s)
|
||||
{
|
||||
STREAM* data_out;
|
||||
int pos;
|
||||
int error;
|
||||
UINT32 ChannelId;
|
||||
STREAM* data_out;
|
||||
|
||||
ChannelId = drdynvc_read_variable_uint(s, cbChId);
|
||||
pos = stream_get_pos(s);
|
||||
DEBUG_DVC("ChannelId=%d ChannelName=%s", ChannelId, stream_get_tail(s));
|
||||
|
||||
error = dvcman_create_channel(drdynvc->channel_mgr, ChannelId, (char*)stream_get_tail(s));
|
||||
error = dvcman_create_channel(drdynvc->channel_mgr, ChannelId, (char*) stream_get_tail(s));
|
||||
|
||||
data_out = stream_new(pos + 4);
|
||||
stream_write_BYTE(data_out, 0x10 | cbChId);
|
||||
@@ -247,26 +257,29 @@ static int drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, int cb
|
||||
stream_write_UINT32(data_out, (UINT32)(-1));
|
||||
}
|
||||
|
||||
error = svc_plugin_send((rdpSvcPlugin*)drdynvc, data_out);
|
||||
error = svc_plugin_send((rdpSvcPlugin*) drdynvc, data_out);
|
||||
|
||||
if (error != CHANNEL_RC_OK)
|
||||
{
|
||||
DEBUG_WARN("VirtualChannelWrite failed %d", error);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int drdynvc_process_data_first(drdynvcPlugin* drdynvc, int Sp, int cbChId, STREAM* s)
|
||||
{
|
||||
UINT32 ChannelId;
|
||||
UINT32 Length;
|
||||
int error;
|
||||
UINT32 Length;
|
||||
UINT32 ChannelId;
|
||||
|
||||
ChannelId = drdynvc_read_variable_uint(s, cbChId);
|
||||
Length = drdynvc_read_variable_uint(s, Sp);
|
||||
DEBUG_DVC("ChannelId=%d Length=%d", ChannelId, Length);
|
||||
|
||||
error = dvcman_receive_channel_data_first(drdynvc->channel_mgr, ChannelId, Length);
|
||||
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
@@ -298,11 +311,11 @@ static int drdynvc_process_close_request(drdynvcPlugin* drdynvc, int Sp, int cbC
|
||||
|
||||
static void drdynvc_process_receive(rdpSvcPlugin* plugin, STREAM* s)
|
||||
{
|
||||
drdynvcPlugin* drdynvc = (drdynvcPlugin*)plugin;
|
||||
int value;
|
||||
int Cmd;
|
||||
int Sp;
|
||||
int cbChId;
|
||||
drdynvcPlugin* drdynvc = (drdynvcPlugin*) plugin;
|
||||
|
||||
stream_read_BYTE(s, value);
|
||||
Cmd = (value & 0xf0) >> 4;
|
||||
@@ -338,13 +351,24 @@ static void drdynvc_process_receive(rdpSvcPlugin* plugin, STREAM* s)
|
||||
|
||||
static void drdynvc_process_connect(rdpSvcPlugin* plugin)
|
||||
{
|
||||
int index;
|
||||
ADDIN_ARGV* args;
|
||||
rdpSettings* settings;
|
||||
drdynvcPlugin* drdynvc = (drdynvcPlugin*)plugin;
|
||||
|
||||
DEBUG_DVC("connecting");
|
||||
|
||||
drdynvc->channel_mgr = dvcman_new(drdynvc);
|
||||
drdynvc->channel_error = 0;
|
||||
dvcman_load_plugin(drdynvc->channel_mgr, svc_plugin_get_data(plugin));
|
||||
|
||||
settings = (rdpSettings*) ((rdpSvcPlugin*) plugin)->channel_entry_points.pExtendedData;
|
||||
|
||||
for (index = 0; index < settings->DynamicChannelCount; index++)
|
||||
{
|
||||
args = settings->DynamicChannelArray[index];
|
||||
dvcman_load_addin(drdynvc->channel_mgr, args);
|
||||
}
|
||||
|
||||
dvcman_init(drdynvc->channel_mgr);
|
||||
}
|
||||
|
||||
@@ -355,7 +379,7 @@ static void drdynvc_process_event(rdpSvcPlugin* plugin, RDP_EVENT* event)
|
||||
|
||||
static void drdynvc_process_terminate(rdpSvcPlugin* plugin)
|
||||
{
|
||||
drdynvcPlugin* drdynvc = (drdynvcPlugin*)plugin;
|
||||
drdynvcPlugin* drdynvc = (drdynvcPlugin*) plugin;
|
||||
|
||||
DEBUG_DVC("terminating");
|
||||
|
||||
@@ -391,4 +415,3 @@ int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,10 +28,10 @@
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/synch.h>
|
||||
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/addin.h>
|
||||
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/list.h>
|
||||
#include <freerdp/utils/load_plugin.h>
|
||||
|
||||
#include "drdynvc_types.h"
|
||||
#include "dvcman.h"
|
||||
@@ -39,6 +39,7 @@
|
||||
#define MAX_PLUGINS 10
|
||||
|
||||
typedef struct _DVCMAN DVCMAN;
|
||||
|
||||
struct _DVCMAN
|
||||
{
|
||||
IWTSVirtualChannelManager iface;
|
||||
@@ -72,7 +73,7 @@ struct _DVCMAN_ENTRY_POINTS
|
||||
IDRDYNVC_ENTRY_POINTS iface;
|
||||
|
||||
DVCMAN* dvcman;
|
||||
RDP_PLUGIN_DATA* plugin_data;
|
||||
ADDIN_ARGV* args;
|
||||
};
|
||||
|
||||
typedef struct _DVCMAN_CHANNEL DVCMAN_CHANNEL;
|
||||
@@ -100,13 +101,16 @@ static int dvcman_create_listener(IWTSVirtualChannelManager* pChannelMgr,
|
||||
const char* pszChannelName, UINT32 ulFlags,
|
||||
IWTSListenerCallback* pListenerCallback, IWTSListener** ppListener)
|
||||
{
|
||||
DVCMAN* dvcman = (DVCMAN*)pChannelMgr;
|
||||
DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
|
||||
DVCMAN_LISTENER* listener;
|
||||
|
||||
if (dvcman->num_listeners < MAX_PLUGINS)
|
||||
{
|
||||
DEBUG_DVC("%d.%s.", dvcman->num_listeners, pszChannelName);
|
||||
listener = xnew(DVCMAN_LISTENER);
|
||||
|
||||
listener = (DVCMAN_LISTENER*) malloc(sizeof(DVCMAN_LISTENER));
|
||||
ZeroMemory(listener, sizeof(DVCMAN_LISTENER));
|
||||
|
||||
listener->iface.GetConfiguration = dvcman_get_configuration;
|
||||
listener->dvcman = dvcman;
|
||||
listener->channel_name = _strdup(pszChannelName);
|
||||
@@ -181,14 +185,14 @@ IWTSPlugin* dvcman_get_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints, const char* n
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RDP_PLUGIN_DATA* dvcman_get_plugin_data(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
|
||||
ADDIN_ARGV* dvcman_get_plugin_data(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
|
||||
{
|
||||
return ((DVCMAN_ENTRY_POINTS*) pEntryPoints)->plugin_data;
|
||||
return ((DVCMAN_ENTRY_POINTS*) pEntryPoints)->args;
|
||||
}
|
||||
|
||||
UINT32 dvcman_get_channel_id(IWTSVirtualChannel * channel)
|
||||
{
|
||||
return ((DVCMAN_CHANNEL*)channel)->channel_id;
|
||||
return ((DVCMAN_CHANNEL*) channel)->channel_id;
|
||||
}
|
||||
|
||||
IWTSVirtualChannel* dvcman_find_channel_by_id(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId)
|
||||
@@ -200,7 +204,7 @@ IWTSVirtualChannel* dvcman_find_channel_by_id(IWTSVirtualChannelManager* pChanne
|
||||
{
|
||||
if (((DVCMAN_CHANNEL*) curr->data)->channel_id == ChannelId)
|
||||
{
|
||||
return (IWTSVirtualChannel*)curr->data;
|
||||
return (IWTSVirtualChannel*) curr->data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,7 +215,9 @@ IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin)
|
||||
{
|
||||
DVCMAN* dvcman;
|
||||
|
||||
dvcman = xnew(DVCMAN);
|
||||
dvcman = (DVCMAN*) malloc(sizeof(DVCMAN));
|
||||
ZeroMemory(dvcman, sizeof(DVCMAN));
|
||||
|
||||
dvcman->iface.CreateListener = dvcman_create_listener;
|
||||
dvcman->iface.PushEvent = dvcman_push_event;
|
||||
dvcman->iface.FindChannelById = dvcman_find_channel_by_id;
|
||||
@@ -222,26 +228,24 @@ IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin)
|
||||
return (IWTSVirtualChannelManager*) dvcman;
|
||||
}
|
||||
|
||||
int dvcman_load_plugin(IWTSVirtualChannelManager* pChannelMgr, RDP_PLUGIN_DATA* data)
|
||||
int dvcman_load_addin(IWTSVirtualChannelManager* pChannelMgr, ADDIN_ARGV* args)
|
||||
{
|
||||
DVCMAN_ENTRY_POINTS entryPoints;
|
||||
PDVC_PLUGIN_ENTRY pDVCPluginEntry = NULL;
|
||||
|
||||
while (data && data->size > 0)
|
||||
{
|
||||
pDVCPluginEntry = (PDVC_PLUGIN_ENTRY) freerdp_load_plugin((char*) data->data[0], "DVCPluginEntry");
|
||||
printf("Loading Dynamic Virtual Channel %s\n", args->argv[0]);
|
||||
|
||||
if (pDVCPluginEntry != NULL)
|
||||
{
|
||||
entryPoints.iface.RegisterPlugin = dvcman_register_plugin;
|
||||
entryPoints.iface.GetPlugin = dvcman_get_plugin;
|
||||
entryPoints.iface.GetPluginData = dvcman_get_plugin_data;
|
||||
entryPoints.dvcman = (DVCMAN*) pChannelMgr;
|
||||
entryPoints.plugin_data = data;
|
||||
pDVCPluginEntry((IDRDYNVC_ENTRY_POINTS*) &entryPoints);
|
||||
}
|
||||
|
||||
data = (RDP_PLUGIN_DATA*)(((BYTE*) data) + data->size);
|
||||
pDVCPluginEntry = (PDVC_PLUGIN_ENTRY) freerdp_load_channel_addin_entry(args->argv[0],
|
||||
NULL, NULL, FREERDP_ADDIN_CHANNEL_DYNAMIC);
|
||||
|
||||
if (pDVCPluginEntry != NULL)
|
||||
{
|
||||
entryPoints.iface.RegisterPlugin = dvcman_register_plugin;
|
||||
entryPoints.iface.GetPlugin = dvcman_get_plugin;
|
||||
entryPoints.iface.GetPluginData = dvcman_get_plugin_data;
|
||||
entryPoints.dvcman = (DVCMAN*) pChannelMgr;
|
||||
entryPoints.args = args;
|
||||
pDVCPluginEntry((IDRDYNVC_ENTRY_POINTS*) &entryPoints);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -341,11 +345,13 @@ int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 Channel
|
||||
|
||||
for (i = 0; i < dvcman->num_listeners; i++)
|
||||
{
|
||||
listener = (DVCMAN_LISTENER*)dvcman->listeners[i];
|
||||
listener = (DVCMAN_LISTENER*) dvcman->listeners[i];
|
||||
|
||||
if (strcmp(listener->channel_name, ChannelName) == 0)
|
||||
{
|
||||
channel = xnew(DVCMAN_CHANNEL);
|
||||
channel = (DVCMAN_CHANNEL*) malloc(sizeof(DVCMAN_CHANNEL));
|
||||
ZeroMemory(channel, sizeof(DVCMAN_CHANNEL));
|
||||
|
||||
channel->iface.Write = dvcman_write_channel;
|
||||
channel->iface.Close = dvcman_close_channel_iface;
|
||||
channel->dvcman = dvcman;
|
||||
@@ -377,7 +383,6 @@ int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 Channel
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId)
|
||||
{
|
||||
DVCMAN_CHANNEL* channel;
|
||||
|
||||
@@ -21,10 +21,12 @@
|
||||
#define __DVCMAN_H
|
||||
|
||||
#include <freerdp/dvc.h>
|
||||
#include <freerdp/addin.h>
|
||||
|
||||
#include "drdynvc_main.h"
|
||||
|
||||
IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin);
|
||||
int dvcman_load_plugin(IWTSVirtualChannelManager* pChannelMgr, RDP_PLUGIN_DATA* data);
|
||||
int dvcman_load_addin(IWTSVirtualChannelManager* pChannelMgr, ADDIN_ARGV* args);
|
||||
void dvcman_free(IWTSVirtualChannelManager* pChannelMgr);
|
||||
int dvcman_init(IWTSVirtualChannelManager* pChannelMgr);
|
||||
int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, const char* ChannelName);
|
||||
|
||||
@@ -8,10 +8,6 @@ if(ANDROID)
|
||||
set(OPTION_SERVER_DEFAULT OFF)
|
||||
endif()
|
||||
|
||||
if(${OPTION_CLIENT_DEFAULT} OR ${OPTION_SERVER_DEFAULT})
|
||||
set(OPTION_DEFAULT ON)
|
||||
endif()
|
||||
|
||||
define_channel_options(NAME "drive" TYPE "device"
|
||||
DESCRIPTION "Drive Redirection Virtual Channel Extension"
|
||||
SPECIFICATIONS "[MS-RDPEFS]"
|
||||
|
||||
@@ -41,9 +41,7 @@
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/file.h>
|
||||
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/unicode.h>
|
||||
#include <freerdp/channels/rdpdr.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
|
||||
@@ -291,7 +289,9 @@ DRIVE_FILE* drive_file_new(const char* base_path, const char* path, UINT32 id,
|
||||
{
|
||||
DRIVE_FILE* file;
|
||||
|
||||
file = xnew(DRIVE_FILE);
|
||||
file = (DRIVE_FILE*) malloc(sizeof(DRIVE_FILE));
|
||||
ZeroMemory(file, sizeof(DRIVE_FILE));
|
||||
|
||||
file->id = id;
|
||||
file->basepath = (char*) base_path;
|
||||
drive_file_set_fullpath(file, drive_file_combine_fullpath(base_path, path));
|
||||
@@ -431,9 +431,9 @@ BOOL drive_file_query_information(DRIVE_FILE* file, UINT32 FsInformationClass, S
|
||||
BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UINT32 Length, STREAM* input)
|
||||
{
|
||||
char* s;
|
||||
|
||||
mode_t m;
|
||||
UINT64 size;
|
||||
int status;
|
||||
char* fullpath;
|
||||
struct STAT st;
|
||||
struct timeval tv[2];
|
||||
@@ -501,7 +501,11 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN
|
||||
stream_seek_BYTE(input); /* RootDirectory */
|
||||
stream_read_UINT32(input, FileNameLength);
|
||||
|
||||
freerdp_UnicodeToAsciiAlloc((WCHAR*) stream_get_tail(input), &s, FileNameLength / 2);
|
||||
status = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) stream_get_tail(input),
|
||||
FileNameLength / 2, &s, 0, NULL, NULL);
|
||||
|
||||
if (status < 1)
|
||||
s = (char*) calloc(1, 1);
|
||||
|
||||
fullpath = drive_file_combine_fullpath(file->basepath, s);
|
||||
free(s);
|
||||
@@ -597,8 +601,9 @@ BOOL drive_file_query_directory(DRIVE_FILE* file, UINT32 FsInformationClass, BYT
|
||||
|
||||
DEBUG_SVC(" pattern %s matched %s", file->pattern, ent_path);
|
||||
free(ent_path);
|
||||
ent_path = NULL;
|
||||
|
||||
length = freerdp_AsciiToUnicodeAlloc(ent->d_name, &ent_path, 0) * 2;
|
||||
length = ConvertToUnicode(CP_UTF8, 0, ent->d_name, -1, &ent_path, 0) * 2;
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
|
||||
@@ -35,18 +35,16 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/unicode.h>
|
||||
#include <freerdp/utils/list.h>
|
||||
#include <freerdp/channels/rdpdr.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/synch.h>
|
||||
#include <winpr/thread.h>
|
||||
#include <winpr/interlocked.h>
|
||||
|
||||
#include <freerdp/utils/list.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/channels/rdpdr.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
|
||||
#include "drive_file.h"
|
||||
|
||||
typedef struct _DRIVE_DEVICE DRIVE_DEVICE;
|
||||
@@ -120,6 +118,7 @@ static DRIVE_FILE* drive_get_file_by_id(DRIVE_DEVICE* disk, UINT32 id)
|
||||
static void drive_process_irp_create(DRIVE_DEVICE* disk, IRP* irp)
|
||||
{
|
||||
char* path;
|
||||
int status;
|
||||
UINT32 FileId;
|
||||
DRIVE_FILE* file;
|
||||
BYTE Information;
|
||||
@@ -134,7 +133,11 @@ static void drive_process_irp_create(DRIVE_DEVICE* disk, IRP* irp)
|
||||
stream_read_UINT32(irp->input, CreateOptions);
|
||||
stream_read_UINT32(irp->input, PathLength);
|
||||
|
||||
freerdp_UnicodeToAsciiAlloc((WCHAR*) stream_get_tail(irp->input), &path, PathLength / 2);
|
||||
status = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) stream_get_tail(irp->input),
|
||||
PathLength / 2, &path, 0, NULL, NULL);
|
||||
|
||||
if (status < 1)
|
||||
path = (char*) calloc(1, 1);
|
||||
|
||||
FileId = irp->devman->id_sequence++;
|
||||
|
||||
@@ -388,7 +391,7 @@ static void drive_process_irp_query_volume_information(DRIVE_DEVICE* disk, IRP*
|
||||
struct STAT st;
|
||||
char* volumeLabel = {"FREERDP"};
|
||||
char* diskType = {"FAT32"};
|
||||
WCHAR* outStr;
|
||||
WCHAR* outStr = NULL;
|
||||
int length;
|
||||
|
||||
stream_read_UINT32(irp->input, FsInformationClass);
|
||||
@@ -400,7 +403,7 @@ static void drive_process_irp_query_volume_information(DRIVE_DEVICE* disk, IRP*
|
||||
{
|
||||
case FileFsVolumeInformation:
|
||||
/* http://msdn.microsoft.com/en-us/library/cc232108.aspx */
|
||||
length = freerdp_AsciiToUnicodeAlloc(volumeLabel, &outStr, 0) * 2;
|
||||
length = ConvertToUnicode(CP_UTF8, 0, volumeLabel, -1, &outStr, 0) * 2;
|
||||
stream_write_UINT32(output, 17 + length); /* Length */
|
||||
stream_check_size(output, 17 + length);
|
||||
stream_write_UINT64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_ctime)); /* VolumeCreationTime */
|
||||
@@ -424,7 +427,7 @@ static void drive_process_irp_query_volume_information(DRIVE_DEVICE* disk, IRP*
|
||||
|
||||
case FileFsAttributeInformation:
|
||||
/* http://msdn.microsoft.com/en-us/library/cc232101.aspx */
|
||||
length = freerdp_AsciiToUnicodeAlloc(diskType, &outStr, 0) * 2;
|
||||
length = ConvertToUnicode(CP_UTF8, 0, diskType, -1, &outStr, 0) * 2;
|
||||
stream_write_UINT32(output, 12 + length); /* Length */
|
||||
stream_check_size(output, 12 + length);
|
||||
stream_write_UINT32(output,
|
||||
@@ -469,6 +472,7 @@ static void drive_process_irp_query_volume_information(DRIVE_DEVICE* disk, IRP*
|
||||
static void drive_process_irp_query_directory(DRIVE_DEVICE* disk, IRP* irp)
|
||||
{
|
||||
char* path;
|
||||
int status;
|
||||
DRIVE_FILE* file;
|
||||
BYTE InitialQuery;
|
||||
UINT32 PathLength;
|
||||
@@ -479,7 +483,11 @@ static void drive_process_irp_query_directory(DRIVE_DEVICE* disk, IRP* irp)
|
||||
stream_read_UINT32(irp->input, PathLength);
|
||||
stream_seek(irp->input, 23); /* Padding */
|
||||
|
||||
freerdp_UnicodeToAsciiAlloc((WCHAR*) stream_get_tail(irp->input), &path, PathLength / 2);
|
||||
status = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) stream_get_tail(irp->input),
|
||||
PathLength / 2, &path, 0, NULL, NULL);
|
||||
|
||||
if (status < 1)
|
||||
path = (char*) calloc(1, 1);
|
||||
|
||||
file = drive_get_file_by_id(disk, irp->FileId);
|
||||
|
||||
@@ -640,6 +648,7 @@ static void drive_free(DEVICE* device)
|
||||
drive_file_free(file);
|
||||
|
||||
list_free(disk->files);
|
||||
|
||||
free(disk);
|
||||
}
|
||||
|
||||
@@ -664,7 +673,8 @@ void drive_register_drive_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, char*
|
||||
|
||||
if (name[0] && path[0])
|
||||
{
|
||||
disk = xnew(DRIVE_DEVICE);
|
||||
disk = (DRIVE_DEVICE*) malloc(sizeof(DRIVE_DEVICE));
|
||||
ZeroMemory(disk, sizeof(DRIVE_DEVICE));
|
||||
|
||||
disk->device.type = RDPDR_DTYP_FILESYSTEM;
|
||||
disk->device.name = name;
|
||||
|
||||
@@ -13,10 +13,6 @@ if(ANDROID)
|
||||
set(OPTION_SERVER_DEFAULT OFF)
|
||||
endif()
|
||||
|
||||
if(${OPTION_CLIENT_DEFAULT} OR ${OPTION_SERVER_DEFAULT})
|
||||
set(OPTION_DEFAULT ON)
|
||||
endif()
|
||||
|
||||
define_channel_options(NAME "parallel" TYPE "device"
|
||||
DESCRIPTION "Parallel Port Virtual Channel Extension"
|
||||
SPECIFICATIONS "[MS-RDPESP]"
|
||||
|
||||
@@ -53,9 +53,7 @@
|
||||
#include <freerdp/constants.h>
|
||||
#include <freerdp/utils/list.h>
|
||||
#include <freerdp/utils/thread.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/unicode.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
#include <freerdp/channels/rdpdr.h>
|
||||
|
||||
@@ -75,6 +73,7 @@ typedef struct _PARALLEL_DEVICE PARALLEL_DEVICE;
|
||||
static void parallel_process_irp_create(PARALLEL_DEVICE* parallel, IRP* irp)
|
||||
{
|
||||
char* path;
|
||||
int status;
|
||||
UINT32 PathLength;
|
||||
|
||||
stream_seek(irp->input, 28);
|
||||
@@ -82,7 +81,11 @@ static void parallel_process_irp_create(PARALLEL_DEVICE* parallel, IRP* irp)
|
||||
/* SharedAccess(4) CreateDisposition(4), CreateOptions(4) */
|
||||
stream_read_UINT32(irp->input, PathLength);
|
||||
|
||||
freerdp_UnicodeToAsciiAlloc((WCHAR*) stream_get_tail(irp->input), &path, PathLength / 2);
|
||||
status = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) stream_get_tail(irp->input),
|
||||
PathLength / 2, &path, 0, NULL, NULL);
|
||||
|
||||
if (status < 1)
|
||||
path = (char*) calloc(1, 1);
|
||||
|
||||
parallel->id = irp->devman->id_sequence++;
|
||||
parallel->file = open(parallel->path, O_RDWR);
|
||||
@@ -325,7 +328,8 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
|
||||
if (name[0] && path[0])
|
||||
{
|
||||
parallel = xnew(PARALLEL_DEVICE);
|
||||
parallel = (PARALLEL_DEVICE*) malloc(sizeof(PARALLEL_DEVICE));
|
||||
ZeroMemory(parallel, sizeof(PARALLEL_DEVICE));
|
||||
|
||||
parallel->device.type = RDPDR_DTYP_PARALLEL;
|
||||
parallel->device.name = name;
|
||||
|
||||
@@ -14,10 +14,6 @@ else()
|
||||
set(OPTION_SERVER_DEFAULT OFF)
|
||||
endif()
|
||||
|
||||
if(${OPTION_CLIENT_DEFAULT} OR ${OPTION_SERVER_DEFAULT})
|
||||
set(OPTION_DEFAULT ON)
|
||||
endif()
|
||||
|
||||
define_channel_options(NAME "printer" TYPE "device"
|
||||
DESCRIPTION "Print Virtual Channel Extension"
|
||||
SPECIFICATIONS "[MS-RDPEPC]"
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
#include <freerdp/channels/rdpdr.h>
|
||||
|
||||
@@ -79,36 +78,39 @@ static void printer_cups_get_printjob_name(char* buf, int size)
|
||||
|
||||
static void printer_cups_write_printjob(rdpPrintJob* printjob, BYTE* data, int size)
|
||||
{
|
||||
rdpCupsPrintJob* cups_printjob = (rdpCupsPrintJob*)printjob;
|
||||
rdpCupsPrintJob* cups_printjob = (rdpCupsPrintJob*) printjob;
|
||||
|
||||
#ifndef _CUPS_API_1_4
|
||||
|
||||
{
|
||||
FILE* fp;
|
||||
|
||||
fp = fopen((const char*)cups_printjob->printjob_object, "a+b");
|
||||
fp = fopen((const char*) cups_printjob->printjob_object, "a+b");
|
||||
|
||||
if (fp == NULL)
|
||||
{
|
||||
DEBUG_WARN("failed to open file %s", (char*)cups_printjob->printjob_object);
|
||||
DEBUG_WARN("failed to open file %s", (char*) cups_printjob->printjob_object);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fwrite(data, 1, size, fp) < size)
|
||||
{
|
||||
DEBUG_WARN("failed to write file %s", (char*)cups_printjob->printjob_object);
|
||||
DEBUG_WARN("failed to write file %s", (char*) cups_printjob->printjob_object);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
cupsWriteRequestData((http_t*)cups_printjob->printjob_object, (const char*)data, size);
|
||||
cupsWriteRequestData((http_t*) cups_printjob->printjob_object, (const char*) data, size);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
static void printer_cups_close_printjob(rdpPrintJob* printjob)
|
||||
{
|
||||
rdpCupsPrintJob* cups_printjob = (rdpCupsPrintJob*)printjob;
|
||||
rdpCupsPrintJob* cups_printjob = (rdpCupsPrintJob*) printjob;
|
||||
|
||||
#ifndef _CUPS_API_1_4
|
||||
|
||||
@@ -116,35 +118,38 @@ static void printer_cups_close_printjob(rdpPrintJob* printjob)
|
||||
char buf[100];
|
||||
|
||||
printer_cups_get_printjob_name(buf, sizeof(buf));
|
||||
if (cupsPrintFile(printjob->printer->name, (const char *)cups_printjob->printjob_object, buf, 0, NULL) == 0)
|
||||
|
||||
if (cupsPrintFile(printjob->printer->name, (const char*) cups_printjob->printjob_object, buf, 0, NULL) == 0)
|
||||
{
|
||||
DEBUG_WARN("cupsPrintFile: %s", cupsLastErrorString());
|
||||
}
|
||||
|
||||
unlink(cups_printjob->printjob_object);
|
||||
free(cups_printjob->printjob_object);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
cupsFinishDocument((http_t*)cups_printjob->printjob_object, printjob->printer->name);
|
||||
cupsFinishDocument((http_t*) cups_printjob->printjob_object, printjob->printer->name);
|
||||
cups_printjob->printjob_id = 0;
|
||||
httpClose((http_t*)cups_printjob->printjob_object);
|
||||
httpClose((http_t*) cups_printjob->printjob_object);
|
||||
|
||||
#endif
|
||||
|
||||
((rdpCupsPrinter*)printjob->printer)->printjob = NULL;
|
||||
((rdpCupsPrinter*) printjob->printer)->printjob = NULL;
|
||||
free(cups_printjob) ;
|
||||
}
|
||||
|
||||
static rdpPrintJob* printer_cups_create_printjob(rdpPrinter* printer, UINT32 id)
|
||||
{
|
||||
rdpCupsPrinter* cups_printer = (rdpCupsPrinter*)printer;
|
||||
rdpCupsPrinter* cups_printer = (rdpCupsPrinter*) printer;
|
||||
rdpCupsPrintJob* cups_printjob;
|
||||
|
||||
if (cups_printer->printjob != NULL)
|
||||
return NULL;
|
||||
|
||||
cups_printjob = xnew(rdpCupsPrintJob);
|
||||
cups_printjob = (rdpCupsPrintJob*) malloc(sizeof(rdpCupsPrintJob));
|
||||
ZeroMemory(cups_printjob, sizeof(rdpCupsPrintJob));
|
||||
|
||||
cups_printjob->printjob.id = id;
|
||||
cups_printjob->printjob.printer = printer;
|
||||
@@ -161,6 +166,7 @@ static rdpPrintJob* printer_cups_create_printjob(rdpPrinter* printer, UINT32 id)
|
||||
char buf[100];
|
||||
|
||||
cups_printjob->printjob_object = httpConnectEncrypt(cupsServer(), ippPort(), HTTP_ENCRYPT_IF_REQUESTED);
|
||||
|
||||
if (cups_printjob->printjob_object == NULL)
|
||||
{
|
||||
DEBUG_WARN("httpConnectEncrypt: %s", cupsLastErrorString());
|
||||
@@ -169,19 +175,19 @@ static rdpPrintJob* printer_cups_create_printjob(rdpPrinter* printer, UINT32 id)
|
||||
}
|
||||
|
||||
printer_cups_get_printjob_name(buf, sizeof(buf));
|
||||
cups_printjob->printjob_id = cupsCreateJob((http_t*)cups_printjob->printjob_object,
|
||||
cups_printjob->printjob_id = cupsCreateJob((http_t*) cups_printjob->printjob_object,
|
||||
printer->name, buf, 0, NULL);
|
||||
|
||||
if (cups_printjob->printjob_id == 0)
|
||||
{
|
||||
DEBUG_WARN("cupsCreateJob: %s", cupsLastErrorString());
|
||||
httpClose((http_t*)cups_printjob->printjob_object);
|
||||
httpClose((http_t*) cups_printjob->printjob_object);
|
||||
free(cups_printjob);
|
||||
return NULL;
|
||||
}
|
||||
cupsStartDocument((http_t*)cups_printjob->printjob_object,
|
||||
printer->name, cups_printjob->printjob_id, buf,
|
||||
CUPS_FORMAT_AUTO, 1);
|
||||
|
||||
cupsStartDocument((http_t*) cups_printjob->printjob_object,
|
||||
printer->name, cups_printjob->printjob_id, buf, CUPS_FORMAT_AUTO, 1);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -205,10 +211,11 @@ static rdpPrintJob* printer_cups_find_printjob(rdpPrinter* printer, UINT32 id)
|
||||
|
||||
static void printer_cups_free_printer(rdpPrinter* printer)
|
||||
{
|
||||
rdpCupsPrinter* cups_printer = (rdpCupsPrinter*)printer;
|
||||
rdpCupsPrinter* cups_printer = (rdpCupsPrinter*) printer;
|
||||
|
||||
if (cups_printer->printjob)
|
||||
cups_printer->printjob->printjob.Close((rdpPrintJob*)cups_printer->printjob);
|
||||
cups_printer->printjob->printjob.Close((rdpPrintJob*) cups_printer->printjob);
|
||||
|
||||
free(printer->name);
|
||||
free(printer);
|
||||
}
|
||||
@@ -217,7 +224,8 @@ static rdpPrinter* printer_cups_new_printer(rdpCupsPrinterDriver* cups_driver, c
|
||||
{
|
||||
rdpCupsPrinter* cups_printer;
|
||||
|
||||
cups_printer = xnew(rdpCupsPrinter);
|
||||
cups_printer = (rdpCupsPrinter*) malloc(sizeof(rdpCupsPrinter));
|
||||
ZeroMemory(cups_printer, sizeof(rdpCupsPrinter));
|
||||
|
||||
cups_printer->printer.id = cups_driver->id_sequence++;
|
||||
cups_printer->printer.name = _strdup(name);
|
||||
@@ -229,7 +237,7 @@ static rdpPrinter* printer_cups_new_printer(rdpCupsPrinterDriver* cups_driver, c
|
||||
cups_printer->printer.FindPrintJob = printer_cups_find_printjob;
|
||||
cups_printer->printer.Free = printer_cups_free_printer;
|
||||
|
||||
return (rdpPrinter*)cups_printer;
|
||||
return (rdpPrinter*) cups_printer;
|
||||
}
|
||||
|
||||
static rdpPrinter** printer_cups_enum_printers(rdpPrinterDriver* driver)
|
||||
@@ -242,13 +250,16 @@ static rdpPrinter** printer_cups_enum_printers(rdpPrinterDriver* driver)
|
||||
int i;
|
||||
|
||||
num_dests = cupsGetDests(&dests);
|
||||
printers = (rdpPrinter**)xzalloc(sizeof(rdpPrinter*) * (num_dests + 1));
|
||||
printers = (rdpPrinter**) malloc(sizeof(rdpPrinter*) * (num_dests + 1));
|
||||
ZeroMemory(printers, sizeof(rdpPrinter*) * (num_dests + 1));
|
||||
|
||||
num_printers = 0;
|
||||
|
||||
for (i = 0, dest = dests; i < num_dests; i++, dest++)
|
||||
{
|
||||
if (dest->instance == NULL)
|
||||
{
|
||||
printers[num_printers++] = printer_cups_new_printer((rdpCupsPrinterDriver*)driver,
|
||||
printers[num_printers++] = printer_cups_new_printer((rdpCupsPrinterDriver*) driver,
|
||||
dest->name, dest->is_default);
|
||||
}
|
||||
}
|
||||
@@ -259,7 +270,7 @@ static rdpPrinter** printer_cups_enum_printers(rdpPrinterDriver* driver)
|
||||
|
||||
static rdpPrinter* printer_cups_get_printer(rdpPrinterDriver* driver, const char* name)
|
||||
{
|
||||
rdpCupsPrinterDriver* cups_driver = (rdpCupsPrinterDriver*)driver;
|
||||
rdpCupsPrinterDriver* cups_driver = (rdpCupsPrinterDriver*) driver;
|
||||
|
||||
return printer_cups_new_printer(cups_driver, name, cups_driver->id_sequence == 1 ? TRUE : FALSE);
|
||||
}
|
||||
@@ -270,7 +281,8 @@ rdpPrinterDriver* printer_cups_get_driver(void)
|
||||
{
|
||||
if (cups_driver == NULL)
|
||||
{
|
||||
cups_driver = xnew(rdpCupsPrinterDriver);
|
||||
cups_driver = (rdpCupsPrinterDriver*) malloc(sizeof(rdpCupsPrinterDriver));
|
||||
ZeroMemory(cups_driver, sizeof(rdpCupsPrinterDriver));
|
||||
|
||||
cups_driver->driver.EnumPrinters = printer_cups_enum_printers;
|
||||
cups_driver->driver.GetPrinter = printer_cups_get_printer;
|
||||
@@ -284,6 +296,6 @@ rdpPrinterDriver* printer_cups_get_driver(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
return (rdpPrinterDriver*)cups_driver;
|
||||
return (rdpPrinterDriver*) cups_driver;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,8 +31,6 @@
|
||||
#include <winpr/interlocked.h>
|
||||
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/unicode.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/thread.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
#include <freerdp/channels/rdpdr.h>
|
||||
@@ -237,9 +235,9 @@ void printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, rdpPrinter* pri
|
||||
char* port;
|
||||
UINT32 Flags;
|
||||
int DriverNameLen;
|
||||
WCHAR* DriverName;
|
||||
WCHAR* DriverName = NULL;
|
||||
int PrintNameLen;
|
||||
WCHAR* PrintName;
|
||||
WCHAR* PrintName = NULL;
|
||||
UINT32 CachedFieldsLen;
|
||||
BYTE* CachedPrinterConfigData;
|
||||
PRINTER_DEVICE* printer_dev;
|
||||
@@ -247,7 +245,8 @@ void printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, rdpPrinter* pri
|
||||
port = malloc(10);
|
||||
snprintf(port, 10, "PRN%d", printer->id);
|
||||
|
||||
printer_dev = xnew(PRINTER_DEVICE);
|
||||
printer_dev = (PRINTER_DEVICE*) malloc(sizeof(PRINTER_DEVICE));
|
||||
ZeroMemory(printer_dev, sizeof(PRINTER_DEVICE));
|
||||
|
||||
printer_dev->device.type = RDPDR_DTYP_PRINT;
|
||||
printer_dev->device.name = port;
|
||||
@@ -266,8 +265,8 @@ void printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, rdpPrinter* pri
|
||||
if (printer->is_default)
|
||||
Flags |= RDPDR_PRINTER_ANNOUNCE_FLAG_DEFAULTPRINTER;
|
||||
|
||||
DriverNameLen = freerdp_AsciiToUnicodeAlloc(printer->driver, &DriverName, 0) * 2;
|
||||
PrintNameLen = freerdp_AsciiToUnicodeAlloc(printer->name, &PrintName, 0) * 2;
|
||||
DriverNameLen = ConvertToUnicode(CP_UTF8, 0, printer->driver, -1, &DriverName, 0) * 2;
|
||||
PrintNameLen = ConvertToUnicode(CP_UTF8, 0, printer->name, -1, &PrintName, 0) * 2;
|
||||
|
||||
printer_dev->device.data = stream_new(28 + DriverNameLen + PrintNameLen + CachedFieldsLen);
|
||||
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
#include <string.h>
|
||||
#include <winspool.h>
|
||||
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
|
||||
#include "printer_main.h"
|
||||
@@ -121,7 +120,8 @@ static rdpPrintJob* printer_win_create_printjob(rdpPrinter* printer, UINT32 id)
|
||||
if (win_printer->printjob != NULL)
|
||||
return NULL;
|
||||
|
||||
win_printjob = xnew(rdpWinPrintJob);
|
||||
win_printjob = (rdpWinPrintJob*) malloc(sizeof(rdpWinPrintJob));
|
||||
ZeroMemory(win_printjob, sizeof(rdpWinPrintJob));
|
||||
|
||||
win_printjob->printjob.id = id;
|
||||
win_printjob->printjob.printer = printer;
|
||||
@@ -129,44 +129,46 @@ static rdpPrintJob* printer_win_create_printjob(rdpPrinter* printer, UINT32 id)
|
||||
win_printjob->di.pDatatype= NULL;
|
||||
win_printjob->di.pOutputFile = NULL;
|
||||
|
||||
win_printjob->handle = StartDocPrinter(win_printer->hPrinter, 1, (LPBYTE)&(win_printjob->di) );
|
||||
if(! win_printjob->handle) DEBUG_WINPR("StartDocPrinter failed");
|
||||
if ( ! StartPagePrinter(win_printer->hPrinter) )
|
||||
DEBUG_WINPR("ClosePrinter failed");
|
||||
win_printjob->handle = StartDocPrinter(win_printer->hPrinter, 1, (LPBYTE) &(win_printjob->di));
|
||||
|
||||
if (!win_printjob->handle)
|
||||
DEBUG_WINPR("StartDocPrinter failed");
|
||||
|
||||
if (!StartPagePrinter(win_printer->hPrinter))
|
||||
DEBUG_WINPR("ClosePrinter failed");
|
||||
|
||||
win_printjob->printjob.Write = printer_win_write_printjob;
|
||||
win_printjob->printjob.Close = printer_win_close_printjob;
|
||||
|
||||
|
||||
|
||||
win_printer->printjob = win_printjob;
|
||||
|
||||
return (rdpPrintJob*)win_printjob;
|
||||
return (rdpPrintJob*) win_printjob;
|
||||
}
|
||||
|
||||
static rdpPrintJob* printer_win_find_printjob(rdpPrinter* printer, UINT32 id)
|
||||
{
|
||||
rdpWinPrinter* win_printer = (rdpWinPrinter*)printer;
|
||||
rdpWinPrinter* win_printer = (rdpWinPrinter*) printer;
|
||||
|
||||
DEBUG_WINPR("");
|
||||
DEBUG_WINPR("");
|
||||
|
||||
if (win_printer->printjob == NULL)
|
||||
return NULL;
|
||||
|
||||
if (win_printer->printjob->printjob.id != id)
|
||||
return NULL;
|
||||
|
||||
return (rdpPrintJob*)win_printer->printjob;
|
||||
return (rdpPrintJob*) win_printer->printjob;
|
||||
}
|
||||
|
||||
static void printer_win_free_printer(rdpPrinter* printer)
|
||||
{
|
||||
rdpWinPrinter* win_printer = (rdpWinPrinter*)printer;
|
||||
rdpWinPrinter* win_printer = (rdpWinPrinter*) printer;
|
||||
|
||||
DEBUG_WINPR("");
|
||||
DEBUG_WINPR("");
|
||||
|
||||
if (win_printer->printjob)
|
||||
win_printer->printjob->printjob.Close((rdpPrintJob*)win_printer->printjob);
|
||||
win_printer->printjob->printjob.Close((rdpPrintJob*) win_printer->printjob);
|
||||
|
||||
free(printer->name);
|
||||
free(printer);
|
||||
}
|
||||
@@ -174,13 +176,14 @@ static void printer_win_free_printer(rdpPrinter* printer)
|
||||
static rdpPrinter* printer_win_new_printer(rdpWinPrinterDriver* win_driver, const char* name, const wchar_t* drivername, BOOL is_default)
|
||||
{
|
||||
rdpWinPrinter* win_printer;
|
||||
wchar_t wname[256];
|
||||
wchar_t wname[256];
|
||||
DWORD needed;
|
||||
PRINTER_INFO_2 *prninfo=NULL;
|
||||
size_t charsConverted;
|
||||
DEBUG_WINPR("");
|
||||
|
||||
win_printer = xnew(rdpWinPrinter);
|
||||
win_printer = (rdpWinPrinter*) malloc(sizeof(rdpWinPrinter));
|
||||
ZeroMemory(win_printer, sizeof(rdpWinPrinter));
|
||||
|
||||
win_printer->printer.id = win_driver->id_sequence++;
|
||||
win_printer->printer.name = _strdup(name);
|
||||
@@ -190,7 +193,7 @@ static rdpPrinter* printer_win_new_printer(rdpWinPrinterDriver* win_driver, cons
|
||||
win_printer->printer.FindPrintJob = printer_win_find_printjob;
|
||||
win_printer->printer.Free = printer_win_free_printer;
|
||||
|
||||
swprintf(wname, 256, L"%hs", name);
|
||||
swprintf(wname, 256, L"%hs", name);
|
||||
OpenPrinter(wname, &(win_printer->hPrinter), NULL);
|
||||
DEBUG_WINPR("handle: 0x%08X", win_printer->hPrinter);
|
||||
|
||||
@@ -211,31 +214,30 @@ static rdpPrinter** printer_win_enum_printers(rdpPrinterDriver* driver)
|
||||
int i;
|
||||
char pname[1000];
|
||||
size_t charsConverted;
|
||||
|
||||
PRINTER_INFO_2 *prninfo=NULL;
|
||||
DWORD needed, returned;
|
||||
PRINTER_INFO_2* prninfo = NULL;
|
||||
DWORD needed, returned;
|
||||
|
||||
DEBUG_WINPR("");
|
||||
DEBUG_WINPR("");
|
||||
|
||||
/* find required size for the buffer */
|
||||
EnumPrinters(PRINTER_ENUM_LOCAL|PRINTER_ENUM_CONNECTIONS, NULL, 2, NULL, 0, &needed, &returned);
|
||||
|
||||
|
||||
//find required size for the buffer
|
||||
EnumPrinters(PRINTER_ENUM_LOCAL|PRINTER_ENUM_CONNECTIONS, NULL, 2, NULL, 0, &needed, &returned);
|
||||
|
||||
|
||||
//allocate array of PRINTER_INFO structures
|
||||
prninfo = (PRINTER_INFO_2*) GlobalAlloc(GPTR,needed);
|
||||
/* allocate array of PRINTER_INFO structures */
|
||||
prninfo = (PRINTER_INFO_2*) GlobalAlloc(GPTR,needed);
|
||||
|
||||
//call again
|
||||
if ( !EnumPrinters(PRINTER_ENUM_LOCAL|PRINTER_ENUM_CONNECTIONS, NULL, 2, (LPBYTE) prninfo, needed, &needed, &returned) ) {
|
||||
/* call again */
|
||||
if ( !EnumPrinters(PRINTER_ENUM_LOCAL|PRINTER_ENUM_CONNECTIONS, NULL, 2, (LPBYTE) prninfo, needed, &needed, &returned) )
|
||||
{
|
||||
DEBUG_WINPR("EnumPrinters failed");
|
||||
|
||||
} ; /* eRROR... */
|
||||
} ; /* ERROR... */
|
||||
|
||||
DEBUG_WINPR("printers found: %d", returned);
|
||||
|
||||
printers = (rdpPrinter**) malloc(sizeof(rdpPrinter*) * (returned + 1));
|
||||
ZeroMemory(printers, sizeof(rdpPrinter*) * (returned + 1));
|
||||
|
||||
printers = (rdpPrinter**)xzalloc(sizeof(rdpPrinter*) * (returned + 1));
|
||||
num_printers = 0;
|
||||
num_printers = 0;
|
||||
|
||||
for (i = 0; i < (int)returned; i++)
|
||||
{
|
||||
@@ -268,20 +270,15 @@ rdpPrinterDriver* printer_win_get_driver(void)
|
||||
|
||||
if (win_driver == NULL)
|
||||
{
|
||||
win_driver = xnew(rdpWinPrinterDriver);
|
||||
win_driver = (rdpWinPrinterDriver*) malloc(sizeof(rdpWinPrinterDriver));
|
||||
ZeroMemory(win_driver, sizeof(rdpWinPrinterDriver));
|
||||
|
||||
win_driver->driver.EnumPrinters = printer_win_enum_printers;
|
||||
win_driver->driver.GetPrinter = printer_win_get_printer;
|
||||
|
||||
win_driver->id_sequence = 1;
|
||||
|
||||
//#ifdef _win_API_1_4
|
||||
// DEBUG_SVC("using win API 1.4");
|
||||
//#else
|
||||
// DEBUG_SVC("using win API 1.2");
|
||||
//#endif
|
||||
}
|
||||
|
||||
return (rdpPrinterDriver*)win_driver;
|
||||
return (rdpPrinterDriver*) win_driver;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,10 +3,6 @@ set(OPTION_DEFAULT OFF)
|
||||
set(OPTION_CLIENT_DEFAULT ON)
|
||||
set(OPTION_SERVER_DEFAULT OFF)
|
||||
|
||||
if(${OPTION_CLIENT_DEFAULT} OR ${OPTION_SERVER_DEFAULT})
|
||||
set(OPTION_DEFAULT ON)
|
||||
endif()
|
||||
|
||||
define_channel_options(NAME "rail" TYPE "static"
|
||||
DESCRIPTION "Remote Programs Virtual Channel Extension"
|
||||
SPECIFICATIONS "[MS-RDPERP]"
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/constants.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
#include <freerdp/utils/rail.h>
|
||||
#include <freerdp/rail.h>
|
||||
@@ -80,7 +79,7 @@ static void rail_process_connect(rdpSvcPlugin* plugin)
|
||||
railPlugin* rail = (railPlugin*) plugin;
|
||||
|
||||
rail->rail_order = rail_order_new();
|
||||
rail->rail_order->plugin_data = (RDP_PLUGIN_DATA*)plugin->channel_entry_points.pExtendedData;
|
||||
rail->rail_order->settings = (rdpSettings*) plugin->channel_entry_points.pExtendedData;
|
||||
rail->rail_order->plugin = rail;
|
||||
}
|
||||
|
||||
@@ -96,11 +95,11 @@ static void rail_process_receive(rdpSvcPlugin* plugin, STREAM* s)
|
||||
stream_free(s);
|
||||
}
|
||||
|
||||
static void rail_process_plugin_data(rdpRailOrder* rail_order, RDP_PLUGIN_DATA* data)
|
||||
static void rail_process_addin_args(rdpRailOrder* rail_order, rdpSettings* settings)
|
||||
{
|
||||
char* exeOrFile;
|
||||
|
||||
exeOrFile = (char*) data->data[0];
|
||||
exeOrFile = settings->RemoteApplicationProgram;
|
||||
|
||||
if (strlen(exeOrFile) >= 2)
|
||||
{
|
||||
@@ -108,21 +107,20 @@ static void rail_process_plugin_data(rdpRailOrder* rail_order, RDP_PLUGIN_DATA*
|
||||
rail_order->exec.flags |= RAIL_EXEC_FLAG_FILE;
|
||||
}
|
||||
|
||||
rail_string_to_unicode_string(rail_order, (char*) data->data[0], &rail_order->exec.exeOrFile);
|
||||
rail_string_to_unicode_string(rail_order, (char*) data->data[1], &rail_order->exec.workingDir);
|
||||
rail_string_to_unicode_string(rail_order, (char*) data->data[2], &rail_order->exec.arguments);
|
||||
rail_string_to_unicode_string(rail_order, settings->RemoteApplicationProgram, &rail_order->exec.exeOrFile);
|
||||
rail_string_to_unicode_string(rail_order, settings->ShellWorkingDirectory, &rail_order->exec.workingDir);
|
||||
rail_string_to_unicode_string(rail_order, settings->RemoteApplicationCmdLine, &rail_order->exec.arguments);
|
||||
|
||||
rail_send_client_exec_order(rail_order);
|
||||
}
|
||||
|
||||
static void rail_recv_set_sysparams_event(rdpRailOrder* rail_order, RDP_EVENT* event)
|
||||
{
|
||||
RDP_PLUGIN_DATA* data;
|
||||
RAIL_SYSPARAM_ORDER* sysparam;
|
||||
|
||||
/* Send System Parameters */
|
||||
|
||||
sysparam = (RAIL_SYSPARAM_ORDER*)event->user_data;
|
||||
sysparam = (RAIL_SYSPARAM_ORDER*) event->user_data;
|
||||
memmove(&rail_order->sysparam, sysparam, sizeof(RAIL_SYSPARAM_ORDER));
|
||||
|
||||
rail_send_client_sysparams_order(rail_order);
|
||||
@@ -131,19 +129,18 @@ static void rail_recv_set_sysparams_event(rdpRailOrder* rail_order, RDP_EVENT* e
|
||||
|
||||
rail_order->exec.flags = RAIL_EXEC_FLAG_EXPAND_ARGUMENTS;
|
||||
|
||||
data = rail_order->plugin_data;
|
||||
while (data && data->size > 0)
|
||||
{
|
||||
rail_process_plugin_data(rail_order, data);
|
||||
data = (RDP_PLUGIN_DATA*)((char *)(data) + data->size);
|
||||
}
|
||||
rail_process_addin_args(rail_order, rail_order->settings);
|
||||
}
|
||||
|
||||
static void rail_recv_exec_remote_app_event(rdpRailOrder* rail_order, RDP_EVENT* event)
|
||||
{
|
||||
RDP_PLUGIN_DATA* data = (RDP_PLUGIN_DATA*) event->user_data;
|
||||
/**
|
||||
* TODO: replace event system by an API to allow the execution
|
||||
* of multiple remote apps over the same connection. RAIL is
|
||||
* always built-in, so clients can safely link to it.
|
||||
*/
|
||||
|
||||
rail_process_plugin_data(rail_order, data);
|
||||
//rail_process_addin_args(rail_order, data);
|
||||
}
|
||||
|
||||
static void rail_recv_activate_event(rdpRailOrder* rail_order, RDP_EVENT* event)
|
||||
@@ -279,4 +276,3 @@ int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,17 +19,18 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __RAIL_MAIN_H
|
||||
#define __RAIL_MAIN_H
|
||||
#ifndef FREERDP_CHANNEL_CLIENT_RAIL_MAIN_H
|
||||
#define FREERDP_CHANNEL_CLIENT_RAIL_MAIN_H
|
||||
|
||||
#include <freerdp/rail.h>
|
||||
#include <freerdp/settings.h>
|
||||
#include <freerdp/utils/debug.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
|
||||
struct rdp_rail_order
|
||||
{
|
||||
RDP_PLUGIN_DATA* plugin_data;
|
||||
rdpSettings* settings;
|
||||
void* plugin;
|
||||
RAIL_HANDSHAKE_ORDER handshake;
|
||||
RAIL_CLIENT_STATUS_ORDER client_status;
|
||||
@@ -65,4 +66,4 @@ void rail_send_channel_data(void* rail_object, void* data, size_t length);
|
||||
#define DEBUG_RAIL(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#endif /* __RAIL_MAIN_H */
|
||||
#endif /* FREERDP_CHANNEL_CLIENT_RAIL_MAIN_H */
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <freerdp/utils/rail.h>
|
||||
#include <freerdp/utils/unicode.h>
|
||||
|
||||
#include "rail_orders.h"
|
||||
|
||||
@@ -71,7 +70,7 @@ static const char* const RAIL_ORDER_TYPE_STRINGS[] =
|
||||
|
||||
void rail_string_to_unicode_string(rdpRailOrder* rail_order, char* string, RAIL_UNICODE_STRING* unicode_string)
|
||||
{
|
||||
WCHAR* buffer;
|
||||
WCHAR* buffer = NULL;
|
||||
int length = 0;
|
||||
|
||||
if (unicode_string->string != NULL)
|
||||
@@ -83,16 +82,19 @@ void rail_string_to_unicode_string(rdpRailOrder* rail_order, char* string, RAIL_
|
||||
if (string == NULL || strlen(string) < 1)
|
||||
return;
|
||||
|
||||
length = freerdp_AsciiToUnicodeAlloc(string, &buffer, 0) * 2;
|
||||
length = ConvertToUnicode(CP_UTF8, 0, string, -1, &buffer, 0) * 2;
|
||||
|
||||
unicode_string->string = (BYTE*) buffer;
|
||||
unicode_string->length = (UINT16) length;
|
||||
}
|
||||
|
||||
void rail_read_pdu_header(STREAM* s, UINT16* orderType, UINT16* orderLength)
|
||||
BOOL rail_read_pdu_header(STREAM* s, UINT16* orderType, UINT16* orderLength)
|
||||
{
|
||||
if(stream_get_left(s) < 4)
|
||||
return FALSE;
|
||||
stream_read_UINT16(s, *orderType); /* orderType (2 bytes) */
|
||||
stream_read_UINT16(s, *orderLength); /* orderLength (2 bytes) */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void rail_write_pdu_header(STREAM* s, UINT16 orderType, UINT16 orderLength)
|
||||
@@ -134,23 +136,31 @@ void rail_write_high_contrast(STREAM* s, HIGH_CONTRAST* high_contrast)
|
||||
rail_write_unicode_string(s, &high_contrast->colorScheme); /* colorScheme */
|
||||
}
|
||||
|
||||
void rail_read_handshake_order(STREAM* s, RAIL_HANDSHAKE_ORDER* handshake)
|
||||
BOOL rail_read_handshake_order(STREAM* s, RAIL_HANDSHAKE_ORDER* handshake)
|
||||
{
|
||||
if(stream_get_left(s) < 4)
|
||||
return FALSE;
|
||||
stream_read_UINT32(s, handshake->buildNumber); /* buildNumber (4 bytes) */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void rail_read_server_exec_result_order(STREAM* s, RAIL_EXEC_RESULT_ORDER* exec_result)
|
||||
BOOL rail_read_server_exec_result_order(STREAM* s, RAIL_EXEC_RESULT_ORDER* exec_result)
|
||||
{
|
||||
if(stream_get_left(s) < 8)
|
||||
return FALSE;
|
||||
stream_read_UINT16(s, exec_result->flags); /* flags (2 bytes) */
|
||||
stream_read_UINT16(s, exec_result->execResult); /* execResult (2 bytes) */
|
||||
stream_read_UINT32(s, exec_result->rawResult); /* rawResult (4 bytes) */
|
||||
stream_seek_UINT16(s); /* padding (2 bytes) */
|
||||
rail_read_unicode_string(s, &exec_result->exeOrFile); /* exeOrFile */
|
||||
return rail_read_unicode_string(s, &exec_result->exeOrFile); /* exeOrFile */
|
||||
}
|
||||
|
||||
void rail_read_server_sysparam_order(STREAM* s, RAIL_SYSPARAM_ORDER* sysparam)
|
||||
BOOL rail_read_server_sysparam_order(STREAM* s, RAIL_SYSPARAM_ORDER* sysparam)
|
||||
{
|
||||
BYTE body;
|
||||
|
||||
if(stream_get_left(s) < 5)
|
||||
return FALSE;
|
||||
stream_read_UINT32(s, sysparam->param); /* systemParam (4 bytes) */
|
||||
stream_read_BYTE(s, body); /* body (1 byte) */
|
||||
|
||||
@@ -167,10 +177,13 @@ void rail_read_server_sysparam_order(STREAM* s, RAIL_SYSPARAM_ORDER* sysparam)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void rail_read_server_minmaxinfo_order(STREAM* s, RAIL_MINMAXINFO_ORDER* minmaxinfo)
|
||||
BOOL rail_read_server_minmaxinfo_order(STREAM* s, RAIL_MINMAXINFO_ORDER* minmaxinfo)
|
||||
{
|
||||
if(stream_get_left(s) < 20)
|
||||
return FALSE;
|
||||
stream_read_UINT32(s, minmaxinfo->windowId); /* windowId (4 bytes) */
|
||||
stream_read_UINT16(s, minmaxinfo->maxWidth); /* maxWidth (2 bytes) */
|
||||
stream_read_UINT16(s, minmaxinfo->maxHeight); /* maxHeight (2 bytes) */
|
||||
@@ -180,11 +193,14 @@ void rail_read_server_minmaxinfo_order(STREAM* s, RAIL_MINMAXINFO_ORDER* minmaxi
|
||||
stream_read_UINT16(s, minmaxinfo->minTrackHeight); /* minTrackHeight (2 bytes) */
|
||||
stream_read_UINT16(s, minmaxinfo->maxTrackWidth); /* maxTrackWidth (2 bytes) */
|
||||
stream_read_UINT16(s, minmaxinfo->maxTrackHeight); /* maxTrackHeight (2 bytes) */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void rail_read_server_localmovesize_order(STREAM* s, RAIL_LOCALMOVESIZE_ORDER* localmovesize)
|
||||
BOOL rail_read_server_localmovesize_order(STREAM* s, RAIL_LOCALMOVESIZE_ORDER* localmovesize)
|
||||
{
|
||||
UINT16 isMoveSizeStart;
|
||||
if(stream_get_left(s) < 12)
|
||||
return FALSE;
|
||||
stream_read_UINT32(s, localmovesize->windowId); /* windowId (4 bytes) */
|
||||
|
||||
stream_read_UINT16(s, isMoveSizeStart); /* isMoveSizeStart (2 bytes) */
|
||||
@@ -193,20 +209,27 @@ void rail_read_server_localmovesize_order(STREAM* s, RAIL_LOCALMOVESIZE_ORDER* l
|
||||
stream_read_UINT16(s, localmovesize->moveSizeType); /* moveSizeType (2 bytes) */
|
||||
stream_read_UINT16(s, localmovesize->posX); /* posX (2 bytes) */
|
||||
stream_read_UINT16(s, localmovesize->posY); /* posY (2 bytes) */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void rail_read_server_get_appid_resp_order(STREAM* s, RAIL_GET_APPID_RESP_ORDER* get_appid_resp)
|
||||
BOOL rail_read_server_get_appid_resp_order(STREAM* s, RAIL_GET_APPID_RESP_ORDER* get_appid_resp)
|
||||
{
|
||||
if(stream_get_left(s) < 516)
|
||||
return FALSE;
|
||||
stream_read_UINT32(s, get_appid_resp->windowId); /* windowId (4 bytes) */
|
||||
stream_read(s, &get_appid_resp->applicationIdBuffer[0], 512); /* applicationId (256 UNICODE chars) */
|
||||
|
||||
get_appid_resp->applicationId.length = 512;
|
||||
get_appid_resp->applicationId.string = &get_appid_resp->applicationIdBuffer[0];
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void rail_read_langbar_info_order(STREAM* s, RAIL_LANGBAR_INFO_ORDER* langbar_info)
|
||||
BOOL rail_read_langbar_info_order(STREAM* s, RAIL_LANGBAR_INFO_ORDER* langbar_info)
|
||||
{
|
||||
if(stream_get_left(s) < 4)
|
||||
return FALSE;
|
||||
stream_read_UINT32(s, langbar_info->languageBarStatus); /* languageBarStatus (4 bytes) */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void rail_write_handshake_order(STREAM* s, RAIL_HANDSHAKE_ORDER* handshake)
|
||||
@@ -333,9 +356,10 @@ void rail_write_langbar_info_order(STREAM* s, RAIL_LANGBAR_INFO_ORDER* langbar_i
|
||||
stream_write_UINT32(s, langbar_info->languageBarStatus); /* languageBarStatus (4 bytes) */
|
||||
}
|
||||
|
||||
void rail_recv_handshake_order(rdpRailOrder* rail_order, STREAM* s)
|
||||
BOOL rail_recv_handshake_order(rdpRailOrder* rail_order, STREAM* s)
|
||||
{
|
||||
rail_read_handshake_order(s, &rail_order->handshake);
|
||||
if(!rail_read_handshake_order(s, &rail_order->handshake))
|
||||
return FALSE;
|
||||
|
||||
rail_order->handshake.buildNumber = 0x00001DB0;
|
||||
rail_send_handshake_order(rail_order);
|
||||
@@ -372,56 +396,70 @@ void rail_recv_handshake_order(rdpRailOrder* rail_order, STREAM* s)
|
||||
|
||||
rail_send_channel_event(rail_order->plugin,
|
||||
RDP_EVENT_TYPE_RAIL_CHANNEL_GET_SYSPARAMS, &rail_order->sysparam);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void rail_recv_exec_result_order(rdpRailOrder* rail_order, STREAM* s)
|
||||
BOOL rail_recv_exec_result_order(rdpRailOrder* rail_order, STREAM* s)
|
||||
{
|
||||
rail_read_server_exec_result_order(s, &rail_order->exec_result);
|
||||
if(!rail_read_server_exec_result_order(s, &rail_order->exec_result))
|
||||
return FALSE;
|
||||
rail_send_channel_event(rail_order->plugin,
|
||||
RDP_EVENT_TYPE_RAIL_CHANNEL_EXEC_RESULTS, &rail_order->exec_result);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void rail_recv_server_sysparam_order(rdpRailOrder* rail_order, STREAM* s)
|
||||
BOOL rail_recv_server_sysparam_order(rdpRailOrder* rail_order, STREAM* s)
|
||||
{
|
||||
rail_read_server_sysparam_order(s, &rail_order->sysparam);
|
||||
if(!rail_read_server_sysparam_order(s, &rail_order->sysparam))
|
||||
return FALSE;
|
||||
rail_send_channel_event(rail_order->plugin,
|
||||
RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_SYSPARAM, &rail_order->sysparam);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void rail_recv_server_minmaxinfo_order(rdpRailOrder* rail_order, STREAM* s)
|
||||
BOOL rail_recv_server_minmaxinfo_order(rdpRailOrder* rail_order, STREAM* s)
|
||||
{
|
||||
rail_read_server_minmaxinfo_order(s, &rail_order->minmaxinfo);
|
||||
if(!rail_read_server_minmaxinfo_order(s, &rail_order->minmaxinfo))
|
||||
return FALSE;
|
||||
rail_send_channel_event(rail_order->plugin,
|
||||
RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_MINMAXINFO, &rail_order->minmaxinfo);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void rail_recv_server_localmovesize_order(rdpRailOrder* rail_order, STREAM* s)
|
||||
BOOL rail_recv_server_localmovesize_order(rdpRailOrder* rail_order, STREAM* s)
|
||||
{
|
||||
rail_read_server_localmovesize_order(s, &rail_order->localmovesize);
|
||||
if(!rail_read_server_localmovesize_order(s, &rail_order->localmovesize))
|
||||
return FALSE;
|
||||
rail_send_channel_event(rail_order->plugin,
|
||||
RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_LOCALMOVESIZE, &rail_order->localmovesize);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void rail_recv_server_get_appid_resp_order(rdpRailOrder* rail_order, STREAM* s)
|
||||
BOOL rail_recv_server_get_appid_resp_order(rdpRailOrder* rail_order, STREAM* s)
|
||||
{
|
||||
rail_read_server_get_appid_resp_order(s, &rail_order->get_appid_resp);
|
||||
if(!rail_read_server_get_appid_resp_order(s, &rail_order->get_appid_resp))
|
||||
return FALSE;
|
||||
rail_send_channel_event(rail_order->plugin,
|
||||
RDP_EVENT_TYPE_RAIL_CHANNEL_APPID_RESP, &rail_order->get_appid_resp);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void rail_recv_langbar_info_order(rdpRailOrder* rail_order, STREAM* s)
|
||||
BOOL rail_recv_langbar_info_order(rdpRailOrder* rail_order, STREAM* s)
|
||||
{
|
||||
rail_read_langbar_info_order(s, &rail_order->langbar_info);
|
||||
if(!rail_read_langbar_info_order(s, &rail_order->langbar_info))
|
||||
return FALSE;
|
||||
rail_send_channel_event(rail_order->plugin,
|
||||
RDP_EVENT_TYPE_RAIL_CHANNEL_LANGBARINFO, &rail_order->langbar_info);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void rail_order_recv(rdpRailOrder* rail_order, STREAM* s)
|
||||
BOOL rail_order_recv(rdpRailOrder* rail_order, STREAM* s)
|
||||
{
|
||||
UINT16 orderType;
|
||||
UINT16 orderLength;
|
||||
|
||||
rail_read_pdu_header(s, &orderType, &orderLength);
|
||||
if(!rail_read_pdu_header(s, &orderType, &orderLength))
|
||||
return FALSE;
|
||||
|
||||
DEBUG_RAIL("Received %s PDU, length:%d",
|
||||
RAIL_ORDER_TYPE_STRINGS[((orderType & 0xF0) >> 3) + (orderType & 0x0F)], orderLength);
|
||||
@@ -429,37 +467,31 @@ void rail_order_recv(rdpRailOrder* rail_order, STREAM* s)
|
||||
switch (orderType)
|
||||
{
|
||||
case RDP_RAIL_ORDER_HANDSHAKE:
|
||||
rail_recv_handshake_order(rail_order, s);
|
||||
break;
|
||||
return rail_recv_handshake_order(rail_order, s);
|
||||
|
||||
case RDP_RAIL_ORDER_EXEC_RESULT:
|
||||
rail_recv_exec_result_order(rail_order, s);
|
||||
break;
|
||||
return rail_recv_exec_result_order(rail_order, s);
|
||||
|
||||
case RDP_RAIL_ORDER_SYSPARAM:
|
||||
rail_recv_server_sysparam_order(rail_order, s);
|
||||
break;
|
||||
return rail_recv_server_sysparam_order(rail_order, s);
|
||||
|
||||
case RDP_RAIL_ORDER_MINMAXINFO:
|
||||
rail_recv_server_minmaxinfo_order(rail_order, s);
|
||||
break;
|
||||
return rail_recv_server_minmaxinfo_order(rail_order, s);
|
||||
|
||||
case RDP_RAIL_ORDER_LOCALMOVESIZE:
|
||||
rail_recv_server_localmovesize_order(rail_order, s);
|
||||
break;
|
||||
return rail_recv_server_localmovesize_order(rail_order, s);
|
||||
|
||||
case RDP_RAIL_ORDER_GET_APPID_RESP:
|
||||
rail_recv_server_get_appid_resp_order(rail_order, s);
|
||||
break;
|
||||
return rail_recv_server_get_appid_resp_order(rail_order, s);
|
||||
|
||||
case RDP_RAIL_ORDER_LANGBARINFO:
|
||||
rail_recv_langbar_info_order(rail_order, s);
|
||||
break;
|
||||
return rail_recv_langbar_info_order(rail_order, s);
|
||||
|
||||
default:
|
||||
printf("Unknown RAIL PDU order reveived.");
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void rail_send_handshake_order(rdpRailOrder* rail_order)
|
||||
|
||||
@@ -56,13 +56,13 @@
|
||||
|
||||
void rail_string_to_unicode_string(rdpRailOrder* rail_order, char* string, RAIL_UNICODE_STRING* unicode_string);
|
||||
|
||||
void rail_read_handshake_order(STREAM* s, RAIL_HANDSHAKE_ORDER* handshake);
|
||||
void rail_read_server_exec_result_order(STREAM* s, RAIL_EXEC_RESULT_ORDER* exec_result);
|
||||
void rail_read_server_sysparam_order(STREAM* s, RAIL_SYSPARAM_ORDER* sysparam);
|
||||
void rail_read_server_minmaxinfo_order(STREAM* s, RAIL_MINMAXINFO_ORDER* minmaxinfo);
|
||||
void rail_read_server_localmovesize_order(STREAM* s, RAIL_LOCALMOVESIZE_ORDER* localmovesize);
|
||||
void rail_read_server_get_appid_resp_order(STREAM* s, RAIL_GET_APPID_RESP_ORDER* get_appid_resp);
|
||||
void rail_read_langbar_info_order(STREAM* s, RAIL_LANGBAR_INFO_ORDER* langbar_info);
|
||||
BOOL rail_read_handshake_order(STREAM* s, RAIL_HANDSHAKE_ORDER* handshake);
|
||||
BOOL rail_read_server_exec_result_order(STREAM* s, RAIL_EXEC_RESULT_ORDER* exec_result);
|
||||
BOOL rail_read_server_sysparam_order(STREAM* s, RAIL_SYSPARAM_ORDER* sysparam);
|
||||
BOOL rail_read_server_minmaxinfo_order(STREAM* s, RAIL_MINMAXINFO_ORDER* minmaxinfo);
|
||||
BOOL rail_read_server_localmovesize_order(STREAM* s, RAIL_LOCALMOVESIZE_ORDER* localmovesize);
|
||||
BOOL rail_read_server_get_appid_resp_order(STREAM* s, RAIL_GET_APPID_RESP_ORDER* get_appid_resp);
|
||||
BOOL rail_read_langbar_info_order(STREAM* s, RAIL_LANGBAR_INFO_ORDER* langbar_info);
|
||||
|
||||
void rail_write_handshake_order(STREAM* s, RAIL_HANDSHAKE_ORDER* handshake);
|
||||
void rail_write_client_status_order(STREAM* s, RAIL_CLIENT_STATUS_ORDER* client_status);
|
||||
@@ -76,7 +76,7 @@ void rail_write_client_window_move_order(STREAM* s, RAIL_WINDOW_MOVE_ORDER* wind
|
||||
void rail_write_client_get_appid_req_order(STREAM* s, RAIL_GET_APPID_REQ_ORDER* get_appid_req);
|
||||
void rail_write_langbar_info_order(STREAM* s, RAIL_LANGBAR_INFO_ORDER* langbar_info);
|
||||
|
||||
void rail_order_recv(rdpRailOrder* rail_order, STREAM* s);
|
||||
BOOL rail_order_recv(rdpRailOrder* rail_order, STREAM* s);
|
||||
|
||||
void rail_send_handshake_order(rdpRailOrder* rail_order);
|
||||
void rail_send_client_status_order(rdpRailOrder* rail_order);
|
||||
|
||||
@@ -3,10 +3,6 @@ set(OPTION_DEFAULT OFF)
|
||||
set(OPTION_CLIENT_DEFAULT ON)
|
||||
set(OPTION_SERVER_DEFAULT OFF)
|
||||
|
||||
if(${OPTION_CLIENT_DEFAULT} OR ${OPTION_SERVER_DEFAULT})
|
||||
set(OPTION_DEFAULT ON)
|
||||
endif()
|
||||
|
||||
define_channel_options(NAME "rdpdr" TYPE "static"
|
||||
DESCRIPTION "Device Redirection Virtual Channel Extension"
|
||||
SPECIFICATIONS "[MS-RDPEFS] [MS-RDPEPC] [MS-RDPESC] [MS-RDPESP]"
|
||||
|
||||
@@ -29,10 +29,10 @@
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/addin.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/list.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
#include <freerdp/utils/load_plugin.h>
|
||||
#include <freerdp/client/channels.h>
|
||||
|
||||
#include "rdpdr_main.h"
|
||||
@@ -99,17 +99,8 @@ BOOL devman_load_device_service(DEVMAN* devman, RDPDR_DEVICE* device)
|
||||
if (!ServiceName)
|
||||
return FALSE;
|
||||
|
||||
entry = (PDEVICE_SERVICE_ENTRY) freerdp_channels_client_find_static_entry("DeviceServiceEntry", ServiceName);
|
||||
|
||||
if (!entry)
|
||||
{
|
||||
printf("loading device service %s (dynamic)\n", ServiceName);
|
||||
entry = freerdp_load_plugin(ServiceName, "DeviceServiceEntry");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("loading device service %s (static)\n", ServiceName);
|
||||
}
|
||||
printf("Loading device service %s (static)\n", ServiceName);
|
||||
entry = (PDEVICE_SERVICE_ENTRY) freerdp_load_channel_addin_entry(ServiceName, NULL, "DeviceServiceEntry", 0);
|
||||
|
||||
if (entry == NULL)
|
||||
return FALSE;
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
|
||||
|
||||
@@ -30,9 +30,7 @@
|
||||
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/constants.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/unicode.h>
|
||||
#include <freerdp/channels/rdpdr.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
|
||||
@@ -94,13 +92,13 @@ static void rdpdr_send_client_announce_reply(rdpdrPlugin* rdpdr)
|
||||
static void rdpdr_send_client_name_request(rdpdrPlugin* rdpdr)
|
||||
{
|
||||
STREAM* data_out;
|
||||
WCHAR* computerNameW;
|
||||
WCHAR* computerNameW = NULL;
|
||||
size_t computerNameLenW;
|
||||
|
||||
if (!rdpdr->computerName[0])
|
||||
gethostname(rdpdr->computerName, sizeof(rdpdr->computerName) - 1);
|
||||
|
||||
computerNameLenW = freerdp_AsciiToUnicodeAlloc(rdpdr->computerName, &computerNameW, 0) * 2;
|
||||
computerNameLenW = ConvertToUnicode(CP_UTF8, 0, rdpdr->computerName, -1, &computerNameW, 0) * 2;
|
||||
|
||||
data_out = stream_new(16 + computerNameLenW + 2);
|
||||
|
||||
@@ -173,8 +171,9 @@ static void rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, BOOL use
|
||||
* 2. smartcard devices should be always sent
|
||||
* 3. other devices are sent only after user_loggedon
|
||||
*/
|
||||
if (rdpdr->versionMinor == 0x0005 ||
|
||||
device->type == RDPDR_DTYP_SMARTCARD || user_loggedon)
|
||||
|
||||
if ((rdpdr->versionMinor == 0x0005) ||
|
||||
(device->type == RDPDR_DTYP_SMARTCARD) || user_loggedon)
|
||||
{
|
||||
data_len = (device->data == NULL ? 0 : stream_get_length(device->data));
|
||||
stream_check_size(data_out, 20 + data_len);
|
||||
|
||||
@@ -3,10 +3,6 @@ set(OPTION_DEFAULT OFF)
|
||||
set(OPTION_CLIENT_DEFAULT ON)
|
||||
set(OPTION_SERVER_DEFAULT ON)
|
||||
|
||||
if(${OPTION_CLIENT_DEFAULT} OR ${OPTION_SERVER_DEFAULT})
|
||||
set(OPTION_DEFAULT ON)
|
||||
endif()
|
||||
|
||||
define_channel_options(NAME "rdpsnd" TYPE "static"
|
||||
DESCRIPTION "Audio Output Virtual Channel Extension"
|
||||
SPECIFICATIONS "[MS-RDPEA]"
|
||||
|
||||
@@ -29,6 +29,11 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||
MODULE freerdp
|
||||
MODULES freerdp-utils)
|
||||
|
||||
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||
MODULE winpr
|
||||
MODULES winpr-utils)
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
@@ -45,3 +50,7 @@ endif()
|
||||
if(WITH_MACAUDIO)
|
||||
add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "mac" "")
|
||||
endif()
|
||||
|
||||
if(WITH_WINMM)
|
||||
add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "winmm" "")
|
||||
endif()
|
||||
|
||||
@@ -23,7 +23,7 @@ set(${MODULE_PREFIX}_SRCS
|
||||
include_directories(..)
|
||||
include_directories(${ALSA_INCLUDE_DIRS})
|
||||
|
||||
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE "")
|
||||
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
|
||||
|
||||
@@ -32,6 +32,11 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
MODULE freerdp
|
||||
MODULES freerdp-utils)
|
||||
|
||||
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||
MODULE winpr
|
||||
MODULES winpr-utils)
|
||||
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${ALSA_LIBRARIES})
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
@@ -27,17 +27,18 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/cmdline.h>
|
||||
|
||||
#include <alsa/asoundlib.h>
|
||||
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/dsp.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
|
||||
#include "rdpsnd_main.h"
|
||||
|
||||
typedef struct rdpsnd_alsa_plugin rdpsndAlsaPlugin;
|
||||
|
||||
struct rdpsnd_alsa_plugin
|
||||
{
|
||||
rdpsndDevicePlugin device;
|
||||
@@ -416,16 +417,53 @@ static void rdpsnd_alsa_start(rdpsndDevicePlugin* device)
|
||||
snd_pcm_start(alsa->out_handle);
|
||||
}
|
||||
|
||||
COMMAND_LINE_ARGUMENT_A rdpsnd_alsa_args[] =
|
||||
{
|
||||
{ "dev", COMMAND_LINE_VALUE_REQUIRED, "<device>", NULL, NULL, -1, NULL, "device" },
|
||||
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
|
||||
};
|
||||
|
||||
static void rdpsnd_alsa_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV* args)
|
||||
{
|
||||
int status;
|
||||
DWORD flags;
|
||||
COMMAND_LINE_ARGUMENT_A* arg;
|
||||
rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*) device;
|
||||
|
||||
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON;
|
||||
|
||||
status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv, rdpsnd_alsa_args, flags, alsa, NULL, NULL);
|
||||
|
||||
arg = rdpsnd_alsa_args;
|
||||
|
||||
do
|
||||
{
|
||||
if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT))
|
||||
continue;
|
||||
|
||||
CommandLineSwitchStart(arg)
|
||||
|
||||
CommandLineSwitchCase(arg, "dev")
|
||||
{
|
||||
alsa->device_name = _strdup(arg->Value);
|
||||
}
|
||||
|
||||
CommandLineSwitchEnd(arg)
|
||||
}
|
||||
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define freerdp_rdpsnd_client_subsystem_entry alsa_freerdp_rdpsnd_client_subsystem_entry
|
||||
#endif
|
||||
|
||||
int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints)
|
||||
{
|
||||
ADDIN_ARGV* args;
|
||||
rdpsndAlsaPlugin* alsa;
|
||||
RDP_PLUGIN_DATA* data;
|
||||
|
||||
alsa = xnew(rdpsndAlsaPlugin);
|
||||
alsa = (rdpsndAlsaPlugin*) malloc(sizeof(rdpsndAlsaPlugin));
|
||||
ZeroMemory(alsa, sizeof(rdpsndAlsaPlugin));
|
||||
|
||||
alsa->device.Open = rdpsnd_alsa_open;
|
||||
alsa->device.FormatSupported = rdpsnd_alsa_format_supported;
|
||||
@@ -436,17 +474,11 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE
|
||||
alsa->device.Close = rdpsnd_alsa_close;
|
||||
alsa->device.Free = rdpsnd_alsa_free;
|
||||
|
||||
data = pEntryPoints->plugin_data;
|
||||
args = pEntryPoints->args;
|
||||
rdpsnd_alsa_parse_addin_args((rdpsndDevicePlugin*) alsa, args);
|
||||
|
||||
if (data && strcmp((char*) data->data[0], "alsa") == 0)
|
||||
{
|
||||
alsa->device_name = _strdup((char*) data->data[1]);
|
||||
}
|
||||
|
||||
if (alsa->device_name == NULL)
|
||||
{
|
||||
if (!alsa->device_name)
|
||||
alsa->device_name = _strdup("default");
|
||||
}
|
||||
|
||||
alsa->out_handle = 0;
|
||||
alsa->source_rate = 22050;
|
||||
|
||||
@@ -24,7 +24,7 @@ set(${MODULE_PREFIX}_SRCS
|
||||
include_directories(..)
|
||||
include_directories(${MACAUDIO_INCLUDE_DIRS})
|
||||
|
||||
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE "")
|
||||
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
|
||||
|
||||
|
||||
@@ -29,8 +29,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/dsp.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
|
||||
@@ -203,10 +204,11 @@ static void aq_playback_cb(void* user_data, AudioQueueRef aq_ref, AudioQueueBuff
|
||||
|
||||
int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints)
|
||||
{
|
||||
ADDIN_ARGV* args;
|
||||
rdpsndAudioQPlugin* aqPlugin;
|
||||
RDP_PLUGIN_DATA* data;
|
||||
|
||||
aqPlugin = xnew(rdpsndAudioQPlugin);
|
||||
aqPlugin = (rdpsndAudioQPlugin*) malloc(sizeof(rdpsndAudioQPlugin));
|
||||
ZeroMemory(aqPlugin, sizeof(rdpsndAudioQPlugin));
|
||||
|
||||
aqPlugin->device.Open = rdpsnd_audio_open;
|
||||
aqPlugin->device.FormatSupported = rdpsnd_audio_format_supported;
|
||||
@@ -217,14 +219,11 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE
|
||||
aqPlugin->device.Close = rdpsnd_audio_close;
|
||||
aqPlugin->device.Free = rdpsnd_audio_free;
|
||||
|
||||
data = pEntryPoints->plugin_data;
|
||||
args = pEntryPoints->args;
|
||||
|
||||
if (data && strcmp((char *)data->data[0], "macaudio") == 0)
|
||||
if (args->argc > 2)
|
||||
{
|
||||
if(strlen((char *)data->data[1]) > 0)
|
||||
aqPlugin->device_name = strdup((char *)data->data[1]);
|
||||
else
|
||||
aqPlugin->device_name = NULL;
|
||||
/* TODO: parse device name */
|
||||
}
|
||||
|
||||
pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*) aqPlugin);
|
||||
|
||||
@@ -23,7 +23,7 @@ set(${MODULE_PREFIX}_SRCS
|
||||
include_directories(..)
|
||||
include_directories(${PULSE_INCLUDE_DIR})
|
||||
|
||||
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE "")
|
||||
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
|
||||
|
||||
|
||||
@@ -26,11 +26,11 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/cmdline.h>
|
||||
|
||||
#include <pulse/pulseaudio.h>
|
||||
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/dsp.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
|
||||
@@ -523,16 +523,54 @@ static void rdpsnd_pulse_start(rdpsndDevicePlugin* device)
|
||||
pa_stream_trigger(pulse->stream, NULL, NULL);
|
||||
}
|
||||
|
||||
COMMAND_LINE_ARGUMENT_A rdpsnd_pulse_args[] =
|
||||
{
|
||||
{ "dev", COMMAND_LINE_VALUE_REQUIRED, "<device>", NULL, NULL, -1, NULL, "device" },
|
||||
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
|
||||
};
|
||||
|
||||
static void rdpsnd_pulse_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV* args)
|
||||
{
|
||||
int status;
|
||||
DWORD flags;
|
||||
COMMAND_LINE_ARGUMENT_A* arg;
|
||||
rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*) device;
|
||||
|
||||
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON;
|
||||
|
||||
status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv,
|
||||
rdpsnd_pulse_args, flags, pulse, NULL, NULL);
|
||||
|
||||
arg = rdpsnd_pulse_args;
|
||||
|
||||
do
|
||||
{
|
||||
if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT))
|
||||
continue;
|
||||
|
||||
CommandLineSwitchStart(arg)
|
||||
|
||||
CommandLineSwitchCase(arg, "dev")
|
||||
{
|
||||
pulse->device_name = _strdup(arg->Value);
|
||||
}
|
||||
|
||||
CommandLineSwitchEnd(arg)
|
||||
}
|
||||
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define freerdp_rdpsnd_client_subsystem_entry pulse_freerdp_rdpsnd_client_subsystem_entry
|
||||
#endif
|
||||
|
||||
int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints)
|
||||
{
|
||||
ADDIN_ARGV* args;
|
||||
rdpsndPulsePlugin* pulse;
|
||||
RDP_PLUGIN_DATA* data;
|
||||
|
||||
pulse = xnew(rdpsndPulsePlugin);
|
||||
pulse = (rdpsndPulsePlugin*) malloc(sizeof(rdpsndPulsePlugin));
|
||||
ZeroMemory(pulse, sizeof(rdpsndPulsePlugin));
|
||||
|
||||
pulse->device.Open = rdpsnd_pulse_open;
|
||||
pulse->device.FormatSupported = rdpsnd_pulse_format_supported;
|
||||
@@ -543,15 +581,8 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE
|
||||
pulse->device.Close = rdpsnd_pulse_close;
|
||||
pulse->device.Free = rdpsnd_pulse_free;
|
||||
|
||||
data = pEntryPoints->plugin_data;
|
||||
|
||||
if (data && strcmp((char*)data->data[0], "pulse") == 0)
|
||||
{
|
||||
if(data->data[1] && strlen((char*)data->data[1]) > 0)
|
||||
pulse->device_name = _strdup((char*)data->data[1]);
|
||||
else
|
||||
pulse->device_name = NULL;
|
||||
}
|
||||
args = pEntryPoints->args;
|
||||
rdpsnd_pulse_parse_addin_args((rdpsndDevicePlugin*) pulse, args);
|
||||
|
||||
pulse->dsp_context = freerdp_dsp_context_new();
|
||||
|
||||
|
||||
@@ -31,13 +31,13 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/cmdline.h>
|
||||
|
||||
#include <freerdp/constants.h>
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/addin.h>
|
||||
#include <freerdp/constants.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/list.h>
|
||||
#include <freerdp/utils/load_plugin.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
|
||||
#include "rdpsnd_main.h"
|
||||
@@ -67,6 +67,9 @@ struct rdpsnd_plugin
|
||||
UINT32 fixed_rate;
|
||||
int latency;
|
||||
|
||||
char* subsystem;
|
||||
char* device_name;
|
||||
|
||||
/* Device plugin */
|
||||
rdpsndDevicePlugin* device;
|
||||
};
|
||||
@@ -190,7 +193,8 @@ static void rdpsnd_process_message_formats(rdpsndPlugin* rdpsnd, STREAM* data_in
|
||||
return;
|
||||
}
|
||||
|
||||
out_formats = (rdpsndFormat*)xzalloc(wNumberOfFormats * sizeof(rdpsndFormat));
|
||||
out_formats = (rdpsndFormat*) malloc(wNumberOfFormats * sizeof(rdpsndFormat));
|
||||
ZeroMemory(out_formats, wNumberOfFormats * sizeof(rdpsndFormat));
|
||||
n_out_formats = 0;
|
||||
|
||||
data_out = stream_new(24);
|
||||
@@ -315,20 +319,27 @@ static void rdpsnd_process_message_wave_info(rdpsndPlugin* rdpsnd, STREAM* data_
|
||||
DEBUG_SVC("waveDataSize %d wFormatNo %d", rdpsnd->waveDataSize, wFormatNo);
|
||||
|
||||
rdpsnd->close_timestamp = 0;
|
||||
|
||||
if (!rdpsnd->is_open)
|
||||
{
|
||||
rdpsnd->current_format = wFormatNo;
|
||||
rdpsnd->is_open = TRUE;
|
||||
|
||||
if (rdpsnd->device)
|
||||
{
|
||||
IFCALL(rdpsnd->device->Open, rdpsnd->device, &rdpsnd->supported_formats[wFormatNo],
|
||||
rdpsnd->latency);
|
||||
}
|
||||
}
|
||||
else if (wFormatNo != rdpsnd->current_format)
|
||||
{
|
||||
rdpsnd->current_format = wFormatNo;
|
||||
|
||||
if (rdpsnd->device)
|
||||
{
|
||||
IFCALL(rdpsnd->device->SetFormat, rdpsnd->device, &rdpsnd->supported_formats[wFormatNo],
|
||||
rdpsnd->latency);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -341,14 +352,19 @@ static void rdpsnd_process_message_wave(rdpsndPlugin* rdpsnd, STREAM* data_in)
|
||||
struct data_out_item* item;
|
||||
|
||||
rdpsnd->expectingWave = 0;
|
||||
|
||||
memcpy(stream_get_head(data_in), rdpsnd->waveData, 4);
|
||||
|
||||
if (stream_get_size(data_in) != rdpsnd->waveDataSize)
|
||||
{
|
||||
DEBUG_WARN("size error");
|
||||
return;
|
||||
}
|
||||
|
||||
if (rdpsnd->device)
|
||||
{
|
||||
IFCALL(rdpsnd->device->Play, rdpsnd->device, stream_get_head(data_in), stream_get_size(data_in));
|
||||
}
|
||||
|
||||
process_ms = get_mstime() - rdpsnd->wave_timestamp;
|
||||
delay_ms = 250;
|
||||
@@ -357,7 +373,9 @@ static void rdpsnd_process_message_wave(rdpsndPlugin* rdpsnd, STREAM* data_in)
|
||||
DEBUG_SVC("data_size %d delay_ms %u process_ms %u",
|
||||
stream_get_size(data_in), delay_ms, process_ms);
|
||||
|
||||
item = xnew(struct data_out_item);
|
||||
item = (struct data_out_item*) malloc(sizeof(struct data_out_item));
|
||||
ZeroMemory(item, sizeof(struct data_out_item));
|
||||
|
||||
item->data_out = stream_new(8);
|
||||
stream_write_BYTE(item->data_out, SNDC_WAVECONFIRM);
|
||||
stream_write_BYTE(item->data_out, 0);
|
||||
@@ -374,8 +392,12 @@ static void rdpsnd_process_message_wave(rdpsndPlugin* rdpsnd, STREAM* data_in)
|
||||
static void rdpsnd_process_message_close(rdpsndPlugin* rdpsnd)
|
||||
{
|
||||
DEBUG_SVC("server closes.");
|
||||
|
||||
if (rdpsnd->device)
|
||||
{
|
||||
IFCALL(rdpsnd->device->Start, rdpsnd->device);
|
||||
}
|
||||
|
||||
rdpsnd->close_timestamp = get_mstime() + 2000;
|
||||
rdpsnd->plugin.interval_ms = 10;
|
||||
}
|
||||
@@ -386,8 +408,11 @@ static void rdpsnd_process_message_setvolume(rdpsndPlugin* rdpsnd, STREAM* data_
|
||||
|
||||
stream_read_UINT32(data_in, dwVolume);
|
||||
DEBUG_SVC("dwVolume 0x%X", dwVolume);
|
||||
|
||||
if (rdpsnd->device)
|
||||
{
|
||||
IFCALL(rdpsnd->device->SetVolume, rdpsnd->device, dwVolume);
|
||||
}
|
||||
}
|
||||
|
||||
static void rdpsnd_process_receive(rdpSvcPlugin* plugin, STREAM* data_in)
|
||||
@@ -414,18 +439,23 @@ static void rdpsnd_process_receive(rdpSvcPlugin* plugin, STREAM* data_in)
|
||||
case SNDC_FORMATS:
|
||||
rdpsnd_process_message_formats(rdpsnd, data_in);
|
||||
break;
|
||||
|
||||
case SNDC_TRAINING:
|
||||
rdpsnd_process_message_training(rdpsnd, data_in);
|
||||
break;
|
||||
|
||||
case SNDC_WAVE:
|
||||
rdpsnd_process_message_wave_info(rdpsnd, data_in, BodySize);
|
||||
break;
|
||||
|
||||
case SNDC_CLOSE:
|
||||
rdpsnd_process_message_close(rdpsnd);
|
||||
break;
|
||||
|
||||
case SNDC_SETVOLUME:
|
||||
rdpsnd_process_message_setvolume(rdpsnd, data_in);
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUG_WARN("unknown msgType %d", msgType);
|
||||
break;
|
||||
@@ -444,32 +474,19 @@ static void rdpsnd_register_device_plugin(rdpsndPlugin* rdpsnd, rdpsndDevicePlug
|
||||
rdpsnd->device = device;
|
||||
}
|
||||
|
||||
static BOOL rdpsnd_load_device_plugin(rdpsndPlugin* rdpsnd, const char* name, RDP_PLUGIN_DATA* data)
|
||||
static BOOL rdpsnd_load_device_plugin(rdpsndPlugin* rdpsnd, const char* name, ADDIN_ARGV* args)
|
||||
{
|
||||
FREERDP_RDPSND_DEVICE_ENTRY_POINTS entryPoints;
|
||||
PFREERDP_RDPSND_DEVICE_ENTRY entry;
|
||||
char* fullname;
|
||||
FREERDP_RDPSND_DEVICE_ENTRY_POINTS entryPoints;
|
||||
|
||||
entry = (PFREERDP_RDPSND_DEVICE_ENTRY) freerdp_load_channel_addin_entry("rdpsnd", (LPSTR) name, NULL, 0);
|
||||
|
||||
if (strrchr(name, '.') != NULL)
|
||||
{
|
||||
entry = (PFREERDP_RDPSND_DEVICE_ENTRY) freerdp_load_plugin(name, RDPSND_DEVICE_EXPORT_FUNC_NAME);
|
||||
}
|
||||
else
|
||||
{
|
||||
fullname = xzalloc(strlen(name) + 8);
|
||||
strcpy(fullname, "rdpsnd-client-");
|
||||
strcat(fullname, name);
|
||||
entry = (PFREERDP_RDPSND_DEVICE_ENTRY) freerdp_load_plugin(fullname, RDPSND_DEVICE_EXPORT_FUNC_NAME);
|
||||
free(fullname);
|
||||
}
|
||||
if (entry == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
entryPoints.rdpsnd = rdpsnd;
|
||||
entryPoints.pRegisterRdpsndDevice = rdpsnd_register_device_plugin;
|
||||
entryPoints.plugin_data = data;
|
||||
entryPoints.args = args;
|
||||
|
||||
if (entry(&entryPoints) != 0)
|
||||
{
|
||||
@@ -480,35 +497,91 @@ static BOOL rdpsnd_load_device_plugin(rdpsndPlugin* rdpsnd, const char* name, RD
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void rdpsnd_process_plugin_data(rdpsndPlugin* rdpsnd, RDP_PLUGIN_DATA* data)
|
||||
void rdpsnd_set_subsystem(rdpsndPlugin* rdpsnd, char* subsystem)
|
||||
{
|
||||
if (strcmp((char*)data->data[0], "format") == 0)
|
||||
if (rdpsnd->subsystem)
|
||||
free(rdpsnd->subsystem);
|
||||
|
||||
rdpsnd->subsystem = _strdup(subsystem);
|
||||
}
|
||||
|
||||
void rdpsnd_set_device_name(rdpsndPlugin* rdpsnd, char* device_name)
|
||||
{
|
||||
if (rdpsnd->device_name)
|
||||
free(rdpsnd->device_name);
|
||||
|
||||
rdpsnd->device_name = _strdup(device_name);
|
||||
}
|
||||
|
||||
COMMAND_LINE_ARGUMENT_A rdpsnd_args[] =
|
||||
{
|
||||
{ "sys", COMMAND_LINE_VALUE_REQUIRED, "<subsystem>", NULL, NULL, -1, NULL, "subsystem" },
|
||||
{ "dev", COMMAND_LINE_VALUE_REQUIRED, "<device>", NULL, NULL, -1, NULL, "device" },
|
||||
{ "format", COMMAND_LINE_VALUE_REQUIRED, "<format>", NULL, NULL, -1, NULL, "format" },
|
||||
{ "rate", COMMAND_LINE_VALUE_REQUIRED, "<rate>", NULL, NULL, -1, NULL, "rate" },
|
||||
{ "channel", COMMAND_LINE_VALUE_REQUIRED, "<channel>", NULL, NULL, -1, NULL, "channel" },
|
||||
{ "latency", COMMAND_LINE_VALUE_REQUIRED, "<latency>", NULL, NULL, -1, NULL, "latency" },
|
||||
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
|
||||
};
|
||||
|
||||
static void rdpsnd_process_addin_args(rdpsndPlugin* rdpsnd, ADDIN_ARGV* args)
|
||||
{
|
||||
int status;
|
||||
DWORD flags;
|
||||
COMMAND_LINE_ARGUMENT_A* arg;
|
||||
|
||||
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON;
|
||||
|
||||
status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv,
|
||||
rdpsnd_args, flags, rdpsnd, NULL, NULL);
|
||||
|
||||
arg = rdpsnd_args;
|
||||
|
||||
do
|
||||
{
|
||||
rdpsnd->fixed_format = atoi(data->data[1]);
|
||||
}
|
||||
else if (strcmp((char*)data->data[0], "rate") == 0)
|
||||
{
|
||||
rdpsnd->fixed_rate = atoi(data->data[1]);
|
||||
}
|
||||
else if (strcmp((char*)data->data[0], "channel") == 0)
|
||||
{
|
||||
rdpsnd->fixed_channel = atoi(data->data[1]);
|
||||
}
|
||||
else if (strcmp((char*)data->data[0], "latency") == 0)
|
||||
{
|
||||
rdpsnd->latency = atoi(data->data[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
rdpsnd_load_device_plugin(rdpsnd, (char*) data->data[0], data);
|
||||
if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT))
|
||||
continue;
|
||||
|
||||
CommandLineSwitchStart(arg)
|
||||
|
||||
CommandLineSwitchCase(arg, "sys")
|
||||
{
|
||||
rdpsnd_set_subsystem(rdpsnd, arg->Value);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "dev")
|
||||
{
|
||||
rdpsnd_set_device_name(rdpsnd, arg->Value);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "format")
|
||||
{
|
||||
rdpsnd->fixed_format = atoi(arg->Value);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "rate")
|
||||
{
|
||||
rdpsnd->fixed_rate = atoi(arg->Value);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "channel")
|
||||
{
|
||||
rdpsnd->fixed_channel = atoi(arg->Value);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "latency")
|
||||
{
|
||||
rdpsnd->latency = atoi(arg->Value);
|
||||
}
|
||||
CommandLineSwitchDefault(arg)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CommandLineSwitchEnd(arg)
|
||||
}
|
||||
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
|
||||
}
|
||||
|
||||
static void rdpsnd_process_connect(rdpSvcPlugin* plugin)
|
||||
{
|
||||
ADDIN_ARGV* args;
|
||||
rdpsndPlugin* rdpsnd = (rdpsndPlugin*) plugin;
|
||||
RDP_PLUGIN_DATA* data;
|
||||
RDP_PLUGIN_DATA default_data[2] = { { 0 }, { 0 } };
|
||||
|
||||
DEBUG_SVC("connecting");
|
||||
|
||||
@@ -517,42 +590,47 @@ static void rdpsnd_process_connect(rdpSvcPlugin* plugin)
|
||||
rdpsnd->data_out_list = list_new();
|
||||
rdpsnd->latency = -1;
|
||||
|
||||
data = (RDP_PLUGIN_DATA*) plugin->channel_entry_points.pExtendedData;
|
||||
args = (ADDIN_ARGV*) plugin->channel_entry_points.pExtendedData;
|
||||
|
||||
while (data && data->size > 0)
|
||||
if (args)
|
||||
rdpsnd_process_addin_args(rdpsnd, args);
|
||||
|
||||
if (rdpsnd->subsystem)
|
||||
{
|
||||
rdpsnd_process_plugin_data(rdpsnd, data);
|
||||
data = (RDP_PLUGIN_DATA*) (((BYTE*) data) + data->size);
|
||||
if (strcmp(rdpsnd->subsystem, "fake") == 0)
|
||||
return;
|
||||
|
||||
rdpsnd_load_device_plugin(rdpsnd, rdpsnd->subsystem, args);
|
||||
}
|
||||
|
||||
if (rdpsnd->device == NULL)
|
||||
if (!rdpsnd->device)
|
||||
{
|
||||
default_data[0].size = sizeof(RDP_PLUGIN_DATA);
|
||||
default_data[0].data[0] = "pulse";
|
||||
default_data[0].data[1] = "";
|
||||
|
||||
if (!rdpsnd_load_device_plugin(rdpsnd, "pulse", default_data))
|
||||
{
|
||||
default_data[0].data[0] = "alsa";
|
||||
default_data[0].data[1] = "default";
|
||||
|
||||
if (!rdpsnd_load_device_plugin(rdpsnd, "alsa", default_data))
|
||||
{
|
||||
default_data[0].data[0] = "macaudio";
|
||||
default_data[0].data[1] = "default";
|
||||
|
||||
rdpsnd_load_device_plugin(rdpsnd, "macaudio", default_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("rdpsnd: successfully loaded alsa plugin\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("rdpsnd: successfully loaded pulseaudio plugin\n");
|
||||
}
|
||||
rdpsnd_set_subsystem(rdpsnd, "pulse");
|
||||
rdpsnd_set_device_name(rdpsnd, "");
|
||||
rdpsnd_load_device_plugin(rdpsnd, rdpsnd->subsystem, args);
|
||||
}
|
||||
|
||||
if (!rdpsnd->device)
|
||||
{
|
||||
rdpsnd_set_subsystem(rdpsnd, "alsa");
|
||||
rdpsnd_set_device_name(rdpsnd, "default");
|
||||
rdpsnd_load_device_plugin(rdpsnd, rdpsnd->subsystem, args);
|
||||
}
|
||||
|
||||
if (!rdpsnd->device)
|
||||
{
|
||||
rdpsnd_set_subsystem(rdpsnd, "macaudio");
|
||||
rdpsnd_set_device_name(rdpsnd, "default");
|
||||
rdpsnd_load_device_plugin(rdpsnd, rdpsnd->subsystem, args);
|
||||
}
|
||||
|
||||
if (!rdpsnd->device)
|
||||
{
|
||||
rdpsnd_set_subsystem(rdpsnd, "winmm");
|
||||
rdpsnd_set_device_name(rdpsnd, "");
|
||||
rdpsnd_load_device_plugin(rdpsnd, rdpsnd->subsystem, args);
|
||||
}
|
||||
|
||||
if (rdpsnd->device == NULL)
|
||||
{
|
||||
DEBUG_WARN("no sound device.");
|
||||
@@ -579,6 +657,12 @@ static void rdpsnd_process_terminate(rdpSvcPlugin* plugin)
|
||||
}
|
||||
list_free(rdpsnd->data_out_list);
|
||||
|
||||
if (rdpsnd->subsystem)
|
||||
free(rdpsnd->subsystem);
|
||||
|
||||
if (rdpsnd->device_name)
|
||||
free(rdpsnd->device_name);
|
||||
|
||||
rdpsnd_free_supported_formats(rdpsnd);
|
||||
|
||||
free(plugin);
|
||||
|
||||
@@ -55,7 +55,7 @@ struct _FREERDP_RDPSND_DEVICE_ENTRY_POINTS
|
||||
{
|
||||
rdpsndPlugin* rdpsnd;
|
||||
PREGISTERRDPSNDDEVICE pRegisterRdpsndDevice;
|
||||
RDP_PLUGIN_DATA* plugin_data;
|
||||
ADDIN_ARGV* args;
|
||||
};
|
||||
typedef struct _FREERDP_RDPSND_DEVICE_ENTRY_POINTS FREERDP_RDPSND_DEVICE_ENTRY_POINTS;
|
||||
typedef FREERDP_RDPSND_DEVICE_ENTRY_POINTS* PFREERDP_RDPSND_DEVICE_ENTRY_POINTS;
|
||||
|
||||
45
channels/rdpsnd/client/winmm/CMakeLists.txt
Normal file
45
channels/rdpsnd/client/winmm/CMakeLists.txt
Normal file
@@ -0,0 +1,45 @@
|
||||
# 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_client_subsystem("rdpsnd" "winmm" "")
|
||||
|
||||
set(${MODULE_PREFIX}_SRCS
|
||||
rdpsnd_winmm.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_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||
MODULE winpr
|
||||
MODULES winpr-utils)
|
||||
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} winmm.lib)
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
if(NOT STATIC_CHANNELS)
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH})
|
||||
endif()
|
||||
290
channels/rdpsnd/client/winmm/rdpsnd_winmm.c
Normal file
290
channels/rdpsnd/client/winmm/rdpsnd_winmm.c
Normal file
@@ -0,0 +1,290 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Audio Output Virtual Channel
|
||||
*
|
||||
* Copyright 2009-2012 Jay Sorg
|
||||
* Copyright 2010-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 <Windows.h>
|
||||
#include <MMSystem.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/cmdline.h>
|
||||
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/utils/dsp.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
|
||||
#include "rdpsnd_main.h"
|
||||
|
||||
typedef struct rdpsnd_winmm_datablock rdpsndWinmmDatablock;
|
||||
|
||||
struct rdpsnd_winmm_datablock
|
||||
{
|
||||
WAVEHDR header;
|
||||
rdpsndWinmmDatablock* next;
|
||||
};
|
||||
|
||||
typedef struct rdpsnd_winmm_plugin rdpsndWinmmPlugin;
|
||||
|
||||
struct rdpsnd_winmm_plugin
|
||||
{
|
||||
rdpsndDevicePlugin device;
|
||||
|
||||
HWAVEOUT out_handle;
|
||||
WAVEFORMATEX format;
|
||||
int wformat;
|
||||
int block_size;
|
||||
int latency;
|
||||
HANDLE event;
|
||||
rdpsndWinmmDatablock* datablock_head;
|
||||
|
||||
FREERDP_DSP_CONTEXT* dsp_context;
|
||||
};
|
||||
|
||||
static BOOL rdpsnd_winmm_convert_format(const rdpsndFormat* in, WAVEFORMATEX* out)
|
||||
{
|
||||
BOOL result = FALSE;
|
||||
|
||||
ZeroMemory(out, sizeof(WAVEFORMATEX));
|
||||
out->wFormatTag = WAVE_FORMAT_PCM;
|
||||
out->nChannels = in->nChannels;
|
||||
out->nSamplesPerSec = in->nSamplesPerSec;
|
||||
switch (in->wFormatTag)
|
||||
{
|
||||
case WAVE_FORMAT_PCM:
|
||||
out->wBitsPerSample = in->wBitsPerSample;
|
||||
result = TRUE;
|
||||
break;
|
||||
|
||||
case 2: /* MS ADPCM */
|
||||
case 0x11: /* IMA ADPCM */
|
||||
out->wBitsPerSample = 16;
|
||||
result = TRUE;
|
||||
break;
|
||||
}
|
||||
out->nBlockAlign = out->nChannels * out->wBitsPerSample / 8;
|
||||
out->nAvgBytesPerSec = out->nSamplesPerSec * out->nBlockAlign;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void rdpsnd_winmm_clear_datablocks(rdpsndWinmmPlugin* winmm, BOOL drain)
|
||||
{
|
||||
rdpsndWinmmDatablock* datablock;
|
||||
|
||||
while ((datablock = winmm->datablock_head) != NULL)
|
||||
{
|
||||
if (!drain && (datablock->header.dwFlags & WHDR_DONE) == 0)
|
||||
break;
|
||||
while ((datablock->header.dwFlags & WHDR_DONE) == 0)
|
||||
WaitForSingleObject(winmm->event, INFINITE);
|
||||
winmm->datablock_head = datablock->next;
|
||||
free(datablock->header.lpData);
|
||||
free(datablock);
|
||||
}
|
||||
}
|
||||
|
||||
static void rdpsnd_winmm_set_format(rdpsndDevicePlugin* device, rdpsndFormat* format, int latency)
|
||||
{
|
||||
rdpsndWinmmPlugin* winmm = (rdpsndWinmmPlugin*)device;
|
||||
|
||||
if (format != NULL)
|
||||
{
|
||||
rdpsnd_winmm_convert_format(format, &winmm->format);
|
||||
|
||||
winmm->wformat = format->wFormatTag;
|
||||
winmm->block_size = format->nBlockAlign;
|
||||
}
|
||||
|
||||
winmm->latency = latency;
|
||||
}
|
||||
|
||||
static void rdpsnd_winmm_open(rdpsndDevicePlugin* device, rdpsndFormat* format, int latency)
|
||||
{
|
||||
MMRESULT result;
|
||||
rdpsndWinmmPlugin* winmm = (rdpsndWinmmPlugin*) device;
|
||||
|
||||
if (winmm->out_handle != NULL)
|
||||
return;
|
||||
|
||||
DEBUG_SVC("opening");
|
||||
|
||||
rdpsnd_winmm_set_format(device, format, latency);
|
||||
freerdp_dsp_context_reset_adpcm(winmm->dsp_context);
|
||||
|
||||
result = waveOutOpen(&winmm->out_handle, WAVE_MAPPER, &winmm->format, (DWORD_PTR) winmm->event, 0, CALLBACK_EVENT);
|
||||
if (result != MMSYSERR_NOERROR)
|
||||
{
|
||||
DEBUG_WARN("waveOutOpen failed: %d", result);
|
||||
}
|
||||
}
|
||||
|
||||
static void rdpsnd_winmm_close(rdpsndDevicePlugin* device)
|
||||
{
|
||||
rdpsndWinmmPlugin* winmm = (rdpsndWinmmPlugin*)device;
|
||||
|
||||
if (winmm->out_handle != NULL)
|
||||
{
|
||||
DEBUG_SVC("close");
|
||||
rdpsnd_winmm_clear_datablocks(winmm, TRUE);
|
||||
if (waveOutClose(winmm->out_handle) != MMSYSERR_NOERROR)
|
||||
{
|
||||
DEBUG_WARN("waveOutClose error");
|
||||
}
|
||||
winmm->out_handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void rdpsnd_winmm_free(rdpsndDevicePlugin* device)
|
||||
{
|
||||
rdpsndWinmmPlugin* winmm = (rdpsndWinmmPlugin*)device;
|
||||
|
||||
rdpsnd_winmm_close(device);
|
||||
freerdp_dsp_context_free(winmm->dsp_context);
|
||||
CloseHandle(winmm->event);
|
||||
free(winmm);
|
||||
}
|
||||
|
||||
static BOOL rdpsnd_winmm_format_supported(rdpsndDevicePlugin* device, rdpsndFormat* format)
|
||||
{
|
||||
MMRESULT result;
|
||||
WAVEFORMATEX out;
|
||||
|
||||
if (rdpsnd_winmm_convert_format(format, &out))
|
||||
{
|
||||
result = waveOutOpen(NULL, WAVE_MAPPER, &out, 0, 0, WAVE_FORMAT_QUERY);
|
||||
if (result == MMSYSERR_NOERROR)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void rdpsnd_winmm_set_volume(rdpsndDevicePlugin* device, UINT32 value)
|
||||
{
|
||||
rdpsndWinmmPlugin* winmm = (rdpsndWinmmPlugin*) device;
|
||||
|
||||
if (winmm->out_handle == NULL)
|
||||
return;
|
||||
|
||||
waveOutSetVolume(winmm->out_handle, value);
|
||||
}
|
||||
|
||||
static void rdpsnd_winmm_play(rdpsndDevicePlugin* device, BYTE* data, int size)
|
||||
{
|
||||
BYTE* src;
|
||||
MMRESULT result;
|
||||
rdpsndWinmmDatablock* last;
|
||||
rdpsndWinmmDatablock* datablock;
|
||||
rdpsndWinmmPlugin* winmm = (rdpsndWinmmPlugin*) device;
|
||||
|
||||
if (winmm->out_handle == NULL)
|
||||
return;
|
||||
|
||||
if (winmm->wformat == 2)
|
||||
{
|
||||
winmm->dsp_context->decode_ms_adpcm(winmm->dsp_context,
|
||||
data, size, winmm->format.nChannels, winmm->block_size);
|
||||
size = winmm->dsp_context->adpcm_size;
|
||||
src = winmm->dsp_context->adpcm_buffer;
|
||||
}
|
||||
else if (winmm->wformat == 0x11)
|
||||
{
|
||||
winmm->dsp_context->decode_ima_adpcm(winmm->dsp_context,
|
||||
data, size, winmm->format.nChannels, winmm->block_size);
|
||||
size = winmm->dsp_context->adpcm_size;
|
||||
src = winmm->dsp_context->adpcm_buffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
src = data;
|
||||
}
|
||||
|
||||
rdpsnd_winmm_clear_datablocks(winmm, FALSE);
|
||||
for (last = winmm->datablock_head; last && last->next; last = last->next)
|
||||
{
|
||||
}
|
||||
datablock = (rdpsndWinmmDatablock*) malloc(sizeof(rdpsndWinmmDatablock));
|
||||
ZeroMemory(datablock, sizeof(rdpsndWinmmDatablock));
|
||||
if (last)
|
||||
last->next = datablock;
|
||||
else
|
||||
winmm->datablock_head = datablock;
|
||||
datablock->header.dwBufferLength = size;
|
||||
datablock->header.lpData = (LPSTR) malloc(size);
|
||||
CopyMemory(datablock->header.lpData, src, size);
|
||||
|
||||
result = waveOutPrepareHeader(winmm->out_handle, &datablock->header, sizeof(datablock->header));
|
||||
if (result != MMSYSERR_NOERROR)
|
||||
{
|
||||
DEBUG_WARN("waveOutPrepareHeader: %d", result);
|
||||
return;
|
||||
}
|
||||
ResetEvent(winmm->event);
|
||||
waveOutWrite(winmm->out_handle, &datablock->header, sizeof(datablock->header));
|
||||
}
|
||||
|
||||
static void rdpsnd_winmm_start(rdpsndDevicePlugin* device)
|
||||
{
|
||||
rdpsndWinmmPlugin* winmm = (rdpsndWinmmPlugin*) device;
|
||||
|
||||
rdpsnd_winmm_clear_datablocks(winmm, FALSE);
|
||||
}
|
||||
|
||||
static void rdpsnd_winmm_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV* args)
|
||||
{
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define freerdp_rdpsnd_client_subsystem_entry winmm_freerdp_rdpsnd_client_subsystem_entry
|
||||
#endif
|
||||
|
||||
int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints)
|
||||
{
|
||||
ADDIN_ARGV* args;
|
||||
rdpsndWinmmPlugin* winmm;
|
||||
|
||||
winmm = (rdpsndWinmmPlugin*) malloc(sizeof(rdpsndWinmmPlugin));
|
||||
ZeroMemory(winmm, sizeof(rdpsndWinmmPlugin));
|
||||
|
||||
winmm->device.Open = rdpsnd_winmm_open;
|
||||
winmm->device.FormatSupported = rdpsnd_winmm_format_supported;
|
||||
winmm->device.SetFormat = rdpsnd_winmm_set_format;
|
||||
winmm->device.SetVolume = rdpsnd_winmm_set_volume;
|
||||
winmm->device.Play = rdpsnd_winmm_play;
|
||||
winmm->device.Start = rdpsnd_winmm_start;
|
||||
winmm->device.Close = rdpsnd_winmm_close;
|
||||
winmm->device.Free = rdpsnd_winmm_free;
|
||||
|
||||
args = pEntryPoints->args;
|
||||
rdpsnd_winmm_parse_addin_args((rdpsndDevicePlugin*) winmm, args);
|
||||
|
||||
winmm->dsp_context = freerdp_dsp_context_new();
|
||||
winmm->event = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*) winmm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -27,11 +27,9 @@
|
||||
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/dsp.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/thread.h>
|
||||
#include <freerdp/utils/wait_obj.h>
|
||||
#include <freerdp/channels/wtsvc.h>
|
||||
#include <freerdp/server/rdpsnd.h>
|
||||
|
||||
@@ -109,6 +107,8 @@ static BOOL rdpsnd_server_send_formats(rdpsnd_server* rdpsnd, STREAM* s)
|
||||
}
|
||||
|
||||
RDPSND_PDU_FINISH(s);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL rdpsnd_server_recv_formats(rdpsnd_server* rdpsnd, STREAM* s)
|
||||
@@ -172,9 +172,10 @@ static void* rdpsnd_server_thread_func(void* arg)
|
||||
|
||||
if (WTSVirtualChannelQuery(rdpsnd->rdpsnd_channel, WTSVirtualFileHandle, &buffer, &bytes_returned) == TRUE)
|
||||
{
|
||||
fd = *((void**)buffer);
|
||||
fd = *((void**) buffer);
|
||||
WTSFreeMemory(buffer);
|
||||
thread->signals[thread->num_signals++] = wait_obj_new_with_fd(fd);
|
||||
|
||||
thread->signals[thread->num_signals++] = CreateWaitObjectEvent(NULL, TRUE, FALSE, fd);
|
||||
}
|
||||
|
||||
s = stream_new(4096);
|
||||
@@ -451,7 +452,9 @@ rdpsnd_server_context* rdpsnd_server_context_new(WTSVirtualChannelManager* vcm)
|
||||
{
|
||||
rdpsnd_server* rdpsnd;
|
||||
|
||||
rdpsnd = xnew(rdpsnd_server);
|
||||
rdpsnd = (rdpsnd_server*) malloc(sizeof(rdpsnd_server));
|
||||
ZeroMemory(rdpsnd, sizeof(rdpsnd_server));
|
||||
|
||||
rdpsnd->context.vcm = vcm;
|
||||
rdpsnd->context.selected_client_format = -1;
|
||||
rdpsnd->context.Initialize = rdpsnd_server_initialize;
|
||||
|
||||
@@ -8,10 +8,6 @@ if(WITH_SAMPLE)
|
||||
set(OPTION_SERVER_DEFAULT OFF)
|
||||
endif()
|
||||
|
||||
if(${OPTION_CLIENT_DEFAULT} OR ${OPTION_SERVER_DEFAULT})
|
||||
set(OPTION_DEFAULT ON)
|
||||
endif()
|
||||
|
||||
define_channel_options(NAME "sample" TYPE "static"
|
||||
DESCRIPTION "Sample Virtual Channel Extension"
|
||||
SPECIFICATIONS ""
|
||||
|
||||
@@ -34,10 +34,8 @@
|
||||
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/constants.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/list.h>
|
||||
#include <freerdp/utils/load_plugin.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
|
||||
#include "sample_main.h"
|
||||
|
||||
@@ -13,10 +13,6 @@ if(ANDROID)
|
||||
set(OPTION_SERVER_DEFAULT OFF)
|
||||
endif()
|
||||
|
||||
if(${OPTION_CLIENT_DEFAULT} OR ${OPTION_SERVER_DEFAULT})
|
||||
set(OPTION_DEFAULT ON)
|
||||
endif()
|
||||
|
||||
define_channel_options(NAME "serial" TYPE "device"
|
||||
DESCRIPTION "Serial Port Virtual Channel Extension"
|
||||
SPECIFICATIONS "[MS-RDPESP]"
|
||||
|
||||
@@ -43,11 +43,11 @@
|
||||
#include "serial_tty.h"
|
||||
#include "serial_constants.h"
|
||||
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/thread.h>
|
||||
#include <freerdp/utils/unicode.h>
|
||||
#include <freerdp/utils/wait_obj.h>
|
||||
#include <freerdp/channels/rdpdr.h>
|
||||
|
||||
typedef struct _SERIAL_DEVICE SERIAL_DEVICE;
|
||||
@@ -62,7 +62,7 @@ struct _SERIAL_DEVICE
|
||||
LIST* irp_list;
|
||||
LIST* pending_irps;
|
||||
freerdp_thread* thread;
|
||||
struct wait_obj* in_event;
|
||||
HANDLE in_event;
|
||||
|
||||
fd_set read_fds;
|
||||
fd_set write_fds;
|
||||
@@ -80,6 +80,7 @@ static BOOL serial_check_fds(SERIAL_DEVICE* serial);
|
||||
static void serial_process_irp_create(SERIAL_DEVICE* serial, IRP* irp)
|
||||
{
|
||||
char* path;
|
||||
int status;
|
||||
SERIAL_TTY* tty;
|
||||
UINT32 PathLength;
|
||||
UINT32 FileId;
|
||||
@@ -88,7 +89,11 @@ static void serial_process_irp_create(SERIAL_DEVICE* serial, IRP* irp)
|
||||
/* SharedAccess(4) CreateDisposition(4), CreateOptions(4) */
|
||||
stream_read_UINT32(irp->input, PathLength);
|
||||
|
||||
freerdp_UnicodeToAsciiAlloc((WCHAR*) stream_get_tail(irp->input), &path, PathLength / 2);
|
||||
status = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) stream_get_tail(irp->input),
|
||||
PathLength / 2, &path, 0, NULL, NULL);
|
||||
|
||||
if (status < 1)
|
||||
path = (char*) calloc(1, 1);
|
||||
|
||||
FileId = irp->devman->id_sequence++;
|
||||
|
||||
@@ -351,10 +356,10 @@ static void* serial_thread_func(void* arg)
|
||||
freerdp_thread_reset(serial->thread);
|
||||
serial_process_irp_list(serial);
|
||||
|
||||
if (wait_obj_is_set(serial->in_event))
|
||||
if (WaitForSingleObject(serial->in_event, 0) == WAIT_OBJECT_0)
|
||||
{
|
||||
if (serial_check_fds(serial))
|
||||
wait_obj_clear(serial->in_event);
|
||||
ResetEvent(serial->in_event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -442,7 +447,7 @@ static void serial_abort_single_io(SERIAL_DEVICE* serial, UINT32 file_id, UINT32
|
||||
stream_write_UINT32(irp->output, 0);
|
||||
irp->Complete(irp);
|
||||
|
||||
wait_obj_set(serial->in_event);
|
||||
SetEvent(serial->in_event);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -480,7 +485,7 @@ static void serial_check_for_events(SERIAL_DEVICE* serial)
|
||||
irp = (IRP*) list_next(serial->pending_irps, irp);
|
||||
list_remove(serial->pending_irps, prev);
|
||||
|
||||
wait_obj_set(serial->in_event);
|
||||
SetEvent(serial->in_event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -556,7 +561,7 @@ static void serial_handle_async_irp(SERIAL_DEVICE* serial, IRP* irp)
|
||||
|
||||
irp->IoStatus = STATUS_PENDING;
|
||||
list_enqueue(serial->pending_irps, irp);
|
||||
wait_obj_set(serial->in_event);
|
||||
SetEvent(serial->in_event);
|
||||
}
|
||||
|
||||
static void __serial_check_fds(SERIAL_DEVICE* serial)
|
||||
@@ -616,7 +621,7 @@ static void __serial_check_fds(SERIAL_DEVICE* serial)
|
||||
if (prev->IoStatus == STATUS_SUCCESS)
|
||||
{
|
||||
list_remove(serial->pending_irps, prev);
|
||||
wait_obj_set(serial->in_event);
|
||||
SetEvent(serial->in_event);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -708,7 +713,8 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
|
||||
if (name[0] && path[0])
|
||||
{
|
||||
serial = xnew(SERIAL_DEVICE);
|
||||
serial = (SERIAL_DEVICE*) malloc(sizeof(SERIAL_DEVICE));
|
||||
ZeroMemory(serial, sizeof(SERIAL_DEVICE));
|
||||
|
||||
serial->device.type = RDPDR_DTYP_SERIAL;
|
||||
serial->device.name = name;
|
||||
@@ -725,9 +731,9 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
serial->irp_list = list_new();
|
||||
serial->pending_irps = list_new();
|
||||
serial->thread = freerdp_thread_new();
|
||||
serial->in_event = wait_obj_new();
|
||||
serial->in_event = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*)serial);
|
||||
pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*) serial);
|
||||
|
||||
freerdp_thread_start(serial->thread, serial_thread_func, serial);
|
||||
}
|
||||
|
||||
@@ -26,13 +26,13 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/print.h>
|
||||
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/unicode.h>
|
||||
#include <freerdp/utils/list.h>
|
||||
#include <freerdp/utils/thread.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
#include <freerdp/utils/hexdump.h>
|
||||
#include <freerdp/channels/rdpdr.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
@@ -467,31 +467,40 @@ SERIAL_TTY* serial_tty_new(const char* path, UINT32 id)
|
||||
{
|
||||
SERIAL_TTY* tty;
|
||||
|
||||
tty = xnew(SERIAL_TTY);
|
||||
tty = (SERIAL_TTY*) malloc(sizeof(SERIAL_TTY));
|
||||
ZeroMemory(tty, sizeof(SERIAL_TTY));
|
||||
|
||||
tty->id = id;
|
||||
tty->fd = open(path, O_RDWR | O_NOCTTY | O_NONBLOCK);
|
||||
|
||||
if (tty->fd < 0)
|
||||
{
|
||||
perror("open");
|
||||
DEBUG_WARN("failed to open device %s", path);
|
||||
serial_tty_free(tty) ;
|
||||
serial_tty_free(tty);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_SVC("tty fd %d successfully opened", tty->fd);
|
||||
}
|
||||
|
||||
tty->ptermios = (struct termios*) malloc(sizeof(struct termios));
|
||||
ZeroMemory(tty->ptermios, sizeof(struct termios));
|
||||
|
||||
tty->ptermios = (struct termios*) xzalloc(sizeof(struct termios));
|
||||
if (tty->ptermios == NULL)
|
||||
{
|
||||
serial_tty_free(tty) ;
|
||||
serial_tty_free(tty);
|
||||
return NULL ;
|
||||
}
|
||||
|
||||
tty->pold_termios = (struct termios*) xzalloc(sizeof(struct termios));
|
||||
tty->pold_termios = (struct termios*) malloc(sizeof(struct termios));
|
||||
ZeroMemory(tty->pold_termios, sizeof(struct termios));
|
||||
|
||||
if (tty->pold_termios == NULL)
|
||||
{
|
||||
serial_tty_free(tty) ;
|
||||
return NULL ;
|
||||
serial_tty_free(tty);
|
||||
return NULL;
|
||||
}
|
||||
tcgetattr(tty->fd, tty->pold_termios);
|
||||
|
||||
@@ -499,7 +508,7 @@ SERIAL_TTY* serial_tty_new(const char* path, UINT32 id)
|
||||
{
|
||||
DEBUG_WARN("%s access denied", path);
|
||||
fflush(stdout);
|
||||
serial_tty_free(tty) ;
|
||||
serial_tty_free(tty);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -976,6 +985,7 @@ static UINT32 tty_write_data(SERIAL_TTY* tty, BYTE* data, int len)
|
||||
DEBUG_SVC("in");
|
||||
|
||||
r = write(tty->fd, data, len);
|
||||
|
||||
if (r < 0)
|
||||
return tty_get_error_status();
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ endforeach()
|
||||
|
||||
add_library(${MODULE_NAME} STATIC ${${MODULE_PREFIX}_SRCS})
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${FREERDP_VERSION_FULL} SOVERSION ${FREERDP_VERSION} PREFIX "lib")
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${FREERDP_VERSION} SOVERSION ${FREERDP_API_VERSION} PREFIX "lib")
|
||||
|
||||
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||
|
||||
@@ -27,9 +27,9 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <freerdp/constants.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/server/channels.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/synch.h>
|
||||
|
||||
#include "channels.h"
|
||||
@@ -99,7 +99,9 @@ static void wts_queue_receive_data(rdpPeerChannel* channel, const BYTE* buffer,
|
||||
{
|
||||
wts_data_item* item;
|
||||
|
||||
item = xnew(wts_data_item);
|
||||
item = (wts_data_item*) malloc(sizeof(wts_data_item));
|
||||
ZeroMemory(item, sizeof(wts_data_item));
|
||||
|
||||
item->length = length;
|
||||
item->buffer = malloc(length);
|
||||
memcpy(item->buffer, buffer, length);
|
||||
@@ -108,7 +110,7 @@ static void wts_queue_receive_data(rdpPeerChannel* channel, const BYTE* buffer,
|
||||
list_enqueue(channel->receive_queue, item);
|
||||
ReleaseMutex(channel->mutex);
|
||||
|
||||
wait_obj_set(channel->receive_event);
|
||||
SetEvent(channel->receive_event);
|
||||
}
|
||||
|
||||
static void wts_queue_send_item(rdpPeerChannel* channel, wts_data_item* item)
|
||||
@@ -123,7 +125,7 @@ static void wts_queue_send_item(rdpPeerChannel* channel, wts_data_item* item)
|
||||
list_enqueue(vcm->send_queue, item);
|
||||
ReleaseMutex(vcm->mutex);
|
||||
|
||||
wait_obj_set(vcm->send_event);
|
||||
SetEvent(vcm->send_event);
|
||||
}
|
||||
|
||||
static int wts_read_variable_uint(STREAM* s, int cbLen, UINT32 *val)
|
||||
@@ -174,15 +176,16 @@ static void wts_read_drdynvc_create_response(rdpPeerChannel* channel, STREAM* s,
|
||||
|
||||
if ((INT32) CreationStatus < 0)
|
||||
{
|
||||
DEBUG_DVC("ChannelId %d creation failed (%d)", channel->ChannelId, (INT32)CreationStatus);
|
||||
DEBUG_DVC("ChannelId %d creation failed (%d)", channel->channel_id, (INT32) CreationStatus);
|
||||
channel->dvc_open_state = DVC_OPEN_STATE_FAILED;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_DVC("ChannelId %d creation succeeded", channel->ChannelId);
|
||||
DEBUG_DVC("ChannelId %d creation succeeded", channel->channel_id);
|
||||
channel->dvc_open_state = DVC_OPEN_STATE_SUCCEEDED;
|
||||
}
|
||||
wait_obj_set(channel->receive_event);
|
||||
|
||||
SetEvent(channel->receive_event);
|
||||
}
|
||||
|
||||
static void wts_read_drdynvc_data_first(rdpPeerChannel* channel, STREAM* s, int cbLen, UINT32 length)
|
||||
@@ -231,7 +234,7 @@ static void wts_read_drdynvc_data(rdpPeerChannel* channel, STREAM* s, UINT32 len
|
||||
|
||||
static void wts_read_drdynvc_close_response(rdpPeerChannel* channel)
|
||||
{
|
||||
DEBUG_DVC("ChannelId %d close response", channel->ChannelId);
|
||||
DEBUG_DVC("ChannelId %d close response", channel->channel_id);
|
||||
channel->dvc_open_state = DVC_OPEN_STATE_CLOSED;
|
||||
}
|
||||
|
||||
@@ -411,12 +414,14 @@ WTSVirtualChannelManager* WTSCreateVirtualChannelManager(freerdp_peer* client)
|
||||
{
|
||||
WTSVirtualChannelManager* vcm;
|
||||
|
||||
vcm = xnew(WTSVirtualChannelManager);
|
||||
vcm = (WTSVirtualChannelManager*) malloc(sizeof(WTSVirtualChannelManager));
|
||||
|
||||
if (vcm != NULL)
|
||||
{
|
||||
ZeroMemory(vcm, sizeof(WTSVirtualChannelManager));
|
||||
|
||||
vcm->client = client;
|
||||
vcm->send_event = wait_obj_new();
|
||||
vcm->send_event = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
vcm->send_queue = list_new();
|
||||
vcm->mutex = CreateMutex(NULL, FALSE, NULL);
|
||||
vcm->dvc_channel_id_seq = 1;
|
||||
@@ -448,7 +453,7 @@ void WTSDestroyVirtualChannelManager(WTSVirtualChannelManager* vcm)
|
||||
vcm->drdynvc_channel = NULL;
|
||||
}
|
||||
|
||||
wait_obj_free(vcm->send_event);
|
||||
CloseHandle(vcm->send_event);
|
||||
|
||||
while ((item = (wts_data_item*) list_dequeue(vcm->send_queue)) != NULL)
|
||||
{
|
||||
@@ -464,11 +469,25 @@ void WTSDestroyVirtualChannelManager(WTSVirtualChannelManager* vcm)
|
||||
void WTSVirtualChannelManagerGetFileDescriptor(WTSVirtualChannelManager* vcm,
|
||||
void** fds, int* fds_count)
|
||||
{
|
||||
wait_obj_get_fds(vcm->send_event, fds, fds_count);
|
||||
void* fd;
|
||||
|
||||
fd = GetEventWaitObject(vcm->send_event);
|
||||
|
||||
if (fd)
|
||||
{
|
||||
fds[*fds_count] = fd;
|
||||
(*fds_count)++;
|
||||
}
|
||||
|
||||
if (vcm->drdynvc_channel)
|
||||
{
|
||||
wait_obj_get_fds(vcm->drdynvc_channel->receive_event, fds, fds_count);
|
||||
fd = GetEventWaitObject(vcm->drdynvc_channel->receive_event);
|
||||
|
||||
if (fd)
|
||||
{
|
||||
fds[*fds_count] = fd;
|
||||
(*fds_count)++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -494,7 +513,7 @@ BOOL WTSVirtualChannelManagerCheckFileDescriptor(WTSVirtualChannelManager* vcm)
|
||||
}
|
||||
}
|
||||
|
||||
wait_obj_clear(vcm->send_event);
|
||||
ResetEvent(vcm->send_event);
|
||||
|
||||
WaitForSingleObject(vcm->mutex, INFINITE);
|
||||
|
||||
@@ -535,12 +554,14 @@ void* WTSVirtualChannelOpenEx(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
channel = xnew(rdpPeerChannel);
|
||||
channel = (rdpPeerChannel*) malloc(sizeof(rdpPeerChannel));
|
||||
ZeroMemory(channel, sizeof(rdpPeerChannel));
|
||||
|
||||
channel->vcm = vcm;
|
||||
channel->client = client;
|
||||
channel->channel_type = RDP_PEER_CHANNEL_TYPE_DVC;
|
||||
channel->receive_data = stream_new(client->settings->VirtualChannelChunkSize);
|
||||
channel->receive_event = wait_obj_new();
|
||||
channel->receive_event = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
channel->receive_queue = list_new();
|
||||
channel->mutex = CreateMutex(NULL, FALSE, NULL);
|
||||
|
||||
@@ -554,7 +575,7 @@ void* WTSVirtualChannelOpenEx(
|
||||
WTSVirtualChannelWrite(vcm->drdynvc_channel, stream_get_head(s), stream_get_length(s), NULL);
|
||||
stream_free(s);
|
||||
|
||||
DEBUG_DVC("ChannelId %d.%s (total %d)", channel->ChannelId, pVirtualName, list_size(vcm->dvc_channel_list));
|
||||
DEBUG_DVC("ChannelId %d.%s (total %d)", channel->channel_id, pVirtualName, list_size(vcm->dvc_channel_list));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -579,14 +600,16 @@ void* WTSVirtualChannelOpenEx(
|
||||
|
||||
if (channel == NULL)
|
||||
{
|
||||
channel = xnew(rdpPeerChannel);
|
||||
channel = (rdpPeerChannel*) malloc(sizeof(rdpPeerChannel));
|
||||
ZeroMemory(channel, sizeof(rdpPeerChannel));
|
||||
|
||||
channel->vcm = vcm;
|
||||
channel->client = client;
|
||||
channel->channel_id = client->settings->ChannelDefArray[i].ChannelId;
|
||||
channel->index = i;
|
||||
channel->channel_type = RDP_PEER_CHANNEL_TYPE_SVC;
|
||||
channel->receive_data = stream_new(client->settings->VirtualChannelChunkSize);
|
||||
channel->receive_event = wait_obj_new();
|
||||
channel->receive_event = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
channel->receive_queue = list_new();
|
||||
channel->mutex = CreateMutex(NULL, FALSE, NULL);
|
||||
|
||||
@@ -603,6 +626,7 @@ BOOL WTSVirtualChannelQuery(
|
||||
/* __out */ void** ppBuffer,
|
||||
/* __out */ UINT32* pBytesReturned)
|
||||
{
|
||||
void* pfd;
|
||||
BOOL bval;
|
||||
void* fds[10];
|
||||
int fds_count = 0;
|
||||
@@ -612,7 +636,15 @@ BOOL WTSVirtualChannelQuery(
|
||||
switch (WtsVirtualClass)
|
||||
{
|
||||
case WTSVirtualFileHandle:
|
||||
wait_obj_get_fds(channel->receive_event, fds, &fds_count);
|
||||
|
||||
pfd = GetEventWaitObject(channel->receive_event);
|
||||
|
||||
if (pfd)
|
||||
{
|
||||
fds[fds_count] = pfd;
|
||||
(fds_count)++;
|
||||
}
|
||||
|
||||
*ppBuffer = malloc(sizeof(void*));
|
||||
memcpy(*ppBuffer, &fds[0], sizeof(void*));
|
||||
*pBytesReturned = sizeof(void*);
|
||||
@@ -674,7 +706,7 @@ BOOL WTSVirtualChannelRead(
|
||||
|
||||
if (item == NULL)
|
||||
{
|
||||
wait_obj_clear(channel->receive_event);
|
||||
ResetEvent(channel->receive_event);
|
||||
*pBytesRead = 0;
|
||||
return TRUE;
|
||||
}
|
||||
@@ -689,7 +721,7 @@ BOOL WTSVirtualChannelRead(
|
||||
list_dequeue(channel->receive_queue);
|
||||
|
||||
if (list_size(channel->receive_queue) == 0)
|
||||
wait_obj_clear(channel->receive_event);
|
||||
ResetEvent(channel->receive_event);
|
||||
|
||||
ReleaseMutex(channel->mutex);
|
||||
|
||||
@@ -718,7 +750,9 @@ BOOL WTSVirtualChannelWrite(
|
||||
|
||||
if (channel->channel_type == RDP_PEER_CHANNEL_TYPE_SVC)
|
||||
{
|
||||
item = xnew(wts_data_item);
|
||||
item = (wts_data_item*) malloc(sizeof(wts_data_item));
|
||||
ZeroMemory(item, sizeof(wts_data_item));
|
||||
|
||||
item->buffer = malloc(Length);
|
||||
item->length = Length;
|
||||
memcpy(item->buffer, Buffer, Length);
|
||||
@@ -737,7 +771,9 @@ BOOL WTSVirtualChannelWrite(
|
||||
|
||||
while (Length > 0)
|
||||
{
|
||||
item = xnew(wts_data_item);
|
||||
item = (wts_data_item*) malloc(sizeof(wts_data_item));
|
||||
ZeroMemory(item, sizeof(wts_data_item));
|
||||
|
||||
item->buffer = malloc(channel->client->settings->VirtualChannelChunkSize);
|
||||
stream_attach(s, item->buffer, channel->client->settings->VirtualChannelChunkSize);
|
||||
|
||||
@@ -813,7 +849,7 @@ BOOL WTSVirtualChannelClose(
|
||||
stream_free(channel->receive_data);
|
||||
|
||||
if (channel->receive_event)
|
||||
wait_obj_free(channel->receive_event);
|
||||
CloseHandle(channel->receive_event);
|
||||
|
||||
if (channel->receive_queue)
|
||||
{
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/list.h>
|
||||
#include <freerdp/utils/debug.h>
|
||||
#include <freerdp/utils/wait_obj.h>
|
||||
#include <freerdp/channels/wtsvc.h>
|
||||
|
||||
#include <winpr/synch.h>
|
||||
@@ -58,6 +57,7 @@ enum
|
||||
};
|
||||
|
||||
typedef struct rdp_peer_channel rdpPeerChannel;
|
||||
|
||||
struct rdp_peer_channel
|
||||
{
|
||||
WTSVirtualChannelManager* vcm;
|
||||
@@ -67,7 +67,7 @@ struct rdp_peer_channel
|
||||
UINT16 index;
|
||||
|
||||
STREAM* receive_data;
|
||||
struct wait_obj* receive_event;
|
||||
HANDLE receive_event;
|
||||
LIST* receive_queue;
|
||||
HANDLE mutex;
|
||||
|
||||
@@ -78,7 +78,7 @@ struct rdp_peer_channel
|
||||
struct WTSVirtualChannelManager
|
||||
{
|
||||
freerdp_peer* client;
|
||||
struct wait_obj* send_event;
|
||||
HANDLE send_event;
|
||||
LIST* send_queue;
|
||||
HANDLE mutex;
|
||||
|
||||
|
||||
@@ -8,10 +8,6 @@ if(WITH_PCSC)
|
||||
set(OPTION_SERVER_DEFAULT OFF)
|
||||
endif()
|
||||
|
||||
if(${OPTION_CLIENT_DEFAULT} OR ${OPTION_SERVER_DEFAULT})
|
||||
set(OPTION_DEFAULT ON)
|
||||
endif()
|
||||
|
||||
define_channel_options(NAME "smartcard" TYPE "device"
|
||||
DESCRIPTION "Smart Card Virtual Channel Extension"
|
||||
SPECIFICATIONS "[MS-RDPESC]"
|
||||
|
||||
@@ -18,8 +18,9 @@
|
||||
define_channel_client("smartcard")
|
||||
|
||||
set(${MODULE_PREFIX}_SRCS
|
||||
scard_main.c
|
||||
scard_operations.c)
|
||||
smartcard_main.c
|
||||
smartcard_main.h
|
||||
smartcard_operations.c)
|
||||
|
||||
include_directories(${PCSC_INCLUDE_DIR})
|
||||
|
||||
@@ -46,3 +47,4 @@ if(NOT STATIC_CHANNELS)
|
||||
endif()
|
||||
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")
|
||||
|
||||
|
||||
@@ -27,47 +27,49 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <freerdp/utils/list.h>
|
||||
#include <freerdp/utils/thread.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
#include <freerdp/utils/debug.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
|
||||
#include <freerdp/channels/rdpdr.h>
|
||||
|
||||
#include "scard_main.h"
|
||||
#include "smartcard_main.h"
|
||||
|
||||
static void scard_free(DEVICE* dev)
|
||||
static void smartcard_free(DEVICE* dev)
|
||||
{
|
||||
IRP* irp;
|
||||
COMPLETIONIDINFO* CompletionIdInfo;
|
||||
SCARD_DEVICE* scard = (SCARD_DEVICE*) dev;
|
||||
SMARTCARD_DEVICE* smartcard = (SMARTCARD_DEVICE*) dev;
|
||||
|
||||
freerdp_thread_stop(scard->thread);
|
||||
freerdp_thread_free(scard->thread);
|
||||
SetEvent(smartcard->stopEvent);
|
||||
CloseHandle(smartcard->thread);
|
||||
CloseHandle(smartcard->irpEvent);
|
||||
|
||||
while ((irp = (IRP*) InterlockedPopEntrySList(scard->pIrpList)) != NULL)
|
||||
while ((irp = (IRP*) InterlockedPopEntrySList(smartcard->pIrpList)) != NULL)
|
||||
irp->Discard(irp);
|
||||
|
||||
_aligned_free(scard->pIrpList);
|
||||
_aligned_free(smartcard->pIrpList);
|
||||
|
||||
/* Begin TS Client defect workaround. */
|
||||
|
||||
while ((CompletionIdInfo = (COMPLETIONIDINFO*) list_dequeue(scard->CompletionIds)) != NULL)
|
||||
while ((CompletionIdInfo = (COMPLETIONIDINFO*) list_dequeue(smartcard->CompletionIds)) != NULL)
|
||||
free(CompletionIdInfo);
|
||||
|
||||
list_free(scard->CompletionIds);
|
||||
list_free(smartcard->CompletionIds);
|
||||
|
||||
/* End TS Client defect workaround. */
|
||||
|
||||
free(dev);
|
||||
return;
|
||||
}
|
||||
|
||||
static void scard_process_irp(SCARD_DEVICE* scard, IRP* irp)
|
||||
static void smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
||||
{
|
||||
switch (irp->MajorFunction)
|
||||
{
|
||||
case IRP_MJ_DEVICE_CONTROL:
|
||||
scard_device_control(scard, irp);
|
||||
smartcard_device_control(smartcard, irp);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -79,77 +81,83 @@ static void scard_process_irp(SCARD_DEVICE* scard, IRP* irp)
|
||||
}
|
||||
}
|
||||
|
||||
static void scard_process_irp_list(SCARD_DEVICE* scard)
|
||||
static void smartcard_process_irp_list(SMARTCARD_DEVICE* smartcard)
|
||||
{
|
||||
IRP* irp;
|
||||
|
||||
while (!freerdp_thread_is_stopped(scard->thread))
|
||||
while (1)
|
||||
{
|
||||
irp = (IRP*) InterlockedPopEntrySList(scard->pIrpList);
|
||||
if (WaitForSingleObject(smartcard->stopEvent, 0) == WAIT_OBJECT_0)
|
||||
break;
|
||||
|
||||
irp = (IRP*) InterlockedPopEntrySList(smartcard->pIrpList);
|
||||
|
||||
if (irp == NULL)
|
||||
break;
|
||||
|
||||
scard_process_irp(scard, irp);
|
||||
smartcard_process_irp(smartcard, irp);
|
||||
}
|
||||
}
|
||||
|
||||
struct scard_irp_thread_args
|
||||
struct _SMARTCARD_IRP_WORKER
|
||||
{
|
||||
SCARD_DEVICE* scard;
|
||||
SMARTCARD_DEVICE* smartcard;
|
||||
IRP* irp;
|
||||
freerdp_thread* thread;
|
||||
HANDLE thread;
|
||||
};
|
||||
typedef struct _SMARTCARD_IRP_WORKER SMARTCARD_IRP_WORKER;
|
||||
|
||||
static void scard_process_irp_thread_func(struct scard_irp_thread_args* args)
|
||||
static void smartcard_process_irp_thread_func(SMARTCARD_IRP_WORKER* irpWorker)
|
||||
{
|
||||
scard_process_irp(args->scard, args->irp);
|
||||
smartcard_process_irp(irpWorker->smartcard, irpWorker->irp);
|
||||
|
||||
freerdp_thread_free(args->thread);
|
||||
free(args);
|
||||
CloseHandle(irpWorker->thread);
|
||||
|
||||
free(irpWorker);
|
||||
}
|
||||
|
||||
static void* scard_thread_func(void* arg)
|
||||
static void* smartcard_thread_func(void* arg)
|
||||
{
|
||||
SCARD_DEVICE* scard = (SCARD_DEVICE*) arg;
|
||||
SMARTCARD_DEVICE* smartcard = (SMARTCARD_DEVICE*) arg;
|
||||
|
||||
while (1)
|
||||
{
|
||||
freerdp_thread_wait(scard->thread);
|
||||
WaitForSingleObject(smartcard->irpEvent, INFINITE);
|
||||
|
||||
if (freerdp_thread_is_stopped(scard->thread))
|
||||
if (WaitForSingleObject(smartcard->stopEvent, 0) == WAIT_OBJECT_0)
|
||||
break;
|
||||
|
||||
freerdp_thread_reset(scard->thread);
|
||||
scard_process_irp_list(scard);
|
||||
ResetEvent(smartcard->irpEvent);
|
||||
smartcard_process_irp_list(smartcard);
|
||||
}
|
||||
|
||||
freerdp_thread_quit(scard->thread);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Begin TS Client defect workaround. */
|
||||
static COMPLETIONIDINFO* scard_mark_duplicate_id(SCARD_DEVICE* scard, UINT32 CompletionId)
|
||||
static COMPLETIONIDINFO* smartcard_mark_duplicate_id(SMARTCARD_DEVICE* smartcard, UINT32 CompletionId)
|
||||
{
|
||||
LIST_ITEM* item;
|
||||
COMPLETIONIDINFO* CompletionIdInfo;
|
||||
|
||||
/*
|
||||
* Search from the beginning of the LIST for one outstanding "CompletionID"
|
||||
* that matches the one passed in. If there is one, mark it as a duplicate
|
||||
* if it is not already marked.
|
||||
*/
|
||||
LIST_ITEM* item;
|
||||
COMPLETIONIDINFO* CompletionIdInfo;
|
||||
|
||||
for (item = scard->CompletionIds->head; item; item = item->next)
|
||||
for (item = smartcard->CompletionIds->head; item; item = item->next)
|
||||
{
|
||||
CompletionIdInfo = (COMPLETIONIDINFO*)item->data;
|
||||
CompletionIdInfo = (COMPLETIONIDINFO*) item->data;
|
||||
|
||||
if (CompletionIdInfo->ID == CompletionId)
|
||||
{
|
||||
if (FALSE == CompletionIdInfo->duplicate)
|
||||
if (!CompletionIdInfo->duplicate)
|
||||
{
|
||||
CompletionIdInfo->duplicate = TRUE;
|
||||
DEBUG_WARN("CompletionID number %u is now marked as a duplicate.", CompletionId);
|
||||
}
|
||||
|
||||
return CompletionIdInfo;
|
||||
}
|
||||
}
|
||||
@@ -157,30 +165,35 @@ static COMPLETIONIDINFO* scard_mark_duplicate_id(SCARD_DEVICE* scard, UINT32 Com
|
||||
return NULL; /* Either no items in the list or no match. */
|
||||
}
|
||||
|
||||
static BOOL scard_check_for_duplicate_id(SCARD_DEVICE* scard, UINT32 CompletionId)
|
||||
static BOOL smartcard_check_for_duplicate_id(SMARTCARD_DEVICE* smartcard, UINT32 CompletionId)
|
||||
{
|
||||
BOOL duplicate;
|
||||
LIST_ITEM* item;
|
||||
COMPLETIONIDINFO* CompletionIdInfo;
|
||||
|
||||
/*
|
||||
* Search from the end of the LIST for one outstanding "CompletionID"
|
||||
* that matches the one passed in. Remove it from the list and free the
|
||||
* memory associated with it. Return whether or not it was marked
|
||||
* as a duplicate.
|
||||
*/
|
||||
LIST_ITEM* item;
|
||||
COMPLETIONIDINFO* CompletionIdInfo;
|
||||
BOOL duplicate;
|
||||
|
||||
for (item = scard->CompletionIds->tail; item; item = item->prev)
|
||||
for (item = smartcard->CompletionIds->tail; item; item = item->prev)
|
||||
{
|
||||
CompletionIdInfo = (COMPLETIONIDINFO*)item->data;
|
||||
CompletionIdInfo = (COMPLETIONIDINFO*) item->data;
|
||||
|
||||
if (CompletionIdInfo->ID == CompletionId)
|
||||
{
|
||||
duplicate = CompletionIdInfo->duplicate;
|
||||
if (TRUE == duplicate)
|
||||
|
||||
if (duplicate)
|
||||
{
|
||||
DEBUG_WARN("CompletionID number %u was previously marked as a duplicate. The response to the command is removed.", CompletionId);
|
||||
DEBUG_WARN("CompletionID number %u was previously marked as a duplicate.", CompletionId);
|
||||
}
|
||||
list_remove(scard->CompletionIds, CompletionIdInfo);
|
||||
|
||||
list_remove(smartcard->CompletionIds, CompletionIdInfo);
|
||||
free(CompletionIdInfo);
|
||||
|
||||
return duplicate;
|
||||
}
|
||||
}
|
||||
@@ -193,16 +206,17 @@ static BOOL scard_check_for_duplicate_id(SCARD_DEVICE* scard, UINT32 Completion
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void scard_irp_complete(IRP* irp)
|
||||
static void smartcard_irp_complete(IRP* irp)
|
||||
{
|
||||
int pos;
|
||||
BOOL duplicate;
|
||||
SMARTCARD_DEVICE* smartcard = (SMARTCARD_DEVICE*) irp->device;
|
||||
|
||||
/* This function is (mostly) a copy of the statically-declared "irp_complete()"
|
||||
* function except that this function adds extra operations for the
|
||||
* smart card's handling of duplicate "CompletionID"s. This function needs
|
||||
* to be in this file so that "scard_irp_request()" can reference it.
|
||||
* to be in this file so that "smartcard_irp_request()" can reference it.
|
||||
*/
|
||||
int pos;
|
||||
BOOL duplicate;
|
||||
SCARD_DEVICE* scard = (SCARD_DEVICE*)irp->device;
|
||||
|
||||
DEBUG_SVC("DeviceId %d FileId %d CompletionId %d", irp->device->id, irp->FileId, irp->CompletionId);
|
||||
|
||||
@@ -212,18 +226,19 @@ static void scard_irp_complete(IRP* irp)
|
||||
stream_set_pos(irp->output, pos);
|
||||
|
||||
/* Begin TS Client defect workaround. */
|
||||
WaitForSingleObject(scard->CompletionIdsMutex, INFINITE);
|
||||
WaitForSingleObject(smartcard->CompletionIdsMutex, INFINITE);
|
||||
/* Remove from the list the item identified by the CompletionID.
|
||||
* The function returns whether or not it was a duplicate CompletionID.
|
||||
*/
|
||||
duplicate = scard_check_for_duplicate_id(scard, irp->CompletionId);
|
||||
ReleaseMutex(scard->CompletionIdsMutex);
|
||||
duplicate = smartcard_check_for_duplicate_id(smartcard, irp->CompletionId);
|
||||
ReleaseMutex(smartcard->CompletionIdsMutex);
|
||||
|
||||
if (FALSE == duplicate)
|
||||
if (!duplicate)
|
||||
{
|
||||
svc_plugin_send(irp->devman->plugin, irp->output);
|
||||
irp->output = NULL;
|
||||
}
|
||||
|
||||
/* End TS Client defect workaround. */
|
||||
|
||||
/* irp_free(irp); The "irp_free()" function is statically-declared
|
||||
@@ -237,49 +252,48 @@ static void scard_irp_complete(IRP* irp)
|
||||
}
|
||||
/* End TS Client defect workaround. */
|
||||
|
||||
static void scard_irp_request(DEVICE* device, IRP* irp)
|
||||
static void smartcard_irp_request(DEVICE* device, IRP* irp)
|
||||
{
|
||||
COMPLETIONIDINFO* CompletionIdInfo;
|
||||
SCARD_DEVICE* scard = (SCARD_DEVICE*) device;
|
||||
SMARTCARD_DEVICE* smartcard = (SMARTCARD_DEVICE*) device;
|
||||
|
||||
/* Begin TS Client defect workaround. */
|
||||
CompletionIdInfo= xnew(COMPLETIONIDINFO);
|
||||
CompletionIdInfo->ID = irp->CompletionId;/* "duplicate" member is set
|
||||
* to FALSE by "xnew()"
|
||||
*/
|
||||
WaitForSingleObject(scard->CompletionIdsMutex, INFINITE);
|
||||
scard_mark_duplicate_id(scard, irp->CompletionId);
|
||||
list_enqueue(scard->CompletionIds, CompletionIdInfo);
|
||||
ReleaseMutex(scard->CompletionIdsMutex);
|
||||
|
||||
irp->Complete = scard_irp_complete; /* Overwrite the previous
|
||||
* assignment made in
|
||||
* "irp_new()".
|
||||
*/
|
||||
CompletionIdInfo = (COMPLETIONIDINFO*) malloc(sizeof(COMPLETIONIDINFO));
|
||||
ZeroMemory(CompletionIdInfo, sizeof(COMPLETIONIDINFO));
|
||||
|
||||
CompletionIdInfo->ID = irp->CompletionId;
|
||||
|
||||
WaitForSingleObject(smartcard->CompletionIdsMutex, INFINITE);
|
||||
smartcard_mark_duplicate_id(smartcard, irp->CompletionId);
|
||||
list_enqueue(smartcard->CompletionIds, CompletionIdInfo);
|
||||
ReleaseMutex(smartcard->CompletionIdsMutex);
|
||||
|
||||
/* Overwrite the previous assignment made in irp_new() */
|
||||
irp->Complete = smartcard_irp_complete;
|
||||
|
||||
/* End TS Client defect workaround. */
|
||||
|
||||
if (irp->MajorFunction == IRP_MJ_DEVICE_CONTROL &&
|
||||
scard_async_op(irp))
|
||||
if ((irp->MajorFunction == IRP_MJ_DEVICE_CONTROL) && smartcard_async_op(irp))
|
||||
{
|
||||
/*
|
||||
* certain potentially long running operations
|
||||
* get their own thread
|
||||
* TODO: revise this mechanism.. maybe worker pool
|
||||
*/
|
||||
struct scard_irp_thread_args *args = malloc(sizeof(struct scard_irp_thread_args));
|
||||
/* certain potentially long running operations get their own thread */
|
||||
SMARTCARD_IRP_WORKER* irpWorker = malloc(sizeof(SMARTCARD_IRP_WORKER));
|
||||
|
||||
irpWorker->thread = CreateThread(NULL, 0,
|
||||
(LPTHREAD_START_ROUTINE) smartcard_process_irp_thread_func,
|
||||
irpWorker, CREATE_SUSPENDED, NULL);
|
||||
|
||||
args->thread = freerdp_thread_new();
|
||||
args->scard = scard;
|
||||
args->irp = irp;
|
||||
freerdp_thread_start(args->thread, scard_process_irp_thread_func, args);
|
||||
irpWorker->smartcard = smartcard;
|
||||
irpWorker->irp = irp;
|
||||
|
||||
ResumeThread(irpWorker->thread);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
InterlockedPushEntrySList(scard->pIrpList, &(irp->ItemEntry));
|
||||
InterlockedPushEntrySList(smartcard->pIrpList, &(irp->ItemEntry));
|
||||
|
||||
freerdp_thread_signal(scard->thread);
|
||||
SetEvent(smartcard->irpEvent);
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
@@ -292,7 +306,7 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
char* path;
|
||||
int i, length;
|
||||
RDPDR_SMARTCARD* device;
|
||||
SCARD_DEVICE* scard;
|
||||
SMARTCARD_DEVICE* smartcard;
|
||||
|
||||
device = (RDPDR_SMARTCARD*) pEntryPoints->device;
|
||||
name = device->Name;
|
||||
@@ -302,33 +316,38 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
{
|
||||
/* TODO: check if server supports sc redirect (version 5.1) */
|
||||
|
||||
scard = xnew(SCARD_DEVICE);
|
||||
smartcard = (SMARTCARD_DEVICE*) malloc(sizeof(SMARTCARD_DEVICE));
|
||||
ZeroMemory(smartcard, sizeof(SMARTCARD_DEVICE));
|
||||
|
||||
scard->device.type = RDPDR_DTYP_SMARTCARD;
|
||||
scard->device.name = "SCARD";
|
||||
scard->device.IRPRequest = scard_irp_request;
|
||||
scard->device.Free = scard_free;
|
||||
smartcard->device.type = RDPDR_DTYP_SMARTCARD;
|
||||
smartcard->device.name = "SCARD";
|
||||
smartcard->device.IRPRequest = smartcard_irp_request;
|
||||
smartcard->device.Free = smartcard_free;
|
||||
|
||||
length = strlen(scard->device.name);
|
||||
scard->device.data = stream_new(length + 1);
|
||||
length = strlen(smartcard->device.name);
|
||||
smartcard->device.data = stream_new(length + 1);
|
||||
|
||||
for (i = 0; i <= length; i++)
|
||||
stream_write_BYTE(scard->device.data, name[i] < 0 ? '_' : name[i]);
|
||||
stream_write_BYTE(smartcard->device.data, name[i] < 0 ? '_' : name[i]);
|
||||
|
||||
scard->path = path;
|
||||
smartcard->path = path;
|
||||
|
||||
scard->pIrpList = (PSLIST_HEADER) _aligned_malloc(sizeof(SLIST_HEADER), MEMORY_ALLOCATION_ALIGNMENT);
|
||||
InitializeSListHead(scard->pIrpList);
|
||||
smartcard->pIrpList = (PSLIST_HEADER) _aligned_malloc(sizeof(SLIST_HEADER), MEMORY_ALLOCATION_ALIGNMENT);
|
||||
InitializeSListHead(smartcard->pIrpList);
|
||||
|
||||
scard->thread = freerdp_thread_new();
|
||||
smartcard->irpEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
smartcard->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
smartcard->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) smartcard_thread_func,
|
||||
smartcard, CREATE_SUSPENDED, NULL);
|
||||
|
||||
scard->CompletionIds = list_new();
|
||||
scard->CompletionIdsMutex = CreateMutex(NULL, FALSE, NULL);
|
||||
smartcard->CompletionIds = list_new();
|
||||
smartcard->CompletionIdsMutex = CreateMutex(NULL, FALSE, NULL);
|
||||
|
||||
pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE *)scard);
|
||||
pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*) smartcard);
|
||||
|
||||
freerdp_thread_start(scard->thread, scard_thread_func, scard);
|
||||
ResumeThread(smartcard->thread);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __SCARD_MAIN_H
|
||||
#define __SCARD_MAIN_H
|
||||
#ifndef FREERDP_CHANNEL_SMARTCARD_CLIENT_MAIN_H
|
||||
#define FREERDP_CHANNEL_SMARTCARD_CLIENT_MAIN_H
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <freerdp/utils/debug.h>
|
||||
#include <freerdp/channels/rdpdr.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/synch.h>
|
||||
|
||||
/*
|
||||
@@ -81,6 +82,7 @@
|
||||
* This structure tracks outstanding Terminal Services server "CompletionIDs"
|
||||
* used by the redirected smart card device.
|
||||
*/
|
||||
|
||||
struct _COMPLETIONIDINFO
|
||||
{
|
||||
UINT32 ID; /* CompletionID */
|
||||
@@ -89,11 +91,9 @@ struct _COMPLETIONIDINFO
|
||||
* earlier, outstanding, CompletionID.
|
||||
*/
|
||||
};
|
||||
|
||||
typedef struct _COMPLETIONIDINFO COMPLETIONIDINFO;
|
||||
|
||||
|
||||
struct _SCARD_DEVICE
|
||||
struct _SMARTCARD_DEVICE
|
||||
{
|
||||
DEVICE device;
|
||||
|
||||
@@ -102,12 +102,14 @@ struct _SCARD_DEVICE
|
||||
|
||||
PSLIST_HEADER pIrpList;
|
||||
|
||||
freerdp_thread* thread;
|
||||
HANDLE thread;
|
||||
HANDLE irpEvent;
|
||||
HANDLE stopEvent;
|
||||
|
||||
LIST* CompletionIds;
|
||||
HANDLE CompletionIdsMutex;
|
||||
};
|
||||
typedef struct _SCARD_DEVICE SCARD_DEVICE;
|
||||
typedef struct _SMARTCARD_DEVICE SMARTCARD_DEVICE;
|
||||
|
||||
#ifdef WITH_DEBUG_SCARD
|
||||
#define DEBUG_SCARD(fmt, ...) DEBUG_CLASS(SCARD, fmt, ## __VA_ARGS__)
|
||||
@@ -115,7 +117,7 @@ typedef struct _SCARD_DEVICE SCARD_DEVICE;
|
||||
#define DEBUG_SCARD(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
BOOL scard_async_op(IRP*);
|
||||
void scard_device_control(SCARD_DEVICE*, IRP*);
|
||||
BOOL smartcard_async_op(IRP*);
|
||||
void smartcard_device_control(SMARTCARD_DEVICE*, IRP*);
|
||||
|
||||
#endif
|
||||
#endif /* FREERDP_CHANNEL_SMARTCARD_CLIENT_MAIN_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -20,5 +20,3 @@ define_channel("tsmf")
|
||||
if(WITH_CLIENT_CHANNELS)
|
||||
add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME})
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
@@ -13,10 +13,6 @@ if(ANDROID)
|
||||
set(OPTION_SERVER_DEFAULT OFF)
|
||||
endif()
|
||||
|
||||
if(${OPTION_CLIENT_DEFAULT} OR ${OPTION_SERVER_DEFAULT})
|
||||
set(OPTION_DEFAULT ON)
|
||||
endif()
|
||||
|
||||
define_channel_options(NAME "tsmf" TYPE "dynamic"
|
||||
DESCRIPTION "Video Redirection Virtual Channel Extension"
|
||||
SPECIFICATIONS "[MS-RDPEV]"
|
||||
|
||||
@@ -43,7 +43,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-utils freerdp-common)
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
@@ -54,19 +54,19 @@ endif()
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")
|
||||
|
||||
if(WITH_FFMPEG)
|
||||
add_subdirectory(ffmpeg)
|
||||
add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "ffmpeg" "decoder")
|
||||
endif()
|
||||
|
||||
if(WITH_XRANDR)
|
||||
if(GSTREAMER_FOUND)
|
||||
add_subdirectory(gstreamer)
|
||||
add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "gstreamer" "decoder")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_ALSA)
|
||||
add_subdirectory(alsa)
|
||||
add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "alsa" "audio")
|
||||
endif()
|
||||
|
||||
if(WITH_PULSE)
|
||||
add_subdirectory(pulse)
|
||||
add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "pulse" "audio")
|
||||
endif()
|
||||
|
||||
@@ -23,7 +23,7 @@ set(${MODULE_PREFIX}_SRCS
|
||||
include_directories(..)
|
||||
include_directories(${ALSA_INCLUDE_DIRS})
|
||||
|
||||
add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
|
||||
|
||||
@@ -36,6 +36,6 @@ set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${ALSA_LIBRARIES})
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_PLUGIN_PATH})
|
||||
|
||||
|
||||
if(NOT STATIC_CHANNELS)
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH})
|
||||
endif()
|
||||
|
||||
@@ -26,9 +26,12 @@
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <alsa/asoundlib.h>
|
||||
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/dsp.h>
|
||||
|
||||
#include "tsmf_audio.h"
|
||||
@@ -46,13 +49,14 @@ typedef struct _TSMFALSAAudioDevice
|
||||
UINT32 bytes_per_sample;
|
||||
|
||||
FREERDP_DSP_CONTEXT* dsp_context;
|
||||
} TSMFALSAAudioDevice;
|
||||
} TSMFAlsaAudioDevice;
|
||||
|
||||
static BOOL tsmf_alsa_open_device(TSMFALSAAudioDevice* alsa)
|
||||
static BOOL tsmf_alsa_open_device(TSMFAlsaAudioDevice* alsa)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = snd_pcm_open(&alsa->out_handle, alsa->device, SND_PCM_STREAM_PLAYBACK, 0);
|
||||
|
||||
if (error < 0)
|
||||
{
|
||||
DEBUG_WARN("failed to open device %s", alsa->device);
|
||||
@@ -65,7 +69,7 @@ static BOOL tsmf_alsa_open_device(TSMFALSAAudioDevice* alsa)
|
||||
|
||||
static BOOL tsmf_alsa_open(ITSMFAudioDevice* audio, const char* device)
|
||||
{
|
||||
TSMFALSAAudioDevice* alsa = (TSMFALSAAudioDevice*) audio;
|
||||
TSMFAlsaAudioDevice* alsa = (TSMFAlsaAudioDevice*) audio;
|
||||
|
||||
if (!device)
|
||||
{
|
||||
@@ -87,7 +91,7 @@ static BOOL tsmf_alsa_set_format(ITSMFAudioDevice* audio,
|
||||
snd_pcm_uframes_t frames;
|
||||
snd_pcm_hw_params_t* hw_params;
|
||||
snd_pcm_sw_params_t* sw_params;
|
||||
TSMFALSAAudioDevice* alsa = (TSMFALSAAudioDevice*) audio;
|
||||
TSMFAlsaAudioDevice* alsa = (TSMFAlsaAudioDevice*) audio;
|
||||
|
||||
if (!alsa->out_handle)
|
||||
return FALSE;
|
||||
@@ -99,11 +103,13 @@ static BOOL tsmf_alsa_set_format(ITSMFAudioDevice* audio,
|
||||
alsa->bytes_per_sample = bits_per_sample / 8;
|
||||
|
||||
error = snd_pcm_hw_params_malloc(&hw_params);
|
||||
|
||||
if (error < 0)
|
||||
{
|
||||
DEBUG_WARN("snd_pcm_hw_params_malloc failed");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
snd_pcm_hw_params_any(alsa->out_handle, hw_params);
|
||||
snd_pcm_hw_params_set_access(alsa->out_handle, hw_params,
|
||||
SND_PCM_ACCESS_RW_INTERLEAVED);
|
||||
@@ -120,11 +126,13 @@ static BOOL tsmf_alsa_set_format(ITSMFAudioDevice* audio,
|
||||
snd_pcm_hw_params_free(hw_params);
|
||||
|
||||
error = snd_pcm_sw_params_malloc(&sw_params);
|
||||
|
||||
if (error < 0)
|
||||
{
|
||||
DEBUG_WARN("snd_pcm_sw_params_malloc");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
snd_pcm_sw_params_current(alsa->out_handle, sw_params);
|
||||
snd_pcm_sw_params_set_start_threshold(alsa->out_handle, sw_params,
|
||||
frames / 2);
|
||||
@@ -136,6 +144,7 @@ static BOOL tsmf_alsa_set_format(ITSMFAudioDevice* audio,
|
||||
DEBUG_DVC("sample_rate %d channels %d bits_per_sample %d",
|
||||
sample_rate, channels, bits_per_sample);
|
||||
DEBUG_DVC("hardware buffer %d frames", (int)frames);
|
||||
|
||||
if ((alsa->actual_rate != alsa->source_rate) ||
|
||||
(alsa->actual_channels != alsa->source_channels))
|
||||
{
|
||||
@@ -144,6 +153,7 @@ static BOOL tsmf_alsa_set_format(ITSMFAudioDevice* audio,
|
||||
alsa->actual_rate, alsa->actual_channels,
|
||||
alsa->source_rate, alsa->source_channels);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -157,7 +167,7 @@ static BOOL tsmf_alsa_play(ITSMFAudioDevice* audio, BYTE* data, UINT32 data_size
|
||||
BYTE* pindex;
|
||||
int rbytes_per_frame;
|
||||
int sbytes_per_frame;
|
||||
TSMFALSAAudioDevice* alsa = (TSMFALSAAudioDevice*) audio;
|
||||
TSMFAlsaAudioDevice* alsa = (TSMFAlsaAudioDevice*) audio;
|
||||
|
||||
DEBUG_DVC("data_size %d", data_size);
|
||||
|
||||
@@ -190,6 +200,7 @@ static BOOL tsmf_alsa_play(ITSMFAudioDevice* audio, BYTE* data, UINT32 data_size
|
||||
len = end - pindex;
|
||||
frames = len / rbytes_per_frame;
|
||||
error = snd_pcm_writei(alsa->out_handle, pindex, frames);
|
||||
|
||||
if (error == -EPIPE)
|
||||
{
|
||||
snd_pcm_recover(alsa->out_handle, error, 0);
|
||||
@@ -203,9 +214,12 @@ static BOOL tsmf_alsa_play(ITSMFAudioDevice* audio, BYTE* data, UINT32 data_size
|
||||
tsmf_alsa_open_device(alsa);
|
||||
break;
|
||||
}
|
||||
|
||||
DEBUG_DVC("%d frames played.", error);
|
||||
|
||||
if (error == 0)
|
||||
break;
|
||||
|
||||
pindex += error * rbytes_per_frame;
|
||||
}
|
||||
}
|
||||
@@ -218,14 +232,15 @@ static UINT64 tsmf_alsa_get_latency(ITSMFAudioDevice* audio)
|
||||
{
|
||||
UINT64 latency = 0;
|
||||
snd_pcm_sframes_t frames = 0;
|
||||
TSMFALSAAudioDevice* alsa = (TSMFALSAAudioDevice*) audio;
|
||||
TSMFAlsaAudioDevice* alsa = (TSMFAlsaAudioDevice*) audio;
|
||||
|
||||
if (alsa->out_handle && alsa->actual_rate > 0 &&
|
||||
snd_pcm_delay(alsa->out_handle, &frames) == 0 &&
|
||||
frames > 0)
|
||||
{
|
||||
latency = ((UINT64)frames) * 10000000LL / (UINT64)alsa->actual_rate;
|
||||
latency = ((UINT64)frames) * 10000000LL / (UINT64) alsa->actual_rate;
|
||||
}
|
||||
|
||||
return latency;
|
||||
}
|
||||
|
||||
@@ -235,7 +250,7 @@ static void tsmf_alsa_flush(ITSMFAudioDevice* audio)
|
||||
|
||||
static void tsmf_alsa_free(ITSMFAudioDevice* audio)
|
||||
{
|
||||
TSMFALSAAudioDevice* alsa = (TSMFALSAAudioDevice*) audio;
|
||||
TSMFAlsaAudioDevice* alsa = (TSMFAlsaAudioDevice*) audio;
|
||||
|
||||
DEBUG_DVC("");
|
||||
|
||||
@@ -244,15 +259,21 @@ static void tsmf_alsa_free(ITSMFAudioDevice* audio)
|
||||
snd_pcm_drain(alsa->out_handle);
|
||||
snd_pcm_close(alsa->out_handle);
|
||||
}
|
||||
|
||||
freerdp_dsp_context_free(alsa->dsp_context);
|
||||
free(alsa);
|
||||
}
|
||||
|
||||
ITSMFAudioDevice* TSMFAudioDeviceEntry(void)
|
||||
{
|
||||
TSMFALSAAudioDevice* alsa;
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define freerdp_tsmf_client_audio_subsystem_entry alsa_freerdp_tsmf_client_audio_subsystem_entry
|
||||
#endif
|
||||
|
||||
alsa = xnew(TSMFALSAAudioDevice);
|
||||
ITSMFAudioDevice* freerdp_tsmf_client_audio_subsystem_entry(void)
|
||||
{
|
||||
TSMFAlsaAudioDevice* alsa;
|
||||
|
||||
alsa = (TSMFAlsaAudioDevice*) malloc(sizeof(TSMFAlsaAudioDevice));
|
||||
ZeroMemory(alsa, sizeof(TSMFAlsaAudioDevice));
|
||||
|
||||
alsa->iface.Open = tsmf_alsa_open;
|
||||
alsa->iface.SetFormat = tsmf_alsa_set_format;
|
||||
@@ -265,4 +286,3 @@ ITSMFAudioDevice* TSMFAudioDeviceEntry(void)
|
||||
|
||||
return (ITSMFAudioDevice*) alsa;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
define_channel_client_subsystem("tsmf" "ffmpeg" "video")
|
||||
define_channel_client_subsystem("tsmf" "ffmpeg" "decoder")
|
||||
|
||||
set(${MODULE_PREFIX}_SRCS
|
||||
tsmf_ffmpeg.c)
|
||||
@@ -23,7 +23,7 @@ set(${MODULE_PREFIX}_SRCS
|
||||
include_directories(..)
|
||||
include_directories(${FFMPEG_INCLUDE_DIRS})
|
||||
|
||||
add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
|
||||
|
||||
@@ -36,4 +36,6 @@ set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${FFMPEG_LIBRARIES})
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_PLUGIN_PATH})
|
||||
if(NOT STATIC_CHANNELS)
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH})
|
||||
endif()
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <freerdp/utils/event.h>
|
||||
#include <freerdp/client/tsmf.h>
|
||||
#include <libavcodec/avcodec.h>
|
||||
@@ -60,6 +61,7 @@ static BOOL tsmf_ffmpeg_init_context(ITSMFDecoder* decoder)
|
||||
TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
|
||||
|
||||
mdecoder->codec_context = avcodec_alloc_context3(NULL);
|
||||
|
||||
if (!mdecoder->codec_context)
|
||||
{
|
||||
DEBUG_WARN("avcodec_alloc_context failed.");
|
||||
@@ -108,12 +110,13 @@ static BOOL tsmf_ffmpeg_init_audio_stream(ITSMFDecoder* decoder, const TS_AM_MED
|
||||
|
||||
static BOOL tsmf_ffmpeg_init_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYPE* media_type)
|
||||
{
|
||||
TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
|
||||
BYTE* p;
|
||||
UINT32 size;
|
||||
const BYTE* s;
|
||||
BYTE* p;
|
||||
TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
|
||||
|
||||
mdecoder->codec = avcodec_find_decoder(mdecoder->codec_id);
|
||||
|
||||
if (!mdecoder->codec)
|
||||
{
|
||||
DEBUG_WARN("avcodec_find_decoder failed.");
|
||||
@@ -142,7 +145,8 @@ static BOOL tsmf_ffmpeg_init_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYP
|
||||
/* The extradata format that FFmpeg uses is following CodecPrivate in Matroska.
|
||||
See http://haali.su/mkv/codecs.pdf */
|
||||
mdecoder->codec_context->extradata_size = media_type->ExtraDataSize + 8;
|
||||
mdecoder->codec_context->extradata = xzalloc(mdecoder->codec_context->extradata_size);
|
||||
mdecoder->codec_context->extradata = malloc(mdecoder->codec_context->extradata_size);
|
||||
ZeroMemory(mdecoder->codec_context->extradata, mdecoder->codec_context->extradata_size);
|
||||
p = mdecoder->codec_context->extradata;
|
||||
*p++ = 1; /* Reserved? */
|
||||
*p++ = media_type->ExtraData[8]; /* Profile */
|
||||
@@ -163,7 +167,8 @@ static BOOL tsmf_ffmpeg_init_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYP
|
||||
{
|
||||
/* Add a padding to avoid invalid memory read in some codec */
|
||||
mdecoder->codec_context->extradata_size = media_type->ExtraDataSize + 8;
|
||||
mdecoder->codec_context->extradata = xzalloc(mdecoder->codec_context->extradata_size);
|
||||
mdecoder->codec_context->extradata = malloc(mdecoder->codec_context->extradata_size);
|
||||
ZeroMemory(mdecoder->codec_context->extradata, mdecoder->codec_context->extradata_size);
|
||||
memcpy(mdecoder->codec_context->extradata, media_type->ExtraData, media_type->ExtraDataSize);
|
||||
memset(mdecoder->codec_context->extradata + media_type->ExtraDataSize, 0, 8);
|
||||
}
|
||||
@@ -303,13 +308,14 @@ static BOOL tsmf_ffmpeg_decode_video(ITSMFDecoder* decoder, const BYTE* data, UI
|
||||
|
||||
mdecoder->decoded_size = avpicture_get_size(mdecoder->codec_context->pix_fmt,
|
||||
mdecoder->codec_context->width, mdecoder->codec_context->height);
|
||||
mdecoder->decoded_data = xzalloc(mdecoder->decoded_size);
|
||||
mdecoder->decoded_data = malloc(mdecoder->decoded_size);
|
||||
ZeroMemory(mdecoder->decoded_data, mdecoder->decoded_size);
|
||||
frame = avcodec_alloc_frame();
|
||||
avpicture_fill((AVPicture *) frame, mdecoder->decoded_data,
|
||||
avpicture_fill((AVPicture*) frame, mdecoder->decoded_data,
|
||||
mdecoder->codec_context->pix_fmt,
|
||||
mdecoder->codec_context->width, mdecoder->codec_context->height);
|
||||
|
||||
av_picture_copy((AVPicture *) frame, (AVPicture *) mdecoder->frame,
|
||||
av_picture_copy((AVPicture*) frame, (AVPicture*) mdecoder->frame,
|
||||
mdecoder->codec_context->pix_fmt,
|
||||
mdecoder->codec_context->width, mdecoder->codec_context->height);
|
||||
|
||||
@@ -343,9 +349,10 @@ static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder* decoder, const BYTE* data, UI
|
||||
|
||||
if (mdecoder->decoded_size_max == 0)
|
||||
mdecoder->decoded_size_max = AVCODEC_MAX_AUDIO_FRAME_SIZE + 16;
|
||||
mdecoder->decoded_data = xzalloc(mdecoder->decoded_size_max);
|
||||
mdecoder->decoded_data = malloc(mdecoder->decoded_size_max);
|
||||
ZeroMemory(mdecoder->decoded_data, mdecoder->decoded_size_max);
|
||||
/* align the memory for SSE2 needs */
|
||||
dst = (BYTE*) (((uintptr_t)mdecoder->decoded_data + 15) & ~ 0x0F);
|
||||
dst = (BYTE*) (((uintptr_t) mdecoder->decoded_data + 15) & ~ 0x0F);
|
||||
dst_offset = dst - mdecoder->decoded_data;
|
||||
src = data;
|
||||
src_size = data_size;
|
||||
@@ -373,7 +380,7 @@ static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder* decoder, const BYTE* data, UI
|
||||
(int16_t*) dst, &frame_size, src, src_size);
|
||||
#else
|
||||
{
|
||||
AVFrame* decoded_frame = avcodec_alloc_frame();
|
||||
AVFrame* decoded_frame = avcodec_alloc_frame();
|
||||
int got_frame = 0;
|
||||
AVPacket pkt;
|
||||
av_init_packet(&pkt);
|
||||
@@ -383,7 +390,7 @@ static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder* decoder, const BYTE* data, UI
|
||||
|
||||
if (len >= 0 && got_frame)
|
||||
{
|
||||
frame_size = av_samples_get_buffer_size(NULL, mdecoder->codec_context->channels,
|
||||
frame_size = av_samples_get_buffer_size(NULL, mdecoder->codec_context->channels,
|
||||
decoded_frame->nb_samples, mdecoder->codec_context->sample_fmt, 1);
|
||||
memcpy(dst, decoded_frame->data[0], frame_size);
|
||||
}
|
||||
@@ -396,6 +403,7 @@ static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder* decoder, const BYTE* data, UI
|
||||
DEBUG_WARN("error decoding");
|
||||
break;
|
||||
}
|
||||
|
||||
src += len;
|
||||
src_size -= len;
|
||||
mdecoder->decoded_size += frame_size;
|
||||
@@ -444,13 +452,14 @@ static BOOL tsmf_ffmpeg_decode(ITSMFDecoder* decoder, const BYTE* data, UINT32 d
|
||||
|
||||
static BYTE* tsmf_ffmpeg_get_decoded_data(ITSMFDecoder* decoder, UINT32* size)
|
||||
{
|
||||
TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
|
||||
BYTE* buf;
|
||||
TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
|
||||
|
||||
*size = mdecoder->decoded_size;
|
||||
buf = mdecoder->decoded_data;
|
||||
mdecoder->decoded_data = NULL;
|
||||
mdecoder->decoded_size = 0;
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
@@ -492,8 +501,10 @@ static void tsmf_ffmpeg_free(ITSMFDecoder* decoder)
|
||||
|
||||
if (mdecoder->frame)
|
||||
av_free(mdecoder->frame);
|
||||
|
||||
if (mdecoder->decoded_data)
|
||||
free(mdecoder->decoded_data);
|
||||
|
||||
if (mdecoder->codec_context)
|
||||
{
|
||||
if (mdecoder->prepared)
|
||||
@@ -502,15 +513,19 @@ static void tsmf_ffmpeg_free(ITSMFDecoder* decoder)
|
||||
free(mdecoder->codec_context->extradata);
|
||||
av_free(mdecoder->codec_context);
|
||||
}
|
||||
|
||||
free(decoder);
|
||||
}
|
||||
|
||||
static BOOL initialized = FALSE;
|
||||
|
||||
ITSMFDecoder*
|
||||
TSMFDecoderEntry(void)
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define freerdp_tsmf_client_decoder_subsystem_entry ffmpeg_freerdp_tsmf_client_decoder_subsystem_entry
|
||||
#endif
|
||||
|
||||
ITSMFDecoder* freerdp_tsmf_client_decoder_subsystem_entry(void)
|
||||
{
|
||||
TSMFFFmpegDecoder * decoder;
|
||||
TSMFFFmpegDecoder* decoder;
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
@@ -518,7 +533,10 @@ TSMFDecoderEntry(void)
|
||||
initialized = TRUE;
|
||||
}
|
||||
|
||||
decoder = xnew(TSMFFFmpegDecoder);
|
||||
printf("TSMFDecoderEntry FFMPEG\n");
|
||||
|
||||
decoder = (TSMFFFmpegDecoder*) malloc(sizeof(TSMFFFmpegDecoder));
|
||||
ZeroMemory(decoder, sizeof(TSMFFFmpegDecoder));
|
||||
|
||||
decoder->iface.SetFormat = tsmf_ffmpeg_set_format;
|
||||
decoder->iface.Decode = tsmf_ffmpeg_decode;
|
||||
@@ -529,4 +547,3 @@ TSMFDecoderEntry(void)
|
||||
|
||||
return (ITSMFDecoder*) decoder;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
define_channel_client_subsystem("tsmf" "gstreamer" "video")
|
||||
define_channel_client_subsystem("tsmf" "gstreamer" "decoder")
|
||||
|
||||
set(${MODULE_PREFIX}_SRCS
|
||||
tsmf_gstreamer.c)
|
||||
@@ -23,7 +23,7 @@ set(${MODULE_PREFIX}_SRCS
|
||||
include_directories(..)
|
||||
include_directories(${GSTREAMER_INCLUDE_DIRS})
|
||||
|
||||
add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
|
||||
|
||||
@@ -40,4 +40,6 @@ set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS}
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_PLUGIN_PATH})
|
||||
if(NOT STATIC_CHANNELS)
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH})
|
||||
endif()
|
||||
|
||||
@@ -1565,10 +1565,13 @@ static void tsmf_gstreamer_update_rendering_area(ITSMFDecoder * decoder, int new
|
||||
|
||||
static int initialized = 0;
|
||||
|
||||
ITSMFDecoder *
|
||||
TSMFDecoderEntry(void)
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define freerdp_tsmf_client_decoder_subsystem_entry gstreamer_freerdp_tsmf_client_decoder_subsystem_entry
|
||||
#endif
|
||||
|
||||
ITSMFDecoder* freerdp_tsmf_client_decoder_subsystem_entry(void)
|
||||
{
|
||||
TSMFGstreamerDecoder * decoder;
|
||||
TSMFGstreamerDecoder* decoder;
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
|
||||
@@ -23,7 +23,7 @@ set(${MODULE_PREFIX}_SRCS
|
||||
include_directories(..)
|
||||
include_directories(${PULSE_INCLUDE_DIR})
|
||||
|
||||
add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
|
||||
|
||||
@@ -36,4 +36,7 @@ set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${PULSE_LIBRARY})
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_PLUGIN_PATH})
|
||||
if(NOT STATIC_CHANNELS)
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH})
|
||||
endif()
|
||||
|
||||
|
||||
@@ -26,8 +26,9 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <pulse/pulseaudio.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
|
||||
#include "tsmf_audio.h"
|
||||
|
||||
@@ -389,11 +390,16 @@ static void tsmf_pulse_free(ITSMFAudioDevice* audio)
|
||||
free(pulse);
|
||||
}
|
||||
|
||||
ITSMFAudioDevice* TSMFAudioDeviceEntry(void)
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define freerdp_tsmf_client_audio_subsystem_entry pulse_freerdp_tsmf_client_audio_subsystem_entry
|
||||
#endif
|
||||
|
||||
ITSMFAudioDevice* freerdp_tsmf_client_audio_subsystem_entry(void)
|
||||
{
|
||||
TSMFPulseAudioDevice* pulse;
|
||||
|
||||
pulse = xnew(TSMFPulseAudioDevice);
|
||||
pulse = (TSMFPulseAudioDevice*) malloc(sizeof(TSMFPulseAudioDevice));
|
||||
ZeroMemory(pulse, sizeof(TSMFPulseAudioDevice));
|
||||
|
||||
pulse->iface.Open = tsmf_pulse_open;
|
||||
pulse->iface.SetFormat = tsmf_pulse_set_format;
|
||||
|
||||
@@ -25,43 +25,32 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/load_plugin.h>
|
||||
|
||||
#include "tsmf_audio.h"
|
||||
|
||||
static ITSMFAudioDevice* tsmf_load_audio_device_by_name(const char* name, const char* device)
|
||||
{
|
||||
ITSMFAudioDevice* audio;
|
||||
TSMF_AUDIO_DEVICE_ENTRY entry;
|
||||
char* fullname;
|
||||
|
||||
if (strrchr(name, '.') != NULL)
|
||||
entry = (TSMF_AUDIO_DEVICE_ENTRY) freerdp_load_plugin(name, TSMF_AUDIO_DEVICE_EXPORT_FUNC_NAME);
|
||||
else
|
||||
{
|
||||
fullname = xzalloc(strlen(name) + 6);
|
||||
strcpy(fullname, "tsmf_");
|
||||
strcat(fullname, name);
|
||||
entry = (TSMF_AUDIO_DEVICE_ENTRY) freerdp_load_plugin(fullname, TSMF_AUDIO_DEVICE_EXPORT_FUNC_NAME);
|
||||
free(fullname);
|
||||
}
|
||||
entry = (TSMF_AUDIO_DEVICE_ENTRY) freerdp_load_channel_addin_entry("tsmf", (LPSTR) name, "audio", 0);
|
||||
|
||||
if (entry == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
audio = entry();
|
||||
|
||||
if (audio == NULL)
|
||||
{
|
||||
DEBUG_WARN("failed to call export function in %s", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!audio->Open(audio, device))
|
||||
{
|
||||
audio->Free(audio);
|
||||
audio = NULL;
|
||||
}
|
||||
|
||||
return audio;
|
||||
}
|
||||
|
||||
@@ -76,6 +65,7 @@ ITSMFAudioDevice* tsmf_load_audio_device(const char* name, const char* device)
|
||||
else
|
||||
{
|
||||
audio = tsmf_load_audio_device_by_name("pulse", device);
|
||||
|
||||
if (!audio)
|
||||
audio = tsmf_load_audio_device_by_name("alsa", device);
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/hexdump.h>
|
||||
#include <winpr/print.h>
|
||||
|
||||
#include "tsmf_constants.h"
|
||||
#include "tsmf_types.h"
|
||||
@@ -425,7 +425,7 @@ BOOL tsmf_codec_parse_media_type(TS_AM_MEDIA_TYPE* mediatype, STREAM* s)
|
||||
DEBUG_DVC("cbFormat %d", cbFormat);
|
||||
|
||||
#ifdef WITH_DEBUG_DVC
|
||||
freerdp_hexdump(stream_get_tail(s), cbFormat);
|
||||
winpr_HexDump(stream_get_tail(s), cbFormat);
|
||||
#endif
|
||||
|
||||
switch (mediatype->FormatType)
|
||||
@@ -526,4 +526,3 @@ BOOL tsmf_codec_check_media_type(STREAM* s)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/load_plugin.h>
|
||||
#include <freerdp/addin.h>
|
||||
#include <freerdp/client/channels.h>
|
||||
|
||||
#include "tsmf_types.h"
|
||||
#include "tsmf_constants.h"
|
||||
@@ -36,34 +36,26 @@ static ITSMFDecoder* tsmf_load_decoder_by_name(const char* name, TS_AM_MEDIA_TYP
|
||||
{
|
||||
ITSMFDecoder* decoder;
|
||||
TSMF_DECODER_ENTRY entry;
|
||||
char* fullname;
|
||||
|
||||
if (strrchr(name, '.') != NULL)
|
||||
entry = (TSMF_DECODER_ENTRY) freerdp_load_plugin(name, TSMF_DECODER_EXPORT_FUNC_NAME);
|
||||
else
|
||||
{
|
||||
fullname = xzalloc(strlen(name) + 6);
|
||||
strcpy(fullname, "tsmf_");
|
||||
strcat(fullname, name);
|
||||
entry = (TSMF_DECODER_ENTRY) freerdp_load_plugin(fullname, TSMF_DECODER_EXPORT_FUNC_NAME);
|
||||
free(fullname);
|
||||
}
|
||||
entry = (TSMF_DECODER_ENTRY) freerdp_load_channel_addin_entry("tsmf", (LPSTR) name, "decoder", 0);
|
||||
|
||||
if (entry == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
decoder = entry();
|
||||
|
||||
if (decoder == NULL)
|
||||
{
|
||||
DEBUG_WARN("failed to call export function in %s", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!decoder->SetFormat(decoder, media_type))
|
||||
{
|
||||
decoder->Free(decoder);
|
||||
decoder = NULL;
|
||||
}
|
||||
|
||||
return decoder;
|
||||
}
|
||||
|
||||
@@ -82,4 +74,3 @@ ITSMFDecoder* tsmf_load_decoder(const char* name, TS_AM_MEDIA_TYPE* media_type)
|
||||
|
||||
return decoder;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <freerdp/utils/stream.h>
|
||||
|
||||
#include "tsmf_types.h"
|
||||
@@ -65,11 +66,13 @@ int tsmf_ifman_exchange_capability_request(TSMF_IFMAN* ifman)
|
||||
|
||||
stream_set_pos(ifman->output, pos);
|
||||
stream_read_UINT32(ifman->output, numHostCapabilities);
|
||||
|
||||
for (i = 0; i < numHostCapabilities; i++)
|
||||
{
|
||||
stream_read_UINT32(ifman->output, CapabilityType);
|
||||
stream_read_UINT32(ifman->output, cbCapabilityLength);
|
||||
pos = stream_get_pos(ifman->output);
|
||||
|
||||
switch (CapabilityType)
|
||||
{
|
||||
case 1: /* Protocol version request */
|
||||
@@ -128,10 +131,11 @@ static TSMF_PRESENTATION* pexisted = 0;
|
||||
|
||||
int tsmf_ifman_on_new_presentation(TSMF_IFMAN* ifman)
|
||||
{
|
||||
int error = 0;
|
||||
int status = 0;
|
||||
TSMF_PRESENTATION* presentation;
|
||||
|
||||
DEBUG_DVC("");
|
||||
|
||||
if (pexisted)
|
||||
{
|
||||
ifman->output_pending = FALSE;
|
||||
@@ -141,18 +145,21 @@ int tsmf_ifman_on_new_presentation(TSMF_IFMAN* ifman)
|
||||
|
||||
presentation = tsmf_presentation_new(stream_get_tail(ifman->input), ifman->channel_callback);
|
||||
pexisted = presentation;
|
||||
|
||||
if (presentation == NULL)
|
||||
error = 1;
|
||||
status = 1;
|
||||
else
|
||||
tsmf_presentation_set_audio_device(presentation, ifman->audio_name, ifman->audio_device);
|
||||
|
||||
ifman->output_pending = TRUE;
|
||||
return error;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int tsmf_ifman_add_stream(TSMF_IFMAN* ifman)
|
||||
{
|
||||
UINT32 StreamId;
|
||||
int error = 0;
|
||||
int status = 0;
|
||||
TSMF_STREAM* stream;
|
||||
TSMF_PRESENTATION* presentation;
|
||||
|
||||
@@ -162,17 +169,22 @@ int tsmf_ifman_add_stream(TSMF_IFMAN* ifman)
|
||||
stream_seek(ifman->input, 16);
|
||||
|
||||
if (presentation == NULL)
|
||||
error = 1;
|
||||
{
|
||||
status = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream_read_UINT32(ifman->input, StreamId);
|
||||
stream_seek_UINT32(ifman->input); /* numMediaType */
|
||||
stream = tsmf_stream_new(presentation, StreamId);
|
||||
|
||||
if (stream)
|
||||
tsmf_stream_set_format(stream, ifman->decoder_name, ifman->input);
|
||||
}
|
||||
|
||||
ifman->output_pending = TRUE;
|
||||
return error;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int tsmf_ifman_set_topology_request(TSMF_IFMAN* ifman)
|
||||
@@ -183,12 +195,13 @@ int tsmf_ifman_set_topology_request(TSMF_IFMAN* ifman)
|
||||
stream_write_UINT32(ifman->output, 1); /* TopologyReady */
|
||||
stream_write_UINT32(ifman->output, 0); /* Result */
|
||||
ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tsmf_ifman_remove_stream(TSMF_IFMAN* ifman)
|
||||
{
|
||||
int error = 0;
|
||||
int status = 0;
|
||||
UINT32 StreamId;
|
||||
TSMF_STREAM* stream;
|
||||
TSMF_PRESENTATION* presentation;
|
||||
@@ -199,7 +212,9 @@ int tsmf_ifman_remove_stream(TSMF_IFMAN* ifman)
|
||||
stream_seek(ifman->input, 16);
|
||||
|
||||
if (presentation == NULL)
|
||||
error = 1;
|
||||
{
|
||||
status = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream_read_UINT32(ifman->input, StreamId);
|
||||
@@ -207,10 +222,12 @@ int tsmf_ifman_remove_stream(TSMF_IFMAN* ifman)
|
||||
if (stream)
|
||||
tsmf_stream_free(stream);
|
||||
else
|
||||
error = 1;
|
||||
status = 1;
|
||||
}
|
||||
|
||||
ifman->output_pending = TRUE;
|
||||
return error;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int tsmf_ifman_shutdown_presentation(TSMF_IFMAN* ifman)
|
||||
@@ -220,6 +237,7 @@ int tsmf_ifman_shutdown_presentation(TSMF_IFMAN* ifman)
|
||||
DEBUG_DVC("");
|
||||
|
||||
presentation = tsmf_presentation_find_by_id(stream_get_tail(ifman->input));
|
||||
|
||||
if (presentation)
|
||||
tsmf_presentation_free(presentation);
|
||||
|
||||
@@ -228,6 +246,7 @@ int tsmf_ifman_shutdown_presentation(TSMF_IFMAN* ifman)
|
||||
stream_check_size(ifman->output, 4);
|
||||
stream_write_UINT32(ifman->output, 0); /* Result */
|
||||
ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -335,7 +354,9 @@ int tsmf_ifman_update_geometry_info(TSMF_IFMAN* ifman)
|
||||
{
|
||||
if (num_rects > 0)
|
||||
{
|
||||
rects = (RDP_RECT*) xzalloc(sizeof(RDP_RECT) * num_rects);
|
||||
rects = (RDP_RECT*) malloc(sizeof(RDP_RECT) * num_rects);
|
||||
ZeroMemory(rects, sizeof(RDP_RECT) * num_rects);
|
||||
|
||||
for (i = 0; i < num_rects; i++)
|
||||
{
|
||||
stream_read_UINT16(ifman->input, rects[i].y); /* Top */
|
||||
@@ -402,35 +423,41 @@ int tsmf_ifman_on_sample(TSMF_IFMAN* ifman)
|
||||
(int)ThrottleDuration, SampleExtensions, cbData);
|
||||
|
||||
presentation = tsmf_presentation_find_by_id(ifman->presentation_id);
|
||||
|
||||
if (presentation == NULL)
|
||||
{
|
||||
DEBUG_WARN("unknown presentation id");
|
||||
return 1;
|
||||
}
|
||||
|
||||
stream = tsmf_stream_find_by_id(presentation, StreamId);
|
||||
|
||||
if (stream == NULL)
|
||||
{
|
||||
DEBUG_WARN("unknown stream id");
|
||||
return 1;
|
||||
}
|
||||
|
||||
tsmf_stream_push_sample(stream, ifman->channel_callback,
|
||||
ifman->message_id, SampleStartTime, SampleEndTime, ThrottleDuration, SampleExtensions,
|
||||
cbData, stream_get_tail(ifman->input));
|
||||
|
||||
ifman->output_pending = TRUE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tsmf_ifman_on_flush(TSMF_IFMAN* ifman)
|
||||
{
|
||||
TSMF_PRESENTATION* presentation;
|
||||
UINT32 StreamId;
|
||||
TSMF_PRESENTATION* presentation;
|
||||
|
||||
stream_seek(ifman->input, 16);
|
||||
stream_read_UINT32(ifman->input, StreamId);
|
||||
DEBUG_DVC("StreamId %d", StreamId);
|
||||
|
||||
presentation = tsmf_presentation_find_by_id(ifman->presentation_id);
|
||||
|
||||
if (presentation == NULL)
|
||||
{
|
||||
DEBUG_WARN("unknown presentation id");
|
||||
@@ -440,18 +467,20 @@ int tsmf_ifman_on_flush(TSMF_IFMAN* ifman)
|
||||
tsmf_presentation_flush(presentation);
|
||||
|
||||
ifman->output_pending = TRUE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tsmf_ifman_on_end_of_stream(TSMF_IFMAN* ifman)
|
||||
{
|
||||
TSMF_PRESENTATION* presentation;
|
||||
TSMF_STREAM* stream;
|
||||
UINT32 StreamId;
|
||||
TSMF_STREAM* stream;
|
||||
TSMF_PRESENTATION* presentation;
|
||||
|
||||
presentation = tsmf_presentation_find_by_id(stream_get_tail(ifman->input));
|
||||
stream_seek(ifman->input, 16);
|
||||
stream_read_UINT32(ifman->input, StreamId);
|
||||
|
||||
if (presentation)
|
||||
{
|
||||
stream = tsmf_stream_find_by_id(presentation, StreamId);
|
||||
@@ -477,6 +506,7 @@ int tsmf_ifman_on_playback_started(TSMF_IFMAN* ifman)
|
||||
DEBUG_DVC("");
|
||||
|
||||
presentation = tsmf_presentation_find_by_id(stream_get_tail(ifman->input));
|
||||
|
||||
if (presentation)
|
||||
tsmf_presentation_start(presentation);
|
||||
else
|
||||
@@ -502,10 +532,12 @@ int tsmf_ifman_on_playback_paused(TSMF_IFMAN* ifman)
|
||||
/* Added pause control so gstreamer pipeline can be paused accordingly */
|
||||
|
||||
presentation = tsmf_presentation_find_by_id(stream_get_tail(ifman->input));
|
||||
|
||||
if (presentation)
|
||||
tsmf_presentation_paused(presentation);
|
||||
else
|
||||
DEBUG_WARN("unknown presentation id");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -564,4 +596,3 @@ int tsmf_ifman_on_playback_rate_changed(TSMF_IFMAN * ifman)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/cmdline.h>
|
||||
|
||||
#include <freerdp/utils/stream.h>
|
||||
|
||||
#include "tsmf_types.h"
|
||||
@@ -76,7 +78,7 @@ void tsmf_playback_ack(IWTSVirtualChannelCallback* pChannelCallback,
|
||||
UINT32 message_id, UINT64 duration, UINT32 data_size)
|
||||
{
|
||||
STREAM* s;
|
||||
int error;
|
||||
int status;
|
||||
TSMF_CHANNEL_CALLBACK* callback = (TSMF_CHANNEL_CALLBACK*) pChannelCallback;
|
||||
|
||||
s = stream_new(32);
|
||||
@@ -88,26 +90,29 @@ void tsmf_playback_ack(IWTSVirtualChannelCallback* pChannelCallback,
|
||||
stream_write_UINT64(s, data_size); /* cbData */
|
||||
|
||||
DEBUG_DVC("response size %d", (int) stream_get_length(s));
|
||||
error = callback->channel->Write(callback->channel, stream_get_length(s), stream_get_head(s), NULL);
|
||||
if (error)
|
||||
status = callback->channel->Write(callback->channel, stream_get_length(s), stream_get_head(s), NULL);
|
||||
|
||||
if (status)
|
||||
{
|
||||
DEBUG_WARN("response error %d", error);
|
||||
DEBUG_WARN("response error %d", status);
|
||||
}
|
||||
|
||||
stream_free(s);
|
||||
}
|
||||
|
||||
BOOL tsmf_push_event(IWTSVirtualChannelCallback* pChannelCallback,
|
||||
RDP_EVENT* event)
|
||||
BOOL tsmf_push_event(IWTSVirtualChannelCallback* pChannelCallback, RDP_EVENT* event)
|
||||
{
|
||||
int error;
|
||||
int status;
|
||||
TSMF_CHANNEL_CALLBACK* callback = (TSMF_CHANNEL_CALLBACK*) pChannelCallback;
|
||||
|
||||
error = callback->channel_mgr->PushEvent(callback->channel_mgr, event);
|
||||
if (error)
|
||||
status = callback->channel_mgr->PushEvent(callback->channel_mgr, event);
|
||||
|
||||
if (status)
|
||||
{
|
||||
DEBUG_WARN("response error %d", error);
|
||||
DEBUG_WARN("response error %d", status);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -118,7 +123,7 @@ static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
|
||||
int length;
|
||||
STREAM* input;
|
||||
STREAM* output;
|
||||
int error = -1;
|
||||
int status = -1;
|
||||
TSMF_IFMAN ifman;
|
||||
UINT32 MessageId;
|
||||
UINT32 FunctionId;
|
||||
@@ -163,7 +168,7 @@ static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
|
||||
switch (FunctionId)
|
||||
{
|
||||
case RIM_EXCHANGE_CAPABILITY_REQUEST:
|
||||
error = tsmf_ifman_rim_exchange_capability_request(&ifman);
|
||||
status = tsmf_ifman_rim_exchange_capability_request(&ifman);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -181,91 +186,91 @@ static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
|
||||
stream_read_UINT32(input, callback->stream_id);
|
||||
DEBUG_DVC("SET_CHANNEL_PARAMS StreamId=%d", callback->stream_id);
|
||||
ifman.output_pending = TRUE;
|
||||
error = 0;
|
||||
status = 0;
|
||||
break;
|
||||
|
||||
case EXCHANGE_CAPABILITIES_REQ:
|
||||
error = tsmf_ifman_exchange_capability_request(&ifman);
|
||||
status = tsmf_ifman_exchange_capability_request(&ifman);
|
||||
break;
|
||||
|
||||
case CHECK_FORMAT_SUPPORT_REQ:
|
||||
error = tsmf_ifman_check_format_support_request(&ifman);
|
||||
status = tsmf_ifman_check_format_support_request(&ifman);
|
||||
break;
|
||||
|
||||
case ON_NEW_PRESENTATION:
|
||||
error = tsmf_ifman_on_new_presentation(&ifman);
|
||||
status = tsmf_ifman_on_new_presentation(&ifman);
|
||||
break;
|
||||
|
||||
case ADD_STREAM:
|
||||
error = tsmf_ifman_add_stream(&ifman);
|
||||
status = tsmf_ifman_add_stream(&ifman);
|
||||
break;
|
||||
|
||||
case SET_TOPOLOGY_REQ:
|
||||
error = tsmf_ifman_set_topology_request(&ifman);
|
||||
status = tsmf_ifman_set_topology_request(&ifman);
|
||||
break;
|
||||
|
||||
case REMOVE_STREAM:
|
||||
error = tsmf_ifman_remove_stream(&ifman);
|
||||
status = tsmf_ifman_remove_stream(&ifman);
|
||||
break;
|
||||
|
||||
case SHUTDOWN_PRESENTATION_REQ:
|
||||
error = tsmf_ifman_shutdown_presentation(&ifman);
|
||||
status = tsmf_ifman_shutdown_presentation(&ifman);
|
||||
break;
|
||||
|
||||
case ON_STREAM_VOLUME:
|
||||
error = tsmf_ifman_on_stream_volume(&ifman);
|
||||
status = tsmf_ifman_on_stream_volume(&ifman);
|
||||
break;
|
||||
|
||||
case ON_CHANNEL_VOLUME:
|
||||
error = tsmf_ifman_on_channel_volume(&ifman);
|
||||
status = tsmf_ifman_on_channel_volume(&ifman);
|
||||
break;
|
||||
|
||||
case SET_VIDEO_WINDOW:
|
||||
error = tsmf_ifman_set_video_window(&ifman);
|
||||
status = tsmf_ifman_set_video_window(&ifman);
|
||||
break;
|
||||
|
||||
case UPDATE_GEOMETRY_INFO:
|
||||
error = tsmf_ifman_update_geometry_info(&ifman);
|
||||
status = tsmf_ifman_update_geometry_info(&ifman);
|
||||
break;
|
||||
|
||||
case SET_ALLOCATOR:
|
||||
error = tsmf_ifman_set_allocator(&ifman);
|
||||
status = tsmf_ifman_set_allocator(&ifman);
|
||||
break;
|
||||
|
||||
case NOTIFY_PREROLL:
|
||||
error = tsmf_ifman_notify_preroll(&ifman);
|
||||
status = tsmf_ifman_notify_preroll(&ifman);
|
||||
break;
|
||||
|
||||
case ON_SAMPLE:
|
||||
error = tsmf_ifman_on_sample(&ifman);
|
||||
status = tsmf_ifman_on_sample(&ifman);
|
||||
break;
|
||||
|
||||
case ON_FLUSH:
|
||||
error = tsmf_ifman_on_flush(&ifman);
|
||||
status = tsmf_ifman_on_flush(&ifman);
|
||||
break;
|
||||
|
||||
case ON_END_OF_STREAM:
|
||||
error = tsmf_ifman_on_end_of_stream(&ifman);
|
||||
status = tsmf_ifman_on_end_of_stream(&ifman);
|
||||
break;
|
||||
|
||||
case ON_PLAYBACK_STARTED:
|
||||
error = tsmf_ifman_on_playback_started(&ifman);
|
||||
status = tsmf_ifman_on_playback_started(&ifman);
|
||||
break;
|
||||
|
||||
case ON_PLAYBACK_PAUSED:
|
||||
error = tsmf_ifman_on_playback_paused(&ifman);
|
||||
status = tsmf_ifman_on_playback_paused(&ifman);
|
||||
break;
|
||||
|
||||
case ON_PLAYBACK_RESTARTED:
|
||||
error = tsmf_ifman_on_playback_restarted(&ifman);
|
||||
status = tsmf_ifman_on_playback_restarted(&ifman);
|
||||
break;
|
||||
|
||||
case ON_PLAYBACK_STOPPED:
|
||||
error = tsmf_ifman_on_playback_stopped(&ifman);
|
||||
status = tsmf_ifman_on_playback_stopped(&ifman);
|
||||
break;
|
||||
|
||||
case ON_PLAYBACK_RATE_CHANGED:
|
||||
error = tsmf_ifman_on_playback_rate_changed(&ifman);
|
||||
status = tsmf_ifman_on_playback_rate_changed(&ifman);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -282,34 +287,34 @@ static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
|
||||
input = NULL;
|
||||
ifman.input = NULL;
|
||||
|
||||
if (error == -1)
|
||||
if (status == -1)
|
||||
{
|
||||
switch (FunctionId)
|
||||
{
|
||||
case RIMCALL_RELEASE:
|
||||
/* [MS-RDPEXPS] 2.2.2.2 Interface Release (IFACE_RELEASE)
|
||||
This message does not require a reply. */
|
||||
error = 0;
|
||||
status = 0;
|
||||
ifman.output_pending = 1;
|
||||
break;
|
||||
|
||||
case RIMCALL_QUERYINTERFACE:
|
||||
/* [MS-RDPEXPS] 2.2.2.1.2 Query Interface Response (QI_RSP)
|
||||
This message is not supported in this channel. */
|
||||
error = 0;
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (error == -1)
|
||||
if (status == -1)
|
||||
{
|
||||
DEBUG_WARN("InterfaceId 0x%X FunctionId 0x%X not processed.",
|
||||
InterfaceId, FunctionId);
|
||||
/* When a request is not implemented we return empty response indicating error */
|
||||
}
|
||||
error = 0;
|
||||
status = 0;
|
||||
}
|
||||
|
||||
if (error == 0 && !ifman.output_pending)
|
||||
if (status == 0 && !ifman.output_pending)
|
||||
{
|
||||
/* Response packet does not have FunctionId */
|
||||
length = stream_get_length(output);
|
||||
@@ -318,16 +323,16 @@ static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
|
||||
stream_write_UINT32(output, MessageId);
|
||||
|
||||
DEBUG_DVC("response size %d", length);
|
||||
error = callback->channel->Write(callback->channel, length, stream_get_head(output), NULL);
|
||||
if (error)
|
||||
status = callback->channel->Write(callback->channel, length, stream_get_head(output), NULL);
|
||||
if (status)
|
||||
{
|
||||
DEBUG_WARN("response error %d", error);
|
||||
DEBUG_WARN("response error %d", status);
|
||||
}
|
||||
}
|
||||
|
||||
stream_free(output);
|
||||
|
||||
return error;
|
||||
return status;
|
||||
}
|
||||
|
||||
static int tsmf_on_close(IWTSVirtualChannelCallback* pChannelCallback)
|
||||
@@ -341,13 +346,16 @@ static int tsmf_on_close(IWTSVirtualChannelCallback* pChannelCallback)
|
||||
if (callback->stream_id)
|
||||
{
|
||||
presentation = tsmf_presentation_find_by_id(callback->presentation_id);
|
||||
|
||||
if (presentation)
|
||||
{
|
||||
stream = tsmf_stream_find_by_id(presentation, callback->stream_id);
|
||||
|
||||
if (stream)
|
||||
tsmf_stream_free(stream);
|
||||
}
|
||||
}
|
||||
|
||||
free(pChannelCallback);
|
||||
|
||||
return 0;
|
||||
@@ -364,7 +372,9 @@ static int tsmf_on_new_channel_connection(IWTSListenerCallback* pListenerCallbac
|
||||
|
||||
DEBUG_DVC("");
|
||||
|
||||
callback = xnew(TSMF_CHANNEL_CALLBACK);
|
||||
callback = (TSMF_CHANNEL_CALLBACK*) malloc(sizeof(TSMF_CHANNEL_CALLBACK));
|
||||
ZeroMemory(callback, sizeof(TSMF_CHANNEL_CALLBACK));
|
||||
|
||||
callback->iface.OnDataReceived = tsmf_on_data_received;
|
||||
callback->iface.OnClose = tsmf_on_close;
|
||||
callback->plugin = listener_callback->plugin;
|
||||
@@ -381,10 +391,13 @@ static int tsmf_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager
|
||||
|
||||
DEBUG_DVC("");
|
||||
|
||||
tsmf->listener_callback = xnew(TSMF_LISTENER_CALLBACK);
|
||||
tsmf->listener_callback = (TSMF_LISTENER_CALLBACK*) malloc(sizeof(TSMF_LISTENER_CALLBACK));
|
||||
ZeroMemory(tsmf->listener_callback, sizeof(TSMF_LISTENER_CALLBACK));
|
||||
|
||||
tsmf->listener_callback->iface.OnNewChannelConnection = tsmf_on_new_channel_connection;
|
||||
tsmf->listener_callback->plugin = pPlugin;
|
||||
tsmf->listener_callback->channel_mgr = pChannelMgr;
|
||||
|
||||
return pChannelMgr->CreateListener(pChannelMgr, "TSMF", 0,
|
||||
(IWTSListenerCallback*) tsmf->listener_callback, NULL);
|
||||
}
|
||||
@@ -402,27 +415,55 @@ static int tsmf_plugin_terminated(IWTSPlugin* pPlugin)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tsmf_process_plugin_data(IWTSPlugin* pPlugin, RDP_PLUGIN_DATA* data)
|
||||
COMMAND_LINE_ARGUMENT_A tsmf_args[] =
|
||||
{
|
||||
{ "audio", COMMAND_LINE_VALUE_REQUIRED, "<subsystem>", NULL, NULL, -1, NULL, "audio subsystem" },
|
||||
{ "audio-dev", COMMAND_LINE_VALUE_REQUIRED, "<device>", NULL, NULL, -1, NULL, "audio device name" },
|
||||
{ "decoder", COMMAND_LINE_VALUE_REQUIRED, "<subsystem>", NULL, NULL, -1, NULL, "decoder subsystem" },
|
||||
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
|
||||
};
|
||||
|
||||
static void tsmf_process_addin_args(IWTSPlugin* pPlugin, ADDIN_ARGV* args)
|
||||
{
|
||||
int status;
|
||||
DWORD flags;
|
||||
COMMAND_LINE_ARGUMENT_A* arg;
|
||||
TSMF_PLUGIN* tsmf = (TSMF_PLUGIN*) pPlugin;
|
||||
|
||||
while (data && data->size > 0)
|
||||
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON;
|
||||
|
||||
status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv,
|
||||
tsmf_args, flags, tsmf, NULL, NULL);
|
||||
|
||||
arg = tsmf_args;
|
||||
|
||||
do
|
||||
{
|
||||
if (data->data[0] && ( strcmp((char*)data->data[0], "tsmf") == 0 || strstr((char*)data->data[0], "/tsmf.") != NULL) )
|
||||
if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT))
|
||||
continue;
|
||||
|
||||
CommandLineSwitchStart(arg)
|
||||
|
||||
CommandLineSwitchCase(arg, "audio")
|
||||
{
|
||||
if (data->data[1] && strcmp((char*)data->data[1], "decoder") == 0)
|
||||
{
|
||||
tsmf->decoder_name = data->data[2];
|
||||
}
|
||||
else if (data->data[1] && strcmp((char*)data->data[1], "audio") == 0)
|
||||
{
|
||||
tsmf->audio_name = data->data[2];
|
||||
tsmf->audio_device = data->data[3];
|
||||
}
|
||||
tsmf->audio_name = _strdup(arg->Value);
|
||||
}
|
||||
|
||||
data = (RDP_PLUGIN_DATA*)(((BYTE*)data) + data->size);
|
||||
CommandLineSwitchCase(arg, "audio-dev")
|
||||
{
|
||||
tsmf->audio_device = _strdup(arg->Value);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "decoder")
|
||||
{
|
||||
tsmf->decoder_name = _strdup(arg->Value);
|
||||
}
|
||||
CommandLineSwitchDefault(arg)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CommandLineSwitchEnd(arg)
|
||||
}
|
||||
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
@@ -431,29 +472,29 @@ static void tsmf_process_plugin_data(IWTSPlugin* pPlugin, RDP_PLUGIN_DATA* data)
|
||||
|
||||
int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
|
||||
{
|
||||
int error = 0;
|
||||
int status = 0;
|
||||
TSMF_PLUGIN* tsmf;
|
||||
|
||||
tsmf = (TSMF_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "tsmf");
|
||||
|
||||
if (tsmf == NULL)
|
||||
{
|
||||
tsmf = xnew(TSMF_PLUGIN);
|
||||
tsmf = (TSMF_PLUGIN*) malloc(sizeof(TSMF_PLUGIN));
|
||||
ZeroMemory(tsmf, sizeof(TSMF_PLUGIN));
|
||||
|
||||
tsmf->iface.Initialize = tsmf_plugin_initialize;
|
||||
tsmf->iface.Connected = NULL;
|
||||
tsmf->iface.Disconnected = NULL;
|
||||
tsmf->iface.Terminated = tsmf_plugin_terminated;
|
||||
error = pEntryPoints->RegisterPlugin(pEntryPoints, "tsmf", (IWTSPlugin*) tsmf);
|
||||
status = pEntryPoints->RegisterPlugin(pEntryPoints, "tsmf", (IWTSPlugin*) tsmf);
|
||||
|
||||
tsmf_media_init();
|
||||
}
|
||||
if (error == 0)
|
||||
|
||||
if (status == 0)
|
||||
{
|
||||
tsmf_process_plugin_data((IWTSPlugin*) tsmf,
|
||||
pEntryPoints->GetPluginData(pEntryPoints));
|
||||
tsmf_process_addin_args((IWTSPlugin*) tsmf, pEntryPoints->GetPluginData(pEntryPoints));
|
||||
}
|
||||
|
||||
return error;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,14 +35,15 @@
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/list.h>
|
||||
#include <freerdp/utils/thread.h>
|
||||
#include <freerdp/utils/event.h>
|
||||
#include <freerdp/utils/sleep.h>
|
||||
#include <freerdp/client/tsmf.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/synch.h>
|
||||
|
||||
#include "tsmf_constants.h"
|
||||
@@ -271,7 +272,8 @@ TSMF_PRESENTATION* tsmf_presentation_new(const BYTE* guid, IWTSVirtualChannelCal
|
||||
return NULL;
|
||||
}
|
||||
|
||||
presentation = xnew(TSMF_PRESENTATION);
|
||||
presentation = (TSMF_PRESENTATION*) malloc(sizeof(TSMF_PRESENTATION));
|
||||
ZeroMemory(presentation, sizeof(TSMF_PRESENTATION));
|
||||
|
||||
memcpy(presentation->presentation_id, guid, GUID_SIZE);
|
||||
presentation->channel_callback = pChannelCallback;
|
||||
@@ -339,7 +341,7 @@ static void tsmf_sample_playback_video(TSMF_SAMPLE* sample)
|
||||
(sample->end_time >= presentation->audio_start_time ||
|
||||
sample->end_time < stream->last_end_time))
|
||||
{
|
||||
freerdp_usleep((stream->next_start_time - t) / 10);
|
||||
USleep((stream->next_start_time - t) / 10);
|
||||
}
|
||||
stream->next_start_time = t + sample->duration - 50000;
|
||||
|
||||
@@ -364,10 +366,14 @@ static void tsmf_sample_playback_video(TSMF_SAMPLE* sample)
|
||||
free(presentation->last_rects);
|
||||
presentation->last_rects = NULL;
|
||||
}
|
||||
|
||||
presentation->last_num_rects = presentation->output_num_rects;
|
||||
|
||||
if (presentation->last_num_rects > 0)
|
||||
{
|
||||
presentation->last_rects = xzalloc(presentation->last_num_rects * sizeof(RDP_RECT));
|
||||
presentation->last_rects = malloc(presentation->last_num_rects * sizeof(RDP_RECT));
|
||||
ZeroMemory(presentation->last_rects, presentation->last_num_rects * sizeof(RDP_RECT));
|
||||
|
||||
memcpy(presentation->last_rects, presentation->output_rects,
|
||||
presentation->last_num_rects * sizeof(RDP_RECT));
|
||||
}
|
||||
@@ -384,10 +390,14 @@ static void tsmf_sample_playback_video(TSMF_SAMPLE* sample)
|
||||
vevent->y = presentation->output_y;
|
||||
vevent->width = presentation->output_width;
|
||||
vevent->height = presentation->output_height;
|
||||
|
||||
if (presentation->output_num_rects > 0)
|
||||
{
|
||||
vevent->num_visible_rects = presentation->output_num_rects;
|
||||
vevent->visible_rects = (RDP_RECT*) xzalloc(presentation->output_num_rects * sizeof(RDP_RECT));
|
||||
|
||||
vevent->visible_rects = (RDP_RECT*) malloc(presentation->output_num_rects * sizeof(RDP_RECT));
|
||||
ZeroMemory(vevent->visible_rects, presentation->output_num_rects * sizeof(RDP_RECT));
|
||||
|
||||
memcpy(vevent->visible_rects, presentation->output_rects,
|
||||
presentation->output_num_rects * sizeof(RDP_RECT));
|
||||
}
|
||||
@@ -567,10 +577,13 @@ static void tsmf_sample_playback(TSMF_SAMPLE* sample)
|
||||
free(presentation->last_rects);
|
||||
presentation->last_rects = NULL;
|
||||
}
|
||||
|
||||
presentation->last_num_rects = presentation->output_num_rects;
|
||||
|
||||
if (presentation->last_num_rects > 0)
|
||||
{
|
||||
presentation->last_rects = xzalloc(presentation->last_num_rects * sizeof(RDP_RECT));
|
||||
presentation->last_rects = malloc(presentation->last_num_rects * sizeof(RDP_RECT));
|
||||
ZeroMemory(presentation->last_rects, presentation->last_num_rects * sizeof(RDP_RECT));
|
||||
memcpy(presentation->last_rects, presentation->output_rects, presentation->last_num_rects * sizeof(RDP_RECT));
|
||||
}
|
||||
if(stream->decoder->UpdateRenderingArea)
|
||||
@@ -661,10 +674,11 @@ static void* tsmf_stream_playback_func(void* arg)
|
||||
{
|
||||
tsmf_stream_process_ack(stream);
|
||||
sample = tsmf_stream_pop_sample(stream, 1);
|
||||
|
||||
if (sample)
|
||||
tsmf_sample_playback(sample);
|
||||
else
|
||||
freerdp_usleep(5000);
|
||||
USleep(5000);
|
||||
}
|
||||
if (stream->eos || presentation->eos)
|
||||
{
|
||||
@@ -921,7 +935,8 @@ TSMF_STREAM* tsmf_stream_new(TSMF_PRESENTATION* presentation, UINT32 stream_id)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
stream = xnew(TSMF_STREAM);
|
||||
stream = (TSMF_STREAM*) malloc(sizeof(TSMF_STREAM));
|
||||
ZeroMemory(stream, sizeof(TSMF_STREAM));
|
||||
|
||||
stream->stream_id = stream_id;
|
||||
stream->presentation = presentation;
|
||||
@@ -1035,7 +1050,8 @@ void tsmf_stream_push_sample(TSMF_STREAM* stream, IWTSVirtualChannelCallback* pC
|
||||
|
||||
ReleaseMutex(tsmf_mutex);
|
||||
|
||||
sample = xnew(TSMF_SAMPLE);
|
||||
sample = (TSMF_SAMPLE*) malloc(sizeof(TSMF_SAMPLE));
|
||||
ZeroMemory(sample, sizeof(TSMF_SAMPLE));
|
||||
|
||||
sample->sample_id = sample_id;
|
||||
sample->start_time = start_time;
|
||||
@@ -1045,7 +1061,8 @@ void tsmf_stream_push_sample(TSMF_STREAM* stream, IWTSVirtualChannelCallback* pC
|
||||
sample->stream = stream;
|
||||
sample->channel_callback = pChannelCallback;
|
||||
sample->data_size = data_size;
|
||||
sample->data = xzalloc(data_size + TSMF_BUFFER_PADDING_SIZE);
|
||||
sample->data = malloc(data_size + TSMF_BUFFER_PADDING_SIZE);
|
||||
ZeroMemory(sample->data, data_size + TSMF_BUFFER_PADDING_SIZE);
|
||||
memcpy(sample->data, data, data_size);
|
||||
|
||||
freerdp_thread_lock(stream->thread);
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
|
||||
define_channel("urbdrc")
|
||||
|
||||
add_subdirectory(libusb)
|
||||
|
||||
if(WITH_CLIENT_CHANNELS)
|
||||
add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME})
|
||||
endif()
|
||||
|
||||
@@ -3,15 +3,10 @@ set(OPTION_DEFAULT OFF)
|
||||
set(OPTION_CLIENT_DEFAULT OFF)
|
||||
set(OPTION_SERVER_DEFAULT OFF)
|
||||
|
||||
if(${OPTION_CLIENT_DEFAULT} OR ${OPTION_SERVER_DEFAULT})
|
||||
set(OPTION_DEFAULT ON)
|
||||
endif()
|
||||
|
||||
define_channel_options(NAME "urbdrc" TYPE "dynamic"
|
||||
DESCRIPTION "USB Devices Virtual Channel Extension"
|
||||
SPECIFICATIONS "[MS-RDPEUSB]"
|
||||
DEFAULT ${OPTION_DEFAULT})
|
||||
|
||||
define_channel_client_options(${OPTION_CLIENT_DEFAULT})
|
||||
#define_channel_server_options(${OPTION_SERVER_DEFAULT})
|
||||
|
||||
define_channel_server_options(${OPTION_SERVER_DEFAULT})
|
||||
|
||||
@@ -35,17 +35,22 @@ add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
|
||||
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} libusb-devman)
|
||||
#set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} libusb-devman)
|
||||
|
||||
set(${MODULE_PREFIX}_LIBS
|
||||
dbus-glib-1
|
||||
udev
|
||||
uuid)
|
||||
|
||||
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||
MODULE winpr
|
||||
MODULES winpr-utils)
|
||||
|
||||
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||
MODULE freerdp
|
||||
MODULES freerdp-utils)
|
||||
MODULES freerdp-common freerdp-utils)
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
@@ -55,3 +60,5 @@ endif()
|
||||
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")
|
||||
|
||||
# libusb subsystem
|
||||
add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "libusb" "")
|
||||
|
||||
@@ -715,18 +715,19 @@ static int urb_control_transfer(URBDRC_CHANNEL_CALLBACK* callback, BYTE* data,
|
||||
static int urb_bulk_or_interrupt_transfer(URBDRC_CHANNEL_CALLBACK* callback, BYTE* data,
|
||||
UINT32 data_sizem, UINT32 MessageId, IUDEVMAN* udevman, UINT32 UsbDevice, int transferDir)
|
||||
{
|
||||
IUDEVICE * pdev;
|
||||
UINT32 out_size, RequestId, InterfaceId, EndpointAddress, PipeHandle;
|
||||
UINT32 TransferFlags, OutputBufferSize, usbd_status = 0;
|
||||
BYTE * Buffer;
|
||||
BYTE * out_data;
|
||||
int offset;
|
||||
int offset;
|
||||
BYTE* Buffer;
|
||||
IUDEVICE* pdev;
|
||||
BYTE* out_data;
|
||||
UINT32 out_size, RequestId, InterfaceId, EndpointAddress, PipeHandle;
|
||||
UINT32 TransferFlags, OutputBufferSize, usbd_status = 0;
|
||||
|
||||
pdev = udevman->get_udevice_by_UsbDevice(udevman, UsbDevice);
|
||||
|
||||
if (pdev == NULL)
|
||||
return 0;
|
||||
|
||||
InterfaceId = ((STREAM_ID_PROXY<<30) | pdev->get_ReqCompletion(pdev));
|
||||
InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
|
||||
|
||||
data_read_UINT32(data + 0, RequestId);
|
||||
data_read_UINT32(data + 4, PipeHandle);
|
||||
@@ -740,7 +741,8 @@ static int urb_bulk_or_interrupt_transfer(URBDRC_CHANNEL_CALLBACK* callback, BYT
|
||||
else
|
||||
out_size = 36 + OutputBufferSize;
|
||||
|
||||
out_data = (BYTE *) malloc(out_size);
|
||||
Buffer = NULL;
|
||||
out_data = (BYTE*) malloc(out_size);
|
||||
memset(out_data, 0, out_size);
|
||||
|
||||
switch (transferDir)
|
||||
@@ -748,10 +750,12 @@ static int urb_bulk_or_interrupt_transfer(URBDRC_CHANNEL_CALLBACK* callback, BYT
|
||||
case USBD_TRANSFER_DIRECTION_OUT:
|
||||
Buffer = data + offset;
|
||||
break;
|
||||
|
||||
case USBD_TRANSFER_DIRECTION_IN:
|
||||
Buffer = out_data + 36;
|
||||
break;
|
||||
}
|
||||
|
||||
/** process URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER */
|
||||
pdev->bulk_or_interrupt_transfer(
|
||||
pdev, RequestId, EndpointAddress,
|
||||
@@ -794,8 +798,7 @@ static int urb_bulk_or_interrupt_transfer(URBDRC_CHANNEL_CALLBACK* callback, BYT
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
urb_isoch_transfer(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data,
|
||||
static int urb_isoch_transfer(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data,
|
||||
UINT32 data_sizem,
|
||||
UINT32 MessageId,
|
||||
IUDEVMAN * udevman,
|
||||
@@ -959,8 +962,7 @@ urb_isoch_transfer(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
urb_control_descriptor_request(URBDRC_CHANNEL_CALLBACK * callback,
|
||||
static int urb_control_descriptor_request(URBDRC_CHANNEL_CALLBACK* callback,
|
||||
BYTE * data,
|
||||
UINT32 data_sizem,
|
||||
UINT32 MessageId,
|
||||
@@ -969,17 +971,19 @@ urb_control_descriptor_request(URBDRC_CHANNEL_CALLBACK * callback,
|
||||
BYTE func_recipient,
|
||||
int transferDir)
|
||||
{
|
||||
IUDEVICE * pdev;
|
||||
UINT32 out_size, InterfaceId, RequestId, OutputBufferSize, usbd_status;
|
||||
BYTE bmRequestType, desc_index, desc_type;
|
||||
UINT16 langId;
|
||||
BYTE * buffer;
|
||||
BYTE * out_data;
|
||||
int ret, offset;
|
||||
IUDEVICE* pdev;
|
||||
UINT32 out_size, InterfaceId, RequestId, OutputBufferSize, usbd_status;
|
||||
BYTE bmRequestType, desc_index, desc_type;
|
||||
UINT16 langId;
|
||||
BYTE* buffer;
|
||||
BYTE* out_data;
|
||||
int ret, offset;
|
||||
|
||||
pdev = udevman->get_udevice_by_UsbDevice(udevman, UsbDevice);
|
||||
|
||||
if (pdev == NULL)
|
||||
return 0;
|
||||
|
||||
InterfaceId = ((STREAM_ID_PROXY<<30) | pdev->get_ReqCompletion(pdev));
|
||||
data_read_UINT32(data + 0, RequestId);
|
||||
data_read_BYTE(data + 4, desc_index);
|
||||
@@ -1051,11 +1055,7 @@ urb_control_descriptor_request(URBDRC_CHANNEL_CALLBACK * callback,
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static int
|
||||
urb_control_get_status_request(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data,
|
||||
static int urb_control_get_status_request(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data,
|
||||
UINT32 data_sizem,
|
||||
UINT32 MessageId,
|
||||
IUDEVMAN * udevman,
|
||||
@@ -1063,13 +1063,13 @@ urb_control_get_status_request(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data,
|
||||
BYTE func_recipient,
|
||||
int transferDir)
|
||||
{
|
||||
IUDEVICE * pdev;
|
||||
UINT32 out_size, RequestId, InterfaceId, OutputBufferSize, usbd_status;
|
||||
UINT16 Index;
|
||||
BYTE bmRequestType;
|
||||
BYTE * buffer;
|
||||
BYTE * out_data;
|
||||
int offset, ret;
|
||||
IUDEVICE* pdev;
|
||||
UINT32 out_size, RequestId, InterfaceId, OutputBufferSize, usbd_status;
|
||||
UINT16 Index;
|
||||
BYTE bmRequestType;
|
||||
BYTE* buffer;
|
||||
BYTE* out_data;
|
||||
int offset, ret;
|
||||
|
||||
if (transferDir == 0){
|
||||
LLOGLN(urbdrc_debug, ("urb_control_get_status_request: not support transfer out\n"));
|
||||
@@ -1146,8 +1146,7 @@ urb_control_get_status_request(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
urb_control_vendor_or_class_request(URBDRC_CHANNEL_CALLBACK * callback,
|
||||
static int urb_control_vendor_or_class_request(URBDRC_CHANNEL_CALLBACK * callback,
|
||||
BYTE * data,
|
||||
UINT32 data_sizem,
|
||||
UINT32 MessageId,
|
||||
@@ -1157,14 +1156,14 @@ urb_control_vendor_or_class_request(URBDRC_CHANNEL_CALLBACK * callback,
|
||||
BYTE func_recipient,
|
||||
int transferDir)
|
||||
{
|
||||
IUDEVICE * pdev;
|
||||
UINT32 out_size, RequestId, InterfaceId, TransferFlags, usbd_status;
|
||||
UINT32 OutputBufferSize;
|
||||
BYTE ReqTypeReservedBits, Request, bmRequestType;
|
||||
UINT16 Value, Index, Padding;
|
||||
BYTE * buffer;
|
||||
BYTE * out_data;
|
||||
int offset, ret;
|
||||
IUDEVICE* pdev;
|
||||
UINT32 out_size, RequestId, InterfaceId, TransferFlags, usbd_status;
|
||||
UINT32 OutputBufferSize;
|
||||
BYTE ReqTypeReservedBits, Request, bmRequestType;
|
||||
UINT16 Value, Index, Padding;
|
||||
BYTE* buffer;
|
||||
BYTE* out_data;
|
||||
int offset, ret;
|
||||
/** control by vendor command */
|
||||
|
||||
pdev = udevman->get_udevice_by_UsbDevice(udevman, UsbDevice);
|
||||
@@ -1256,8 +1255,7 @@ urb_control_vendor_or_class_request(URBDRC_CHANNEL_CALLBACK * callback,
|
||||
|
||||
|
||||
|
||||
static int
|
||||
urb_os_feature_descriptor_request(URBDRC_CHANNEL_CALLBACK * callback,
|
||||
static int urb_os_feature_descriptor_request(URBDRC_CHANNEL_CALLBACK * callback,
|
||||
BYTE * data,
|
||||
UINT32 data_sizem,
|
||||
UINT32 MessageId,
|
||||
@@ -1265,17 +1263,19 @@ urb_os_feature_descriptor_request(URBDRC_CHANNEL_CALLBACK * callback,
|
||||
UINT32 UsbDevice,
|
||||
int transferDir)
|
||||
{
|
||||
IUDEVICE * pdev;
|
||||
UINT32 out_size, RequestId, InterfaceId, OutputBufferSize, usbd_status;
|
||||
BYTE Recipient, InterfaceNumber, Ms_PageIndex;
|
||||
UINT16 Ms_featureDescIndex;
|
||||
BYTE * out_data;
|
||||
BYTE * buffer;
|
||||
int offset, ret;
|
||||
IUDEVICE* pdev;
|
||||
UINT32 out_size, RequestId, InterfaceId, OutputBufferSize, usbd_status;
|
||||
BYTE Recipient, InterfaceNumber, Ms_PageIndex;
|
||||
UINT16 Ms_featureDescIndex;
|
||||
BYTE* out_data;
|
||||
BYTE* buffer;
|
||||
int offset, ret;
|
||||
|
||||
pdev = udevman->get_udevice_by_UsbDevice(udevman, UsbDevice);
|
||||
|
||||
if (pdev == NULL)
|
||||
return 0;
|
||||
|
||||
InterfaceId = ((STREAM_ID_PROXY<<30) | pdev->get_ReqCompletion(pdev));
|
||||
|
||||
data_read_UINT32(data + 0, RequestId);
|
||||
@@ -1347,14 +1347,11 @@ urb_os_feature_descriptor_request(URBDRC_CHANNEL_CALLBACK * callback,
|
||||
callback->channel->Write(callback->channel, out_size, out_data, NULL);
|
||||
|
||||
zfree(out_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static int
|
||||
urb_pipe_request(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data,
|
||||
static int urb_pipe_request(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data,
|
||||
UINT32 data_sizem,
|
||||
UINT32 MessageId,
|
||||
IUDEVMAN * udevman,
|
||||
@@ -1362,11 +1359,11 @@ urb_pipe_request(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data,
|
||||
int transferDir,
|
||||
int action)
|
||||
{
|
||||
IUDEVICE * pdev;
|
||||
UINT32 out_size, RequestId, InterfaceId, PipeHandle, EndpointAddress;
|
||||
UINT32 OutputBufferSize, usbd_status = 0;
|
||||
BYTE * out_data;
|
||||
int out_offset, ret;
|
||||
IUDEVICE* pdev;
|
||||
UINT32 out_size, RequestId, InterfaceId, PipeHandle, EndpointAddress;
|
||||
UINT32 OutputBufferSize, usbd_status = 0;
|
||||
BYTE* out_data;
|
||||
int out_offset, ret;
|
||||
|
||||
if (transferDir == 0){
|
||||
LLOGLN(urbdrc_debug, ("urb_pipe_request: not support transfer out\n"));
|
||||
@@ -1374,8 +1371,10 @@ urb_pipe_request(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data,
|
||||
}
|
||||
|
||||
pdev = udevman->get_udevice_by_UsbDevice(udevman, UsbDevice);
|
||||
|
||||
if (pdev == NULL)
|
||||
return 0;
|
||||
|
||||
InterfaceId = ((STREAM_ID_PROXY<<30) | pdev->get_ReqCompletion(pdev));
|
||||
|
||||
data_read_UINT32(data + 0, RequestId);
|
||||
@@ -1441,14 +1440,11 @@ urb_pipe_request(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data,
|
||||
if (!pdev->isSigToEnd(pdev))
|
||||
callback->channel->Write(callback->channel, out_size, out_data, NULL);
|
||||
zfree(out_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static int
|
||||
urb_get_current_frame_number(URBDRC_CHANNEL_CALLBACK * callback,
|
||||
static int urb_get_current_frame_number(URBDRC_CHANNEL_CALLBACK* callback,
|
||||
BYTE * data,
|
||||
UINT32 data_sizem,
|
||||
UINT32 MessageId,
|
||||
@@ -1456,10 +1452,10 @@ urb_get_current_frame_number(URBDRC_CHANNEL_CALLBACK * callback,
|
||||
UINT32 UsbDevice,
|
||||
int transferDir)
|
||||
{
|
||||
IUDEVICE * pdev;
|
||||
UINT32 out_size, RequestId, InterfaceId, OutputBufferSize;
|
||||
UINT32 dummy_frames;
|
||||
BYTE * out_data;
|
||||
IUDEVICE* pdev;
|
||||
UINT32 out_size, RequestId, InterfaceId, OutputBufferSize;
|
||||
UINT32 dummy_frames;
|
||||
BYTE* out_data;
|
||||
|
||||
if (transferDir == 0){
|
||||
LLOGLN(urbdrc_debug, ("urb_get_current_frame_number: not support transfer out\n"));
|
||||
@@ -1506,8 +1502,7 @@ urb_get_current_frame_number(URBDRC_CHANNEL_CALLBACK * callback,
|
||||
|
||||
|
||||
/* Unused function for current server */
|
||||
static int
|
||||
urb_control_get_configuration_request(URBDRC_CHANNEL_CALLBACK * callback,
|
||||
static int urb_control_get_configuration_request(URBDRC_CHANNEL_CALLBACK* callback,
|
||||
BYTE * data,
|
||||
UINT32 data_sizem,
|
||||
UINT32 MessageId,
|
||||
@@ -1515,21 +1510,24 @@ urb_control_get_configuration_request(URBDRC_CHANNEL_CALLBACK * callback,
|
||||
UINT32 UsbDevice,
|
||||
int transferDir)
|
||||
{
|
||||
IUDEVICE * pdev;
|
||||
UINT32 out_size, RequestId, InterfaceId, OutputBufferSize, usbd_status;
|
||||
BYTE * buffer;
|
||||
BYTE * out_data;
|
||||
int ret, offset;
|
||||
IUDEVICE* pdev;
|
||||
UINT32 out_size, RequestId, InterfaceId, OutputBufferSize, usbd_status;
|
||||
BYTE* buffer;
|
||||
BYTE* out_data;
|
||||
int ret, offset;
|
||||
|
||||
if (transferDir == 0){
|
||||
if (transferDir == 0)
|
||||
{
|
||||
LLOGLN(urbdrc_debug, ("urb_control_get_configuration_request:"
|
||||
" not support transfer out\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
pdev = udevman->get_udevice_by_UsbDevice(udevman, UsbDevice);
|
||||
|
||||
if (pdev == NULL)
|
||||
return 0;
|
||||
|
||||
InterfaceId = ((STREAM_ID_PROXY<<30) | pdev->get_ReqCompletion(pdev));
|
||||
|
||||
data_read_UINT32(data + 0, RequestId);
|
||||
@@ -1585,8 +1583,7 @@ urb_control_get_configuration_request(URBDRC_CHANNEL_CALLBACK * callback,
|
||||
}
|
||||
|
||||
/* Unused function for current server */
|
||||
static int
|
||||
urb_control_get_interface_request(URBDRC_CHANNEL_CALLBACK * callback,
|
||||
static int urb_control_get_interface_request(URBDRC_CHANNEL_CALLBACK* callback,
|
||||
BYTE * data,
|
||||
UINT32 data_sizem,
|
||||
UINT32 MessageId,
|
||||
@@ -1594,12 +1591,12 @@ urb_control_get_interface_request(URBDRC_CHANNEL_CALLBACK * callback,
|
||||
UINT32 UsbDevice,
|
||||
int transferDir)
|
||||
{
|
||||
IUDEVICE * pdev;
|
||||
UINT32 out_size, RequestId, InterfaceId, OutputBufferSize, usbd_status;
|
||||
UINT16 interface;
|
||||
BYTE * buffer;
|
||||
BYTE * out_data;
|
||||
int ret, offset;
|
||||
IUDEVICE* pdev;
|
||||
UINT32 out_size, RequestId, InterfaceId, OutputBufferSize, usbd_status;
|
||||
UINT16 interface;
|
||||
BYTE* buffer;
|
||||
BYTE* out_data;
|
||||
int ret, offset;
|
||||
|
||||
if (transferDir == 0){
|
||||
LLOGLN(urbdrc_debug, ("urb_control_get_interface_request: not support transfer out\n"));
|
||||
@@ -1662,8 +1659,7 @@ urb_control_get_interface_request(URBDRC_CHANNEL_CALLBACK * callback,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
urb_control_feature_request(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data,
|
||||
static int urb_control_feature_request(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data,
|
||||
UINT32 data_sizem,
|
||||
UINT32 MessageId,
|
||||
IUDEVMAN * udevman,
|
||||
@@ -1672,17 +1668,19 @@ urb_control_feature_request(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data,
|
||||
BYTE command,
|
||||
int transferDir)
|
||||
{
|
||||
IUDEVICE * pdev;
|
||||
UINT32 out_size, RequestId, InterfaceId, OutputBufferSize, usbd_status;
|
||||
UINT16 FeatureSelector, Index;
|
||||
BYTE bmRequestType, bmRequest;
|
||||
BYTE * buffer;
|
||||
BYTE * out_data;
|
||||
int ret, offset;
|
||||
IUDEVICE* pdev;
|
||||
UINT32 out_size, RequestId, InterfaceId, OutputBufferSize, usbd_status;
|
||||
UINT16 FeatureSelector, Index;
|
||||
BYTE bmRequestType, bmRequest;
|
||||
BYTE* buffer;
|
||||
BYTE* out_data;
|
||||
int ret, offset;
|
||||
|
||||
pdev = udevman->get_udevice_by_UsbDevice(udevman, UsbDevice);
|
||||
|
||||
if (pdev == NULL)
|
||||
return 0;
|
||||
|
||||
InterfaceId = ((STREAM_ID_PROXY<<30) | pdev->get_ReqCompletion(pdev));
|
||||
|
||||
data_read_UINT32(data + 0, RequestId);
|
||||
@@ -1765,8 +1763,7 @@ urb_control_feature_request(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
urbdrc_process_transfer_request(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data,
|
||||
static int urbdrc_process_transfer_request(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data,
|
||||
UINT32 data_sizem,
|
||||
UINT32 MessageId,
|
||||
IUDEVMAN * udevman,
|
||||
@@ -2292,13 +2289,13 @@ urbdrc_process_transfer_request(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data,
|
||||
break;
|
||||
default:
|
||||
LLOGLN(urbdrc_debug, ("URB_Func: %x is not found!", URB_Function));
|
||||
break;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void*
|
||||
urbdrc_process_udev_data_transfer(void* arg)
|
||||
void* urbdrc_process_udev_data_transfer(void* arg)
|
||||
{
|
||||
TRANSFER_DATA* transfer_data = (TRANSFER_DATA*) arg;
|
||||
URBDRC_CHANNEL_CALLBACK * callback = transfer_data->callback;
|
||||
@@ -2446,5 +2443,3 @@ urbdrc_process_udev_data_transfer(void* arg)
|
||||
udevman->push_urb(udevman);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -149,9 +149,11 @@ void isoch_queue_free(ISOCH_CALLBACK_QUEUE* queue)
|
||||
while (queue->has_next(queue))
|
||||
{
|
||||
isoch = queue->get_next(queue);
|
||||
|
||||
if (isoch != NULL)
|
||||
queue->unregister_data(queue, isoch);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&queue->isoch_loading);
|
||||
|
||||
pthread_mutex_destroy(&queue->isoch_loading);
|
||||
|
||||
@@ -16,8 +16,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
set(MODULE_NAME "libusb-devman")
|
||||
set(MODULE_PREFIX "CHANNEL_URBDRC_LIBUSB_DEVMAN")
|
||||
define_channel_client_subsystem("urbdrc" "libusb" "")
|
||||
|
||||
set(${MODULE_PREFIX}_SRCS
|
||||
libusb_udevman.c
|
||||
@@ -26,25 +25,27 @@ set(${MODULE_PREFIX}_SRCS
|
||||
request_queue.c
|
||||
request_queue.h)
|
||||
|
||||
include_directories(../client)
|
||||
include_directories(..)
|
||||
|
||||
if(STATIC_CHANNELS)
|
||||
add_library(${MODULE_NAME} STATIC ${${MODULE_PREFIX}_SRCS})
|
||||
else()
|
||||
add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
endif()
|
||||
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
|
||||
|
||||
set(${MODULE_PREFIX}_LIBS
|
||||
${CMAKE_THREAD_LIBS_INIT})
|
||||
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS}
|
||||
dbus-glib-1
|
||||
usb-1.0
|
||||
pthread
|
||||
udev)
|
||||
|
||||
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||
MODULE winpr
|
||||
MODULES winpr-utils)
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
if(NOT STATIC_CHANNELS)
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_PLUGIN_PATH})
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH})
|
||||
endif()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -22,6 +22,11 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/cmdline.h>
|
||||
|
||||
#include <freerdp/addin.h>
|
||||
|
||||
#include "urbdrc_types.h"
|
||||
#include "urbdrc_main.h"
|
||||
|
||||
@@ -61,19 +66,20 @@ struct _UDEVMAN
|
||||
int sem_timeout;
|
||||
|
||||
pthread_mutex_t devman_loading;
|
||||
sem_t sem_urb_lock;
|
||||
sem_t sem_urb_lock;
|
||||
};
|
||||
typedef UDEVMAN * PUDEVMAN;
|
||||
typedef UDEVMAN* PUDEVMAN;
|
||||
|
||||
static void udevman_rewind(IUDEVMAN* idevman)
|
||||
{
|
||||
UDEVMAN * udevman = (UDEVMAN *) idevman;
|
||||
UDEVMAN* udevman = (UDEVMAN*) idevman;
|
||||
udevman->idev = udevman->head;
|
||||
}
|
||||
|
||||
static int udevman_has_next(IUDEVMAN* idevman)
|
||||
{
|
||||
UDEVMAN * udevman = (UDEVMAN *) idevman;
|
||||
UDEVMAN* udevman = (UDEVMAN*) idevman;
|
||||
|
||||
if (udevman->idev == NULL)
|
||||
return 0;
|
||||
else
|
||||
@@ -82,60 +88,63 @@ static int udevman_has_next(IUDEVMAN* idevman)
|
||||
|
||||
static IUDEVICE* udevman_get_next(IUDEVMAN* idevman)
|
||||
{
|
||||
UDEVMAN * udevman = (UDEVMAN*) idevman;
|
||||
UDEVMAN* udevman = (UDEVMAN*) idevman;
|
||||
IUDEVICE* pdev;
|
||||
|
||||
pdev = udevman->idev;
|
||||
udevman->idev = (IUDEVICE*) ((UDEVICE*)udevman->idev)->next;
|
||||
udevman->idev = (IUDEVICE*) ((UDEVICE*) udevman->idev)->next;
|
||||
|
||||
return pdev;
|
||||
}
|
||||
|
||||
static IUDEVICE* udevman_get_udevice_by_addr(IUDEVMAN* idevman, int bus_number, int dev_number)
|
||||
{
|
||||
IUDEVICE * pdev;
|
||||
IUDEVICE* pdev;
|
||||
|
||||
idevman->loading_lock(idevman);
|
||||
idevman->rewind (idevman);
|
||||
while (idevman->has_next (idevman))
|
||||
idevman->rewind(idevman);
|
||||
|
||||
while (idevman->has_next(idevman))
|
||||
{
|
||||
pdev = idevman->get_next (idevman);
|
||||
if (pdev->get_bus_number(pdev) == bus_number &&
|
||||
pdev->get_dev_number(pdev) == dev_number)
|
||||
pdev = idevman->get_next(idevman);
|
||||
|
||||
if ((pdev->get_bus_number(pdev) == bus_number) && (pdev->get_dev_number(pdev) == dev_number))
|
||||
{
|
||||
idevman->loading_unlock(idevman);
|
||||
return pdev;
|
||||
}
|
||||
}
|
||||
|
||||
idevman->loading_unlock(idevman);
|
||||
LLOGLN(libusb_debug, ("%s: bus:%d dev:%d not exist in udevman",
|
||||
__func__, bus_number, dev_number));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int udevman_register_udevice(IUDEVMAN* idevman, int bus_number, int dev_number,
|
||||
int UsbDevice,
|
||||
UINT16 idVendor,
|
||||
UINT16 idProduct,
|
||||
int flag)
|
||||
int UsbDevice, UINT16 idVendor, UINT16 idProduct, int flag)
|
||||
{
|
||||
UDEVMAN * udevman = (UDEVMAN *) idevman;
|
||||
IUDEVICE * pdev = NULL;
|
||||
IUDEVICE ** devArray;
|
||||
UDEVMAN* udevman = (UDEVMAN*) idevman;
|
||||
IUDEVICE* pdev = NULL;
|
||||
IUDEVICE** devArray;
|
||||
int i, num, addnum = 0;
|
||||
|
||||
pdev = (IUDEVICE *)udevman_get_udevice_by_addr(idevman, bus_number, dev_number);
|
||||
pdev = (IUDEVICE*) udevman_get_udevice_by_addr(idevman, bus_number, dev_number);
|
||||
|
||||
if (pdev != NULL)
|
||||
return 0;
|
||||
|
||||
if (flag == UDEVMAN_FLAG_ADD_BY_ADDR)
|
||||
{
|
||||
pdev = udev_new_by_addr(bus_number, dev_number);
|
||||
|
||||
if (pdev == NULL)
|
||||
return 0;
|
||||
|
||||
pdev->set_UsbDevice(pdev, UsbDevice);
|
||||
idevman->loading_lock(idevman);
|
||||
|
||||
if (udevman->head == NULL)
|
||||
{
|
||||
/* linked list is empty */
|
||||
@@ -149,6 +158,7 @@ static int udevman_register_udevice(IUDEVMAN* idevman, int bus_number, int dev_n
|
||||
pdev->set_p_prev(pdev, udevman->tail);
|
||||
udevman->tail = pdev;
|
||||
}
|
||||
|
||||
udevman->device_num += 1;
|
||||
idevman->loading_unlock(idevman);
|
||||
}
|
||||
@@ -157,13 +167,13 @@ static int udevman_register_udevice(IUDEVMAN* idevman, int bus_number, int dev_n
|
||||
addnum = 0;
|
||||
/* register all device that match pid vid */
|
||||
num = udev_new_by_id(idVendor, idProduct, &devArray);
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
{
|
||||
pdev = devArray[i];
|
||||
|
||||
if (udevman_get_udevice_by_addr(idevman,
|
||||
pdev->get_bus_number(pdev),
|
||||
pdev->get_dev_number(pdev))
|
||||
!= NULL)
|
||||
pdev->get_bus_number(pdev), pdev->get_dev_number(pdev)) != NULL)
|
||||
{
|
||||
zfree(pdev);
|
||||
continue;
|
||||
@@ -171,6 +181,7 @@ static int udevman_register_udevice(IUDEVMAN* idevman, int bus_number, int dev_n
|
||||
|
||||
pdev->set_UsbDevice(pdev, UsbDevice);
|
||||
idevman->loading_lock(idevman);
|
||||
|
||||
if (udevman->head == NULL)
|
||||
{
|
||||
/* linked list is empty */
|
||||
@@ -184,10 +195,12 @@ static int udevman_register_udevice(IUDEVMAN* idevman, int bus_number, int dev_n
|
||||
pdev->set_p_prev(pdev, udevman->tail);
|
||||
udevman->tail = pdev;
|
||||
}
|
||||
|
||||
udevman->device_num += 1;
|
||||
idevman->loading_unlock(idevman);
|
||||
addnum++;
|
||||
}
|
||||
|
||||
zfree(devArray);
|
||||
return addnum;
|
||||
}
|
||||
@@ -196,23 +209,24 @@ static int udevman_register_udevice(IUDEVMAN* idevman, int bus_number, int dev_n
|
||||
printf("udevman_register_udevice: function error!!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int udevman_unregister_udevice(IUDEVMAN* idevman, int bus_number, int dev_number)
|
||||
{
|
||||
UDEVMAN * udevman = (UDEVMAN *) idevman;
|
||||
UDEVMAN* udevman = (UDEVMAN*) idevman;
|
||||
UDEVICE * pdev, * dev;
|
||||
int ret = 0, err = 0;
|
||||
|
||||
dev = (UDEVICE *)udevman_get_udevice_by_addr(idevman, bus_number, dev_number);
|
||||
dev = (UDEVICE*) udevman_get_udevice_by_addr(idevman, bus_number, dev_number);
|
||||
|
||||
idevman->loading_lock(idevman);
|
||||
idevman->rewind(idevman);
|
||||
|
||||
while (idevman->has_next(idevman) != 0)
|
||||
{
|
||||
pdev = (UDEVICE *)idevman->get_next(idevman);
|
||||
pdev = (UDEVICE*) idevman->get_next(idevman);
|
||||
|
||||
if (pdev == dev) /* device exists */
|
||||
{
|
||||
@@ -280,30 +294,33 @@ static int udevman_unregister_udevice(IUDEVMAN* idevman, int bus_number, int dev
|
||||
return 1; /* unregistration successful */
|
||||
}
|
||||
|
||||
|
||||
/* if we reach this point, the device wasn't found */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void udevman_parse_device_addr (char *str, int *id1, int *id2, char sign)
|
||||
static void udevman_parse_device_addr(char* str, int* id1, int* id2, char sign)
|
||||
{
|
||||
char s1[8], *s2;
|
||||
memset(s1, 0, sizeof(s1));
|
||||
char s1[8];
|
||||
char* s2;
|
||||
|
||||
ZeroMemory(s1, sizeof(s1));
|
||||
|
||||
s2 = (strchr(str, sign)) + 1;
|
||||
strncpy(s1, str, strlen(str) - (strlen(s2)+1));
|
||||
strncpy(s1, str, strlen(str) - (strlen(s2) + 1));
|
||||
|
||||
*id1 = atoi(s1);
|
||||
*id2 = atoi(s2);
|
||||
}
|
||||
|
||||
static void udevman_parse_device_pid_vid (char *str, int *id1, int *id2, char sign)
|
||||
static void udevman_parse_device_pid_vid(char* str, int* id1, int* id2, char sign)
|
||||
{
|
||||
char s1[8], *s2;
|
||||
memset(s1, 0, sizeof(s1));
|
||||
char s1[8];
|
||||
char* s2;
|
||||
|
||||
ZeroMemory(s1, sizeof(s1));
|
||||
|
||||
s2 = (strchr(str, sign)) + 1;
|
||||
strncpy(s1, str, strlen(str) - (strlen(s2)+1));
|
||||
strncpy(s1, str, strlen(str) - (strlen(s2) + 1));
|
||||
|
||||
*id1 = (int) strtol(s1, NULL, 16);
|
||||
*id2 = (int) strtol(s2, NULL, 16);
|
||||
@@ -311,7 +328,7 @@ static void udevman_parse_device_pid_vid (char *str, int *id1, int *id2, char si
|
||||
|
||||
static int udevman_check_device_exist_by_id(IUDEVMAN* idevman, UINT16 idVendor, UINT16 idProduct)
|
||||
{
|
||||
if (libusb_open_device_with_vid_pid (NULL, idVendor, idProduct))
|
||||
if (libusb_open_device_with_vid_pid(NULL, idVendor, idProduct))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
@@ -319,106 +336,113 @@ static int udevman_check_device_exist_by_id(IUDEVMAN* idevman, UINT16 idVendor,
|
||||
|
||||
static int udevman_is_auto_add(IUDEVMAN* idevman)
|
||||
{
|
||||
UDEVMAN * udevman = (UDEVMAN *) idevman;
|
||||
UDEVMAN* udevman = (UDEVMAN*) idevman;
|
||||
return (udevman->flags & UDEVMAN_FLAG_ADD_BY_AUTO) ? 1 : 0;
|
||||
}
|
||||
|
||||
static IUDEVICE* udevman_get_udevice_by_UsbDevice_try_again(IUDEVMAN* idevman, UINT32 UsbDevice)
|
||||
{
|
||||
UDEVICE * pdev;
|
||||
UDEVICE* pdev;
|
||||
idevman->loading_lock(idevman);
|
||||
idevman->rewind (idevman);
|
||||
while (idevman->has_next (idevman))
|
||||
idevman->rewind(idevman);
|
||||
|
||||
while (idevman->has_next(idevman))
|
||||
{
|
||||
pdev = (UDEVICE *)idevman->get_next (idevman);
|
||||
pdev = (UDEVICE*) idevman->get_next(idevman);
|
||||
|
||||
if (pdev->UsbDevice == UsbDevice)
|
||||
{
|
||||
idevman->loading_unlock(idevman);
|
||||
return (IUDEVICE *)pdev;
|
||||
return (IUDEVICE*) pdev;
|
||||
}
|
||||
}
|
||||
|
||||
idevman->loading_unlock(idevman);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static IUDEVICE* udevman_get_udevice_by_UsbDevice(IUDEVMAN* idevman, UINT32 UsbDevice)
|
||||
{
|
||||
UDEVICE * pdev;
|
||||
UDEVICE* pdev;
|
||||
idevman->loading_lock(idevman);
|
||||
idevman->rewind (idevman);
|
||||
while (idevman->has_next (idevman))
|
||||
idevman->rewind(idevman);
|
||||
|
||||
while (idevman->has_next(idevman))
|
||||
{
|
||||
pdev = (UDEVICE *)idevman->get_next (idevman);
|
||||
pdev = (UDEVICE*) idevman->get_next(idevman);
|
||||
|
||||
if (pdev->UsbDevice == UsbDevice)
|
||||
{
|
||||
idevman->loading_unlock(idevman);
|
||||
return (IUDEVICE *)pdev;
|
||||
return (IUDEVICE*) pdev;
|
||||
}
|
||||
}
|
||||
|
||||
idevman->loading_unlock(idevman);
|
||||
|
||||
/* try again */
|
||||
pdev = (UDEVICE *)idevman->get_udevice_by_UsbDevice_try_again(idevman, UsbDevice);
|
||||
|
||||
pdev = (UDEVICE*) idevman->get_udevice_by_UsbDevice_try_again(idevman, UsbDevice);
|
||||
|
||||
if (pdev)
|
||||
{
|
||||
return (IUDEVICE *)pdev;
|
||||
return (IUDEVICE*) pdev;
|
||||
}
|
||||
|
||||
LLOGLN(libusb_debug, ("udevman_get_udevice_by_UsbDevice: 0x%x ERROR!!\n",
|
||||
UsbDevice));
|
||||
LLOGLN(libusb_debug, ("udevman_get_udevice_by_UsbDevice: 0x%x ERROR!!\n", UsbDevice));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void udevman_loading_lock(IUDEVMAN* idevman)
|
||||
{
|
||||
UDEVMAN * udevman = (UDEVMAN *) idevman;
|
||||
UDEVMAN* udevman = (UDEVMAN*) idevman;
|
||||
pthread_mutex_lock(&udevman->devman_loading);
|
||||
}
|
||||
|
||||
static void udevman_loading_unlock(IUDEVMAN* idevman)
|
||||
{
|
||||
UDEVMAN * udevman = (UDEVMAN *) idevman;
|
||||
UDEVMAN* udevman = (UDEVMAN*) idevman;
|
||||
pthread_mutex_unlock(&udevman->devman_loading);
|
||||
}
|
||||
|
||||
|
||||
static void udevman_wait_urb(IUDEVMAN* idevman)
|
||||
{
|
||||
UDEVMAN * udevman = (UDEVMAN *) idevman;
|
||||
UDEVMAN* udevman = (UDEVMAN*) idevman;
|
||||
sem_wait(&udevman->sem_urb_lock);
|
||||
}
|
||||
|
||||
|
||||
static void udevman_push_urb(IUDEVMAN* idevman)
|
||||
{
|
||||
UDEVMAN * udevman = (UDEVMAN *) idevman;
|
||||
UDEVMAN* udevman = (UDEVMAN*) idevman;
|
||||
sem_post(&udevman->sem_urb_lock);
|
||||
}
|
||||
|
||||
|
||||
BASIC_STATE_FUNC_DEFINED(defUsbDevice, UINT32)
|
||||
BASIC_STATE_FUNC_DEFINED(device_num, int)
|
||||
BASIC_STATE_FUNC_DEFINED(sem_timeout, int)
|
||||
|
||||
|
||||
static void udevman_free(IUDEVMAN* idevman)
|
||||
{
|
||||
UDEVMAN * udevman = (UDEVMAN *) idevman;
|
||||
UDEVMAN* udevman = (UDEVMAN*) idevman;
|
||||
|
||||
pthread_mutex_destroy(&udevman->devman_loading);
|
||||
sem_destroy(&udevman->sem_urb_lock);
|
||||
|
||||
libusb_exit(NULL);
|
||||
|
||||
/* free udevman */
|
||||
|
||||
if (udevman)
|
||||
zfree(udevman);
|
||||
}
|
||||
|
||||
|
||||
static void udevman_load_interface(UDEVMAN * udevman)
|
||||
{
|
||||
/* standard */
|
||||
udevman->iface.free = udevman_free;
|
||||
|
||||
/* manage devices */
|
||||
udevman->iface.rewind = udevman_rewind;
|
||||
udevman->iface.get_next = udevman_get_next;
|
||||
@@ -428,13 +452,16 @@ static void udevman_load_interface(UDEVMAN * udevman)
|
||||
udevman->iface.get_udevice_by_UsbDevice = udevman_get_udevice_by_UsbDevice;
|
||||
udevman->iface.get_udevice_by_UsbDevice_try_again =
|
||||
udevman_get_udevice_by_UsbDevice_try_again;
|
||||
|
||||
/* Extension */
|
||||
udevman->iface.check_device_exist_by_id = udevman_check_device_exist_by_id;
|
||||
udevman->iface.isAutoAdd = udevman_is_auto_add;
|
||||
|
||||
/* Basic state */
|
||||
BASIC_STATE_FUNC_REGISTER(defUsbDevice, udevman);
|
||||
BASIC_STATE_FUNC_REGISTER(device_num, udevman);
|
||||
BASIC_STATE_FUNC_REGISTER(sem_timeout, udevman);
|
||||
|
||||
/* control semaphore or mutex lock */
|
||||
udevman->iface.loading_lock = udevman_loading_lock;
|
||||
udevman->iface.loading_unlock = udevman_loading_unlock;
|
||||
@@ -442,25 +469,127 @@ static void udevman_load_interface(UDEVMAN * udevman)
|
||||
udevman->iface.wait_urb = udevman_wait_urb;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int FreeRDPUDEVMANEntry(PFREERDP_URBDRC_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
COMMAND_LINE_ARGUMENT_A urbdrc_udevman_args[] =
|
||||
{
|
||||
UDEVMAN* udevman;
|
||||
RDP_PLUGIN_DATA * plugin_data = pEntryPoints->plugin_data;
|
||||
UINT32 UsbDevice = BASE_USBDEVICE_NUM;
|
||||
char * token;
|
||||
char * message = "id";
|
||||
char hardware_id[16];
|
||||
{ "dbg", COMMAND_LINE_VALUE_FLAG, "", NULL, BoolValueFalse, -1, NULL, "debug" },
|
||||
{ "dev", COMMAND_LINE_VALUE_REQUIRED, "<devices>", NULL, NULL, -1, NULL, "device list" },
|
||||
{ "id", COMMAND_LINE_VALUE_FLAG, "", NULL, BoolValueFalse, -1, NULL, "FLAG_ADD_BY_VID_PID" },
|
||||
{ "addr", COMMAND_LINE_VALUE_FLAG, "", NULL, BoolValueFalse, -1, NULL, "FLAG_ADD_BY_ADDR" },
|
||||
{ "auto", COMMAND_LINE_VALUE_FLAG, "", NULL, BoolValueFalse, -1, NULL, "FLAG_ADD_BY_AUTO" },
|
||||
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
|
||||
};
|
||||
|
||||
static void urbdrc_udevman_register_devices(UDEVMAN* udevman, char* devices)
|
||||
{
|
||||
char* token;
|
||||
int idVendor;
|
||||
int idProduct;
|
||||
int bus_number;
|
||||
int dev_number;
|
||||
int bus_number;
|
||||
int dev_number;
|
||||
int success = 0;
|
||||
char hardware_id[16];
|
||||
char* default_devices = "id";
|
||||
UINT32 UsbDevice = BASE_USBDEVICE_NUM;
|
||||
|
||||
if (!devices)
|
||||
devices = default_devices;
|
||||
|
||||
/* register all usb devices */
|
||||
token = strtok(devices, "#");
|
||||
|
||||
while (token)
|
||||
{
|
||||
bus_number = 0;
|
||||
dev_number = 0;
|
||||
idVendor = 0;
|
||||
idProduct = 0;
|
||||
|
||||
strcpy(hardware_id, token);
|
||||
token = strtok(NULL, "#");
|
||||
|
||||
if (udevman->flags & UDEVMAN_FLAG_ADD_BY_VID_PID)
|
||||
{
|
||||
udevman_parse_device_pid_vid(hardware_id, &idVendor, &idProduct, ':');
|
||||
success = udevman->iface.register_udevice((IUDEVMAN*) udevman,
|
||||
0, 0, UsbDevice, (UINT16) idVendor, (UINT16) idProduct, UDEVMAN_FLAG_ADD_BY_VID_PID);
|
||||
}
|
||||
else if (udevman->flags & UDEVMAN_FLAG_ADD_BY_ADDR)
|
||||
{
|
||||
udevman_parse_device_addr(hardware_id, &bus_number, &dev_number, ':');
|
||||
|
||||
success = udevman->iface.register_udevice((IUDEVMAN*) udevman,
|
||||
bus_number, dev_number, UsbDevice, 0, 0, UDEVMAN_FLAG_ADD_BY_ADDR);
|
||||
}
|
||||
|
||||
if (success)
|
||||
UsbDevice++;
|
||||
}
|
||||
|
||||
udevman->defUsbDevice = UsbDevice;
|
||||
}
|
||||
|
||||
static void urbdrc_udevman_parse_addin_args(UDEVMAN* udevman, ADDIN_ARGV* args)
|
||||
{
|
||||
int status;
|
||||
DWORD flags;
|
||||
COMMAND_LINE_ARGUMENT_A* arg;
|
||||
|
||||
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON;
|
||||
|
||||
status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv,
|
||||
urbdrc_udevman_args, flags, udevman, NULL, NULL);
|
||||
|
||||
arg = urbdrc_udevman_args;
|
||||
|
||||
do
|
||||
{
|
||||
if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT))
|
||||
continue;
|
||||
|
||||
CommandLineSwitchStart(arg)
|
||||
|
||||
CommandLineSwitchCase(arg, "dbg")
|
||||
{
|
||||
urbdrc_debug = 0;
|
||||
}
|
||||
CommandLineSwitchCase(arg, "dev")
|
||||
{
|
||||
urbdrc_udevman_register_devices(udevman, arg->Value);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "id")
|
||||
{
|
||||
udevman->flags = UDEVMAN_FLAG_ADD_BY_VID_PID;
|
||||
}
|
||||
CommandLineSwitchCase(arg, "addr")
|
||||
{
|
||||
udevman->flags = UDEVMAN_FLAG_ADD_BY_ADDR;
|
||||
}
|
||||
CommandLineSwitchCase(arg, "auto")
|
||||
{
|
||||
udevman->flags |= UDEVMAN_FLAG_ADD_BY_AUTO;
|
||||
}
|
||||
CommandLineSwitchDefault(arg)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CommandLineSwitchEnd(arg)
|
||||
}
|
||||
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define freerdp_urbdrc_client_subsystem_entry libusb_freerdp_urbdrc_client_subsystem_entry
|
||||
#endif
|
||||
|
||||
int freerdp_urbdrc_client_subsystem_entry(PFREERDP_URBDRC_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
{
|
||||
UDEVMAN* udevman;
|
||||
ADDIN_ARGV* args = pEntryPoints->args;
|
||||
|
||||
libusb_init(NULL);
|
||||
|
||||
udevman = (PUDEVMAN)malloc(sizeof(UDEVMAN));
|
||||
udevman = (PUDEVMAN) malloc(sizeof(UDEVMAN));
|
||||
udevman->device_num = 0;
|
||||
udevman->idev = NULL;
|
||||
udevman->head = NULL;
|
||||
@@ -474,66 +603,11 @@ int FreeRDPUDEVMANEntry(PFREERDP_URBDRC_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
/* load usb device service management */
|
||||
udevman_load_interface(udevman);
|
||||
|
||||
/* set debug flag, to enable Debug message for usb data transfer*/
|
||||
if (plugin_data->data[2])
|
||||
message = (char *)plugin_data->data[2];
|
||||
/* set debug flag, to enable Debug message for usb data transfer */
|
||||
|
||||
if (strstr(message, "id"))
|
||||
udevman->flags = UDEVMAN_FLAG_ADD_BY_VID_PID;
|
||||
else if (strstr(message, "addr"))
|
||||
udevman->flags = UDEVMAN_FLAG_ADD_BY_ADDR;
|
||||
|
||||
if (strstr(message, "auto"))
|
||||
udevman->flags |= UDEVMAN_FLAG_ADD_BY_AUTO;
|
||||
libusb_debug = 10;
|
||||
if (strstr(message, "debug"))
|
||||
{
|
||||
libusb_debug = 0;
|
||||
udevman->flags |= UDEVMAN_FLAG_DEBUG;
|
||||
}
|
||||
/* register all usb device */
|
||||
token = strtok((char *)plugin_data->data[1], "#");
|
||||
while (token)
|
||||
{
|
||||
bus_number = 0;
|
||||
dev_number = 0;
|
||||
idVendor = 0;
|
||||
idProduct = 0;
|
||||
|
||||
strcpy(hardware_id, token);
|
||||
token = strtok(NULL, "#");
|
||||
if (udevman->flags & UDEVMAN_FLAG_ADD_BY_VID_PID)
|
||||
{
|
||||
udevman_parse_device_pid_vid(hardware_id, &idVendor,
|
||||
&idProduct,
|
||||
'_');
|
||||
success = udevman->iface.register_udevice((IUDEVMAN *)udevman,
|
||||
0,
|
||||
0,
|
||||
UsbDevice,
|
||||
(UINT16) idVendor,
|
||||
(UINT16) idProduct,
|
||||
UDEVMAN_FLAG_ADD_BY_VID_PID);
|
||||
}
|
||||
else if (udevman->flags & UDEVMAN_FLAG_ADD_BY_ADDR)
|
||||
{
|
||||
udevman_parse_device_addr(hardware_id, &bus_number,
|
||||
&dev_number,
|
||||
'_');
|
||||
success = udevman->iface.register_udevice((IUDEVMAN *)udevman,
|
||||
bus_number,
|
||||
dev_number,
|
||||
UsbDevice,
|
||||
0,
|
||||
0,
|
||||
UDEVMAN_FLAG_ADD_BY_ADDR);
|
||||
}
|
||||
|
||||
if (success)
|
||||
UsbDevice++;
|
||||
}
|
||||
|
||||
udevman->defUsbDevice = UsbDevice;
|
||||
urbdrc_udevman_parse_addin_args(udevman, args);
|
||||
|
||||
pEntryPoints->pRegisterUDEVMAN(pEntryPoints->plugin, (IUDEVMAN*) udevman);
|
||||
|
||||
@@ -43,12 +43,11 @@ int request_queue_has_next(REQUEST_QUEUE* queue)
|
||||
}
|
||||
|
||||
TRANSFER_REQUEST* request_queue_register_request(REQUEST_QUEUE* queue, UINT32 RequestId,
|
||||
struct libusb_transfer * transfer,
|
||||
BYTE endpoint)
|
||||
struct libusb_transfer* transfer, BYTE endpoint)
|
||||
{
|
||||
TRANSFER_REQUEST* request;
|
||||
TRANSFER_REQUEST* request;
|
||||
|
||||
request = (TRANSFER_REQUEST*)malloc(sizeof(TRANSFER_REQUEST));
|
||||
request = (TRANSFER_REQUEST*) malloc(sizeof(TRANSFER_REQUEST));
|
||||
|
||||
request->prev = NULL;
|
||||
request->next = NULL;
|
||||
@@ -57,7 +56,9 @@ TRANSFER_REQUEST* request_queue_register_request(REQUEST_QUEUE* queue, UINT32 Re
|
||||
request->transfer = transfer;
|
||||
request->endpoint = endpoint;
|
||||
request->submit = 0;
|
||||
|
||||
pthread_mutex_lock(&queue->request_loading);
|
||||
|
||||
if (queue->head == NULL)
|
||||
{
|
||||
/* linked queue is empty */
|
||||
@@ -67,22 +68,24 @@ TRANSFER_REQUEST* request_queue_register_request(REQUEST_QUEUE* queue, UINT32 Re
|
||||
else
|
||||
{
|
||||
/* append data to the end of the linked queue */
|
||||
queue->tail->next = (void*)request;
|
||||
request->prev = (void*)queue->tail;
|
||||
queue->tail->next = (void*) request;
|
||||
request->prev = (void*) queue->tail;
|
||||
queue->tail = request;
|
||||
}
|
||||
|
||||
queue->request_num += 1;
|
||||
pthread_mutex_unlock(&queue->request_loading);
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
void request_queue_rewind(REQUEST_QUEUE *queue)
|
||||
void request_queue_rewind(REQUEST_QUEUE* queue)
|
||||
{
|
||||
queue->ireq = queue->head;
|
||||
}
|
||||
|
||||
/* Get first*/
|
||||
TRANSFER_REQUEST* request_queue_get_request_by_endpoint(REQUEST_QUEUE *queue, BYTE ep)
|
||||
TRANSFER_REQUEST* request_queue_get_request_by_endpoint(REQUEST_QUEUE* queue, BYTE ep)
|
||||
{
|
||||
TRANSFER_REQUEST * request;
|
||||
pthread_mutex_lock(&queue->request_loading);
|
||||
@@ -101,7 +104,7 @@ TRANSFER_REQUEST* request_queue_get_request_by_endpoint(REQUEST_QUEUE *queue, BY
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int request_queue_unregister_request(REQUEST_QUEUE *queue, UINT32 RequestId)
|
||||
int request_queue_unregister_request(REQUEST_QUEUE* queue, UINT32 RequestId)
|
||||
{
|
||||
TRANSFER_REQUEST *request, *request_temp;
|
||||
pthread_mutex_lock(&queue->request_loading);
|
||||
@@ -110,27 +113,28 @@ int request_queue_unregister_request(REQUEST_QUEUE *queue, UINT32 RequestId)
|
||||
while (queue->has_next(queue) != 0)
|
||||
{
|
||||
request = queue->get_next(queue);
|
||||
|
||||
if (request->RequestId == RequestId)
|
||||
{
|
||||
|
||||
if (request->prev != NULL)
|
||||
{
|
||||
request_temp = (TRANSFER_REQUEST*)request->prev;
|
||||
request_temp->next = (TRANSFER_REQUEST*)request->next;
|
||||
request_temp = (TRANSFER_REQUEST*) request->prev;
|
||||
request_temp->next = (TRANSFER_REQUEST*) request->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
queue->head = (TRANSFER_REQUEST*)request->next;
|
||||
queue->head = (TRANSFER_REQUEST*) request->next;
|
||||
}
|
||||
|
||||
if (request->next != NULL)
|
||||
{
|
||||
request_temp = (TRANSFER_REQUEST*)request->next;
|
||||
request_temp->prev = (TRANSFER_REQUEST*)request->prev;
|
||||
request_temp = (TRANSFER_REQUEST*) request->next;
|
||||
request_temp->prev = (TRANSFER_REQUEST*) request->prev;
|
||||
}
|
||||
else
|
||||
{
|
||||
queue->tail = (TRANSFER_REQUEST*)request->prev;
|
||||
queue->tail = (TRANSFER_REQUEST*) request->prev;
|
||||
|
||||
}
|
||||
|
||||
@@ -156,7 +160,7 @@ REQUEST_QUEUE* request_queue_new()
|
||||
{
|
||||
REQUEST_QUEUE* queue;
|
||||
|
||||
queue = (REQUEST_QUEUE*)malloc(sizeof(REQUEST_QUEUE));
|
||||
queue = (REQUEST_QUEUE*) malloc(sizeof(REQUEST_QUEUE));
|
||||
queue->request_num = 0;
|
||||
queue->ireq = NULL;
|
||||
queue->head = NULL;
|
||||
@@ -23,6 +23,10 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/synch.h>
|
||||
|
||||
#include "searchman.h"
|
||||
|
||||
static void searchman_rewind(USB_SEARCHMAN* searchman)
|
||||
@@ -144,7 +148,7 @@ static void searchman_start(USB_SEARCHMAN* self, void* func)
|
||||
/* close thread */
|
||||
static void searchman_close(USB_SEARCHMAN* self)
|
||||
{
|
||||
wait_obj_set(self->term_event);
|
||||
SetEvent(self->term_event);
|
||||
}
|
||||
|
||||
static void searchman_list_show(USB_SEARCHMAN* self)
|
||||
@@ -176,7 +180,7 @@ void searchman_free(USB_SEARCHMAN* self)
|
||||
|
||||
/* free searchman */
|
||||
sem_destroy(&self->sem_term);
|
||||
wait_obj_free(self->term_event);
|
||||
CloseHandle(self->term_event);
|
||||
free(self);
|
||||
}
|
||||
|
||||
@@ -214,7 +218,7 @@ USB_SEARCHMAN* searchman_new(void * urbdrc, UINT32 UsbDevice)
|
||||
searchman->free = searchman_free;
|
||||
|
||||
searchman->strated = 0;
|
||||
searchman->term_event = wait_obj_new();
|
||||
searchman->term_event = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
sem_init(&searchman->sem_term, 0, 0);
|
||||
|
||||
return searchman;
|
||||
|
||||
@@ -22,34 +22,35 @@
|
||||
#define __SEACH_MAN_H
|
||||
|
||||
#include "urbdrc_types.h"
|
||||
#include <freerdp/utils/wait_obj.h>
|
||||
|
||||
typedef struct _USB_SEARCHDEV USB_SEARCHDEV;
|
||||
|
||||
struct _USB_SEARCHDEV
|
||||
{
|
||||
void * inode;
|
||||
void * prev;
|
||||
void * next;
|
||||
void* inode;
|
||||
void* prev;
|
||||
void* next;
|
||||
UINT16 idVendor;
|
||||
UINT16 idProduct;
|
||||
};
|
||||
|
||||
typedef struct _USB_SEARCHMAN USB_SEARCHMAN;
|
||||
|
||||
struct _USB_SEARCHMAN
|
||||
{
|
||||
int usb_numbers;
|
||||
UINT32 UsbDevice;
|
||||
USB_SEARCHDEV * idev; /* iterator device */
|
||||
USB_SEARCHDEV * head; /* head device in linked list */
|
||||
USB_SEARCHDEV * tail; /* tail device in linked list */
|
||||
int usb_numbers;
|
||||
UINT32 UsbDevice;
|
||||
USB_SEARCHDEV* idev; /* iterator device */
|
||||
USB_SEARCHDEV* head; /* head device in linked list */
|
||||
USB_SEARCHDEV* tail; /* tail device in linked list */
|
||||
|
||||
pthread_mutex_t mutex;
|
||||
struct wait_obj * term_event;
|
||||
HANDLE term_event;
|
||||
sem_t sem_term;
|
||||
int strated;
|
||||
|
||||
/* for urbdrc channel call back */
|
||||
void * urbdrc;
|
||||
void* urbdrc;
|
||||
|
||||
/* load service */
|
||||
void (*rewind) (USB_SEARCHMAN* seachman);
|
||||
@@ -71,7 +72,7 @@ struct _USB_SEARCHMAN
|
||||
void (*free) (USB_SEARCHMAN* searchman);
|
||||
};
|
||||
|
||||
USB_SEARCHMAN * searchman_new(void * urbdrc, UINT32 UsbDevice);
|
||||
USB_SEARCHMAN* searchman_new(void* urbdrc, UINT32 UsbDevice);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -25,8 +25,12 @@
|
||||
#include <time.h>
|
||||
#include <libudev.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/synch.h>
|
||||
#include <winpr/cmdline.h>
|
||||
|
||||
#include <freerdp/dvc.h>
|
||||
#include <freerdp/utils/load_plugin.h>
|
||||
#include <freerdp/addin.h>
|
||||
|
||||
#include "urbdrc_types.h"
|
||||
#include "urbdrc_main.h"
|
||||
@@ -54,7 +58,7 @@ static int func_hardware_id_format(IUDEVICE* pdev, char (*HardwareIds)[DEVICE_HA
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int func_compat_id_format(IUDEVICE *pdev, char (*CompatibilityIds)[DEVICE_COMPATIBILITY_ID_SIZE])
|
||||
static int func_compat_id_format(IUDEVICE* pdev, char (*CompatibilityIds)[DEVICE_COMPATIBILITY_ID_SIZE])
|
||||
{
|
||||
char str[DEVICE_COMPATIBILITY_ID_SIZE];
|
||||
int bDeviceClass, bDeviceSubClass, bDeviceProtocol;
|
||||
@@ -260,8 +264,9 @@ static int urbdrc_process_channel_create(URBDRC_CHANNEL_CALLBACK* callback, char
|
||||
InterfaceId = ((STREAM_ID_PROXY<<30) | CLIENT_CHANNEL_NOTIFICATION);
|
||||
|
||||
out_size = 24;
|
||||
out_data = (char *) malloc(out_size);
|
||||
out_data = (char*) malloc(out_size);
|
||||
memset(out_data, 0, out_size);
|
||||
|
||||
data_write_UINT32(out_data + 0, InterfaceId); /* interface id */
|
||||
data_write_UINT32(out_data + 4, MessageId); /* message id */
|
||||
data_write_UINT32(out_data + 8, CHANNEL_CREATED); /* function id */
|
||||
@@ -285,8 +290,9 @@ static int urdbrc_send_virtual_channel_add(IWTSVirtualChannel* channel, UINT32 M
|
||||
InterfaceId = ((STREAM_ID_PROXY<<30) | CLIENT_DEVICE_SINK);
|
||||
|
||||
out_size = 12;
|
||||
out_data = (char *) malloc(out_size);
|
||||
out_data = (char*) malloc(out_size);
|
||||
memset(out_data, 0, out_size);
|
||||
|
||||
data_write_UINT32(out_data + 0, InterfaceId); /* interface */
|
||||
data_write_UINT32(out_data + 4, MessageId); /* message id */
|
||||
data_write_UINT32(out_data + 8, ADD_VIRTUAL_CHANNEL); /* function id */
|
||||
@@ -439,8 +445,8 @@ static void* urbdrc_search_usb_device(void* arg)
|
||||
IWTSVirtualChannel* dvc_channel;
|
||||
USB_SEARCHDEV* sdev;
|
||||
IUDEVICE* pdev = NULL;
|
||||
struct wait_obj* listobj[2];
|
||||
struct wait_obj* mon_fd;
|
||||
HANDLE listobj[2];
|
||||
HANDLE mon_fd;
|
||||
int numobj, timeout;
|
||||
int busnum, devnum;
|
||||
int success = 0, error, on_close = 0, found = 0;
|
||||
@@ -469,7 +475,7 @@ static void* urbdrc_search_usb_device(void* arg)
|
||||
|
||||
/* Get the file descriptor (fd) for the monitor.
|
||||
This fd will get passed to select() */
|
||||
mon_fd = wait_obj_new_with_fd((void*) (size_t) udev_monitor_get_fd(mon));
|
||||
mon_fd = CreateFileDescriptorEvent(NULL, TRUE, FALSE, udev_monitor_get_fd(mon));
|
||||
|
||||
while (1)
|
||||
{
|
||||
@@ -483,15 +489,16 @@ static void* urbdrc_search_usb_device(void* arg)
|
||||
listobj[0] = searchman->term_event;
|
||||
listobj[1] = mon_fd;
|
||||
numobj = 2;
|
||||
wait_obj_select(listobj, numobj, -1);
|
||||
|
||||
if (wait_obj_is_set(searchman->term_event))
|
||||
WaitForMultipleObjects(numobj, listobj, FALSE, INFINITE);
|
||||
|
||||
if (WaitForSingleObject(searchman->term_event, 0) == WAIT_OBJECT_0)
|
||||
{
|
||||
sem_post(&searchman->sem_term);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (wait_obj_is_set(mon_fd))
|
||||
if (WaitForSingleObject(mon_fd, 0) == WAIT_OBJECT_0)
|
||||
{
|
||||
dev = udev_monitor_receive_device(mon);
|
||||
|
||||
@@ -565,11 +572,11 @@ static void* urbdrc_search_usb_device(void* arg)
|
||||
numobj = 1;
|
||||
timeout = 4000; /* milliseconds */
|
||||
|
||||
wait_obj_select(listobj, numobj, timeout);
|
||||
WaitForMultipleObjects(numobj, listobj, FALSE, timeout);
|
||||
|
||||
if (wait_obj_is_set(searchman->term_event))
|
||||
if (WaitForSingleObject(searchman->term_event, 0) == WAIT_OBJECT_0)
|
||||
{
|
||||
wait_obj_free(mon_fd);
|
||||
CloseHandle(mon_fd);
|
||||
sem_post(&searchman->sem_term);
|
||||
return 0;
|
||||
}
|
||||
@@ -621,16 +628,16 @@ static void* urbdrc_search_usb_device(void* arg)
|
||||
numobj = 1;
|
||||
timeout = 3000; /* milliseconds */
|
||||
|
||||
wait_obj_select(listobj, numobj, timeout);
|
||||
WaitForMultipleObjects(numobj, listobj, FALSE, timeout);
|
||||
|
||||
if (wait_obj_is_set(searchman->term_event))
|
||||
if (WaitForSingleObject(searchman->term_event, 0) == WAIT_OBJECT_0)
|
||||
{
|
||||
wait_obj_free(mon_fd);
|
||||
CloseHandle(mon_fd);
|
||||
sem_post(&searchman->sem_term);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(pdev && on_close && dvc_channel && pdev->isSigToEnd(pdev) && !(pdev->isChannelClosed(pdev)))
|
||||
if (pdev && on_close && dvc_channel && pdev->isSigToEnd(pdev) && !(pdev->isChannelClosed(pdev)))
|
||||
{
|
||||
on_close = 0;
|
||||
dvc_channel->Close(dvc_channel);
|
||||
@@ -639,21 +646,22 @@ static void* urbdrc_search_usb_device(void* arg)
|
||||
|
||||
udev_device_unref(dev);
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
printf("No Device from receive_device(). An error occured.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wait_obj_free(mon_fd);
|
||||
CloseHandle(mon_fd);
|
||||
sem_post(&searchman->sem_term);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* urbdrc_new_device_create(void * arg)
|
||||
void* urbdrc_new_device_create(void* arg)
|
||||
{
|
||||
TRANSFER_DATA* transfer_data = (TRANSFER_DATA*) arg;
|
||||
TRANSFER_DATA* transfer_data = (TRANSFER_DATA*) arg;
|
||||
URBDRC_CHANNEL_CALLBACK* callback = transfer_data->callback;
|
||||
IWTSVirtualChannelManager* channel_mgr;
|
||||
URBDRC_PLUGIN* urbdrc = transfer_data->urbdrc;
|
||||
@@ -756,7 +764,7 @@ static int urbdrc_process_channel_notification(URBDRC_CHANNEL_CALLBACK* callback
|
||||
transfer_data->udevman = urbdrc->udevman;
|
||||
transfer_data->urbdrc = urbdrc;
|
||||
transfer_data->cbSize = cbSize;
|
||||
transfer_data->pBuffer = (BYTE *)malloc((cbSize));
|
||||
transfer_data->pBuffer = (BYTE*) malloc((cbSize));
|
||||
|
||||
for (i = 0; i < (cbSize); i++)
|
||||
{
|
||||
@@ -919,7 +927,7 @@ static int urbdrc_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManag
|
||||
{
|
||||
URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*) pPlugin;
|
||||
IUDEVMAN* udevman = NULL;
|
||||
USB_SEARCHMAN * searchman = NULL;
|
||||
USB_SEARCHMAN* searchman = NULL;
|
||||
|
||||
LLOGLN(10, ("urbdrc_plugin_initialize:"));
|
||||
urbdrc->listener_callback = (URBDRC_LISTENER_CALLBACK*) malloc(sizeof(URBDRC_LISTENER_CALLBACK));
|
||||
@@ -935,7 +943,7 @@ static int urbdrc_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManag
|
||||
urbdrc->searchman = searchman;
|
||||
|
||||
return pChannelMgr->CreateListener(pChannelMgr, "URBDRC", 0,
|
||||
(IWTSListenerCallback *) urbdrc->listener_callback, NULL);
|
||||
(IWTSListenerCallback*) urbdrc->listener_callback, NULL);
|
||||
}
|
||||
|
||||
static int urbdrc_plugin_terminated(IWTSPlugin* pPlugin)
|
||||
@@ -979,7 +987,7 @@ static int urbdrc_plugin_terminated(IWTSPlugin* pPlugin)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void urbdrc_register_udevman_plugin(IWTSPlugin* pPlugin, IUDEVMAN* udevman)
|
||||
static void urbdrc_register_udevman_addin(IWTSPlugin* pPlugin, IUDEVMAN* udevman)
|
||||
{
|
||||
URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*) pPlugin;
|
||||
|
||||
@@ -994,31 +1002,19 @@ static void urbdrc_register_udevman_plugin(IWTSPlugin* pPlugin, IUDEVMAN* udevma
|
||||
urbdrc->udevman = udevman;
|
||||
}
|
||||
|
||||
static int urbdrc_load_udevman_plugin(IWTSPlugin* pPlugin, const char* name, RDP_PLUGIN_DATA* data)
|
||||
static int urbdrc_load_udevman_addin(IWTSPlugin* pPlugin, const char* name, ADDIN_ARGV* args)
|
||||
{
|
||||
char* fullname;
|
||||
PFREERDP_URBDRC_DEVICE_ENTRY entry;
|
||||
FREERDP_URBDRC_SERVICE_ENTRY_POINTS entryPoints;
|
||||
|
||||
if (strrchr(name, '.') != NULL)
|
||||
{
|
||||
entry = (PFREERDP_URBDRC_DEVICE_ENTRY) freerdp_load_plugin(name, URBDRC_UDEVMAN_EXPORT_FUNC_NAME);
|
||||
}
|
||||
else
|
||||
{
|
||||
fullname = xzalloc(strlen(name) + 8);
|
||||
strcpy(fullname, name);
|
||||
strcat(fullname, "_udevman");
|
||||
entry = (PFREERDP_URBDRC_DEVICE_ENTRY) freerdp_load_plugin(fullname, URBDRC_UDEVMAN_EXPORT_FUNC_NAME);
|
||||
free(fullname);
|
||||
}
|
||||
entry = (PFREERDP_URBDRC_DEVICE_ENTRY) freerdp_load_channel_addin_entry("urbdrc", (LPSTR) name, NULL, 0);
|
||||
|
||||
if (entry == NULL)
|
||||
return FALSE;
|
||||
|
||||
entryPoints.plugin = pPlugin;
|
||||
entryPoints.pRegisterUDEVMAN = urbdrc_register_udevman_plugin;
|
||||
entryPoints.plugin_data = data;
|
||||
entryPoints.pRegisterUDEVMAN = urbdrc_register_udevman_addin;
|
||||
entryPoints.args = args;
|
||||
|
||||
if (entry(&entryPoints) != 0)
|
||||
{
|
||||
@@ -1029,17 +1025,57 @@ static int urbdrc_load_udevman_plugin(IWTSPlugin* pPlugin, const char* name, RDP
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int urbdrc_process_plugin_data(IWTSPlugin* pPlugin, RDP_PLUGIN_DATA* data)
|
||||
void urbdrc_set_subsystem(URBDRC_PLUGIN* urbdrc, char* subsystem)
|
||||
{
|
||||
BOOL ret;
|
||||
if (urbdrc->subsystem)
|
||||
free(urbdrc->subsystem);
|
||||
|
||||
if (data->data[0] && (strcmp((char*)data->data[0], "urbdrc") == 0 || strstr((char*) data->data[0], "/urbdrc.") != NULL))
|
||||
urbdrc->subsystem = _strdup(subsystem);
|
||||
}
|
||||
|
||||
COMMAND_LINE_ARGUMENT_A urbdrc_args[] =
|
||||
{
|
||||
{ "dbg", COMMAND_LINE_VALUE_FLAG, "", NULL, BoolValueFalse, -1, NULL, "debug" },
|
||||
{ "sys", COMMAND_LINE_VALUE_REQUIRED, "<subsystem>", NULL, NULL, -1, NULL, "subsystem" },
|
||||
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
|
||||
};
|
||||
|
||||
static void urbdrc_process_addin_args(URBDRC_PLUGIN* urbdrc, ADDIN_ARGV* args)
|
||||
{
|
||||
int status;
|
||||
DWORD flags;
|
||||
COMMAND_LINE_ARGUMENT_A* arg;
|
||||
|
||||
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON;
|
||||
|
||||
status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv,
|
||||
urbdrc_args, flags, urbdrc, NULL, NULL);
|
||||
|
||||
arg = urbdrc_args;
|
||||
|
||||
do
|
||||
{
|
||||
ret = urbdrc_load_udevman_plugin(pPlugin, "libusb", data);
|
||||
return ret;
|
||||
}
|
||||
if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT))
|
||||
continue;
|
||||
|
||||
return TRUE;
|
||||
CommandLineSwitchStart(arg)
|
||||
|
||||
CommandLineSwitchCase(arg, "dbg")
|
||||
{
|
||||
urbdrc_debug = 0;
|
||||
}
|
||||
CommandLineSwitchCase(arg, "sys")
|
||||
{
|
||||
urbdrc_set_subsystem(urbdrc, arg->Value);
|
||||
}
|
||||
CommandLineSwitchDefault(arg)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CommandLineSwitchEnd(arg)
|
||||
}
|
||||
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
@@ -1048,16 +1084,17 @@ static int urbdrc_process_plugin_data(IWTSPlugin* pPlugin, RDP_PLUGIN_DATA* data
|
||||
|
||||
int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
|
||||
{
|
||||
int error = 0;
|
||||
int status = 0;
|
||||
ADDIN_ARGV* args;
|
||||
URBDRC_PLUGIN* urbdrc;
|
||||
RDP_PLUGIN_DATA* data;
|
||||
|
||||
urbdrc = (URBDRC_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "urbdrc");
|
||||
data = pEntryPoints->GetPluginData(pEntryPoints);
|
||||
args = pEntryPoints->GetPluginData(pEntryPoints);
|
||||
|
||||
if (urbdrc == NULL)
|
||||
{
|
||||
urbdrc = xnew(URBDRC_PLUGIN);
|
||||
urbdrc = (URBDRC_PLUGIN*) malloc(sizeof(URBDRC_PLUGIN));
|
||||
ZeroMemory(urbdrc, sizeof(URBDRC_PLUGIN));
|
||||
|
||||
urbdrc->iface.Initialize = urbdrc_plugin_initialize;
|
||||
urbdrc->iface.Connected = NULL;
|
||||
@@ -1068,14 +1105,16 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
|
||||
|
||||
urbdrc_debug = 10;
|
||||
|
||||
if (data->data[2] && strstr((char *)data->data[2], "debug"))
|
||||
urbdrc_debug = 0;
|
||||
|
||||
error = pEntryPoints->RegisterPlugin(pEntryPoints, "urbdrc", (IWTSPlugin *) urbdrc);
|
||||
status = pEntryPoints->RegisterPlugin(pEntryPoints, "urbdrc", (IWTSPlugin*) urbdrc);
|
||||
}
|
||||
|
||||
if (error == 0)
|
||||
urbdrc_process_plugin_data((IWTSPlugin*) urbdrc, data);
|
||||
if (status == 0)
|
||||
urbdrc_process_addin_args(urbdrc, args);
|
||||
|
||||
return error;
|
||||
if (!urbdrc->subsystem)
|
||||
urbdrc_set_subsystem(urbdrc, "libusb");
|
||||
|
||||
urbdrc_load_udevman_addin((IWTSPlugin*) urbdrc, urbdrc->subsystem, args);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -35,11 +35,12 @@ typedef struct _IUDEVICE IUDEVICE;
|
||||
typedef struct _IUDEVMAN IUDEVMAN;
|
||||
|
||||
#define BASIC_DEV_STATE_DEFINED(_arg, _type) \
|
||||
_type (*get_##_arg) (IUDEVICE *pdev); \
|
||||
void (*set_##_arg) (IUDEVICE *pdev, _type _arg)
|
||||
_type (*get_##_arg) (IUDEVICE* pdev); \
|
||||
void (*set_##_arg) (IUDEVICE* pdev, _type _arg)
|
||||
|
||||
#define BASIC_DEVMAN_STATE_DEFINED(_arg, _type) \
|
||||
_type (*get_##_arg) (IUDEVMAN *udevman); \
|
||||
void (*set_##_arg) (IUDEVMAN *udevman, _type _arg)
|
||||
_type (*get_##_arg) (IUDEVMAN* udevman); \
|
||||
void (*set_##_arg) (IUDEVMAN* udevman, _type _arg)
|
||||
|
||||
typedef struct _URBDRC_LISTENER_CALLBACK URBDRC_LISTENER_CALLBACK;
|
||||
|
||||
@@ -74,17 +75,16 @@ struct _URBDRC_PLUGIN
|
||||
USB_SEARCHMAN* searchman;
|
||||
UINT32 first_channel_id;
|
||||
UINT32 vchannel_status;
|
||||
char* subsystem;
|
||||
};
|
||||
|
||||
#define URBDRC_UDEVMAN_EXPORT_FUNC_NAME "FreeRDPUDEVMANEntry"
|
||||
|
||||
typedef void (*PREGISTERURBDRCSERVICE)(IWTSPlugin* plugin, IUDEVMAN* udevman);
|
||||
|
||||
struct _FREERDP_URBDRC_SERVICE_ENTRY_POINTS
|
||||
{
|
||||
IWTSPlugin* plugin;
|
||||
PREGISTERURBDRCSERVICE pRegisterUDEVMAN;
|
||||
RDP_PLUGIN_DATA* plugin_data;
|
||||
ADDIN_ARGV* args;
|
||||
};
|
||||
typedef struct _FREERDP_URBDRC_SERVICE_ENTRY_POINTS FREERDP_URBDRC_SERVICE_ENTRY_POINTS;
|
||||
typedef FREERDP_URBDRC_SERVICE_ENTRY_POINTS* PFREERDP_URBDRC_SERVICE_ENTRY_POINTS;
|
||||
@@ -106,107 +106,75 @@ struct _TRANSFER_DATA
|
||||
struct _IUDEVICE
|
||||
{
|
||||
/* Transfer */
|
||||
int (*isoch_transfer) (IUDEVICE * idev, UINT32 RequestId,
|
||||
UINT32 EndpointAddress,
|
||||
UINT32 TransferFlags,
|
||||
int NoAck,
|
||||
UINT32 *ErrorCount,
|
||||
UINT32 *UrbdStatus,
|
||||
UINT32 *StartFrame,
|
||||
UINT32 NumberOfPackets,
|
||||
BYTE *IsoPacket,
|
||||
UINT32 *BufferSize,
|
||||
BYTE *Buffer,
|
||||
int Timeout);
|
||||
int (*isoch_transfer) (IUDEVICE* idev, UINT32 RequestId,
|
||||
UINT32 EndpointAddress, UINT32 TransferFlags, int NoAck, UINT32* ErrorCount,
|
||||
UINT32* UrbdStatus, UINT32* StartFrame, UINT32 NumberOfPackets,
|
||||
BYTE* IsoPacket, UINT32* BufferSize, BYTE* Buffer, int Timeout);
|
||||
|
||||
int (*control_transfer) (IUDEVICE * idev, UINT32 RequestId,
|
||||
UINT32 EndpointAddress,
|
||||
UINT32 TransferFlags,
|
||||
BYTE bmRequestType,
|
||||
BYTE Request,
|
||||
UINT16 Value,
|
||||
UINT16 Index,
|
||||
UINT32 *UrbdStatus,
|
||||
UINT32 *BufferSize,
|
||||
BYTE *Buffer,
|
||||
UINT32 Timeout);
|
||||
int (*control_transfer) (IUDEVICE* idev, UINT32 RequestId,
|
||||
UINT32 EndpointAddress, UINT32 TransferFlags, BYTE bmRequestType, BYTE Request, UINT16 Value,
|
||||
UINT16 Index, UINT32* UrbdStatus, UINT32* BufferSize, BYTE* Buffer, UINT32 Timeout);
|
||||
|
||||
int (*bulk_or_interrupt_transfer) (IUDEVICE * idev, UINT32 RequestId,
|
||||
UINT32 EndpointAddress,
|
||||
UINT32 TransferFlags,
|
||||
UINT32 *UsbdStatus,
|
||||
UINT32 *BufferSize,
|
||||
BYTE *Buffer,
|
||||
UINT32 Timeout);
|
||||
int (*bulk_or_interrupt_transfer) (IUDEVICE* idev, UINT32 RequestId, UINT32 EndpointAddress,
|
||||
UINT32 TransferFlags, UINT32* UsbdStatus, UINT32* BufferSize, BYTE* Buffer, UINT32 Timeout);
|
||||
|
||||
int (*select_configuration) (IUDEVICE* idev, UINT32 bConfigurationValue);
|
||||
|
||||
int (*select_configuration) (IUDEVICE * idev, UINT32 bConfigurationValue);
|
||||
|
||||
int (*select_interface) (IUDEVICE * idev, BYTE InterfaceNumber,
|
||||
int (*select_interface) (IUDEVICE* idev, BYTE InterfaceNumber,
|
||||
BYTE AlternateSetting);
|
||||
|
||||
int (*control_pipe_request) (IUDEVICE * idev, UINT32 RequestId,
|
||||
UINT32 EndpointAddress,
|
||||
UINT32 *UsbdStatus,
|
||||
int command);
|
||||
int (*control_pipe_request) (IUDEVICE* idev, UINT32 RequestId,
|
||||
UINT32 EndpointAddress, UINT32* UsbdStatus, int command);
|
||||
|
||||
int (*control_query_device_text) (IUDEVICE * idev, UINT32 TextType,
|
||||
UINT32 LocaleId,
|
||||
UINT32 *BufferSize,
|
||||
BYTE * Buffer);
|
||||
int (*control_query_device_text) (IUDEVICE* idev, UINT32 TextType,
|
||||
UINT32 LocaleId, UINT32*BufferSize, BYTE* Buffer);
|
||||
|
||||
int (*os_feature_descriptor_request) (IUDEVICE * idev, UINT32 RequestId,
|
||||
BYTE Recipient,
|
||||
BYTE InterfaceNumber,
|
||||
BYTE Ms_PageIndex,
|
||||
UINT16 Ms_featureDescIndex,
|
||||
UINT32 * UsbdStatus,
|
||||
UINT32 * BufferSize,
|
||||
BYTE* Buffer,
|
||||
int Timeout);
|
||||
int (*os_feature_descriptor_request) (IUDEVICE* idev, UINT32 RequestId, BYTE Recipient,
|
||||
BYTE InterfaceNumber, BYTE Ms_PageIndex, UINT16 Ms_featureDescIndex, UINT32* UsbdStatus,
|
||||
UINT32* BufferSize, BYTE* Buffer, int Timeout);
|
||||
|
||||
void (*cancel_all_transfer_request) (IUDEVICE * idev);
|
||||
void (*cancel_all_transfer_request) (IUDEVICE* idev);
|
||||
|
||||
int (*cancel_transfer_request) (IUDEVICE * idev, UINT32 RequestId);
|
||||
int (*cancel_transfer_request) (IUDEVICE* idev, UINT32 RequestId);
|
||||
|
||||
int (*query_device_descriptor) (IUDEVICE * idev, int offset);
|
||||
int (*query_device_descriptor) (IUDEVICE* idev, int offset);
|
||||
|
||||
void (*detach_kernel_driver) (IUDEVICE * idev);
|
||||
void (*detach_kernel_driver) (IUDEVICE* idev);
|
||||
|
||||
void (*attach_kernel_driver) (IUDEVICE * idev);
|
||||
void (*attach_kernel_driver) (IUDEVICE* idev);
|
||||
|
||||
int (*wait_action_completion) (IUDEVICE * idev);
|
||||
int (*wait_action_completion) (IUDEVICE* idev);
|
||||
|
||||
void (*push_action) (IUDEVICE * idev);
|
||||
void (*push_action) (IUDEVICE* idev);
|
||||
|
||||
void (*complete_action) (IUDEVICE * idev);
|
||||
void (*complete_action) (IUDEVICE* idev);
|
||||
|
||||
/* Wait for 5 sec */
|
||||
int (*wait_for_detach) (IUDEVICE * idev);
|
||||
int (*wait_for_detach) (IUDEVICE* idev);
|
||||
|
||||
/* FIXME: Currently this is a way of stupid, SHOULD to improve it.
|
||||
* Isochronous transfer must to FIFO */
|
||||
void (*lock_fifo_isoch) (IUDEVICE * idev);
|
||||
void (*unlock_fifo_isoch) (IUDEVICE * idev);
|
||||
void (*lock_fifo_isoch) (IUDEVICE* idev);
|
||||
void (*unlock_fifo_isoch) (IUDEVICE* idev);
|
||||
|
||||
int (*query_device_port_status) (IUDEVICE * idev, UINT32 *UsbdStatus,
|
||||
UINT32 * BufferSize,
|
||||
BYTE * Buffer);
|
||||
int (*query_device_port_status) (IUDEVICE* idev, UINT32 *UsbdStatus,
|
||||
UINT32* BufferSize,
|
||||
BYTE* Buffer);
|
||||
|
||||
int (*request_queue_is_none) (IUDEVICE * idev);
|
||||
int (*request_queue_is_none) (IUDEVICE* idev);
|
||||
|
||||
MSUSB_CONFIG_DESCRIPTOR * (*complete_msconfig_setup) (IUDEVICE * idev,
|
||||
MSUSB_CONFIG_DESCRIPTOR * MsConfig);
|
||||
MSUSB_CONFIG_DESCRIPTOR* (*complete_msconfig_setup) (IUDEVICE* idev,
|
||||
MSUSB_CONFIG_DESCRIPTOR* MsConfig);
|
||||
/* Basic state */
|
||||
int (*isCompositeDevice) (IUDEVICE * idev);
|
||||
int (*isSigToEnd) (IUDEVICE * idev);
|
||||
int (*isExist) (IUDEVICE * idev);
|
||||
int (*isAlreadySend) (IUDEVICE * idev);
|
||||
int (*isChannelClosed) (IUDEVICE * idev);
|
||||
void (*SigToEnd) (IUDEVICE * idev);
|
||||
void (*setAlreadySend) (IUDEVICE * idev);
|
||||
void (*setChannelClosed) (IUDEVICE * idev);
|
||||
char *(*getPath) (IUDEVICE * idev);
|
||||
int (*isCompositeDevice) (IUDEVICE* idev);
|
||||
int (*isSigToEnd) (IUDEVICE* idev);
|
||||
int (*isExist) (IUDEVICE* idev);
|
||||
int (*isAlreadySend) (IUDEVICE* idev);
|
||||
int (*isChannelClosed) (IUDEVICE* idev);
|
||||
void (*SigToEnd) (IUDEVICE* idev);
|
||||
void (*setAlreadySend) (IUDEVICE* idev);
|
||||
void (*setChannelClosed) (IUDEVICE* idev);
|
||||
char *(*getPath) (IUDEVICE* idev);
|
||||
|
||||
BASIC_DEV_STATE_DEFINED(channel_id, UINT32);
|
||||
BASIC_DEV_STATE_DEFINED(UsbDevice, UINT32);
|
||||
@@ -214,12 +182,12 @@ struct _IUDEVICE
|
||||
BASIC_DEV_STATE_DEFINED(bus_number, UINT16);
|
||||
BASIC_DEV_STATE_DEFINED(dev_number, UINT16);
|
||||
BASIC_DEV_STATE_DEFINED(port_number, int);
|
||||
BASIC_DEV_STATE_DEFINED(isoch_queue, void *);
|
||||
BASIC_DEV_STATE_DEFINED(MsConfig, MSUSB_CONFIG_DESCRIPTOR *);
|
||||
BASIC_DEV_STATE_DEFINED(isoch_queue, void*);
|
||||
BASIC_DEV_STATE_DEFINED(MsConfig, MSUSB_CONFIG_DESCRIPTOR*);
|
||||
|
||||
BASIC_DEV_STATE_DEFINED(p_udev, void *);
|
||||
BASIC_DEV_STATE_DEFINED(p_prev, void *);
|
||||
BASIC_DEV_STATE_DEFINED(p_next, void *);
|
||||
BASIC_DEV_STATE_DEFINED(p_udev, void*);
|
||||
BASIC_DEV_STATE_DEFINED(p_prev, void*);
|
||||
BASIC_DEV_STATE_DEFINED(p_next, void*);
|
||||
|
||||
/* Control semaphore or mutex lock */
|
||||
|
||||
@@ -228,36 +196,32 @@ struct _IUDEVICE
|
||||
struct _IUDEVMAN
|
||||
{
|
||||
/* Standard */
|
||||
void (*free) (IUDEVMAN *idevman);
|
||||
void (*free) (IUDEVMAN* idevman);
|
||||
|
||||
/* Manage devices */
|
||||
void (*rewind) (IUDEVMAN *idevman);
|
||||
int (*has_next) (IUDEVMAN *idevman);
|
||||
int (*unregister_udevice) (IUDEVMAN* idevman, int bus_number,
|
||||
int dev_number);
|
||||
int (*register_udevice) (IUDEVMAN* idevman, int bus_number,
|
||||
int dev_number,
|
||||
int UsbDevice,
|
||||
UINT16 idVendor,
|
||||
UINT16 idProduct,
|
||||
int flag);
|
||||
IUDEVICE *(*get_next) (IUDEVMAN *idevman);
|
||||
IUDEVICE *(*get_udevice_by_UsbDevice) (IUDEVMAN * idevman,
|
||||
UINT32 UsbDevice);
|
||||
IUDEVICE *(*get_udevice_by_UsbDevice_try_again) (IUDEVMAN * idevman,
|
||||
UINT32 UsbDevice);
|
||||
void (*rewind) (IUDEVMAN* idevman);
|
||||
int (*has_next) (IUDEVMAN* idevman);
|
||||
int (*unregister_udevice) (IUDEVMAN* idevman, int bus_number, int dev_number);
|
||||
int (*register_udevice) (IUDEVMAN* idevman, int bus_number,
|
||||
int dev_number, int UsbDevice, UINT16 idVendor, UINT16 idProduct, int flag);
|
||||
IUDEVICE *(*get_next) (IUDEVMAN* idevman);
|
||||
IUDEVICE *(*get_udevice_by_UsbDevice) (IUDEVMAN* idevman, UINT32 UsbDevice);
|
||||
IUDEVICE *(*get_udevice_by_UsbDevice_try_again) (IUDEVMAN* idevman, UINT32 UsbDevice);
|
||||
|
||||
/* Extension */
|
||||
int (*check_device_exist_by_id) (IUDEVMAN * idevman, UINT16 idVendor,
|
||||
UINT16 idProduct);
|
||||
int (*isAutoAdd) (IUDEVMAN * idevman);
|
||||
int (*check_device_exist_by_id) (IUDEVMAN* idevman, UINT16 idVendor, UINT16 idProduct);
|
||||
int (*isAutoAdd) (IUDEVMAN* idevman);
|
||||
|
||||
/* Basic state */
|
||||
BASIC_DEVMAN_STATE_DEFINED(defUsbDevice, UINT32);
|
||||
BASIC_DEVMAN_STATE_DEFINED(device_num, int);
|
||||
BASIC_DEVMAN_STATE_DEFINED(sem_timeout, int);
|
||||
|
||||
/* control semaphore or mutex lock */
|
||||
void (*loading_lock) (IUDEVMAN * idevman);
|
||||
void (*loading_unlock) (IUDEVMAN * idevman);
|
||||
void (*push_urb) (IUDEVMAN * idevman);
|
||||
void (*wait_urb) (IUDEVMAN * idevman);
|
||||
void (*loading_lock) (IUDEVMAN* idevman);
|
||||
void (*loading_unlock) (IUDEVMAN* idevman);
|
||||
void (*push_urb) (IUDEVMAN* idevman);
|
||||
void (*wait_urb) (IUDEVMAN* idevman);
|
||||
};
|
||||
|
||||
#endif /* __URBDRC_MAIN_H */
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include "df_graphics.h"
|
||||
|
||||
@@ -123,7 +123,8 @@ void df_register_graphics(rdpGraphics* graphics)
|
||||
{
|
||||
rdpPointer* pointer;
|
||||
|
||||
pointer = xnew(rdpPointer);
|
||||
pointer = (rdpPointer*) malloc(sizeof(rdpPointer));
|
||||
ZeroMemory(pointer, sizeof(rdpPointer));
|
||||
pointer->size = sizeof(dfPointer);
|
||||
|
||||
pointer->New = df_Pointer_New;
|
||||
|
||||
@@ -22,13 +22,14 @@
|
||||
#include <locale.h>
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/utils/args.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/event.h>
|
||||
#include <freerdp/constants.h>
|
||||
#include <freerdp/utils/event.h>
|
||||
#include <freerdp/client/file.h>
|
||||
#include <freerdp/client/cmdline.h>
|
||||
#include <freerdp/client/channels.h>
|
||||
#include <freerdp/client/cliprdr.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/synch.h>
|
||||
|
||||
#include "df_event.h"
|
||||
@@ -120,7 +121,9 @@ BOOL df_pre_connect(freerdp* instance)
|
||||
dfContext* context;
|
||||
rdpSettings* settings;
|
||||
|
||||
dfi = (dfInfo*) xzalloc(sizeof(dfInfo));
|
||||
dfi = (dfInfo*) malloc(sizeof(dfInfo));
|
||||
ZeroMemory(dfi, sizeof(dfInfo));
|
||||
|
||||
context = ((dfContext*) instance->context);
|
||||
context->dfi = dfi;
|
||||
|
||||
@@ -152,11 +155,15 @@ BOOL df_pre_connect(freerdp* instance)
|
||||
settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE;
|
||||
settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE;
|
||||
|
||||
dfi->clrconv = xnew(CLRCONV);
|
||||
dfi->clrconv = (CLRCONV*) malloc(sizeof(CLRCONV));
|
||||
ZeroMemory(dfi->clrconv, sizeof(CLRCONV));
|
||||
|
||||
dfi->clrconv->alpha = 1;
|
||||
dfi->clrconv->invert = 0;
|
||||
dfi->clrconv->rgb555 = 0;
|
||||
dfi->clrconv->palette = xnew(rdpPalette);
|
||||
|
||||
dfi->clrconv->palette = (rdpPalette*) malloc(sizeof(rdpPalette));
|
||||
ZeroMemory(dfi->clrconv->palette, sizeof(rdpPalette));
|
||||
|
||||
freerdp_channels_pre_connect(instance->context->channels, instance);
|
||||
|
||||
@@ -221,31 +228,10 @@ BOOL df_post_connect(freerdp* instance)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int df_process_plugin_args(rdpSettings* settings, const char* name,
|
||||
RDP_PLUGIN_DATA* plugin_data, void* user_data)
|
||||
{
|
||||
void* entry = NULL;
|
||||
rdpChannels* channels = (rdpChannels*) user_data;
|
||||
|
||||
entry = freerdp_channels_client_find_static_entry("VirtualChannelEntry", name);
|
||||
|
||||
if (entry)
|
||||
{
|
||||
if (freerdp_channels_client_load(channels, settings, entry, plugin_data) == 0)
|
||||
{
|
||||
printf("loading channel %s (static)\n", name);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
printf("loading channel %s (plugin)\n", name);
|
||||
freerdp_channels_load_plugin(channels, settings, name, plugin_data);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
BOOL df_verify_certificate(freerdp* instance, char* subject, char* issuer, char* fingerprint)
|
||||
{
|
||||
char answer;
|
||||
|
||||
printf("Certificate details:\n");
|
||||
printf("\tSubject: %s\n", subject);
|
||||
printf("\tIssuer: %s\n", issuer);
|
||||
@@ -254,7 +240,6 @@ BOOL df_verify_certificate(freerdp* instance, char* subject, char* issuer, char*
|
||||
"the CA certificate in your certificate store, or the certificate has expired. "
|
||||
"Please look at the documentation on how to create local certificate store for a private CA.\n");
|
||||
|
||||
char answer;
|
||||
while (1)
|
||||
{
|
||||
printf("Do you trust the above certificate? (Y/N) ");
|
||||
@@ -445,6 +430,7 @@ void* thread_func(void* param)
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int status;
|
||||
pthread_t thread;
|
||||
freerdp* instance;
|
||||
dfContext* context;
|
||||
@@ -472,9 +458,20 @@ int main(int argc, char* argv[])
|
||||
channels = instance->context->channels;
|
||||
|
||||
DirectFBInit(&argc, &argv);
|
||||
freerdp_parse_args(instance->settings, argc, argv, df_process_plugin_args, channels, NULL, NULL);
|
||||
|
||||
data = (struct thread_data*) xzalloc(sizeof(struct thread_data));
|
||||
instance->context->argc = argc;
|
||||
instance->context->argv = argv;
|
||||
|
||||
status = freerdp_client_parse_command_line_arguments(argc, argv, instance->settings);
|
||||
|
||||
if (status < 0)
|
||||
exit(0);
|
||||
|
||||
freerdp_client_load_addins(instance->context->channels, instance->settings);
|
||||
|
||||
data = (struct thread_data*) malloc(sizeof(struct thread_data));
|
||||
ZeroMemory(data, sizeof(sizeof(struct thread_data)));
|
||||
|
||||
data->instance = instance;
|
||||
|
||||
g_thread_count++;
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
#import "freerdp/graphics.h"
|
||||
#import "freerdp/utils/event.h"
|
||||
#import "freerdp/client/cliprdr.h"
|
||||
#import "freerdp/utils/args.h"
|
||||
#import "freerdp/client/file.h"
|
||||
#import "freerdp/client/cmdline.h"
|
||||
#import "freerdp/rail/rail.h"
|
||||
#import "freerdp/rail.h"
|
||||
#import "freerdp/utils/rail.h"
|
||||
|
||||
@@ -1016,6 +1016,7 @@ int rdp_connect()
|
||||
|
||||
BOOL mac_pre_connect(freerdp *inst)
|
||||
{
|
||||
int status;
|
||||
char *cptr;
|
||||
int len;
|
||||
int i;
|
||||
@@ -1213,12 +1214,19 @@ BOOL mac_pre_connect(freerdp *inst)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
freerdp_parse_args(inst->settings, g_mrdpview->argc, g_mrdpview->argv, process_plugin_args, inst->context->channels, NULL, NULL);
|
||||
if ((strcmp(g_mrdpview->argv[1], "-h") == 0) || (strcmp(g_mrdpview->argv[1], "--help") == 0)) {
|
||||
[NSApp terminate:nil];
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
inst->context->argc = g_mrdpview->argc;
|
||||
inst->context->argv = g_mrdpview->argv;
|
||||
|
||||
status = freerdp_client_parse_command_line_arguments(inst->context->argc, inst->context->argv, inst->settings);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
[NSApp terminate:nil];
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
freerdp_client_load_addins(inst->context->channels, inst->settings);
|
||||
|
||||
[g_mrdpview setViewSize:inst->settings->DesktopWidth :inst->settings->DesktopHeight];
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user